Salome HOME
0023614: EDF 16256 - Coordinates of a group vsr/23614
authorvsr <vsr@opencascade.com>
Mon, 10 Dec 2018 07:35:35 +0000 (10:35 +0300)
committervsr <vsr@opencascade.com>
Tue, 11 Dec 2018 14:27:12 +0000 (17:27 +0300)
src/SMESHGUI/SMESHGUI_MeshInfo.cxx
src/SMESHGUI/SMESHGUI_MeshInfo.h
src/SMESHGUI/SMESHGUI_MultiEditDlg.cxx
src/SMESHGUI/SMESHGUI_SelectionProxy.cxx
src/SMESHGUI/SMESHGUI_SelectionProxy.h
src/SMESHGUI/SMESH_msg_en.ts
src/SMESHGUI/SMESH_msg_fr.ts
src/SMESHGUI/SMESH_msg_ja.ts

index 44d78880deb6c87888850aeae2a3f5e3cbd7f8d2..88726e47dd8266e8dc81ae12dec15fe1327f4220 100644 (file)
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-//  File   : SMESHGUI_MeshInfo.cxx
-//  Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
 
 #include "SMESHGUI_MeshInfo.h"
 
-#include "SMDS_Mesh.hxx"
-#include "SMDS_VolumeTool.hxx"
-#include "SMESH_Actor.h"
+#include "SMDS_Mesh.hxx"//todo:remove?
+#include "SMDS_VolumeTool.hxx"//todo:remove?
+#include "SMESH_Actor.h"//todo:remove?
 #include "SMESHGUI.h"
 #include "SMESHGUI_FilterUtils.h"
 #include "SMESHGUI_IdPreview.h"
 #include <QTreeWidget>
 #include <QVBoxLayout>
 
+////////////////////////////////////////////////////////////////////////////////
+/// \class Field
+/// \brief Field widget.
+/// \internal
+////////////////////////////////////////////////////////////////////////////////
+
+class Field : public QLabel
+{
+public:
+  Field( QWidget*, const QString& = QString() );
+  bool event( QEvent* );
+};
+
+/*!
+  \brief Constructor.
+  \param parent Parent widget.
+  \param name Field name. Defauls to null string.
+*/
+Field::Field( QWidget* parent, const QString& name ): QLabel( parent )
+{
+  setFrameStyle( QLabel::StyledPanel | QLabel::Sunken );
+  setAlignment( Qt::AlignCenter );
+  setAutoFillBackground( true );
+  QPalette pal = palette();
+  QColor base = QApplication::palette().color( QPalette::Active, QPalette::Base );
+  pal.setColor( QPalette::Window, base );
+  setPalette( pal );
+  setMinimumWidth( 60 );
+  if ( !name.isEmpty() )
+    setObjectName( name );
+}
+
+/*!
+  \brief Event handler. Redefined from QLabel.
+*/
+bool Field::event( QEvent* e )
+{
+  if ( e->type() == QEvent::DynamicPropertyChange )
+  {
+    QDynamicPropertyChangeEvent* ce = (QDynamicPropertyChangeEvent*)e;
+    if ( ce->propertyName() == "value" && property( "value" ).isValid() )
+    {
+      setText( QString::number( property( "value" ).toInt() ) );
+      setProperty( "value", QVariant() );
+      return true;
+    }
+  }
+  return QLabel::event( e );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class TreeItemCreator
+/// \brief Generic tree item creator.
+/// \internal
+////////////////////////////////////////////////////////////////////////////////
+
+class TreeItemCreator
+{
+public:
+  TreeItemCreator() {}
+  virtual ~TreeItemCreator() {}
+  virtual QTreeWidgetItem* createItem( QTreeWidgetItem*, int ) = 0;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// General purpose services.
+////////////////////////////////////////////////////////////////////////////////
+
 namespace
 {
   const int SPACING = 6;
   const int MARGIN = 9;
 
+  enum
+  {
+    Bold = 0x01,
+    Italic = 0x02,
+    AllColumns = 0x04,
+    Expanded = 0x08,
+    Editable = 0x10
+  };
+
   enum
   {
     GroupsId = 100,
@@ -117,7 +192,7 @@ namespace
   }
 
   /*!
-    \brief Get spacer for data information.
+    \brief Get spacer.
     \return Spacer string.
     \internal
   */
@@ -129,7 +204,7 @@ namespace
   }
 
   /*!
-    \brief Get indent for data information.
+    \brief Get indent.
     \param length Indent size. Defaults to 1.
     \return Indentation string.
     \internal
@@ -142,7 +217,22 @@ namespace
   }
 
   /*!
-    \brief Get group separator for data information.
+    \brief Get indent.
+    \param spacer Spacer.
+    \param length Indent size. Defaults to 1.
+    \return Indentation string.
+    \internal
+  */
+  QString indent( const QString& spacer, uint length = 1 )
+  {
+    QString result;
+    while( length-- > 0 )
+      result += spacer;
+    return result;
+  }
+
+  /*!
+    \brief Get group separator.
     \param length Length of ruler (number of symbols). Defaults to 80.
     \return Ruler string.
     \internal
@@ -166,176 +256,160 @@ namespace
       v = qobject_cast<QLabel*>( w )->text();
     return v;
   }
-} // end of anonymous namespace
-
-////////////////////////////////////////////////////////////////////////////////
-/// \class Field
-/// \brief Field widget.
-/// \internal
-////////////////////////////////////////////////////////////////////////////////
 
-class Field : public QLabel
-{
-public:
-  Field( QWidget*, const QString& = QString() );
-  bool event( QEvent* );
-};
+  /*!
+    \brief Get font for given options.
+    \param font Initial font.
+    \param options Font attributes.
+    \return Font.
+  */
+  QFont fontFromOptions( const QFont& font, int options )
+  {
+    QFont f = font;
+    f.setBold( options & Bold );
+    f.setItalic( options & Italic );
+    return f;
+  }
 
-/*!
-  \brief Constructor.
-  \param parent Parent widget.
-  \param name Field name. Defauls to null string.
-*/
-Field::Field( QWidget* parent, const QString& name ): QLabel( parent )
-{
-  setFrameStyle( QLabel::StyledPanel | QLabel::Sunken );
-  setAlignment( Qt::AlignCenter );
-  setAutoFillBackground( true );
-  QPalette pal = palette();
-  QColor base = QApplication::palette().color( QPalette::Active, QPalette::Base );
-  pal.setColor( QPalette::Window, base );
-  setPalette( pal );
-  setMinimumWidth( 60 );
-  if ( !name.isEmpty() )
-    setObjectName( name );
-}
+  /*!
+    \brief Set font attributes to given widget.
+    \param w Widget.
+    \param options Font attributes.
+  */
+  void setFontAttributes( QWidget* w, int options )
+  {
+    if ( w )
+      w->setFont( fontFromOptions( w->font(), options ) );
+  }
 
-/*!
-  \brief Event handler. Redefined from QLabel.
-*/
-bool Field::event( QEvent* e )
-{
-  if ( e->type() == QEvent::DynamicPropertyChange )
+  /*!
+    \brief Set attributes to given tree item.
+    \param item Tree widget item.
+    \param options Item attributes.
+  */
+  void setTreeItemAttributes( QTreeWidgetItem* item, int options )
   {
-    QDynamicPropertyChangeEvent* ce = (QDynamicPropertyChangeEvent*)e;
-    if ( ce->propertyName() == "value" && property( "value" ).isValid() )
+    if ( item && item->treeWidget() )
     {
-      setText( QString::number( property( "value" ).toInt() ) );
-      setProperty( "value", QVariant() );
-      return true;
+      for ( int i = 0; i < item->treeWidget()->columnCount(); i++ )
+      {
+        if ( i == 0 || options & AllColumns )
+          item->setFont( i, fontFromOptions( item->font( 0 ), options) );
+      }
     }
+    if ( options & Expanded )
+      item->setExpanded( true );
+    if ( options & Editable )
+      item->setFlags( item->flags() | Qt::ItemIsEditable );
   }
-  return QLabel::event( e );
-}
 
-////////////////////////////////////////////////////////////////////////////////
-/// \class SMESHGUI_Info
-/// \brief Base widget for all information panes.
-////////////////////////////////////////////////////////////////////////////////
-
-/*!
-  \brief Constructor.
-  \param parent Parent widget. Defaults to 0.
-*/
-SMESHGUI_Info::SMESHGUI_Info( QWidget* parent ): QWidget( parent )
-{
-}
+  /*!
+    \brief Create label.
+    \param parent Parent widget.
+    \param options Label options. Defaults to 0 (none).
+    \return New label.
+  */
+  QLabel* createLabel( QWidget* parent, int options = 0 )
+  {
+    QLabel* lab = new QLabel( parent );
+    setFontAttributes( lab, options );
+    return lab;
+  }
 
-/*!
-  \brief Get font for given options.
-  \param options Font attributes.
-  \return Font.
-*/
-QFont SMESHGUI_Info::fontFromOptions( int options )
-{
-  QFont f = font();
-  f.setBold( options & Bold );
-  f.setItalic( options & Italic );
-  return f;
-}
+  /*!
+    \brief Create label.
+    \param text Label text.
+    \param parent Parent widget.
+    \param options Label options. Defaults to 0 (none).
+    \return New label.
+  */
+  QLabel* createLabel( const QString& text, QWidget* parent, int options = 0 )
+  {
+    QLabel* lab = createLabel( parent, options );
+    lab->setText( text );
+    return lab;
+  }
 
-/*!
-  \brief Set font attributes to given widget.
-  \param w Widget.
-  \param options Font attributes.
-*/
-void SMESHGUI_Info::setFontAttributes( QWidget* w, int options )
-{
-  if ( w )
-    w->setFont( fontFromOptions( options ) );
-}
+  /*!
+    \brief Create information field.
+    \param parent Parent widget.
+    \param name Field's object. Default to null string.
+    \return New field.
+  */
+  QLabel* createField( QWidget* parent, const QString& name = QString() )
+  {
+    return new Field( parent, name );
+  }
 
-/*!
-  \brief Set font attributes to given tree item.
-  \param item Tree widget item.
-  \param options Font attributes.
-*/
-void SMESHGUI_Info::setFontAttributes( QTreeWidgetItem* item, int options )
-{
-  if ( item && item->treeWidget() )
+  /*!
+    \brief Create information field.
+    \param parent Parent widget.
+    \param options Label options.
+    \param name Field's object. Default to null string.
+    \return New field.
+  */
+  QLabel* createField( QWidget* parent, int options, const QString& name = QString() )
   {
-    for ( int i = 0; i < item->treeWidget()->columnCount(); i++ )
-    {
-      if ( i == 0 || options & AllColumns )
-        item->setFont( i, fontFromOptions( options) );
-    }
+    QLabel* field = createField( parent, name );
+    setFontAttributes( field, options );
+    return field;
   }
-}
 
-/*!
-  \brief Create label.
-  \param parent Parent widget.
-  \param options Label options. Defaults to 0 (none).
-  \return New label.
-*/
-QLabel* SMESHGUI_Info::createLabel( QWidget* parent, int options )
-{
-  QLabel* lab = new QLabel( parent );
-  setFontAttributes( lab, options );
-  return lab;
-}
+  /*!
+    \brief Create ruler.
+    \param parent Parent widget.
+    \param orientation Ruler orientation. Defaults to horizontal.
+    \return New ruler.
+  */
+  QWidget* createSeparator( QWidget* parent, Qt::Orientation orientation = Qt::Horizontal )
+  {
+    QFrame* line = new QFrame( parent );
+    line->setFrameShape( orientation == Qt::Horizontal ? QFrame::HLine : QFrame::HLine );
+    line->setFrameShadow( QFrame::Sunken );
+    return line;
+  }
 
-/*!
-  \brief Create label.
-  \param text Label text.
-  \param parent Parent widget.
-  \param options Label options. Defaults to 0 (none).
-  \return New label.
-*/
-QLabel* SMESHGUI_Info::createLabel( const QString& text, QWidget* parent, int options )
-{
-  QLabel* lab = createLabel( parent, options );
-  lab->setText( text );
-  return lab;
-}
+  /*!
+    \brief Decorate text as bold.
+    \param text Initial text.
+    \return Decorated text.
+  */
+  QString bold( const QString& text )
+  {
+    return QString("<b>%1</b>").arg( text );
+  }
 
-/*!
-  \brief Create information field.
-  \param parent Parent widget.
-  \param name Field's object. Default to null string.
-  \return New field.
-*/
-QLabel* SMESHGUI_Info::createField( QWidget* parent, const QString& name )
-{
-  return new Field( parent, name );
-}
+  /*!
+    \brief Format connectivity data to string representation.
+    \param connectivity Connectivity map.
+    \param type Element type.
+    \return Stringifed representation of the connectivity.
+  */
+  QString formatConnectivity( SMESH::Connectivity connectivity, int type )
+  {
+    QStringList str;
+    if ( connectivity.contains( type ) )
+    {
+      QList<int> elements = connectivity[ type ];
+      qSort( elements );
+      foreach( int id, elements )
+        str << QString::number( id );
+    }
+    return str.join( " " );
+  }
+} // end of anonymous namespace
 
-/*!
-  \brief Create information field.
-  \param parent Parent widget.
-  \param options Label options.
-  \param name Field's object. Default to null string.
-  \return New field.
-*/
-QLabel* SMESHGUI_Info::createField( QWidget* parent, int options, const QString& name )
-{
-  QLabel* field = createField( parent, name );
-  setFontAttributes( field, options );
-  return field;
-}
+////////////////////////////////////////////////////////////////////////////////
+/// \class SMESHGUI_Info
+/// \brief Base widget for all information panes.
+////////////////////////////////////////////////////////////////////////////////
 
 /*!
-  \brief Create ruler.
-  \param parent Parent widget.
-  \param orientation Ruler orientation. Defaults to horizontal.
-  \return New ruler.
+  \brief Constructor.
+  \param parent Parent widget. Defaults to 0.
 */
-QWidget* SMESHGUI_Info::createSeparator( QWidget* parent, Qt::Orientation orientation )
+SMESHGUI_Info::SMESHGUI_Info( QWidget* parent ): QWidget( parent )
 {
-  QFrame* line = new QFrame( parent );
-  line->setFrameShape( orientation == Qt::Horizontal ? QFrame::HLine : QFrame::HLine );
-  line->setFrameShadow( QFrame::Sunken );
-  return line;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -393,7 +467,7 @@ void ExtraWidget::updateControls( int total, int index )
 
 ////////////////////////////////////////////////////////////////////////////////
 /// \class DumpFileDlg
-/// \brief Save file dialog box, customized for dump info operation.
+/// \brief Standard Save File dialog box, customized for dump info operation.
 /// \internal
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -616,7 +690,7 @@ SMESHGUI_BaseInfo::~SMESHGUI_BaseInfo()
   \brief Show information on given object.
   \param proxy Object to show information on (mesh, sub-mesh, group, ID source).
 */
-void SMESHGUI_BaseInfo::showInfo( const SMESHGUI_SelectionProxy& proxy )
+void SMESHGUI_BaseInfo::showInfo( const SMESH::SelectionProxy& proxy )
 {
   // reset panel
   clear();
@@ -626,25 +700,25 @@ void SMESHGUI_BaseInfo::showInfo( const SMESHGUI_SelectionProxy& proxy )
   {
     myProxy = proxy;
 
-    SMESHGUI_MeshInfo info = proxy.meshInfo();
+    SMESH::MeshInfo info = proxy.meshInfo();
 
     // object info
     // - name
     widget( iName, iSingle )->setProperty( "text", proxy.name() );
     // - type
     QString typeName;
-    SMESHGUI_SelectionProxy::Type type = proxy.type();
-    if ( type == SMESHGUI_SelectionProxy::Mesh )
+    SMESH::SelectionProxy::Type type = proxy.type();
+    if ( type == SMESH::SelectionProxy::Mesh )
     {
       typeName = tr( "OBJECT_MESH" );
     }
-    else if ( type == SMESHGUI_SelectionProxy::Submesh )
+    else if ( type == SMESH::SelectionProxy::Submesh )
     {
       typeName = tr( "OBJECT_SUBMESH" );
     }
-    else if ( type >= SMESHGUI_SelectionProxy::Group )
+    else if ( type >= SMESH::SelectionProxy::Group )
     {
-      switch( proxy.elementType() )
+      switch( proxy.groupElementType() )
       {
       case SMESH::NODE:   typeName = tr( "OBJECT_GROUP_NODES"   ); break;
       case SMESH::EDGE:   typeName = tr( "OBJECT_GROUP_EDGES"   ); break;
@@ -655,11 +729,11 @@ void SMESHGUI_BaseInfo::showInfo( const SMESHGUI_SelectionProxy& proxy )
       default:            typeName = tr( "OBJECT_GROUP"         ); break;
       }
       QString subType;
-      if ( type == SMESHGUI_SelectionProxy::GroupStd )
+      if ( type == SMESH::SelectionProxy::GroupStd )
         subType = tr( "OBJECT_GROUP_STANDALONE" );
-      else if ( type == SMESHGUI_SelectionProxy::GroupGeom )
+      else if ( type == SMESH::SelectionProxy::GroupGeom )
         subType = tr( "OBJECT_GROUP_GEOM" );
-      else if ( type == SMESHGUI_SelectionProxy::GroupFilter )
+      else if ( type == SMESH::SelectionProxy::GroupFilter )
         subType = tr( "OBJECT_GROUP_FILTER" );
       if ( !subType.isEmpty() )
         typeName = QString( "%1 %2" ).arg( typeName, subType );
@@ -1057,9 +1131,263 @@ void SMESHGUI_BaseInfo::saveInfo( QTextStream& out )
   out << endl;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+/// \class InfoWriter
+/// \brief Base info writer class.
+/// \internal
+////////////////////////////////////////////////////////////////////////////////
+
+class InfoWriter
+{
+protected:
+  int myPrecision;
+  bool myRecursive;
+public:
+  InfoWriter( bool = false );
+  void write( const QString&, bool = false );
+  void write( const QString&, const QString&, bool = false );
+  void write( const QString&, int, bool = false );
+  void write( const QString&, double, bool = false );
+  void write( const QString&, const SMESH::XYZ&, bool = false );
+  virtual void indent() {}
+  virtual void unindent() {}
+  virtual void separator() {}
+protected:
+  virtual void put( const QString&, const QString&, bool = false ) = 0;
+};
+
+InfoWriter::InfoWriter( bool r ): myRecursive(r)
+{
+  myPrecision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
+}
+
+void InfoWriter::write( const QString& key, bool emphasize )
+{
+  put( key, QString(), emphasize );
+}
+
+void InfoWriter::write( const QString& key, const QString& value, bool emphasize )
+{
+  put( key, value, emphasize );
+}
+
+void InfoWriter::write( const QString& key, int value, bool emphasize )
+{
+  put( key, QString::number( value ), emphasize );
+}
+
+void InfoWriter::write( const QString& key, double value, bool emphasize )
+{
+  put( key, QString::number( value, myPrecision > 0 ? 'f' : 'g', qAbs( myPrecision ) ), emphasize );
+}
+
+void InfoWriter::write( const QString& key, const SMESH::XYZ& value, bool emphasize )
+{
+  if ( myRecursive )
+  {
+    write( key, emphasize );
+    indent();
+    write( "X", value.x() );
+    write( "Y", value.y() );
+    write( "Z", value.z() );
+    unindent(); 
+  }
+  else
+  {
+    QStringList vl;
+    vl << QString::number( value.x(), myPrecision > 0 ? 'f' : 'g', qAbs( myPrecision ) );
+    vl << QString::number( value.y(), myPrecision > 0 ? 'f' : 'g', qAbs( myPrecision ) );
+    vl << QString::number( value.z(), myPrecision > 0 ? 'f' : 'g', qAbs( myPrecision ) );
+    put( key, vl.join( ", " ), emphasize );
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class SimpleWriter
+/// \brief Base text writer.
+/// \internal
+////////////////////////////////////////////////////////////////////////////////
+
+class SimpleWriter: public InfoWriter
+{
+protected:
+  int myIndent;
+public:
+  SimpleWriter();
+  void indent();
+  void unindent();
+  void separator();
+protected:
+  void put( const QString&, const QString&, bool );
+  virtual QString spacer() const;
+  virtual QString decorate( const QString& ) const;
+  virtual void dumpLine( const QString& ) = 0;
+};
+
+SimpleWriter::SimpleWriter(): InfoWriter(false), myIndent(0)
+{
+}
+
+void SimpleWriter::indent()
+{
+  myIndent += 1;
+}
+
+void SimpleWriter::unindent()
+{
+  myIndent = qMax( myIndent-1, 0 );
+}
+
+void SimpleWriter::separator()
+{
+  write( "" );
+}
+
+QString SimpleWriter::spacer() const
+{
+  return " ";
+}
+
+QString SimpleWriter::decorate( const QString& s ) const
+{
+  return s;
+}
+
+void SimpleWriter::put( const QString& key, const QString& value, bool emphasize )
+{
+  QString line;
+  line += ::indent( spacer(), myIndent*4 );
+  line += decorate( key );
+  if ( !value.isEmpty() )
+  {
+    line += ":";
+    line += emphasize ? decorate( value ) : value;
+  }
+  dumpLine( line );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class StreamWriter
+/// \brief Writer for QTextStream.
+/// \internal
+////////////////////////////////////////////////////////////////////////////////
+
+class StreamWriter: public SimpleWriter
+{
+  QTextStream& myOut;
+public:
+  StreamWriter( QTextStream& );
+protected:
+  void dumpLine( const QString& );
+};
+
+StreamWriter::StreamWriter( QTextStream& out ): SimpleWriter(), myOut(out)
+{
+}
+
+void StreamWriter::dumpLine( const QString& line )
+{
+  myOut << line;
+  myOut << endl;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class TextWriter
+/// \brief Writer for QTextBrowser.
+/// \internal
+////////////////////////////////////////////////////////////////////////////////
+
+class TextWriter: public SimpleWriter
+{
+  QTextBrowser* myInfo;
+public:
+  TextWriter( QTextBrowser* );
+protected:
+  QString spacer() const;
+  QString decorate( const QString& ) const;
+  void dumpLine( const QString& );
+};
+
+TextWriter::TextWriter( QTextBrowser* w ): SimpleWriter(), myInfo(w)
+{
+}
+
+QString TextWriter::spacer() const
+{
+  return "&nbsp;";
+}
+
+QString TextWriter::decorate( const QString& s ) const
+{
+  return bold( s );
+}
+
+void TextWriter::dumpLine( const QString& line )
+{
+  myInfo->append( line );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class TreeWriter
+/// \brief Writer for QTreeWidget.
+/// \internal
+////////////////////////////////////////////////////////////////////////////////
+
+class TreeWriter: public InfoWriter
+{
+  QTreeWidget* myInfo;
+  QTreeWidgetItem* myCurrentItem;
+  TreeItemCreator* myCreator;
+public:
+  TreeWriter( QTreeWidget*, TreeItemCreator* );
+  ~TreeWriter();
+  void indent();
+  void unindent();
+protected:
+  void put( const QString&, const QString&, bool = false );
+};
+
+TreeWriter::TreeWriter( QTreeWidget* w, TreeItemCreator* c ):
+  InfoWriter(true), myInfo(w), myCurrentItem(0), myCreator(c)
+{
+}
+
+TreeWriter::~TreeWriter()
+{
+  delete myCreator;
+}
+
+void TreeWriter::put( const QString& key, const QString& value, bool emphasize )
+{
+  std::string sss = myCurrentItem ? myCurrentItem->text(0).toStdString() : "";
+  int options = Bold;
+  if ( emphasize ) options |= AllColumns;
+  QTreeWidgetItem* item = myCreator->createItem( myCurrentItem, options );
+  item->setText( 0, key );
+  if ( !value.isEmpty() )
+    item->setText( 1, value );
+}
+
+void TreeWriter::indent()
+{
+  QTreeWidgetItem* item = myCurrentItem ? myCurrentItem : myInfo->invisibleRootItem();
+  if ( item->childCount() > 0 )
+    myCurrentItem = item->child( item->childCount()-1 );
+}
+
+void TreeWriter::unindent()
+{
+  if ( myCurrentItem )
+    myCurrentItem = myCurrentItem->parent();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 /// \class SMESHGUI_ElemInfo
 /// \brief Base class for the mesh element information widget.
+///
+/// Displays the detail information about given mesh node(s) or element(s).
+/// Default class does not provide working implementation but onle general
+/// functionalities; main work is done in sub-classes.
 ////////////////////////////////////////////////////////////////////////////////
 
 /*!
@@ -1096,7 +1424,7 @@ SMESHGUI_ElemInfo::~SMESHGUI_ElemInfo()
   \param id Mesh node / element ID.
   \param isElement If \c true, show element info; otherwise show node info.
 */
-void SMESHGUI_ElemInfo::showInfo( const SMESHGUI_SelectionProxy& proxy, uint id, bool isElement )
+void SMESHGUI_ElemInfo::showInfo( const SMESH::SelectionProxy& proxy, uint id, bool isElement )
 {
   QSet<uint> ids;
   ids << id;
@@ -1109,7 +1437,7 @@ void SMESHGUI_ElemInfo::showInfo( const SMESHGUI_SelectionProxy& proxy, uint id,
   \param ids Mesh nodes / elements IDs.
   \param isElement If \c true, show element info; otherwise show node info.
 */
-void SMESHGUI_ElemInfo::showInfo( const SMESHGUI_SelectionProxy& proxy, QSet<uint> ids, bool isElement )
+void SMESHGUI_ElemInfo::showInfo( const SMESH::SelectionProxy& proxy, QSet<uint> ids, bool isElement )
 {
   if ( !proxy )
   {
@@ -1134,26 +1462,26 @@ void SMESHGUI_ElemInfo::showInfo( const SMESHGUI_SelectionProxy& proxy, QSet<uin
   myIndex = 0;
   
   updateControls();
-  information( myIDs.mid( myIndex*blockSize(), blockSize() ));
+  information( myIDs.mid( myIndex*blockSize(), blockSize() ) );
 }
 
 /*!
   \brief Show information on given group.
   \param proxy Object to compute information on (group).
 */
-void SMESHGUI_ElemInfo::showInfo( const SMESHGUI_SelectionProxy& proxy )
+void SMESHGUI_ElemInfo::showInfo( const SMESH::SelectionProxy& proxy )
 {
-  if ( !proxy || proxy.elementType() == SMESH::ALL ) // null proxy or not a group
+  if ( !proxy || proxy.groupElementType() == SMESH::ALL ) // null proxy or not a group
   {
     clear();
     return;
   }
 
-  showInfo( proxy, proxy.ids(), proxy.elementType() != SMESH::NODE );
+  showInfo( proxy, proxy.ids(), proxy.groupElementType() != SMESH::NODE );
 }
 
 /*!
-  \brief Clear mesh element information widget
+  \brief Reset panel (clear all data).
 */
 void SMESHGUI_ElemInfo::clear()
 {
@@ -1164,14 +1492,23 @@ void SMESHGUI_ElemInfo::clear()
 }
 
 /*!
-  \brief Get central area widget
-  \return central widget
+  \brief Get central area widget.
+  \return Central widget.
 */
-QWidget* SMESHGUI_ElemInfo::frame() const
+QWidget* SMESHGUI_ElemInfo::centralWidget() const
 {
   return myFrame;
 }
 
+/*!
+  \brief Get current mesh proxy object information is shown on.
+  \return Current proxy.
+*/
+SMESH::SelectionProxy SMESHGUI_ElemInfo::proxy() const
+{
+  return myProxy;
+}
+
 /*!
   \brief Get current info mode.
   \return Current panel mode.
@@ -1182,127 +1519,432 @@ int SMESHGUI_ElemInfo::what() const
 }
 
 /*!
-  \brief Get current mesh proxy object information is shown on.
-  \return Current proxy.
+  \brief Get title for given element type.
+  \param type Mesh element type.
+  \param multiple Use plural form. Defaults to \c false.
+  \return Element type's title.
 */
-SMESHGUI_SelectionProxy SMESHGUI_ElemInfo::proxy() const
+QString SMESHGUI_ElemInfo::type2str( int type, bool multiple )
 {
-  return myProxy;
+  QString title;
+  switch ( type )
+  {
+  case SMDSAbs_Edge:
+    title = multiple ? tr( "EDGES" ) : tr( "EDGE" ) ; break;
+  case SMDSAbs_Face:
+    title = multiple ? tr( "FACES" ) : tr( "FACE" ); break;
+  case SMDSAbs_Volume:
+    title = multiple ? tr( "VOLUMES" ) : tr( "VOLUME" ); break;
+  case SMDSAbs_0DElement:
+    title = multiple ? tr( "0D_ELEMENTS" ) : tr( "0D_ELEMENT" ); break;
+  case SMDSAbs_Ball:
+    title = multiple ? tr( "BALL_ELEMENTS" ) : tr( "BALL" ); break;
+  default:
+    break;
+  }
+  return title;
+}
+
+/*!
+  \brief Get title for given shape type.
+  \param type Shape type.
+  \return Shape type's title.
+*/
+QString SMESHGUI_ElemInfo::stype2str( int type )
+{
+  QString title;
+  switch ( type )
+  {
+  case GEOM::VERTEX:
+    title = tr( "GEOM_VERTEX" ); break;
+  case GEOM::EDGE:
+    title = tr( "GEOM_EDGE" ); break;
+  case GEOM::FACE:
+    title = tr( "GEOM_FACE" ); break;
+  case GEOM::SOLID:
+  default:
+    title = tr( "GEOM_SOLID" ); break;
+    break;
+  }
+  return title;
+}
+
+/*!
+  \brief Get title for given element type.
+  \param type Mesh element type.
+  \return Element type's title.
+*/
+QString SMESHGUI_ElemInfo::etype2str( int type )
+{
+  QString title;
+  switch ( type )
+  {
+  case SMESH::Entity_0D:
+    title = tr( "SMESH_ELEM0D" ); break;
+  case SMESH::Entity_Edge:
+    title = tr( "SMESH_EDGE" ); break;
+  case SMESH::Entity_Quad_Edge:
+    title = tr( "SMESH_QUADRATIC_EDGE" ); break;
+  case SMESH::Entity_Triangle:
+    title = tr( "SMESH_TRIANGLE" ); break;
+  case SMESH::Entity_Quad_Triangle:
+    title = tr( "SMESH_QUADRATIC_TRIANGLE" ); break;
+  case SMESH::Entity_BiQuad_Triangle:
+    title = tr( "SMESH_BIQUADRATIC_TRIANGLE" ); break;
+  case SMESH::Entity_Quadrangle:
+    title = tr( "SMESH_QUADRANGLE" ); break;
+  case SMESH::Entity_Quad_Quadrangle:
+    title = tr( "SMESH_QUADRATIC_QUADRANGLE" ); break;
+  case SMESH::Entity_BiQuad_Quadrangle:
+    title = tr( "SMESH_BIQUADRATIC_QUADRANGLE" ); break;
+  case SMESH::Entity_Polygon:
+    title = tr( "SMESH_POLYGON" ); break;
+  case SMESH::Entity_Quad_Polygon:
+    title = tr( "SMESH_QUADRATIC_POLYGON" ); break;
+  case SMESH::Entity_Tetra:
+    title = tr( "SMESH_TETRAHEDRON" ); break;
+  case SMESH::Entity_Quad_Tetra:
+    title = tr( "SMESH_QUADRATIC_TETRAHEDRON" ); break;
+  case SMESH::Entity_Pyramid:
+    title = tr( "SMESH_PYRAMID" ); break;
+  case SMESH::Entity_Quad_Pyramid:
+    title = tr( "SMESH_QUADRATIC_PYRAMID" ); break;
+  case SMESH::Entity_Hexa:
+    title = tr( "SMESH_HEXAHEDRON" ); break;
+  case SMESH::Entity_Quad_Hexa:
+    title = tr( "SMESH_QUADRATIC_HEXAHEDRON" ); break;
+  case SMESH::Entity_TriQuad_Hexa:
+    title = tr( "SMESH_TRIQUADRATIC_HEXAHEDRON" ); break;
+  case SMESH::Entity_Penta:
+    title = tr( "SMESH_PENTA" ); break;
+  case SMESH::Entity_Quad_Penta:
+    title = tr( "SMESH_QUADRATIC_PENTAHEDRON" ); break;
+  case SMESH::Entity_BiQuad_Penta:
+    title = tr( "SMESH_BIQUADRATIC_PENTAHEDRON" ); break;
+  case SMESH::Entity_Hexagonal_Prism:
+    title = tr( "SMESH_HEX_PRISM" ); break;
+  case SMESH::Entity_Polyhedra:
+    title = tr( "SMESH_POLYEDRON" ); break;
+  case SMESH::Entity_Quad_Polyhedra:
+    title = tr( "SMESH_QUADRATIC_POLYEDRON" ); break;
+  case SMESH::Entity_Ball:
+    title = tr( "SMESH_BALL" ); break;
+  default:
+    break;
+  }
+  return title;
+}
+
+/*!
+  \brief Get title for given quality control.
+  \param type Mesh control type.
+  \return Quality control's title.
+*/
+QString SMESHGUI_ElemInfo::ctrl2str( int control )
+{
+  QString title;
+  switch ( control )
+  {
+  case SMESH::FT_AspectRatio:
+    title = tr( "ASPECTRATIO_ELEMENTS" ); break;
+  case SMESH::FT_AspectRatio3D:
+    title = tr( "ASPECTRATIO_3D_ELEMENTS" ); break;
+  case SMESH::FT_Warping:
+    title = tr( "WARP_ELEMENTS" ); break;
+  case SMESH::FT_MinimumAngle:
+    title = tr( "MINIMUMANGLE_ELEMENTS" ); break;
+  case SMESH::FT_Taper:
+    title = tr( "TAPER_ELEMENTS" ); break;
+  case SMESH::FT_Skew:
+    title = tr( "SKEW_ELEMENTS" ); break;
+  case SMESH::FT_Area:
+    title = tr( "AREA_ELEMENTS" ); break;
+  case SMESH::FT_Volume3D:
+    title = tr( "VOLUME_3D_ELEMENTS" ); break;
+  case SMESH::FT_MaxElementLength2D:
+    title = tr( "MAX_ELEMENT_LENGTH_2D" ); break;
+  case SMESH::FT_MaxElementLength3D:
+    title = tr( "MAX_ELEMENT_LENGTH_3D" ); break;
+  case SMESH::FT_Length:
+    title = tr( "LENGTH_EDGES" ); break;
+  case SMESH::FT_Length2D:
+    title = tr( "MIN_ELEM_EDGE" ); break;
+  case SMESH::FT_BallDiameter:
+    title = tr( "BALL_DIAMETER" ); break;
+  default:
+    break;
+  }
+  return title;
+}
+
+/*!
+  \brief Write information on given mesh nodes / elements.
+  \param writer Information writer.
+  \param ids Nodes / elements IDs.
+*/
+void SMESHGUI_ElemInfo::writeInfo( InfoWriter* writer, const QList<uint>& ids )
+{
+  if ( !proxy() )
+    return;
+
+  bool grp_details = SMESHGUI::resourceMgr()->booleanValue( "SMESH", "elem_info_grp_details", false );
+  int cprecision = SMESHGUI::resourceMgr()->booleanValue( "SMESH", "use_precision", false ) ? 
+    SMESHGUI::resourceMgr()->integerValue( "SMESH", "controls_precision", -1 ) : -1;
+
+  SMESH::XYZ xyz;
+  SMESH::Connectivity connectivity;
+  SMESH::Position position;
+  bool ok;
+
+  foreach ( uint id, ids )
+  {
+    writer->separator();
+
+    if ( what() == ShowNodes )
+    {
+      // show node info
+      // - check that node exists
+      if ( !proxy().hasNode( id ) )
+        continue;
+      // - id
+      writer->write( tr( "NODE" ), (int)id, true );
+      writer->indent();
+      // - coordinates
+      ok = proxy().nodeCoordinates( id, xyz );
+      if ( ok )
+      {
+        writer->write( tr( "COORDINATES" ), xyz );
+      }
+      // - connectivity
+      ok = proxy().nodeConnectivity( id, connectivity );
+      if ( ok )
+      {
+        if ( !connectivity.isEmpty() )
+        {
+          writer->write( tr( "CONNECTIVITY" ) );
+          writer->indent();
+          for ( int i = SMDSAbs_Edge; i <= SMDSAbs_Ball; i++ )
+          {
+            QString formatted = formatConnectivity( connectivity, i );
+            if ( !formatted.isEmpty() )
+              writer->write( type2str( i, true ), formatted ); //todo: TypeRole: NodeConnectivity
+          }
+          writer->unindent();
+        }
+        else
+        {
+          writer->write( tr( "CONNECTIVITY" ), tr( "FREE_NODE" ) );
+        }
+      }
+      // - position
+      ok = proxy().nodePosition( id, position );
+      if ( ok && position.isValid() )
+      {
+        writer->write( tr( "POSITION" ), (stype2str( position.shapeType() ) + " #%1").arg( position.shapeId() ) );
+        writer->indent();
+        if ( position.hasU() )
+          writer->write( tr("U_POSITION"), position.u() );
+        if ( position.hasV() )
+          writer->write( tr("V_POSITION"), position.v() );
+        writer->unindent();
+      }
+      // - groups node belongs to
+      QList<SMESH::SelectionProxy> groups = proxy().nodeGroups( id );
+      bool topCreated = false;
+      foreach( SMESH::SelectionProxy group, groups )
+      {
+        if ( group && !group.name().isEmpty() )
+        {
+          if ( !topCreated )
+          {
+            writer->write( SMESHGUI_AddInfo::tr( "GROUPS" ) );
+            writer->indent();
+            topCreated = true;
+          }
+          writer->write( group.name().trimmed() ); // trim name
+          if ( grp_details )
+          {
+            writer->indent();
+            int type = group.type();
+            if ( type == SMESH::SelectionProxy::GroupStd )
+            {
+              writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ) );
+            }
+            else if ( type == SMESH::SelectionProxy::GroupGeom )
+            {
+              writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ) );
+              writer->write( SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ), group.shapeName() );
+            }
+            else if ( type == SMESH::SelectionProxy::GroupFilter )
+            {
+              writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ) );
+            }
+            int size = group.size();
+            if ( size != -1 );
+              writer->write( SMESHGUI_AddInfo::tr( "SIZE" ), size );
+            QColor color = group.color();
+            if ( color.isValid() )
+              writer->write( SMESHGUI_AddInfo::tr( "COLOR" ), color.name() );
+            writer->unindent();
+          }
+        }
+      }
+      if ( topCreated )
+        writer->unindent();
+      writer->unindent();
+    }
+    else if ( what() == ShowElements )
+    {
+      // show element info
+      // - check that element exists
+      if ( !proxy().hasElement( id ) )
+        continue;
+      // - id & type
+      int type = proxy().elementType( id );
+      if  ( type == SMESH::ALL )
+        continue;
+      writer->write( type2str( type ), (int)id, true );
+      writer->indent();
+      // - geometry type
+      type = proxy().elementEntityType( id );
+      writer->write( tr( "TYPE" ), etype2str( type ) );
+      // - connectivity
+      ok = proxy().elementConnectivity( id, connectivity );
+      if ( ok )
+      {
+        if ( !connectivity.isEmpty() )
+        {
+          QString formatted = formatConnectivity( connectivity, SMDSAbs_Node );
+          if ( !formatted.isEmpty() )
+            writer->write( tr( "CONNECTIVITY" ), formatted ); //todo: TypeRole: ElemConnectivity
+        }
+      }
+      // - position
+      ok = proxy().elementPosition( id, position );
+      if ( ok && position.isValid() )
+      {
+        writer->write( tr( "POSITION" ), (stype2str( position.shapeType() ) + " #%1").arg( position.shapeId() ) );
+      }
+      // - gravity center
+      ok = proxy().elementGravityCenter( id, xyz );
+      if ( ok )
+      {
+        writer->write( tr( "GRAVITY_CENTER" ), xyz );
+      }
+      // - normal vector
+      ok = proxy().elementNormal( id, xyz );
+      if ( ok )
+      {
+        writer->write( tr( "NORMAL_VECTOR" ), xyz );
+      }
+      // - controls
+      bool topCreated = false;
+      for ( int i = SMESH::FT_AspectRatio; i < SMESH::FT_Undefined; i++ )
+      {
+        QString ctrlTitle = ctrl2str( i );
+        if ( ctrlTitle.isEmpty() )
+          continue;
+        if ( !topCreated )
+        {
+          writer->write( tr( "CONTROLS" ) );
+          writer->indent();
+          topCreated = true;
+        }
+        double value;
+        if ( proxy().elementControl( id, i, cprecision, value ) )
+          writer->write( ctrlTitle, value );
+      }
+      if ( topCreated )
+        writer->unindent();
+      // - groups element belongs to
+      QList<SMESH::SelectionProxy> groups = proxy().elementGroups( id );
+      topCreated = false;
+      foreach( SMESH::SelectionProxy group, groups )
+      {
+        if ( group && !group.name().isEmpty() )
+        {
+          if ( !topCreated )
+          {
+            writer->write( SMESHGUI_AddInfo::tr( "GROUPS" ) );
+            writer->indent();
+            topCreated = true;
+          }
+          writer->write( group.name().trimmed() ); // trim name
+          if ( grp_details )
+          {
+            writer->indent();
+            int type = group.type();
+            if ( type == SMESH::SelectionProxy::GroupStd )
+            {
+              writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ) );
+            }
+            else if ( type == SMESH::SelectionProxy::GroupGeom )
+            {
+              writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ) );
+              writer->write( SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ), group.shapeName() );
+            }
+            else if ( type == SMESH::SelectionProxy::GroupFilter )
+            {
+              writer->write( SMESHGUI_AddInfo::tr( "TYPE" ), SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ) );
+            }
+            int size = group.size();
+            if ( size != -1 );
+              writer->write( SMESHGUI_AddInfo::tr( "SIZE" ), size );
+            QColor color = group.color();
+            if ( color.isValid() )
+              writer->write( SMESHGUI_AddInfo::tr( "COLOR" ), color.name() );
+            writer->unindent();
+          }
+        }
+      }
+      if ( topCreated )
+        writer->unindent();
+      writer->unindent();
+    }
+  }  
 }
 
 /*!
   \fn void SMESHGUI_ElemInfo::information( const QList<uint>& ids )
-  \brief Show information on the specified nodes / elements
-
-  This function is to be redefined in sub-classes.
-
-  \param ids nodes / elements identifiers information is to be shown on
-*/
-
-/*!
-  \brief Internal clean-up (reset widget)
-*/
-void SMESHGUI_ElemInfo::clearInternal()
-{
-}
-
-/*!
-  \brief Get node connectivity
-  \param node mesh node
-  \return node connectivity map
-*/
-SMESHGUI_ElemInfo::Connectivity SMESHGUI_ElemInfo::nodeConnectivity( const SMDS_MeshNode* node )
-{
-  Connectivity elmap;
-  if ( node ) {
-    SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
-    while ( it && it->more() ) {
-      const SMDS_MeshElement* ne = it->next();
-      elmap[ ne->GetType() ] << ne->GetID();
-    }
-  }
-  return elmap;
-}
+  \brief Show information on given mesh nodes / elements.
 
-/*!
-  \brief Format connectivity data to string representation
-  \param connectivity connetivity map
-  \param type element type
-  \return string representation of the connectivity
-*/
-QString SMESHGUI_ElemInfo::formatConnectivity( Connectivity connectivity, int type )
-{
-  QStringList str;
-  if ( connectivity.contains( type )) {
-    QList<int> elements = connectivity[ type ];
-    qSort( elements );
-    foreach( int id, elements )
-      str << QString::number( id );
-  }
-  return str.join( " " );
-}
+  This function has to be redefined in sub-classes.
 
-/*!
-  \brief Calculate gravity center of the mesh element
-  \param element mesh element
+  \param ids Nodes / elements IDs.
 */
-SMESHGUI_ElemInfo::XYZ SMESHGUI_ElemInfo::gravityCenter( const SMDS_MeshElement* element )
-{
-  XYZ xyz;
-  if ( element ) {
-    SMDS_ElemIteratorPtr nodeIt = element->nodesIterator();
-    while ( nodeIt->more() ) {
-      const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
-      xyz.add( node->X(), node->Y(), node->Z() );
-    }
-    xyz.divide( element->NbNodes() );
-  }
-  return xyz;
-}
 
 /*!
-  \brief Calculate gravity center of the mesh element
-  \param element mesh element
-*/
-gp_XYZ SMESHGUI_ElemInfo::getGravityCenter( const SMDS_MeshElement* element )
-{
-  return gravityCenter( element );
-}
+  \brief Internal clean-up (reset panel).
 
-/*!
-  \brief Calculate normal vector to the mesh face
-  \param element mesh face
+  Default implementation does nothing; the method has to be redefined
+  in sub-classes to perform internal clean-up.
 */
-SMESHGUI_ElemInfo::XYZ SMESHGUI_ElemInfo::normal( const SMDS_MeshElement* element )
+void SMESHGUI_ElemInfo::clearInternal()
 {
-  gp_XYZ n = SMESH::getNormale( SMDS_Mesh::DownCast<SMDS_MeshFace>( element ));
-  return XYZ(n.X(), n.Y(), n.Z());
 }
 
 /*!
-  \brief This slot is called from "Show Previous" button click.
-  Shows information on the previous group of the items.
+  \brief Show previous chunk of information.
 */
 void SMESHGUI_ElemInfo::showPrevious()
 {
   myIndex = qMax( 0, myIndex-1 );
   updateControls();
-  information( myIDs.mid( myIndex*blockSize(), blockSize() ));
+  information( myIDs.mid( myIndex*blockSize(), blockSize() ) );
 }
 
 /*!
-  \brief This slot is called from "Show Next" button click.
-  Shows information on the next group of the items.
+  \brief Show next chunk of information.
 */
 void SMESHGUI_ElemInfo::showNext()
 {
   myIndex = qMin( myIndex+1, myIDs.count() / blockSize() );
   updateControls();
-  information( myIDs.mid( myIndex*blockSize(), blockSize() ));
+  information( myIDs.mid( myIndex*blockSize(), blockSize() ) );
 }
 
 /*!
-  \brief Update widgets state
+  \brief Update control widget state.
 */
 void SMESHGUI_ElemInfo::updateControls()
 {
@@ -1310,450 +1952,51 @@ void SMESHGUI_ElemInfo::updateControls()
 }
 
 /*!
-  \class SMESHGUI_SimpleElemInfo
-  \brief Represents mesh element information in the simple text area.
+  \brief Write information from panel to ouput stream.
+  \param out Text stream output.
 */
+void SMESHGUI_ElemInfo::saveInfo( QTextStream &out )
+{
+  // title
+  QString title = tr( "ELEM_INFO" );
+  out << ruler( title.size() ) << endl;
+  out << title << endl;
+  out << ruler( title.size() ) << endl;
+  //  out << endl;
+
+  // info
+  StreamWriter writer( out );
+  writeInfo( &writer, myIDs );
+  out << endl;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class SMESHGUI_SimpleElemInfo
+/// \brief Show mesh element information in the simple text area.
+////////////////////////////////////////////////////////////////////////////////
 
 /*!
-  \brief Constructor
-  \param parent parent widget
+  \brief Constructor.
+  \param parent Parent widget. Defaults to 0.
 */
 SMESHGUI_SimpleElemInfo::SMESHGUI_SimpleElemInfo( QWidget* parent )
   : SMESHGUI_ElemInfo( parent )
 {
-  myInfo = new QTextBrowser( frame() );
-  QVBoxLayout* l = new QVBoxLayout( frame() );
+  myInfo = new QTextBrowser( centralWidget() );
+  QVBoxLayout* l = new QVBoxLayout( centralWidget() );
   l->setMargin( 0 );
   l->addWidget( myInfo );
 }
 
 /*!
-  \brief Show mesh element information
-  \param ids mesh nodes / elements identifiers
+  \brief Show mesh element information.
+  \param ids Nodes / elements IDs.
 */
 void SMESHGUI_SimpleElemInfo::information( const QList<uint>& ids )
 {
   clearInternal();
-
-  SMESH_Actor* actor = proxy().actor();
-
-  if ( actor ) {
-    int grp_details = SMESHGUI::resourceMgr()->booleanValue( "SMESH", "elem_info_grp_details", false );
-    int precision   = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
-    int cprecision = -1;
-    if ( SMESHGUI::resourceMgr()->booleanValue( "SMESH", "use_precision", false ))
-      cprecision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "controls_precision", -1 );
-    foreach ( uint id, ids ) {
-      if ( what() == ShowNodes ) {
-        //
-        // show node info
-        //
-        const SMDS_MeshNode* node = actor->GetObject()->GetMesh()->FindNode( id );
-        if ( !node ) return;
-
-        // node ID
-        myInfo->append( QString( "<b>%1 #%2</b>" ).arg( SMESHGUI_ElemInfo::tr( "NODE" )).arg( id ));
-        // separator
-        myInfo->append( "" );
-        // coordinates
-        myInfo->append( QString( "<b>%1:</b> (%2, %3, %4)" ).arg( SMESHGUI_ElemInfo::tr( "COORDINATES" )).
-                        arg( node->X(), 0, precision > 0 ? 'f' : 'g', qAbs( precision )).
-                        arg( node->Y(), 0, precision > 0 ? 'f' : 'g', qAbs( precision )).
-                        arg( node->Z(), 0, precision > 0 ? 'f' : 'g', qAbs( precision )) );
-        // separator
-        myInfo->append( "" );
-        // connectivity
-        Connectivity connectivity = nodeConnectivity( node );
-        if ( !connectivity.isEmpty() ) {
-          myInfo->append( QString( "<b>%1:</b>" ).arg( SMESHGUI_ElemInfo::tr( "CONNECTIVITY" )) );
-          QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
-          if ( !con.isEmpty() )
-            myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "0D_ELEMENTS" )).arg( con ));
-          con = formatConnectivity( connectivity, SMDSAbs_Edge );
-          if ( !con.isEmpty() )
-            myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "EDGES" )).arg( con ));
-          con = formatConnectivity( connectivity, SMDSAbs_Ball );
-          if ( !con.isEmpty() )
-            myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "BALL_ELEMENTS" )).arg( con ));
-          con = formatConnectivity( connectivity, SMDSAbs_Face );
-          if ( !con.isEmpty() )
-            myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "FACES" )).arg( con ));
-          con = formatConnectivity( connectivity, SMDSAbs_Volume );
-          if ( !con.isEmpty() )
-            myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "VOLUMES" )).arg( con ));
-        }
-        else {
-          myInfo->append( QString( "<b>%1</b>" ).arg( SMESHGUI_ElemInfo::tr( "FREE_NODE" )).arg( id ));
-        }
-        // node position
-        SMESH::SMESH_Mesh_ptr aMeshPtr = actor->GetObject()->GetMeshServer();
-        if ( !CORBA::is_nil( aMeshPtr )) {
-          SMESH::NodePosition_var pos = aMeshPtr->GetNodePosition( id );
-          int shapeID = pos->shapeID;
-          if ( shapeID > 0 ) {
-            QString shapeType;
-            double u = 0, v = 0;
-            switch ( pos->shapeType ) {
-            case GEOM::EDGE:
-              shapeType = SMESHGUI_ElemInfo::tr( "GEOM_EDGE" );
-              if ( pos->params.length() == 1 )
-                u = pos->params[0];
-              break;
-            case GEOM::FACE:
-              shapeType = SMESHGUI_ElemInfo::tr( "GEOM_FACE" );
-              if ( pos->params.length() == 2 ) {
-                u = pos->params[0];
-                v = pos->params[1];
-              }
-              break;
-            case GEOM::VERTEX:
-              shapeType = SMESHGUI_ElemInfo::tr( "GEOM_VERTEX" );
-              break;
-            default:
-              shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SOLID" );
-              break;
-            }
-            // separator
-            myInfo->append( "" );
-            myInfo->append( QString( "<b>%1:" ).arg( SMESHGUI_ElemInfo::tr( "POSITION" )) );
-            myInfo->append( QString( "- <b>%1: #%2</b>" ).arg( shapeType ).arg( shapeID ));
-            if ( pos->shapeType == GEOM::EDGE || pos->shapeType == GEOM::FACE ) {
-              myInfo->append( QString( "- <b>%1: #%2</b>" ).arg( SMESHGUI_ElemInfo::tr( "U_POSITION" )).
-                              arg( QString::number( u, precision > 0 ? 'f' : 'g', qAbs( precision )) ));
-              if ( pos->shapeType == GEOM::FACE ) {
-                myInfo->append( QString( "- <b>%1: #%2</b>" ).arg( SMESHGUI_ElemInfo::tr( "V_POSITION" )).
-                                arg( QString::number( v, precision > 0 ? 'f' : 'g', qAbs( precision )) ));
-              }
-            }
-          }
-        }
-        // groups node belongs to
-        SMESH::SMESH_Mesh_ptr aMesh = actor->GetObject()->GetMeshServer();
-        if ( !CORBA::is_nil( aMesh )) {
-          SMESH::ListOfGroups_var groups = aMesh->GetGroups();
-          myInfo->append( "" ); // separator
-          bool top_created = false;
-          for ( CORBA::ULong i = 0; i < groups->length(); i++ ) {
-            SMESH::SMESH_GroupBase_var aGrp = groups[i];
-            if ( CORBA::is_nil( aGrp )) continue;
-            QString aName = (char*) (CORBA::String_var) aGrp->GetName();
-            if ( aGrp->GetType() == SMESH::NODE && !aName.isEmpty() && aGrp->Contains( id )) {
-              if ( !top_created ) {
-                myInfo->append( QString( "<b>%1:</b>" ).arg( SMESHGUI_AddInfo::tr( "GROUPS" )) );
-                top_created = true;
-              }
-              myInfo->append( QString( "+ <b>%1:</b>" ).arg( aName.trimmed() ));
-              if ( grp_details ) {
-                SMESH::SMESH_Group_var         aStdGroup  = SMESH::SMESH_Group::_narrow( aGrp );
-                SMESH::SMESH_GroupOnGeom_var   aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( aGrp );
-                SMESH::SMESH_GroupOnFilter_var aFltGroup  = SMESH::SMESH_GroupOnFilter::_narrow( aGrp );
-
-                // type : group on geometry, standalone group, group on filter
-                if ( !CORBA::is_nil( aStdGroup )) {
-                  myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "TYPE" )).
-                                  arg( SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" )) );
-                }
-                else if ( !CORBA::is_nil( aGeomGroup )) {
-                  myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "TYPE" )).
-                                  arg( SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" )) );
-                  GEOM::GEOM_Object_var gobj = aGeomGroup->GetShape();
-                  _PTR(SObject) sobj = SMESH::ObjectToSObject( gobj );
-                  if ( sobj ) {
-                    myInfo->append( QString( "  - <b>%1:</b> %2: %3" ).arg( SMESHGUI_AddInfo::tr( "TYPE" )).
-                                    arg( SMESHGUI_AddInfo::tr( "GEOM_OBJECT" )).arg( sobj->GetName().c_str() ));
-                  }
-                }
-                else if ( !CORBA::is_nil( aFltGroup )) {
-                  myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "TYPE" )).
-                                  arg( SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" )) );
-                }
-
-                // size
-                myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "SIZE" )).
-                                arg( QString::number( aGrp->Size() )) );
-
-                // color
-                SALOMEDS::Color color = aGrp->GetColor();
-                myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "COLOR" )).
-                                arg( QColor( color.R*255., color.G*255., color.B*255. ).name() ));
-              }
-            }
-          }
-        }
-      }
-      else if ( what() == ShowElements ) {
-        //
-        // show element info
-        //
-        const SMDS_MeshElement* e = actor->GetObject()->GetMesh()->FindElement( id );
-        SMESH::Controls::NumericalFunctorPtr afunctor;
-        if ( !e ) return;
-
-        // Element ID && Type
-        QString stype;
-        switch( e->GetType() ) {
-        case SMDSAbs_0DElement:
-          stype = SMESHGUI_ElemInfo::tr( "0D_ELEMENT" ); break;
-        case SMDSAbs_Ball:
-          stype = SMESHGUI_ElemInfo::tr( "BALL" ); break;
-        case SMDSAbs_Edge:
-          stype = SMESHGUI_ElemInfo::tr( "EDGE" ); break;
-        case SMDSAbs_Face:
-          stype = SMESHGUI_ElemInfo::tr( "FACE" ); break;
-        case SMDSAbs_Volume:
-          stype = SMESHGUI_ElemInfo::tr( "VOLUME" ); break;
-        default:
-          break;
-        }
-        if ( stype.isEmpty() ) return;
-        myInfo->append( QString( "<b>%1 #%2</b>" ).arg( stype ).arg( id ));
-        // separator
-        myInfo->append( "" );
-
-        // Geometry type
-        QString gtype;
-        switch( e->GetEntityType() ) {
-        case SMDSEntity_Triangle:
-        case SMDSEntity_Quad_Triangle:
-        case SMDSEntity_BiQuad_Triangle:
-          gtype = SMESHGUI_ElemInfo::tr( "TRIANGLE" ); break;
-        case SMDSEntity_Quadrangle:
-        case SMDSEntity_Quad_Quadrangle:
-        case SMDSEntity_BiQuad_Quadrangle:
-          gtype = SMESHGUI_ElemInfo::tr( "QUADRANGLE" ); break;
-        case SMDSEntity_Polygon:
-        case SMDSEntity_Quad_Polygon:
-          gtype = SMESHGUI_ElemInfo::tr( "POLYGON" ); break;
-        case SMDSEntity_Tetra:
-        case SMDSEntity_Quad_Tetra:
-          gtype = SMESHGUI_ElemInfo::tr( "TETRAHEDRON" ); break;
-        case SMDSEntity_Pyramid:
-        case SMDSEntity_Quad_Pyramid:
-          gtype = SMESHGUI_ElemInfo::tr( "PYRAMID" ); break;
-        case SMDSEntity_Hexa:
-        case SMDSEntity_Quad_Hexa:
-        case SMDSEntity_TriQuad_Hexa:
-          gtype = SMESHGUI_ElemInfo::tr( "HEXAHEDRON" ); break;
-        case SMDSEntity_Penta:
-        case SMDSEntity_Quad_Penta:
-        case SMDSEntity_BiQuad_Penta:
-          gtype = SMESHGUI_ElemInfo::tr( "PRISM" ); break;
-        case SMDSEntity_Hexagonal_Prism:
-          gtype = SMESHGUI_ElemInfo::tr( "HEX_PRISM" ); break;
-        case SMDSEntity_Polyhedra:
-        case SMDSEntity_Quad_Polyhedra:
-          gtype = SMESHGUI_ElemInfo::tr( "POLYHEDRON" ); break;
-        default:
-          break;
-        }
-        if ( !gtype.isEmpty() )
-          myInfo->append( QString( "<b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "TYPE" )).arg( gtype ));
-
-        // Quadratic flag (any element except 0D)
-        if ( e->GetEntityType() > SMDSEntity_0D && e->GetEntityType() < SMDSEntity_Ball ) {
-          myInfo->append( QString( "<b>%1?</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "QUADRATIC" )).arg( e->IsQuadratic() ? SMESHGUI_ElemInfo::tr( "YES" ) : SMESHGUI_ElemInfo::tr( "NO" )) );
-        }
-        if ( const SMDS_BallElement* ball = SMDS_Mesh::DownCast<SMDS_BallElement>( e )) {
-          // Ball diameter
-          myInfo->append( QString( "<b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "BALL_DIAMETER" )).arg( ball->GetDiameter() ));
-        }
-        // separator
-        myInfo->append( "" );
-
-        // Connectivity
-        SMDS_ElemIteratorPtr nodeIt = e->nodesIterator();
-        for ( int idx = 1; nodeIt->more(); idx++ ) {
-          const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
-          // node number and ID
-          myInfo->append( QString( "<b>%1 %2/%3</b> - #%4" ).arg( SMESHGUI_ElemInfo::tr( "NODE" )).arg( idx ).arg( e->NbNodes() ).arg( node->GetID() ));
-          // node coordinates
-          myInfo->append( QString( "<b>%1:</b> (%2, %3, %4)" ).arg( SMESHGUI_ElemInfo::tr( "COORDINATES" )).
-                          arg( node->X(), 0, precision > 0 ? 'f' : 'g', qAbs( precision )).
-                          arg( node->Y(), 0, precision > 0 ? 'f' : 'g', qAbs( precision )).
-                          arg( node->Z(), 0, precision > 0 ? 'f' : 'g', qAbs( precision )) );
-          // node connectivity
-          Connectivity connectivity = nodeConnectivity( node );
-          if ( !connectivity.isEmpty() ) {
-            myInfo->append( QString( "<b>%1:</b>" ).arg( SMESHGUI_ElemInfo::tr( "CONNECTIVITY" )) );
-            QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
-            if ( !con.isEmpty() )
-              myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "0D_ELEMENTS" )).arg( con ));
-            con = formatConnectivity( connectivity, SMDSAbs_Edge );
-            if ( !con.isEmpty() )
-              myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "EDGES" )).arg( con ));
-            con = formatConnectivity( connectivity, SMDSAbs_Face );
-            if ( !con.isEmpty() )
-              myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "FACES" )).arg( con ));
-            con = formatConnectivity( connectivity, SMDSAbs_Volume );
-            if ( !con.isEmpty() )
-              myInfo->append( QString( "- <b>%1:</b> %2" ).arg( SMESHGUI_ElemInfo::tr( "VOLUMES" )).arg( con ));
-          }
-          else {
-            myInfo->append( QString( "<b>%1</b>" ).arg( SMESHGUI_ElemInfo::tr( "FREE_NODE" )).arg( id ));
-          }
-        }
-        // separator
-        myInfo->append( "" );
-
-        // Controls
-        myInfo->append( QString( "<b>%1:</b>" ).arg( SMESHGUI_ElemInfo::tr( "CONTROLS" )) );
-        //Length
-        if ( e->GetType() == SMDSAbs_Edge ) {
-          afunctor.reset( new SMESH::Controls::Length() );
-          afunctor->SetMesh( actor->GetObject()->GetMesh() );
-          afunctor->SetPrecision( cprecision );
-          myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "LENGTH_EDGES" )).arg( afunctor->GetValue( id )) );
-        }
-        if( e->GetType() == SMDSAbs_Face ) {
-          //Area
-          afunctor.reset(  new SMESH::Controls::Area() );
-          afunctor->SetMesh( actor->GetObject()->GetMesh() );
-          afunctor->SetPrecision( cprecision );
-          myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "AREA_ELEMENTS" )).arg( afunctor->GetValue( id )) );
-          //Taper
-          afunctor.reset( new SMESH::Controls::Taper() );
-          afunctor->SetMesh( actor->GetObject()->GetMesh() );
-          afunctor->SetPrecision( cprecision );
-          myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "TAPER_ELEMENTS" )).arg( afunctor->GetValue( id )) );
-          //AspectRatio2D
-          afunctor.reset( new SMESH::Controls::AspectRatio() );
-          afunctor->SetMesh( actor->GetObject()->GetMesh() );
-          myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "ASPECTRATIO_ELEMENTS" )).arg( afunctor->GetValue( id )) );
-          //Minimum angle
-          afunctor.reset( new SMESH::Controls::MinimumAngle() );
-          afunctor->SetMesh( actor->GetObject()->GetMesh() );
-          afunctor->SetPrecision( cprecision );
-          myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "MINIMUMANGLE_ELEMENTS" )).arg( afunctor->GetValue( id )) );
-          //Warping angle
-          afunctor.reset( new SMESH::Controls::Warping() );
-          afunctor->SetMesh( actor->GetObject()->GetMesh() );
-          afunctor->SetPrecision( cprecision );
-          myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "WARP_ELEMENTS" )).arg( afunctor->GetValue( id )) );
-          //Skew
-          afunctor.reset( new SMESH::Controls::Skew() );
-          afunctor->SetMesh( actor->GetObject()->GetMesh() );
-          afunctor->SetPrecision( cprecision );
-          myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "SKEW_ELEMENTS" )).arg( afunctor->GetValue( id )) );
-          //ElemDiam2D
-          afunctor.reset( new SMESH::Controls::MaxElementLength2D() );
-          afunctor->SetMesh( actor->GetObject()->GetMesh() );
-          afunctor->SetPrecision( cprecision );
-          myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "MAX_ELEMENT_LENGTH_2D" )).arg( afunctor->GetValue( id )) );
-          //min edge length
-          afunctor.reset( new SMESH::Controls::Length2D() );
-          afunctor->SetMesh( actor->GetObject()->GetMesh() );
-          myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "MIN_ELEM_EDGE" )).arg( afunctor->GetValue( id )) );
-        }
-        if( e->GetType() == SMDSAbs_Volume ) {
-          //AspectRatio3D
-          afunctor.reset(  new SMESH::Controls::AspectRatio3D() );
-          afunctor->SetMesh( actor->GetObject()->GetMesh() );
-          myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "ASPECTRATIO_3D_ELEMENTS" )).arg( afunctor->GetValue( id )) );
-          //Volume
-          afunctor.reset(  new SMESH::Controls::Volume() );
-          afunctor->SetMesh( actor->GetObject()->GetMesh() );
-          myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "VOLUME_3D_ELEMENTS" )).arg( afunctor->GetValue( id )) );
-          //ElementDiameter3D
-          afunctor.reset(  new SMESH::Controls::Volume() );
-          afunctor->SetMesh( actor->GetObject()->GetMesh() );
-          myInfo->append( QString( "- <b>%1:</b> %2" ).arg( tr( "MAX_ELEMENT_LENGTH_3D" )).arg( afunctor->GetValue( id )) );
-        }
-        // separator
-        myInfo->append( "" );
-
-        // Gravity center
-        XYZ gc = gravityCenter( e );
-        myInfo->append( QString( "<b>%1:</b> (%2, %3, %4)" ).arg( SMESHGUI_ElemInfo::tr( "GRAVITY_CENTER" )).arg( gc.x() ).arg( gc.y() ).arg( gc.z() ));
-
-        // Normal vector
-        if( e->GetType() == SMDSAbs_Face ) {
-          XYZ gc = normal( e );
-          myInfo->append( QString( "<b>%1:</b> (%2, %3, %4)" ).arg( SMESHGUI_ElemInfo::tr( "NORMAL_VECTOR" )).arg( gc.x() ).arg( gc.y() ).arg( gc.z() ));
-        }
-
-        // Element position
-        if ( e->GetType() >= SMDSAbs_Edge && e->GetType() <= SMDSAbs_Volume ) {
-          SMESH::SMESH_Mesh_ptr aMesh = actor->GetObject()->GetMeshServer();
-          if ( !CORBA::is_nil( aMesh )) {
-            SMESH::ElementPosition pos = aMesh->GetElementPosition( id );
-            int shapeID = pos.shapeID;
-            if ( shapeID > 0 ) {
-              myInfo->append( "" ); // separator
-              QString shapeType;
-              switch ( pos.shapeType ) {
-              case GEOM::EDGE:   shapeType = SMESHGUI_ElemInfo::tr( "GEOM_EDGE" );   break;
-              case GEOM::FACE:   shapeType = SMESHGUI_ElemInfo::tr( "GEOM_FACE" );   break;
-              case GEOM::VERTEX: shapeType = SMESHGUI_ElemInfo::tr( "GEOM_VERTEX" ); break;
-              case GEOM::SOLID:  shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SOLID" );  break;
-              case GEOM::SHELL:  shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SHELL" );  break;
-              default:           shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SHAPE" );  break;
-              }
-              myInfo->append( QString( "<b>%1:</b> %2 #%3" ).arg( SMESHGUI_ElemInfo::tr( "POSITION" )).arg( shapeType ).arg( shapeID ));
-            }
-          }
-        }
-
-        // Groups the element belongs to
-        SMESH::SMESH_Mesh_ptr aMesh = actor->GetObject()->GetMeshServer();
-        if ( !CORBA::is_nil( aMesh )) {
-          SMESH::ListOfGroups_var  groups = aMesh->GetGroups();
-          myInfo->append( "" ); // separator
-          bool top_created = false;
-          for ( CORBA::ULong i = 0; i < groups->length(); i++ ) {
-            SMESH::SMESH_GroupBase_var aGrp = groups[i];
-            if ( CORBA::is_nil( aGrp )) continue;
-            QString aName = (char*) (CORBA::String_var) aGrp->GetName();
-            if ( aGrp->GetType() != SMESH::NODE && !aName.isEmpty() && aGrp->Contains( id )) {
-              if ( !top_created ) {
-                myInfo->append( QString( "<b>%1:</b>" ).arg( SMESHGUI_AddInfo::tr( "GROUPS" )) );
-                top_created = true;
-              }
-              myInfo->append( QString( "+ <b>%1:</b>" ).arg( aName.trimmed() ));
-              if ( grp_details ) {
-                SMESH::SMESH_Group_var         aStdGroup  = SMESH::SMESH_Group::_narrow( aGrp );
-                SMESH::SMESH_GroupOnGeom_var   aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( aGrp );
-                SMESH::SMESH_GroupOnFilter_var aFltGroup  = SMESH::SMESH_GroupOnFilter::_narrow( aGrp );
-
-                // type : group on geometry, standalone group, group on filter
-                if ( !CORBA::is_nil( aStdGroup )) {
-                  myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "TYPE" )).
-                                  arg( SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" )) );
-                }
-                else if ( !CORBA::is_nil( aGeomGroup )) {
-                  myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "TYPE" )).
-                                  arg( SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" )) );
-                  GEOM::GEOM_Object_var gobj = aGeomGroup->GetShape();
-                  _PTR(SObject) sobj = SMESH::ObjectToSObject( gobj );
-                  if ( sobj ) {
-                    myInfo->append( QString( "  - <b>%1:</b> %2: %3" ).arg( SMESHGUI_AddInfo::tr( "TYPE" )).
-                                    arg( SMESHGUI_AddInfo::tr( "GEOM_OBJECT" )).arg( sobj->GetName().c_str() ));
-                  }
-                }
-                else if ( !CORBA::is_nil( aFltGroup )) {
-                  myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "TYPE" )).
-                                  arg( SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" )) );
-                }
-
-                myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "SIZE" )).
-                                arg( QString::number( aGrp->Size() )) );
-
-                // color
-                SALOMEDS::Color color = aGrp->GetColor();
-                myInfo->append( QString( "  - <b>%1:</b> %2" ).arg( SMESHGUI_AddInfo::tr( "COLOR" )).
-                                arg( QColor( color.R*255., color.G*255., color.B*255. ).name() ));
-              }
-            }
-          }
-        }
-      }
-      // separator
-      if ( ids.count() > 1 ) {
-        myInfo->append( "" );
-        myInfo->append( "------" );
-        myInfo->append( "" );
-      }
-    }
-  }
+  TextWriter writer( myInfo );
+  writeInfo( &writer, ids );
 }
 
 /*!
@@ -1764,21 +2007,12 @@ void SMESHGUI_SimpleElemInfo::clearInternal()
   myInfo->clear();
 }
 
-void SMESHGUI_SimpleElemInfo::saveInfo( QTextStream &out )
-{
-  out << ruler( 12 ) << endl;
-  out << SMESHGUI_ElemInfo::tr( "ELEM_INFO" ) << endl;
-  out << ruler( 12 ) << endl;
-  out << myInfo->toPlainText();
-  out << endl;
-}
-
+////////////////////////////////////////////////////////////////////////////////
+/// \class SMESHGUI_TreeElemInfo::ItemDelegate
+/// \brief Item delegate for tree mesh info widget.
+/// \internal
+////////////////////////////////////////////////////////////////////////////////
 
-/*!
-  \class SMESHGUI_TreeElemInfo::ItemDelegate
-  \brief Item delegate for tree mesh info widget
-  \internal
-*/
 class SMESHGUI_TreeElemInfo::ItemDelegate : public QItemDelegate
 {
 public:
@@ -1787,7 +2021,7 @@ public:
 };
 
 /*!
-  \brief Constructor
+  \brief Constructor.
   \internal
 */
 SMESHGUI_TreeElemInfo::ItemDelegate::ItemDelegate( QObject* parent ): QItemDelegate( parent )
@@ -1795,29 +2029,65 @@ SMESHGUI_TreeElemInfo::ItemDelegate::ItemDelegate( QObject* parent ): QItemDeleg
 }
 
 /*!
-  \brief Create item editor widget
+  \brief Redefined from QItemDelegate.
   \internal
 */
 QWidget* SMESHGUI_TreeElemInfo::ItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
 {
   QWidget* w = index.column() == 0 ? 0: QItemDelegate::createEditor( parent, option, index );
-  if ( qobject_cast<QLineEdit*>( w )) qobject_cast<QLineEdit*>( w )->setReadOnly(  true );
+  if ( qobject_cast<QLineEdit*>( w ) )
+    qobject_cast<QLineEdit*>( w )->setReadOnly( true );
   return w;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+/// \class SMESHGUI_TreeElemInfo::ItemCreator
+/// \brief Item creator for tree mesh info widget.
+/// \internal
+////////////////////////////////////////////////////////////////////////////////
+
+class SMESHGUI_TreeElemInfo::ItemCreator : public TreeItemCreator
+{
+  SMESHGUI_TreeElemInfo* myView;
+public:
+  ItemCreator( SMESHGUI_TreeElemInfo* );
+  QTreeWidgetItem* createItem( QTreeWidgetItem*, int );
+};
+
+/*!
+  \brief Constructor.
+  \param view Parent view.
+  \internal
+*/
+SMESHGUI_TreeElemInfo::ItemCreator::ItemCreator( SMESHGUI_TreeElemInfo* view ): TreeItemCreator(), myView( view )
+{
+}
+
 /*!
-  \class SMESHGUI_TreeElemInfo
-  \brief Represents mesh element information in the tree-like form.
+  \brief Create new tree item.
+  \param parent Parent tree item.
+  \param options Item options.
+  \return New tree widget item.
+  \internal
 */
+QTreeWidgetItem* SMESHGUI_TreeElemInfo::ItemCreator::createItem( QTreeWidgetItem* parent, int options )
+{
+  return myView->createItem( parent, options );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class SMESHGUI_TreeElemInfo
+/// \brief Show mesh element information as the tree.
+////////////////////////////////////////////////////////////////////////////////
 
 /*!
-  \brief Constructor
-  \param parent parent widget
+  \brief Constructor.
+  \param parent Parent widget. Defaults to 0.
 */
 SMESHGUI_TreeElemInfo::SMESHGUI_TreeElemInfo( QWidget* parent )
   : SMESHGUI_ElemInfo( parent )
 {
-  myInfo = new QTreeWidget( frame() );
+  myInfo = new QTreeWidget( centralWidget() );
   myInfo->setColumnCount( 2 );
   myInfo->setHeaderLabels( QStringList() << tr( "PROPERTY" ) << tr( "VALUE" ) );
   myInfo->header()->setStretchLastSection( true );
@@ -1826,538 +2096,22 @@ SMESHGUI_TreeElemInfo::SMESHGUI_TreeElemInfo( QWidget* parent )
 #else
   myInfo->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
 #endif
-  myInfo->setItemDelegate( new ItemDelegate( myInfo ));
-  QVBoxLayout* l = new QVBoxLayout( frame() );
+  myInfo->setItemDelegate( new ItemDelegate( myInfo ) );
+  QVBoxLayout* l = new QVBoxLayout( centralWidget() );
   l->setMargin( 0 );
   l->addWidget( myInfo );
-  connect( myInfo, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int )), this, SLOT( itemDoubleClicked( QTreeWidgetItem*, int )) );
-  connect( myInfo, SIGNAL( itemCollapsed( QTreeWidgetItem* )), this, SLOT( saveExpanded( QTreeWidgetItem* )) );
-  connect( myInfo, SIGNAL( itemExpanded( QTreeWidgetItem* )), this, SLOT( saveExpanded( QTreeWidgetItem* )) );
+  connect( myInfo, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ), this, SLOT( itemDoubleClicked( QTreeWidgetItem*, int ) ) );
 }
 
 /*!
-  \brief Show mesh element information
-  \param ids mesh nodes / elements identifiers
+  \brief Show mesh element information.
+  \param ids Nodes / elements IDs.
 */
 void SMESHGUI_TreeElemInfo::information( const QList<uint>& ids )
 {
   clearInternal();
-
-  if ( !proxy() )
-    return;
-
-  bool hasShapeToMesh = proxy().hasShapeToMesh();
-  SMESH_Actor* actor = proxy().actor();
-
-  if ( actor ) {
-    int grp_details = SMESHGUI::resourceMgr()->booleanValue( "SMESH", "elem_info_grp_details", false );
-    int precision   = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
-    int cprecision = -1;
-    if ( SMESHGUI::resourceMgr()->booleanValue( "SMESH", "use_precision", false )) 
-      cprecision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "controls_precision", -1 );
-    foreach ( uint id, ids ) {
-      if ( what() == ShowNodes ) {
-        //
-        // show node info
-        //
-        const SMDS_MeshElement* e = actor->GetObject()->GetMesh()->FindNode( id );
-        if ( !e ) return;
-        const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( e );
-      
-        // node ID
-        QTreeWidgetItem* nodeItem = createItem( 0, Bold | AllColumns );
-        nodeItem->setText( 0, SMESHGUI_ElemInfo::tr( "NODE" ));
-        nodeItem->setText( 1, QString( "#%1" ).arg( id ));
-        // coordinates
-        QTreeWidgetItem* coordItem = createItem( nodeItem, Bold );
-        coordItem->setText( 0, SMESHGUI_ElemInfo::tr( "COORDINATES" ));
-        QTreeWidgetItem* xItem = createItem( coordItem );
-        xItem->setText( 0, "X" );
-        xItem->setText( 1, QString::number( node->X(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
-        QTreeWidgetItem* yItem = createItem( coordItem );
-        yItem->setText( 0, "Y" );
-        yItem->setText( 1, QString::number( node->Y(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
-        QTreeWidgetItem* zItem = createItem( coordItem );
-        zItem->setText( 0, "Z" );
-        zItem->setText( 1, QString::number( node->Z(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
-        // connectivity
-        QTreeWidgetItem* conItem = createItem( nodeItem, Bold );
-        conItem->setText( 0, SMESHGUI_ElemInfo::tr( "CONNECTIVITY" ));
-        Connectivity connectivity = nodeConnectivity( node );
-        if ( !connectivity.isEmpty() ) {
-          QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
-          if ( !con.isEmpty() ) {
-            QTreeWidgetItem* i = createItem( conItem );
-            i->setText( 0, SMESHGUI_ElemInfo::tr( "0D_ELEMENTS" ));
-            i->setText( 1, con );
-          }
-          con = formatConnectivity( connectivity, SMDSAbs_Ball );
-          if ( !con.isEmpty() ) {
-            QTreeWidgetItem* i = createItem( conItem );
-            i->setText( 0, SMESHGUI_ElemInfo::tr( "BALL_ELEMENTS" ));
-            i->setText( 1, con );
-            i->setData( 1, TypeRole, NodeConnectivity );
-          }
-          con = formatConnectivity( connectivity, SMDSAbs_Edge );
-          if ( !con.isEmpty() ) {
-            QTreeWidgetItem* i = createItem( conItem );
-            i->setText( 0, SMESHGUI_ElemInfo::tr( "EDGES" ));
-            i->setText( 1, con );
-            i->setData( 1, TypeRole, NodeConnectivity );
-          }
-          con = formatConnectivity( connectivity, SMDSAbs_Face );
-          if ( !con.isEmpty() ) {
-            QTreeWidgetItem* i = createItem( conItem );
-            i->setText( 0, SMESHGUI_ElemInfo::tr( "FACES" ));
-            i->setText( 1, con );
-            i->setData( 1, TypeRole, NodeConnectivity );
-          }
-          con = formatConnectivity( connectivity, SMDSAbs_Volume );
-          if ( !con.isEmpty() ) {
-            QTreeWidgetItem* i = createItem( conItem );
-            i->setText( 0, SMESHGUI_ElemInfo::tr( "VOLUMES" ));
-            i->setText( 1, con );
-            i->setData( 1, TypeRole, NodeConnectivity );
-          }
-        }
-        else {
-          conItem->setText( 1, SMESHGUI_ElemInfo::tr( "FREE_NODE" ));
-        }
-        // node position
-        SMESH::SMESH_Mesh_ptr aMeshPtr = actor->GetObject()->GetMeshServer();   
-        if ( !CORBA::is_nil( aMeshPtr )) {
-          SMESH::NodePosition_var pos = aMeshPtr->GetNodePosition( id );
-          int shapeID = pos->shapeID;
-          if ( shapeID > 0 ) {
-            QString shapeType;
-            double u = 0, v = 0;
-            switch ( pos->shapeType ) {
-            case GEOM::EDGE:
-              shapeType = SMESHGUI_ElemInfo::tr( "GEOM_EDGE" );
-              if ( pos->params.length() == 1 )
-                u = pos->params[0];
-              break;
-            case GEOM::FACE:
-              shapeType = SMESHGUI_ElemInfo::tr( "GEOM_FACE" );
-              if ( pos->params.length() == 2 ) {
-                u = pos->params[0];
-                v = pos->params[1];
-              }
-              break;
-            case GEOM::VERTEX:
-              shapeType = SMESHGUI_ElemInfo::tr( "GEOM_VERTEX" );
-              break;
-            default:
-              shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SOLID" );
-              break;
-            }
-            QTreeWidgetItem* posItem = createItem( nodeItem, Bold );
-            posItem->setText( 0, SMESHGUI_ElemInfo::tr("POSITION") );
-            posItem->setText( 1, (shapeType + " #%1").arg( shapeID ));
-            if ( pos->shapeType == GEOM::EDGE || pos->shapeType == GEOM::FACE ) {
-              QTreeWidgetItem* uItem = createItem( posItem );
-              uItem->setText( 0, SMESHGUI_ElemInfo::tr("U_POSITION") );
-              uItem->setText( 1, QString::number( u, precision > 0 ? 'f' : 'g', qAbs( precision )));
-              if ( pos->shapeType == GEOM::FACE ) {
-                QTreeWidgetItem* vItem = createItem( posItem );
-                vItem->setText( 0, SMESHGUI_ElemInfo::tr("V_POSITION") );
-                vItem->setText( 1, QString::number( v, precision > 0 ? 'f' : 'g', qAbs( precision )));
-              }
-            }
-          }
-        }
-        // groups node belongs to
-        SMESH::SMESH_Mesh_ptr aMesh = actor->GetObject()->GetMeshServer();
-        if ( !CORBA::is_nil( aMesh )) {
-          SMESH::ListOfGroups_var groups = aMesh->GetGroups();
-          QTreeWidgetItem* groupsItem = 0;
-          for ( CORBA::ULong i = 0; i < groups->length(); i++ ) {
-            SMESH::SMESH_GroupBase_var aGrp = groups[i];
-            if ( CORBA::is_nil( aGrp )) continue;
-            QString aName = (char*) (CORBA::String_var) aGrp->GetName();
-            if ( aGrp->GetType() == SMESH::NODE && !aName.isEmpty() && aGrp->Contains( id )) {
-              if ( !groupsItem ) {
-                groupsItem = createItem( nodeItem, Bold );
-                groupsItem->setText( 0, SMESHGUI_AddInfo::tr( "GROUPS" ));
-              }
-              QTreeWidgetItem* it = createItem( groupsItem, Bold );
-              it->setText( 0, aName.trimmed() );
-              if ( grp_details ) {
-                SMESH::SMESH_Group_var         aStdGroup  = SMESH::SMESH_Group::_narrow( aGrp );
-                SMESH::SMESH_GroupOnGeom_var   aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( aGrp );
-                SMESH::SMESH_GroupOnFilter_var aFltGroup  = SMESH::SMESH_GroupOnFilter::_narrow( aGrp );
-                
-                // type : group on geometry, standalone group, group on filter
-                QTreeWidgetItem* typeItem = createItem( it );
-                typeItem->setText( 0, SMESHGUI_AddInfo::tr( "TYPE" ));
-                if ( !CORBA::is_nil( aStdGroup )) {
-                  typeItem->setText( 1, SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ));
-                }
-                else if ( !CORBA::is_nil( aGeomGroup )) {
-                  typeItem->setText( 1, SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ));
-                  GEOM::GEOM_Object_var gobj = aGeomGroup->GetShape();
-                  _PTR(SObject) sobj = SMESH::ObjectToSObject( gobj );
-                  if ( sobj ) {
-                    QTreeWidgetItem* gobjItem = createItem( typeItem );
-                    gobjItem->setText( 0, SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ));
-                    gobjItem->setText( 1, sobj->GetName().c_str() );
-                  }
-                }
-                else if ( !CORBA::is_nil( aFltGroup )) {
-                  typeItem->setText( 1, SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ));
-                }
-                
-                // size
-                QTreeWidgetItem* sizeItem = createItem( it );
-                sizeItem->setText( 0, SMESHGUI_AddInfo::tr( "SIZE" ));
-                sizeItem->setText( 1, QString::number( aGrp->Size() ));
-                
-                // color
-                SALOMEDS::Color color = aGrp->GetColor();
-                QTreeWidgetItem* colorItem = createItem( it );
-                colorItem->setText( 0, SMESHGUI_AddInfo::tr( "COLOR" ));
-                colorItem->setBackground( 1, QBrush( QColor( color.R*255., color.G*255., color.B*255.) ));
-              }
-            }
-          }
-        }
-      }
-      if ( what() == ShowElements ) {
-        //
-        // show element info
-        // 
-        const SMDS_MeshElement* e = actor->GetObject()->GetMesh()->FindElement( id );
-        SMESH::Controls::NumericalFunctorPtr afunctor;
-        if ( !e ) return;
-        
-        // element ID && type
-        QString stype;
-        switch( e->GetType() ) {
-        case SMDSAbs_0DElement: stype = SMESHGUI_ElemInfo::tr( "0D_ELEMENT" ); break;
-        case SMDSAbs_Ball:      stype = SMESHGUI_ElemInfo::tr( "BALL" ); break;
-        case SMDSAbs_Edge:      stype = SMESHGUI_ElemInfo::tr( "EDGE" ); break;
-        case SMDSAbs_Face:      stype = SMESHGUI_ElemInfo::tr( "FACE" ); break;
-        case SMDSAbs_Volume:    stype = SMESHGUI_ElemInfo::tr( "VOLUME" ); break;
-        default:;
-        }
-        if ( stype.isEmpty() ) return;
-        QTreeWidgetItem* elemItem = createItem( 0, Bold | AllColumns );
-        elemItem->setText( 0, stype );
-        elemItem->setText( 1, QString( "#%1" ).arg( id ));
-        // geometry type
-        QString gtype;
-        switch( e->GetEntityType() ) {
-        case SMDSEntity_Triangle:
-        case SMDSEntity_Quad_Triangle:
-        case SMDSEntity_BiQuad_Triangle:
-          gtype = SMESHGUI_ElemInfo::tr( "TRIANGLE" ); break;
-        case SMDSEntity_Quadrangle:
-        case SMDSEntity_Quad_Quadrangle:
-        case SMDSEntity_BiQuad_Quadrangle:
-          gtype = SMESHGUI_ElemInfo::tr( "QUADRANGLE" ); break;
-        case SMDSEntity_Polygon:
-        case SMDSEntity_Quad_Polygon:
-          gtype = SMESHGUI_ElemInfo::tr( "POLYGON" ); break;
-        case SMDSEntity_Tetra:
-        case SMDSEntity_Quad_Tetra:
-          gtype = SMESHGUI_ElemInfo::tr( "TETRAHEDRON" ); break;
-        case SMDSEntity_Pyramid:
-        case SMDSEntity_Quad_Pyramid:
-          gtype = SMESHGUI_ElemInfo::tr( "PYRAMID" ); break;
-        case SMDSEntity_Hexa:
-        case SMDSEntity_Quad_Hexa:
-        case SMDSEntity_TriQuad_Hexa:
-          gtype = SMESHGUI_ElemInfo::tr( "HEXAHEDRON" ); break;
-        case SMDSEntity_Penta:
-        case SMDSEntity_Quad_Penta:
-        case SMDSEntity_BiQuad_Penta:
-          gtype = SMESHGUI_ElemInfo::tr( "PRISM" ); break;
-        case SMDSEntity_Hexagonal_Prism:
-          gtype = SMESHGUI_ElemInfo::tr( "HEX_PRISM" ); break;
-        case SMDSEntity_Polyhedra:
-        case SMDSEntity_Quad_Polyhedra:
-          gtype = SMESHGUI_ElemInfo::tr( "POLYHEDRON" ); break;
-        default:
-          break;
-        }
-        if ( !gtype.isEmpty() ) {
-          QTreeWidgetItem* typeItem = createItem( elemItem, Bold );
-          typeItem->setText( 0, SMESHGUI_ElemInfo::tr( "TYPE" ));
-          typeItem->setText( 1, gtype );
-        }
-        // quadratic flag (for edges, faces and volumes)
-        if ( e->GetType() >= SMDSAbs_Edge && e->GetType() <= SMDSAbs_Volume ) {
-          // quadratic flag
-          QTreeWidgetItem* quadItem = createItem( elemItem, Bold );
-          quadItem->setText( 0, SMESHGUI_ElemInfo::tr( "QUADRATIC" ));
-          quadItem->setText( 1, e->IsQuadratic() ? SMESHGUI_ElemInfo::tr( "YES" ) : SMESHGUI_ElemInfo::tr( "NO" ));
-        }
-        if ( const SMDS_BallElement* ball = SMDS_Mesh::DownCast< SMDS_BallElement >( e )) {
-          // ball diameter
-          QTreeWidgetItem* diamItem = createItem( elemItem, Bold );
-          diamItem->setText( 0, SMESHGUI_ElemInfo::tr( "BALL_DIAMETER" ));
-          diamItem->setText( 1, QString( "%1" ).arg( ball->GetDiameter() ));
-        }
-        // connectivity
-        QTreeWidgetItem* conItem = createItem( elemItem, Bold );
-        conItem->setText( 0, SMESHGUI_ElemInfo::tr( "CONNECTIVITY" ));
-
-
-        if( e->GetGeomType() != SMDSGeom_POLYHEDRA ) {
-          SMDS_ElemIteratorPtr nodeIt = e->nodesIterator();
-          for ( int idx = 1; nodeIt->more(); idx++ ) {
-            const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
-            nodeInfo( node, idx, e->NbNodes(), conItem );
-          }
-        }
-        else {
-          SMDS_NodeIteratorPtr nodeIt = e->nodeIterator();
-          std::set< const SMDS_MeshNode* > addedNodes;
-          QList<const SMDS_MeshElement*> uniqueNodes;
-          while ( nodeIt->more() ) {
-            const SMDS_MeshNode* node = nodeIt->next();
-            if ( addedNodes.insert( node ).second )
-              uniqueNodes.append( nodeIt->next() );
-          }
-          SMDS_VolumeTool vtool( e );
-          const int nbFaces = vtool.NbFaces();
-          for( int face_id = 0; face_id < nbFaces; face_id++ ) {
-            QTreeWidgetItem* faceItem = createItem( conItem, Bold );
-            faceItem->setText( 0, QString( "%1 %2 / %3" ).arg( SMESHGUI_ElemInfo::tr( "FACE" )).arg( face_id + 1 ).arg( nbFaces ));
-            faceItem->setExpanded( true );
-
-            const SMDS_MeshNode** aNodeIds = vtool.GetFaceNodes( face_id );
-            const int              nbNodes = vtool.NbFaceNodes ( face_id );
-            for( int node_id = 0; node_id < nbNodes; node_id++ ) {
-              const SMDS_MeshNode* node = aNodeIds[node_id];
-              nodeInfo( node, uniqueNodes.indexOf(node) + 1, uniqueNodes.size(), faceItem );
-            }
-          }
-        }
-        //Controls
-        QTreeWidgetItem* cntrItem = createItem( elemItem, Bold );
-        cntrItem->setText( 0, SMESHGUI_ElemInfo::tr( "CONTROLS" ));
-        //Length
-        if( e->GetType()==SMDSAbs_Edge){
-          afunctor.reset( new SMESH::Controls::Length() );
-          afunctor->SetMesh( actor->GetObject()->GetMesh() );
-          afunctor->SetPrecision( cprecision );
-          QTreeWidgetItem* lenItem = createItem( cntrItem, Bold );
-          lenItem->setText( 0, tr( "LENGTH_EDGES" ));
-          lenItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id )) );
-        }
-        if( e->GetType() == SMDSAbs_Face ) {
-          //Area
-          afunctor.reset( new SMESH::Controls::Area() );
-          afunctor->SetMesh( actor->GetObject()->GetMesh() );
-          afunctor->SetPrecision( cprecision );
-          QTreeWidgetItem* areaItem = createItem( cntrItem, Bold );
-          areaItem->setText( 0, tr( "AREA_ELEMENTS" ));
-          areaItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue(id) ));
-          //Taper
-          if ( e->NbNodes() == 4 ) // see SMESH_Controls.cxx
-          {
-            afunctor.reset( new SMESH::Controls::Taper() );
-            afunctor->SetMesh( actor->GetObject()->GetMesh() );
-            afunctor->SetPrecision( cprecision );
-            QTreeWidgetItem* taperlItem = createItem( cntrItem, Bold );
-            taperlItem->setText( 0, tr( "TAPER_ELEMENTS" ));
-            taperlItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id )) );
-            //Warping angle
-            afunctor.reset( new SMESH::Controls::Warping() );
-            afunctor->SetMesh( actor->GetObject()->GetMesh() );
-            afunctor->SetPrecision( cprecision );
-            QTreeWidgetItem* warpItem = createItem( cntrItem, Bold );
-            warpItem->setText( 0, tr( "WARP_ELEMENTS" ));
-            warpItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id )) );
-          }
-          //AspectRatio2D
-          if ( !e->IsPoly() )
-          {
-            afunctor.reset( new SMESH::Controls::AspectRatio() );
-            afunctor->SetMesh( actor->GetObject()->GetMesh() );
-            QTreeWidgetItem* ratlItem = createItem( cntrItem, Bold );
-            ratlItem->setText( 0, tr( "ASPECTRATIO_ELEMENTS" ));
-            ratlItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id )) );
-          }
-          //Minimum angle
-          afunctor.reset( new SMESH::Controls::MinimumAngle() );
-          afunctor->SetMesh( actor->GetObject()->GetMesh() );
-          afunctor->SetPrecision( cprecision );
-          QTreeWidgetItem* minanglItem = createItem( cntrItem, Bold );
-          minanglItem->setText( 0, tr( "MINIMUMANGLE_ELEMENTS" ));
-          minanglItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id )) );
-          //Skew
-          if ( e->NbNodes() == 3 || e->NbNodes() == 4 )
-          {
-            afunctor.reset( new SMESH::Controls::Skew() );
-            afunctor->SetMesh( actor->GetObject()->GetMesh() );
-            afunctor->SetPrecision( cprecision );
-            QTreeWidgetItem* skewItem = createItem( cntrItem, Bold );
-            skewItem->setText( 0, tr( "SKEW_ELEMENTS" ));
-            skewItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id )) );
-          }
-          //Deflection
-          if ( hasShapeToMesh )
-          {
-            afunctor.reset( new SMESH::Controls::Deflection2D() );
-            afunctor->SetMesh( actor->GetObject()->GetMesh() );
-            QTreeWidgetItem* deflItem = createItem( cntrItem, Bold );
-            deflItem->setText( 0, tr( "DEFLECTION_2D" ));
-            deflItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id )) );
-          }
-          //ElemDiam2D
-          if ( !e->IsPoly() )
-          {
-            afunctor.reset( new SMESH::Controls::MaxElementLength2D() );
-            afunctor->SetMesh( actor->GetObject()->GetMesh() );
-            QTreeWidgetItem* diamItem = createItem( cntrItem, Bold );
-            diamItem->setText( 0, tr( "MAX_ELEMENT_LENGTH_2D" ));
-            diamItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id )) );
-          }
-        }
-        if( e->GetType() == SMDSAbs_Volume ) {
-          if ( !e->IsPoly() )
-          {
-            //AspectRatio3D
-            afunctor.reset( new SMESH::Controls::AspectRatio3D() );
-            afunctor->SetMesh( actor->GetObject()->GetMesh() );
-            QTreeWidgetItem* ratlItem3 = createItem( cntrItem, Bold );
-            ratlItem3->setText( 0, tr( "ASPECTRATIO_3D_ELEMENTS" ));
-            ratlItem3->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id )) );
-          }
-          //Volume
-          afunctor.reset( new SMESH::Controls::Volume() );
-          afunctor->SetMesh( actor->GetObject()->GetMesh() );
-          QTreeWidgetItem* volItem = createItem( cntrItem, Bold );
-          volItem->setText( 0, tr( "VOLUME_3D_ELEMENTS" ));
-          volItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id )) );
-          //ElementDiameter3D
-          afunctor.reset( new SMESH::Controls::MaxElementLength3D() );
-          afunctor->SetMesh( actor->GetObject()->GetMesh() );
-          QTreeWidgetItem* diam3Item = createItem( cntrItem, Bold );
-          diam3Item->setText( 0, tr( "MAX_ELEMENT_LENGTH_3D" ));
-          diam3Item->setText( 1, QString( "%1" ).arg( afunctor->GetValue( id )) );
-        }
-
-        //min edge length
-        afunctor.reset( new SMESH::Controls::Length2D() );
-        afunctor->SetMesh( actor->GetObject()->GetMesh() );
-        QTreeWidgetItem* minEdgeItem = createItem( cntrItem, Bold );
-        minEdgeItem->setText( 0, tr( "MIN_ELEM_EDGE" ));
-        SMESH::Controls::TSequenceOfXYZ points;
-        afunctor->GetPoints( e, points ); // "non-standard" way, to make it work for all elem types
-        minEdgeItem->setText( 1, QString( "%1" ).arg( afunctor->GetValue( points )) );
-
-        // gravity center
-        XYZ gc = gravityCenter( e );
-        QTreeWidgetItem* gcItem = createItem( elemItem, Bold );
-        gcItem->setText( 0, SMESHGUI_ElemInfo::tr( "GRAVITY_CENTER" ));
-        QTreeWidgetItem* xItem = createItem( gcItem );
-        xItem->setText( 0, "X" );
-        xItem->setText( 1, QString::number( gc.x(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
-        QTreeWidgetItem* yItem = createItem( gcItem );
-        yItem->setText( 0, "Y" );
-        yItem->setText( 1, QString::number( gc.y(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
-        QTreeWidgetItem* zItem = createItem( gcItem );
-        zItem->setText( 0, "Z" );
-        zItem->setText( 1, QString::number( gc.z(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
-
-        // normal vector
-        if( e->GetType() == SMDSAbs_Face ) {
-          XYZ gc = normal( e );
-          QTreeWidgetItem* nItem = createItem( elemItem, Bold );
-          nItem->setText( 0, SMESHGUI_ElemInfo::tr( "NORMAL_VECTOR" ));
-          QTreeWidgetItem* xItem = createItem( nItem );
-          xItem->setText( 0, "X" );
-          xItem->setText( 1, QString::number( gc.x(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
-          QTreeWidgetItem* yItem = createItem( nItem );
-          yItem->setText( 0, "Y" );
-          yItem->setText( 1, QString::number( gc.y(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
-          QTreeWidgetItem* zItem = createItem( nItem );
-          zItem->setText( 0, "Z" );
-          zItem->setText( 1, QString::number( gc.z(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
-        }
-
-        // element position
-        SMESH::SMESH_Mesh_ptr aMesh = actor->GetObject()->GetMeshServer();
-        if ( e->GetType() >= SMDSAbs_Edge && e->GetType() <= SMDSAbs_Volume ) {
-          if ( !CORBA::is_nil( aMesh )) {
-            SMESH::ElementPosition pos = aMesh->GetElementPosition( id );
-            int shapeID = pos.shapeID;
-            if ( shapeID > 0 ) {
-              QTreeWidgetItem* shItem = createItem( elemItem, Bold );
-              QString shapeType;
-              switch ( pos.shapeType ) {
-              case GEOM::EDGE:   shapeType = SMESHGUI_ElemInfo::tr( "GEOM_EDGE" );   break;
-              case GEOM::FACE:   shapeType = SMESHGUI_ElemInfo::tr( "GEOM_FACE" );   break;
-              case GEOM::VERTEX: shapeType = SMESHGUI_ElemInfo::tr( "GEOM_VERTEX" ); break;
-              case GEOM::SOLID:  shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SOLID" );  break;
-              case GEOM::SHELL:  shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SHELL" );  break;
-              default:           shapeType = SMESHGUI_ElemInfo::tr( "GEOM_SHAPE" );  break;
-              }
-              shItem->setText( 0, SMESHGUI_ElemInfo::tr( "POSITION" ));
-              shItem->setText( 1, QString( "%1 #%2" ).arg( shapeType ).arg( shapeID ));
-            }
-          }
-        }
-        // groups element belongs to
-        if ( !CORBA::is_nil( aMesh )) {
-          SMESH::ListOfGroups_var  groups = aMesh->GetGroups();
-          QTreeWidgetItem* groupsItem = 0;
-          for ( CORBA::ULong i = 0; i < groups->length(); i++ ) {
-            SMESH::SMESH_GroupBase_var aGrp = groups[i];
-            if ( CORBA::is_nil( aGrp )) continue;
-            QString aName = (char*) (CORBA::String_var) aGrp->GetName();
-            if ( aGrp->GetType() != SMESH::NODE && !aName.isEmpty() && aGrp->Contains( id )) {
-              if ( !groupsItem ) {
-                groupsItem = createItem( elemItem, Bold );
-                groupsItem->setText( 0, SMESHGUI_AddInfo::tr( "GROUPS" ));
-              }
-              QTreeWidgetItem* it = createItem( groupsItem, Bold );
-              it->setText( 0, aName.trimmed() );
-              if ( grp_details ) {
-                SMESH::SMESH_Group_var         aStdGroup  = SMESH::SMESH_Group::_narrow( aGrp );
-                SMESH::SMESH_GroupOnGeom_var   aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( aGrp );
-                SMESH::SMESH_GroupOnFilter_var aFltGroup  = SMESH::SMESH_GroupOnFilter::_narrow( aGrp );
-                
-                // type : group on geometry, standalone group, group on filter
-                QTreeWidgetItem* typeItem = createItem( it );
-                typeItem->setText( 0, SMESHGUI_AddInfo::tr( "TYPE" ));
-                if ( !CORBA::is_nil( aStdGroup )) {
-                  typeItem->setText( 1, SMESHGUI_AddInfo::tr( "STANDALONE_GROUP" ));
-                }
-                else if ( !CORBA::is_nil( aGeomGroup )) {
-                  typeItem->setText( 1, SMESHGUI_AddInfo::tr( "GROUP_ON_GEOMETRY" ));
-                  GEOM::GEOM_Object_var gobj = aGeomGroup->GetShape();
-                  _PTR(SObject) sobj = SMESH::ObjectToSObject( gobj );
-                  if ( sobj ) {
-                    QTreeWidgetItem* gobjItem = createItem( typeItem );
-                    gobjItem->setText( 0, SMESHGUI_AddInfo::tr( "GEOM_OBJECT" ));
-                    gobjItem->setText( 1, sobj->GetName().c_str() );
-                  }
-                }
-                else if ( !CORBA::is_nil( aFltGroup )) {
-                  typeItem->setText( 1, SMESHGUI_AddInfo::tr( "GROUP_ON_FILTER" ));
-                }
-                
-                // size
-                QTreeWidgetItem* sizeItem = createItem( it );
-                sizeItem->setText( 0, SMESHGUI_AddInfo::tr( "SIZE" ));
-                sizeItem->setText( 1, QString::number( aGrp->Size() ));
-                
-                // color
-                SALOMEDS::Color color = aGrp->GetColor();
-                QTreeWidgetItem* colorItem = createItem( it );
-                colorItem->setText( 0, SMESHGUI_AddInfo::tr( "COLOR" ));
-                colorItem->setBackground( 1, QBrush( QColor( color.R*255., color.G*255., color.B*255.) ));
-              }
-            }
-          }
-        }
-      }
-    }
-  }
+  TreeWriter writer( myInfo, new ItemCreator( this ) );
+  writeInfo( &writer, ids );
 }
 
 /*!
@@ -2370,66 +2124,66 @@ void SMESHGUI_TreeElemInfo::information( const QList<uint>& ids )
 void SMESHGUI_TreeElemInfo::nodeInfo( const SMDS_MeshNode* node, int index,
                                       int nbNodes, QTreeWidgetItem* parentItem )
 {
-  int precision   = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
-  // node number and ID
-  QTreeWidgetItem* nodeItem = createItem( parentItem, Bold );
-  nodeItem->setText( 0, QString( "%1 %2 / %3" ).arg( SMESHGUI_ElemInfo::tr( "NODE" )).arg( index ).arg( nbNodes ));
-  nodeItem->setText( 1, QString( "#%1" ).arg( node->GetID() ));
-  nodeItem->setData( 1, TypeRole, ElemConnectivity );
-  nodeItem->setData( 1, IdRole, node->GetID() );
-  nodeItem->setExpanded( false );
-  // node coordinates
-  QTreeWidgetItem* coordItem = createItem( nodeItem );
-  coordItem->setText( 0, SMESHGUI_ElemInfo::tr( "COORDINATES" ));
-  QTreeWidgetItem* xItem = createItem( coordItem );
-  xItem->setText( 0, "X" );
-  xItem->setText( 1, QString::number( node->X(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
-  QTreeWidgetItem* yItem = createItem( coordItem );
-  yItem->setText( 0, "Y" );
-  yItem->setText( 1, QString::number( node->Y(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
-  QTreeWidgetItem* zItem = createItem( coordItem );
-  zItem->setText( 0, "Z" );
-  zItem->setText( 1, QString::number( node->Z(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
-  // node connectivity
-  QTreeWidgetItem* nconItem = createItem( nodeItem );
-  nconItem->setText( 0, SMESHGUI_ElemInfo::tr( "CONNECTIVITY" ));
-  Connectivity connectivity = nodeConnectivity( node );
-  if ( !connectivity.isEmpty() ) {
-    QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
-    if ( !con.isEmpty() ) {
-      QTreeWidgetItem* i = createItem( nconItem );
-      i->setText( 0, SMESHGUI_ElemInfo::tr( "0D_ELEMENTS" ));
-      i->setText( 1, con );
-    }
-    con = formatConnectivity( connectivity, SMDSAbs_Edge );
-    if ( !con.isEmpty() ) {
-      QTreeWidgetItem* i = createItem( nconItem );
-      i->setText( 0, SMESHGUI_ElemInfo::tr( "EDGES" ));
-      i->setText( 1, con );
-      i->setData( 1, TypeRole, NodeConnectivity );
-    }
-    con = formatConnectivity( connectivity, SMDSAbs_Ball );
-    if ( !con.isEmpty() ) {
-      QTreeWidgetItem* i = createItem( nconItem );
-      i->setText( 0, SMESHGUI_ElemInfo::tr( "BALL_ELEMENTS" ));
-      i->setText( 1, con );
-      i->setData( 1, TypeRole, NodeConnectivity );
-    }
-    con = formatConnectivity( connectivity, SMDSAbs_Face );
-    if ( !con.isEmpty() ) {
-      QTreeWidgetItem* i = createItem( nconItem );
-      i->setText( 0, SMESHGUI_ElemInfo::tr( "FACES" ));
-      i->setText( 1, con );
-      i->setData( 1, TypeRole, NodeConnectivity );
-    }
-    con = formatConnectivity( connectivity, SMDSAbs_Volume );
-    if ( !con.isEmpty() ) {
-      QTreeWidgetItem* i = createItem( nconItem );
-      i->setText( 0, SMESHGUI_ElemInfo::tr( "VOLUMES" ));
-      i->setText( 1, con );
-      i->setData( 1, TypeRole, NodeConnectivity );
-    }
-  }
+  // int precision   = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
+  // // node number and ID
+  // QTreeWidgetItem* nodeItem = createItem( parentItem, Bold );
+  // nodeItem->setText( 0, QString( "%1 %2 / %3" ).arg( SMESHGUI_ElemInfo::tr( "NODE" )).arg( index ).arg( nbNodes ));
+  // nodeItem->setText( 1, QString( "#%1" ).arg( node->GetID() ));
+  // nodeItem->setData( 1, TypeRole, ElemConnectivity );
+  // nodeItem->setData( 1, IdRole, node->GetID() );
+  // nodeItem->setExpanded( false );
+  // // node coordinates
+  // QTreeWidgetItem* coordItem = createItem( nodeItem );
+  // coordItem->setText( 0, SMESHGUI_ElemInfo::tr( "COORDINATES" ));
+  // QTreeWidgetItem* xItem = createItem( coordItem );
+  // xItem->setText( 0, "X" );
+  // xItem->setText( 1, QString::number( node->X(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
+  // QTreeWidgetItem* yItem = createItem( coordItem );
+  // yItem->setText( 0, "Y" );
+  // yItem->setText( 1, QString::number( node->Y(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
+  // QTreeWidgetItem* zItem = createItem( coordItem );
+  // zItem->setText( 0, "Z" );
+  // zItem->setText( 1, QString::number( node->Z(), precision > 0 ? 'f' : 'g', qAbs( precision )) );
+  // // node connectivity
+  // QTreeWidgetItem* nconItem = createItem( nodeItem );
+  // nconItem->setText( 0, SMESHGUI_ElemInfo::tr( "CONNECTIVITY" ));
+  // Connectivity connectivity = nodeConnectivity( node );
+  // if ( !connectivity.isEmpty() ) {
+  //   QString con = formatConnectivity( connectivity, SMDSAbs_0DElement );
+  //   if ( !con.isEmpty() ) {
+  //     QTreeWidgetItem* i = createItem( nconItem );
+  //     i->setText( 0, SMESHGUI_ElemInfo::tr( "0D_ELEMENTS" ));
+  //     i->setText( 1, con );
+  //   }
+  //   con = formatConnectivity( connectivity, SMDSAbs_Edge );
+  //   if ( !con.isEmpty() ) {
+  //     QTreeWidgetItem* i = createItem( nconItem );
+  //     i->setText( 0, SMESHGUI_ElemInfo::tr( "EDGES" ));
+  //     i->setText( 1, con );
+  //     i->setData( 1, TypeRole, NodeConnectivity );
+  //   }
+  //   con = formatConnectivity( connectivity, SMDSAbs_Ball );
+  //   if ( !con.isEmpty() ) {
+  //     QTreeWidgetItem* i = createItem( nconItem );
+  //     i->setText( 0, SMESHGUI_ElemInfo::tr( "BALL_ELEMENTS" ));
+  //     i->setText( 1, con );
+  //     i->setData( 1, TypeRole, NodeConnectivity );
+  //   }
+  //   con = formatConnectivity( connectivity, SMDSAbs_Face );
+  //   if ( !con.isEmpty() ) {
+  //     QTreeWidgetItem* i = createItem( nconItem );
+  //     i->setText( 0, SMESHGUI_ElemInfo::tr( "FACES" ));
+  //     i->setText( 1, con );
+  //     i->setData( 1, TypeRole, NodeConnectivity );
+  //   }
+  //   con = formatConnectivity( connectivity, SMDSAbs_Volume );
+  //   if ( !con.isEmpty() ) {
+  //     QTreeWidgetItem* i = createItem( nconItem );
+  //     i->setText( 0, SMESHGUI_ElemInfo::tr( "VOLUMES" ));
+  //     i->setText( 1, con );
+  //     i->setData( 1, TypeRole, NodeConnectivity );
+  //   }
+  // }
 }
 /*!
   \brief Internal clean-up (reset widget)
@@ -2441,35 +2195,15 @@ void SMESHGUI_TreeElemInfo::clearInternal()
 }
 
 /*!
-  \brief Create new tree item.
-  \param parent parent tree widget item
-  \param flags item flag
-  \return new tree widget item
+  \brief Create new item and add it to the tree.
+  \param parent Parent tree widget item. Defaults to 0 (top-level item).
+  \param options Item flags. Defaults to 0 (none).
+  \return New tree widget item.
 */
-QTreeWidgetItem* SMESHGUI_TreeElemInfo::createItem( QTreeWidgetItem* parent, int flags )
+QTreeWidgetItem* SMESHGUI_TreeElemInfo::createItem( QTreeWidgetItem* parent, int options )
 {
-  QTreeWidgetItem* item;
-  if ( parent )
-    item = new QTreeWidgetItem( parent );
-  else
-    item = new QTreeWidgetItem( myInfo );
-
-  item->setFlags( item->flags() | Qt::ItemIsEditable );
-
-  QFont f = item->font( 0 );
-  f.setBold( true );
-  for ( int i = 0; i < myInfo->columnCount(); i++ ) {
-    if ( ( flags & Bold ) && ( i == 0 || flags & AllColumns ))
-      item->setFont( i, f );
-  }
-
-  if ( parent && parent->childCount() == 1 && itemDepth( parent ) == 1 )
-  {
-    QString resName = expandedResource( parent );
-    parent->setExpanded( SMESHGUI::resourceMgr()->booleanValue("SMESH", resName, true ));
-  }
-
-  item->setExpanded( true );
+  QTreeWidgetItem* item = new QTreeWidgetItem( parent ? parent : myInfo->invisibleRootItem() );
+  setTreeItemAttributes( item, options | Expanded | Editable );
   return item;
 }
 
@@ -2500,45 +2234,6 @@ void SMESHGUI_TreeElemInfo::itemDoubleClicked( QTreeWidgetItem* theItem, int the
   }
 }
 
-void SMESHGUI_TreeElemInfo::saveExpanded( QTreeWidgetItem* theItem )
-{
-  if ( theItem )
-    SMESHGUI::resourceMgr()->setValue("SMESH", expandedResource( theItem ), theItem->isExpanded() );
-}
-
-QString SMESHGUI_TreeElemInfo::expandedResource( QTreeWidgetItem* theItem )
-{
-  QString suffix;
-  switch( what() )
-  {
-  case ShowNodes:
-    suffix = "N_"; break;
-  case ShowElements:
-    suffix = "E_"; break;
-  default:
-    break;
-  }
-  return QString( "Expanded_" ) + suffix + theItem->text( 0 );
-}
-
-void SMESHGUI_TreeElemInfo::saveInfo( QTextStream &out )
-{
-  out << ruler( 12 ) << endl;
-  out << SMESHGUI_ElemInfo::tr( "ELEM_INFO" ) << endl;
-  out << ruler( 12 ) << endl;
-
-  QTreeWidgetItemIterator it( myInfo );
-  while ( *it ) {
-    if ( !( *it )->text(0).isEmpty() ) {
-      out << indent( itemDepth( *it ) ) << ( *it )->text(0);
-      if ( !( *it )->text(1).isEmpty() ) out << ": " << ( *it )->text(1);
-      out << endl;
-    }
-    ++it;
-  }
-  out << endl;
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 /// \class InfoComputor
 /// \brief Mesh information computor.
@@ -2556,7 +2251,7 @@ void SMESHGUI_TreeElemInfo::saveInfo( QTextStream &out )
   \param operation Value to compute.
   \internal
 */
-InfoComputor::InfoComputor( QObject* parent, const SMESHGUI_SelectionProxy& proxy, int operation )
+InfoComputor::InfoComputor( QObject* parent, const SMESH::SelectionProxy& proxy, int operation )
   : QObject( parent ), myProxy( proxy ), myOperation( operation )
 {
 }
@@ -2631,7 +2326,7 @@ SMESHGUI_AddInfo::~SMESHGUI_AddInfo()
   \brief Show information on given object.
   \param proxy Object to show information on (mesh, sub-mesh, group).
 */
-void SMESHGUI_AddInfo::showInfo( const SMESHGUI_SelectionProxy& proxy )
+void SMESHGUI_AddInfo::showInfo( const SMESH::SelectionProxy& proxy )
 {
   // reset panel
   setProperty( "group_index", 0 );
@@ -2650,11 +2345,11 @@ void SMESHGUI_AddInfo::showInfo( const SMESHGUI_SelectionProxy& proxy )
     nameItem->setText( 1, proxy.name() );
 
     // object info
-    if ( proxy.type() == SMESHGUI_SelectionProxy::Mesh )
+    if ( proxy.type() == SMESH::SelectionProxy::Mesh )
       meshInfo( proxy, nameItem );
-    else if ( proxy.type() == SMESHGUI_SelectionProxy::Submesh )
+    else if ( proxy.type() == SMESH::SelectionProxy::Submesh )
       subMeshInfo( proxy, nameItem );
-    else if ( proxy.type() >= SMESHGUI_SelectionProxy::Group )
+    else if ( proxy.type() >= SMESH::SelectionProxy::Group )
       groupInfo( proxy, nameItem );
   }
 }
@@ -2683,13 +2378,9 @@ void SMESHGUI_AddInfo::clear()
 */
 QTreeWidgetItem* SMESHGUI_AddInfo::createItem( QTreeWidgetItem* parent, int options )
 {
-  QTreeWidgetItem* item;
-  if ( parent )
-    item = new QTreeWidgetItem( parent );
-  else
-    item = new QTreeWidgetItem( myTree );
-  setFontAttributes( item, options );
-  item->setExpanded( true );
+  QTreeWidgetItem* item = parent ? new QTreeWidgetItem( parent ) : 
+    new QTreeWidgetItem( myTree->invisibleRootItem() );
+  setTreeItemAttributes( item, options | Expanded );
   return item;
 }
 
@@ -2698,13 +2389,13 @@ QTreeWidgetItem* SMESHGUI_AddInfo::createItem( QTreeWidgetItem* parent, int opti
   \param proxy Proxy object (mesh).
   \param parent Parent tree item.
 */
-void SMESHGUI_AddInfo::meshInfo( const SMESHGUI_SelectionProxy& proxy, QTreeWidgetItem* parent )
+void SMESHGUI_AddInfo::meshInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
 {
   if ( !proxy )
     return;
 
   QString shapeName = proxy.shapeName();
-  SMESHGUI_MedFileInfo inf = proxy.medFileInfo();
+  SMESH::MedInfo inf = proxy.medFileInfo();
 
   // type
   QTreeWidgetItem* typeItem = createItem( parent, Bold );
@@ -2750,7 +2441,7 @@ void SMESHGUI_AddInfo::meshInfo( const SMESHGUI_SelectionProxy& proxy, QTreeWidg
   \param proxy Proxy object (sub-mesh).
   \param parent Parent tree item.
 */
-void SMESHGUI_AddInfo::subMeshInfo( const SMESHGUI_SelectionProxy& proxy, QTreeWidgetItem* parent )
+void SMESHGUI_AddInfo::subMeshInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
 {
   if ( !proxy )
     return;
@@ -2760,7 +2451,7 @@ void SMESHGUI_AddInfo::subMeshInfo( const SMESHGUI_SelectionProxy& proxy, QTreeW
   if ( !isShort )
   {
     // parent mesh
-    SMESHGUI_SelectionProxy meshProxy = proxy.mesh();
+    SMESH::SelectionProxy meshProxy = proxy.mesh();
     if ( meshProxy )
     {
       QTreeWidgetItem* nameItem = createItem( parent, Bold );
@@ -2783,7 +2474,7 @@ void SMESHGUI_AddInfo::subMeshInfo( const SMESHGUI_SelectionProxy& proxy, QTreeW
   \param proxy Proxy object (group).
   \param parent Parent tree item.
 */
-void SMESHGUI_AddInfo::groupInfo( const SMESHGUI_SelectionProxy& proxy, QTreeWidgetItem* parent )
+void SMESHGUI_AddInfo::groupInfo( const SMESH::SelectionProxy& proxy, QTreeWidgetItem* parent )
 {
   if ( !proxy )
     return;
@@ -2793,7 +2484,7 @@ void SMESHGUI_AddInfo::groupInfo( const SMESHGUI_SelectionProxy& proxy, QTreeWid
   if ( !isShort )
   {
     // parent mesh
-    SMESHGUI_SelectionProxy meshProxy = proxy.mesh();
+    SMESH::SelectionProxy meshProxy = proxy.mesh();
     if ( meshProxy )
     {
       QTreeWidgetItem* nameItem = createItem( parent, Bold );
@@ -2803,14 +2494,14 @@ void SMESHGUI_AddInfo::groupInfo( const SMESHGUI_SelectionProxy& proxy, QTreeWid
   }
 
   // type
-  SMESHGUI_SelectionProxy::Type type = proxy.type();
+  SMESH::SelectionProxy::Type type = proxy.type();
   QTreeWidgetItem* typeItem = createItem( parent, Bold );
   typeItem->setText( 0, tr( "TYPE" ) );
-  if ( type == SMESHGUI_SelectionProxy::GroupStd )
+  if ( type == SMESH::SelectionProxy::GroupStd )
   {
     typeItem->setText( 1, tr( "STANDALONE_GROUP" ) );
   }
-  else if ( type == SMESHGUI_SelectionProxy::GroupGeom )
+  else if ( type == SMESH::SelectionProxy::GroupGeom )
   {
     typeItem->setText( 1, tr( "GROUP_ON_GEOMETRY" ) );
     // shape
@@ -2818,13 +2509,13 @@ void SMESHGUI_AddInfo::groupInfo( const SMESHGUI_SelectionProxy& proxy, QTreeWid
     gobjItem->setText( 0, tr( "GEOM_OBJECT" ) );
     gobjItem->setText( 1, proxy.shapeName() );
   }
-  else if ( type == SMESHGUI_SelectionProxy::GroupFilter )
+  else if ( type == SMESH::SelectionProxy::GroupFilter )
   {
     typeItem->setText( 1, tr( "GROUP_ON_FILTER" ) );
   }
 
   // element type
-  int etype = proxy.elementType();
+  int etype = proxy.groupElementType();
   if ( !isShort )
   {
     QString typeName = tr( "UNKNOWN" );
@@ -2940,11 +2631,11 @@ void SMESHGUI_AddInfo::showGroups()
   QMap<int, QTreeWidgetItem*> grpItems;
   for ( int i = idx*blockSize() ; i < qMin( (idx+1)*blockSize(), (int)myGroups.count() ); i++ )
   {
-    SMESHGUI_SelectionProxy grp = myGroups[i];
+    SMESH::SelectionProxy grp = myGroups[i];
     if ( !grp )
       continue;
 
-    int grpType = grp.elementType();
+    int grpType = grp.groupElementType();
 
     // create top-level groups container item if it does not exist
     if ( !itemGroups )
@@ -3013,7 +2704,7 @@ void SMESHGUI_AddInfo::showSubMeshes()
   QMap<int, QTreeWidgetItem*> smItems;
   for ( int i = idx*blockSize() ; i < qMin( (idx+1)*blockSize(), mySubMeshes.count() ); i++ )
   {
-    SMESHGUI_SelectionProxy sm = mySubMeshes[i];
+    SMESH::SelectionProxy sm = mySubMeshes[i];
     if ( !sm )
       continue;
     
@@ -3140,24 +2831,24 @@ class GroupCombo: public QComboBox
   class Item: public QStandardItem
   {
   public:
-    SMESHGUI_SelectionProxy myGroup;
-    Item( const SMESHGUI_SelectionProxy& group )
+    SMESH::SelectionProxy myGroup;
+    Item( const SMESH::SelectionProxy& group )
     {
       myGroup = group;
       setText( myGroup.name() );
     }
-    SMESHGUI_SelectionProxy group()
+    SMESH::SelectionProxy group()
     {
       return myGroup;
     }
   };
 
-  SMESHGUI_SelectionProxy myProxy;
+  SMESH::SelectionProxy myProxy;
 
 public:
   GroupCombo( QWidget* );
-  void setSource( const SMESHGUI_SelectionProxy& );
-  SMESHGUI_SelectionProxy currentGroup() const;
+  void setSource( const SMESH::SelectionProxy& );
+  SMESH::SelectionProxy currentGroup() const;
 };
 
 /*!
@@ -3175,7 +2866,7 @@ GroupCombo::GroupCombo( QWidget* parent ): QComboBox( parent )
   \param obj Mesh source.
   \internal
 */
-void GroupCombo::setSource( const SMESHGUI_SelectionProxy& proxy )
+void GroupCombo::setSource( const SMESH::SelectionProxy& proxy )
 {
   if ( myProxy == proxy )
     return;
@@ -3188,9 +2879,9 @@ void GroupCombo::setSource( const SMESHGUI_SelectionProxy& proxy )
 
   if ( myProxy )
   {
-    if ( myProxy.type() == SMESHGUI_SelectionProxy::Mesh )
+    if ( myProxy.type() == SMESH::SelectionProxy::Mesh )
     {
-      QList<SMESHGUI_SelectionProxy> groups = myProxy.groups();
+      QList<SMESH::SelectionProxy> groups = myProxy.groups();
       for ( int i = 0; i < groups.count(); ++i )
       {
         if ( groups[i] )
@@ -3202,7 +2893,7 @@ void GroupCombo::setSource( const SMESHGUI_SelectionProxy& proxy )
       }
       setCurrentIndex( -1 ); // for performance reasons
     }
-    else if ( myProxy.type() >= SMESHGUI_SelectionProxy::Group )
+    else if ( myProxy.type() >= SMESH::SelectionProxy::Group )
     {
       m->appendRow( new Item( myProxy ) );
       setCurrentIndex( 0 );
@@ -3217,9 +2908,9 @@ void GroupCombo::setSource( const SMESHGUI_SelectionProxy& proxy )
   \return Selected group.
   \internal
 */
-SMESHGUI_SelectionProxy GroupCombo::currentGroup() const
+SMESH::SelectionProxy GroupCombo::currentGroup() const
 {
-  SMESHGUI_SelectionProxy group;
+  SMESH::SelectionProxy group;
   QStandardItemModel* m = dynamic_cast<QStandardItemModel*>( model() );
   if ( currentIndex() >= 0 )
     group = dynamic_cast<Item*>( m->item( currentIndex() ) )->group();
@@ -3372,14 +3063,14 @@ SMESHGUI_MeshInfoDlg::~SMESHGUI_MeshInfoDlg()
 void SMESHGUI_MeshInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& io )
 {
   if ( !io.IsNull() )
-    showInfo( SMESHGUI_SelectionProxy( io ) );
+    showInfo( SMESH::SelectionProxy( io ) );
 }
 
 /*!
   \brief Show mesh information on given object.
   \param proxy Selection proxy.
 */
-void SMESHGUI_MeshInfoDlg::showInfo( const SMESHGUI_SelectionProxy& proxy )
+void SMESHGUI_MeshInfoDlg::showInfo( const SMESH::SelectionProxy& proxy )
 {
   SUIT_OverrideCursor wc;
 
@@ -3404,7 +3095,7 @@ void SMESHGUI_MeshInfoDlg::showInfo( const SMESHGUI_SelectionProxy& proxy )
   // "Element info" tab
   myGroups->setSource( proxy );
   if ( myMode->checkedId() == GroupMode ) {
-    SMESHGUI_SelectionProxy group = myGroups->currentGroup();
+    SMESH::SelectionProxy group = myGroups->currentGroup();
     if ( group )
       myElemInfo->showInfo( group );
     else
@@ -3494,7 +3185,7 @@ void SMESHGUI_MeshInfoDlg::updateSelection()
   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
     aViewWindow->SetSelectionMode( selMode );
 
-  SMESHGUI_SelectionProxy previous = myProxy;
+  SMESH::SelectionProxy previous = myProxy;
   QString ids = myID->text().trimmed();
   myID->clear();
   
@@ -3577,7 +3268,7 @@ void SMESHGUI_MeshInfoDlg::idChanged()
         if ( myMode->checkedId() == ElemMode )
         {
           idVec.push_back( id );
-          aGrCentersXYZ.push_back( myElemInfo->getGravityCenter( e ) );
+          // aGrCentersXYZ.push_back( myElemInfo->gravityCenter( e ) ); //todo?
         }
       }
     }
@@ -3871,7 +3562,7 @@ QwtPlot* SMESHGUI_CtrlInfo::createPlot( QWidget* parent )
   \brief Show information on given object.
   \param proxy Object to show information on (mesh, sub-mesh, group, ID source).
 */
-void SMESHGUI_CtrlInfo::showInfo( const SMESHGUI_SelectionProxy& proxy )
+void SMESHGUI_CtrlInfo::showInfo( const SMESH::SelectionProxy& proxy )
 {
   clearInternal();
 
@@ -4193,10 +3884,16 @@ Plot2d_Histogram* SMESHGUI_CtrlInfo::getHistogram( SMESH::NumericalFunctor_ptr a
 }
 #endif
 
-void SMESHGUI_CtrlInfo::saveInfo( QTextStream &out ) {
-  out << ruler( 20 ) << endl;
-  out << tr( "CTRL_INFO"  ) << endl;
-  out << ruler( 20 ) << endl;
+void SMESHGUI_CtrlInfo::saveInfo( QTextStream &out )
+{
+  // title
+  QString title = tr( "CTRL_INFO" );
+  out << ruler( title.size() ) << endl;
+  out << title << endl;
+  out << ruler( title.size() ) << endl;
+  out << endl;
+
+  // info
   out << tr( "NAME_LAB" ) << "  " << myWidgets[0]->text() << endl;
   out << tr( "NODES_INFO" ) << endl;
   out << indent() << tr( "NUMBER_OF_THE_FREE_NODES" ) << ": " << myWidgets[1]->text() << endl;
@@ -4278,14 +3975,14 @@ SMESHGUI_CtrlInfoDlg::~SMESHGUI_CtrlInfoDlg()
 void SMESHGUI_CtrlInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& io )
 {  
   if ( !io.IsNull() )
-    showInfo( SMESHGUI_SelectionProxy( io ) );
+    showInfo( SMESH::SelectionProxy( io ) );
 }
 
 /*!
   \brief Show mesh quality information on given object.
   \param proxy Selection proxy.
 */
-void SMESHGUI_CtrlInfoDlg::showInfo( const SMESHGUI_SelectionProxy& proxy )
+void SMESHGUI_CtrlInfoDlg::showInfo( const SMESH::SelectionProxy& proxy )
 {
   SUIT_OverrideCursor wc;
 
index 4e8594b71f2e11ea2cf5a1c30dc0cd52e8df9ba8..65a2e2d50f20b6597caf15b5b5e1e2d5720aca0c 100644 (file)
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-//  File   : SMESHGUI_MeshInfo.h
-//  Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
 
 #ifndef SMESHGUI_MESHINFO_H
 #define SMESHGUI_MESHINFO_H
 
 #include "SMESH_SMESHGUI.hxx"
-#include "SMESH_ControlsDef.hxx"
 #include "SMESHGUI_SelectionProxy.h"
 
 #ifndef DISABLE_PLOT2DVIEWER
@@ -41,8 +38,6 @@
 #include <QSet>
 
 #include <SALOMEconfig.h>
-#include CORBA_SERVER_HEADER(SMESH_Mesh)
-#include CORBA_SERVER_HEADER(SMESH_Group)
 #include CORBA_SERVER_HEADER(SMESH_Filter)
 
 #include <SALOME_InteractiveObject.hxx>
@@ -65,24 +60,13 @@ class SMESHGUI_SpinBox;
 
 class ExtraWidget;
 class GroupCombo;
+class InfoWriter;
 
 class SMESHGUI_EXPORT SMESHGUI_Info : public QWidget
 {
 public:
   SMESHGUI_Info( QWidget* = 0 );
-
   virtual void saveInfo( QTextStream& ) = 0;
-
-protected:
-  enum { Bold = 0x01, Italic = 0x02, AllColumns = 0x80 };
-  QFont fontFromOptions( int );
-  void setFontAttributes( QWidget*, int );
-  void setFontAttributes( QTreeWidgetItem*, int );
-  QLabel* createLabel( QWidget*, int = 0 );
-  QLabel* createLabel( const QString&, QWidget*, int = 0 );
-  QLabel* createField( QWidget*, const QString& = QString() );
-  QLabel* createField( QWidget*, int, const QString& = QString() );
-  QWidget* createSeparator( QWidget*, Qt::Orientation = Qt::Horizontal );
 };
 
 class SMESHGUI_EXPORT SMESHGUI_BaseInfo : public SMESHGUI_Info
@@ -153,7 +137,7 @@ public:
   SMESHGUI_BaseInfo( QWidget* = 0 );
   ~SMESHGUI_BaseInfo();
 
-  void showInfo( const SMESHGUI_SelectionProxy& );
+  void showInfo( const SMESH::SelectionProxy& );
   void clear();
   void saveInfo( QTextStream& );
 
@@ -169,7 +153,7 @@ private slots:
 
 private:
   iwlist myWidgets;
-  SMESHGUI_SelectionProxy myProxy;
+  SMESH::SelectionProxy myProxy;
 };
 
 class SMESHGUI_EXPORT SMESHGUI_ElemInfo : public SMESHGUI_Info
@@ -180,43 +164,28 @@ public:
   SMESHGUI_ElemInfo( QWidget* = 0 );
   ~SMESHGUI_ElemInfo();
 
-  void showInfo( const SMESHGUI_SelectionProxy&, uint, bool );
-  void showInfo( const SMESHGUI_SelectionProxy&, QSet<uint>, bool );
-  void showInfo( const SMESHGUI_SelectionProxy& );
+  void showInfo( const SMESH::SelectionProxy&, uint, bool );
+  void showInfo( const SMESH::SelectionProxy&, QSet<uint>, bool );
+  void showInfo( const SMESH::SelectionProxy& );
   void clear();
-
-  gp_XYZ getGravityCenter( const SMDS_MeshElement* );
+  void saveInfo( QTextStream& );
 
 protected:
   enum { ShowNone, ShowNodes, ShowElements };
 
-  struct XYZ
-  {
-    double myX, myY, myZ;
-    XYZ() { myX = myY = myZ = 0.0; }
-    XYZ(double x, double y, double z) { myX = x; myY = y; myZ = z; }
-    void add( double x, double y, double z ) { myX += x; myY += y; myZ += z; }
-    void divide( double a ) { if ( a != 0.) { myX /= a; myY /= a; myZ /= a; } }
-    double x() const { return myX; }
-    double y() const { return myY; }
-    double z() const { return myZ; }
-    operator gp_XYZ() const { return gp_XYZ( myX, myY, myZ ); }
-  };
-  typedef QMap< int, QList<int> > Connectivity;
-
-  QWidget* frame() const;
+  QWidget* centralWidget() const;
 
+  SMESH::SelectionProxy proxy() const;
   int what() const;
-  SMESHGUI_SelectionProxy proxy() const;
 
+  QString type2str( int, bool = false );
+  QString stype2str( int );
+  QString etype2str( int );
+  QString ctrl2str( int );
+  void writeInfo( InfoWriter*, const QList<uint>& );
   virtual void information( const QList<uint>& ) = 0;
   virtual void clearInternal();
 
-  Connectivity nodeConnectivity( const SMDS_MeshNode* );
-  QString formatConnectivity( Connectivity, int );
-  XYZ gravityCenter( const SMDS_MeshElement* );
-  XYZ normal( const SMDS_MeshElement* );
-
 signals:
   void itemInfo( int );
   void itemInfo( const QString& );
@@ -229,7 +198,7 @@ private slots:
 private:
   QWidget* myFrame;
   ExtraWidget* myExtra;
-  SMESHGUI_SelectionProxy myProxy;
+  SMESH::SelectionProxy myProxy;
   int myWhat;
   QList<uint> myIDs;
   int myIndex;
@@ -241,7 +210,6 @@ class SMESHGUI_EXPORT SMESHGUI_SimpleElemInfo : public SMESHGUI_ElemInfo
 
 public:
   SMESHGUI_SimpleElemInfo( QWidget* = 0 );
-  void saveInfo( QTextStream& );
 
 protected:
   void information( const QList<uint>& );
@@ -256,10 +224,10 @@ class SMESHGUI_EXPORT SMESHGUI_TreeElemInfo : public SMESHGUI_ElemInfo
   Q_OBJECT;
 
   class ItemDelegate;
+  class ItemCreator;
 
 public:
   SMESHGUI_TreeElemInfo( QWidget* = 0 );
-  void saveInfo( QTextStream& );
 
 protected:
   void contextMenuEvent( QContextMenuEvent* );
@@ -269,11 +237,9 @@ protected:
 
 private slots:
   void itemDoubleClicked( QTreeWidgetItem*, int );
-  void saveExpanded( QTreeWidgetItem* );
   
 private:
   QTreeWidgetItem* createItem( QTreeWidgetItem* = 0, int = 0 );
-  QString expandedResource( QTreeWidgetItem* );
   
 private:
   QTreeWidget* myInfo;
@@ -286,7 +252,7 @@ class InfoComputor: public QObject
 public:
   enum { GrpSize, GrpNbNodes };
   
-  InfoComputor( QObject*, const SMESHGUI_SelectionProxy&, int );
+  InfoComputor( QObject*, const SMESH::SelectionProxy&, int );
 
 signals:
   void computed();
@@ -295,7 +261,7 @@ public slots:
   void compute();
 
 private:
-  SMESHGUI_SelectionProxy myProxy;
+  SMESH::SelectionProxy myProxy;
   int myOperation;
 };
 
@@ -307,7 +273,7 @@ public:
   SMESHGUI_AddInfo( QWidget* = 0 );
   ~SMESHGUI_AddInfo();
 
-  void showInfo( const SMESHGUI_SelectionProxy& );
+  void showInfo( const SMESH::SelectionProxy& );
   void clear();
   void saveInfo( QTextStream& );
 
@@ -320,19 +286,19 @@ private slots:
 
 private:
   QTreeWidgetItem* createItem( QTreeWidgetItem* = 0, int = 0 );
-  void meshInfo( const SMESHGUI_SelectionProxy&, QTreeWidgetItem* );
-  void subMeshInfo( const SMESHGUI_SelectionProxy&, QTreeWidgetItem* );
-  void groupInfo( const SMESHGUI_SelectionProxy&, QTreeWidgetItem* );
+  void meshInfo( const SMESH::SelectionProxy&, QTreeWidgetItem* );
+  void subMeshInfo( const SMESH::SelectionProxy&, QTreeWidgetItem* );
+  void groupInfo( const SMESH::SelectionProxy&, QTreeWidgetItem* );
 
   void showGroups();
   void showSubMeshes();
 
 private:
-  SMESHGUI_SelectionProxy myProxy;
+  SMESH::SelectionProxy myProxy;
   QTreeWidget* myTree;
   QList<InfoComputor*> myComputors;
-  QList<SMESHGUI_SelectionProxy> myGroups;
-  QList<SMESHGUI_SelectionProxy> mySubMeshes;
+  QList<SMESH::SelectionProxy> myGroups;
+  QList<SMESH::SelectionProxy> mySubMeshes;
 };
 
 class SMESHGUI_EXPORT SMESHGUI_CtrlInfo : public SMESHGUI_Info
@@ -343,7 +309,7 @@ public:
   SMESHGUI_CtrlInfo( QWidget* = 0 );
   ~SMESHGUI_CtrlInfo();
 
-  void showInfo( const SMESHGUI_SelectionProxy& );
+  void showInfo( const SMESH::SelectionProxy& );
   void saveInfo( QTextStream& );
 
 private:
@@ -371,7 +337,7 @@ private slots:
 private:
   typedef SALOME::GenericObj_wrap< SMESH::Predicate > TPredicate;
   typedef SALOME::GenericObj_wrap< SMESH::NumericalFunctor > TNumFunctor;
-  SMESHGUI_SelectionProxy myProxy;
+  SMESH::SelectionProxy myProxy;
   ObjectType myObjectType;
   SMESHGUI_SpinBox* myToleranceWidget;
   QList<QLabel*> myWidgets;
@@ -423,9 +389,9 @@ private slots:
   void dump();
 
 private:
-  void showInfo( const SMESHGUI_SelectionProxy& );
+  void showInfo( const SMESH::SelectionProxy& );
 
-  SMESHGUI_SelectionProxy myProxy;
+  SMESH::SelectionProxy myProxy;
   QTabWidget* myTabWidget;
   SMESHGUI_BaseInfo* myBaseInfo;
   SMESHGUI_ElemInfo* myElemInfo;
@@ -457,9 +423,9 @@ private slots:
   void dump();
 
 private:
-  void showInfo( const SMESHGUI_SelectionProxy& );
+  void showInfo( const SMESH::SelectionProxy& );
 
-  SMESHGUI_SelectionProxy myProxy;
+  SMESH::SelectionProxy myProxy;
   SMESHGUI_CtrlInfo* myCtrlInfo;
 };
 
index 19a08d1b9b1c63c2ca8ebdfd0b88ffad1966ac73..5008c9cb8c448068cb3c99e8b3a0b070560c2c5a 100755 (executable)
@@ -1622,7 +1622,7 @@ SMESHGUI_SplitVolumesDlg::SMESHGUI_SplitVolumesDlg(SMESHGUI* theModule)
   }
   if ( myEntityTypeGrp )
   {
-    myEntityTypeGrp->button(0)->setText( tr("SMESH_TETRAS"));
+    myEntityTypeGrp->button(0)->setText( tr("SMESH_TETRAHEDRON"));
     myEntityTypeGrp->button(1)->setText( tr("SMESH_PRISM"));
     if ( QGroupBox* gb = qobject_cast< QGroupBox* >( myEntityTypeGrp->button(0)->parent() ))
       gb->setTitle( tr("TARGET_ELEM_TYPE"));
index e64e65d8b635fa5be0367443b66c1faec094aeb1..fc2b6c5dff7c263a30a0bb7c8e44251859b370f7 100644 (file)
 #include "SMESHGUI.h"
 #include "SMESHGUI_Utils.h"
 #include "SMESHGUI_VTKUtils.h"
+#include "SMDS_Mesh.hxx"
 #include "SMESH_Actor.h"
+#include "SMESH_ControlsDef.hxx"
 
 #include <SALOMEconfig.h>
+#include CORBA_SERVER_HEADER(SMESH_Filter)
 #include CORBA_SERVER_HEADER(SMESH_Group)
 
 #include <SALOMEDSClient_Study.hxx>
 #include <SUIT_ResourceMgr.h>
 
 ////////////////////////////////////////////////////////////////////////////////
-/// \class SMESHGUI_SelectionProxy
+/// \class SMESH::SelectionProxy
 /// \brief Provide operations over the selected object.
 ///
 /// The selection proxy class is aimed to use in dialogs to access mesh object
 /// - From mesh source object (CORBA reference); for performance reasons in this
 ///   case full initialization is not immediately done and performed only when
 ///   needed.
+///
+/// \todo To show min edge length with volumes, it is necessary to add new
+/// control Length3D.
+/// \todo To avoid showing controls unsuitable for particular elements, the
+/// corresponding check has to be done in each contro's IsSatisfy method.
 ////////////////////////////////////////////////////////////////////////////////
 
 /*!
   \brief Default constructor. Creates null proxy.
 */
-SMESHGUI_SelectionProxy::SMESHGUI_SelectionProxy(): myActor(0), myDirty(false)
+SMESH::SelectionProxy::SelectionProxy(): myActor(0), myDirty(false)
 {
 }
 
@@ -62,7 +70,7 @@ SMESHGUI_SelectionProxy::SMESHGUI_SelectionProxy(): myActor(0), myDirty(false)
   \brief Constructor.
   \param io Interactive object.
 */
-SMESHGUI_SelectionProxy::SMESHGUI_SelectionProxy( const Handle(SALOME_InteractiveObject)& io ): myActor(0), myDirty(true)
+SMESH::SelectionProxy::SelectionProxy( const Handle(SALOME_InteractiveObject)& io ): myActor(0), myDirty(true)
 {
   myObject = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( io );
   init();
@@ -72,7 +80,7 @@ SMESHGUI_SelectionProxy::SMESHGUI_SelectionProxy( const Handle(SALOME_Interactiv
   \brief Constructor.
   \param object Mesh source.
 */
-SMESHGUI_SelectionProxy::SMESHGUI_SelectionProxy( SMESH::SMESH_IDSource_ptr object ): myActor(0), myDirty(true)
+SMESH::SelectionProxy::SelectionProxy( SMESH::SMESH_IDSource_ptr object ): myActor(0), myDirty(true)
 {
   if ( !CORBA::is_nil( object ) )
     myObject = SMESH::SMESH_IDSource::_duplicate( object );
@@ -82,7 +90,7 @@ SMESHGUI_SelectionProxy::SMESHGUI_SelectionProxy( SMESH::SMESH_IDSource_ptr obje
   \brief Copy constructor.
   \param other Proxy being copied.
 */
-SMESHGUI_SelectionProxy::SMESHGUI_SelectionProxy( const SMESHGUI_SelectionProxy& other )
+SMESH::SelectionProxy::SelectionProxy( const SelectionProxy& other )
 {
   myIO = other.myIO;
   myObject = other.myObject;
@@ -94,7 +102,7 @@ SMESHGUI_SelectionProxy::SMESHGUI_SelectionProxy( const SMESHGUI_SelectionProxy&
   \brief Perform internal initialization.
   \internal
 */
-void SMESHGUI_SelectionProxy::init()
+void SMESH::SelectionProxy::init()
 {
   if ( myIO.IsNull() )
     myIO = new SALOME_InteractiveObject(); // create dummy IO to avoid crashes when accesing it
@@ -117,7 +125,7 @@ void SMESHGUI_SelectionProxy::init()
   \brief Assignment operator.
   \param other Proxy being copied.
 */
-SMESHGUI_SelectionProxy& SMESHGUI_SelectionProxy::operator= ( const SMESHGUI_SelectionProxy& other )
+SMESH::SelectionProxy& SMESH::SelectionProxy::operator= ( const SMESH::SelectionProxy& other )
 {
   myIO = other.myIO;
   myObject = other.myObject;
@@ -131,16 +139,16 @@ SMESHGUI_SelectionProxy& SMESHGUI_SelectionProxy::operator= ( const SMESHGUI_Sel
   \param other Proxy to compare with.
   \return \c true if two proxies are equal; \c false otherwise.
 */
-bool SMESHGUI_SelectionProxy::operator== ( const SMESHGUI_SelectionProxy& other )
+bool SMESH::SelectionProxy::operator== ( const SMESH::SelectionProxy& other )
 {
   return !CORBA::is_nil( myObject ) && !CORBA::is_nil( other.myObject ) && 
     myObject->_is_equivalent( other.myObject );
 }
 
 /*!
-  \brief Try to re-initialize proxy.
+  \brief Re-initialize proxy.
 */
-void SMESHGUI_SelectionProxy::refresh()
+void SMESH::SelectionProxy::refresh()
 {
   init();
 }
@@ -149,7 +157,7 @@ void SMESHGUI_SelectionProxy::refresh()
   \brief Check if proxy is null.
   \return \c true if proxy is null; \c false otherwise.
 */
-bool SMESHGUI_SelectionProxy::isNull() const
+bool SMESH::SelectionProxy::isNull() const
 {
   return CORBA::is_nil( myObject );
 }
@@ -158,7 +166,7 @@ bool SMESHGUI_SelectionProxy::isNull() const
   \brief Boolean conversion operator.
   \return \c true if proxy is not null; \c false otherwise.
 */
-SMESHGUI_SelectionProxy::operator bool() const
+SMESH::SelectionProxy::operator bool() const
 {
   return !isNull();
 }
@@ -167,10 +175,10 @@ SMESHGUI_SelectionProxy::operator bool() const
   \brief Get interactive object.
   \return Interactive object referenced by proxy.
 */
-const Handle(SALOME_InteractiveObject)& SMESHGUI_SelectionProxy::io() const
+const Handle(SALOME_InteractiveObject)& SMESH::SelectionProxy::io() const
 {
   if ( myDirty )
-    const_cast<SMESHGUI_SelectionProxy*>(this)->init();
+    const_cast<SMESH::SelectionProxy*>(this)->init();
   return myIO;
 }
 
@@ -178,7 +186,7 @@ const Handle(SALOME_InteractiveObject)& SMESHGUI_SelectionProxy::io() const
   \brief Get mesh object.
   \return Mesh object (mesh, sub-mesh, group, etc.) referenced by proxy.
 */
-SMESH::SMESH_IDSource_ptr SMESHGUI_SelectionProxy::object() const
+SMESH::SMESH_IDSource_ptr SMESH::SelectionProxy::object() const
 {
   return SMESH::SMESH_IDSource::_duplicate( myObject );
 }
@@ -187,21 +195,21 @@ SMESH::SMESH_IDSource_ptr SMESHGUI_SelectionProxy::object() const
   \brief Get actor.
   \return Actor referenced by proxy.
 */
-SMESH_Actor* SMESHGUI_SelectionProxy::actor() const
+SMESH_Actor* SMESH::SelectionProxy::actor() const
 {
   if ( myDirty )
-    const_cast<SMESHGUI_SelectionProxy*>(this)->init();
+    const_cast<SMESH::SelectionProxy*>(this)->init();
   return myActor;
 }
 
 /*!
   \brief Get object's validity.
 
-  Mesh object is valid if it is null and information stored in it is valid.
+  Mesh object is valid if it is not null and information stored in it is valid.
 
   \return \c true if object is valid; \c false otherwise.
 */
-bool SMESHGUI_SelectionProxy::isValid() const
+bool SMESH::SelectionProxy::isValid() const
 {
   return !isNull() && myObject->IsMeshInfoCorrect();
 }
@@ -209,7 +217,7 @@ bool SMESHGUI_SelectionProxy::isValid() const
 /*!
   \brief Load mesh object from study file.
 */
-void SMESHGUI_SelectionProxy::load()
+void SMESH::SelectionProxy::load()
 {
   if ( !isNull() )
   {
@@ -223,7 +231,7 @@ void SMESHGUI_SelectionProxy::load()
   \brief Get name.
   \return Mesh object's name.
 */
-QString SMESHGUI_SelectionProxy::name() const
+QString SMESH::SelectionProxy::name() const
 {
   QString value;
   if ( !isNull() )
@@ -235,7 +243,7 @@ QString SMESHGUI_SelectionProxy::name() const
   \brief Get type.
   \return Mesh object's type.
 */
-SMESHGUI_SelectionProxy::Type SMESHGUI_SelectionProxy::type() const
+SMESH::SelectionProxy::Type SMESH::SelectionProxy::type() const
 {
   Type value = Unknown;
   if ( !isNull() )
@@ -267,9 +275,9 @@ SMESHGUI_SelectionProxy::Type SMESHGUI_SelectionProxy::type() const
   \brief Get mesh information.
   \return Statistics on stored mesh object.
 */
-SMESHGUI_MeshInfo SMESHGUI_SelectionProxy::meshInfo() const
+SMESH::MeshInfo SMESH::SelectionProxy::meshInfo() const
 {
-  SMESHGUI_MeshInfo info;
+  SMESH::MeshInfo info;
   if ( !isNull() )
   {
     SMESH::long_array_var data = myObject->GetMeshInfo();
@@ -287,11 +295,11 @@ SMESHGUI_MeshInfo SMESHGUI_SelectionProxy::meshInfo() const
   \return Proxy object that stores parent mesh object.
   \note For proxy that stores a mesh, returns its copy.
 */
-SMESHGUI_SelectionProxy SMESHGUI_SelectionProxy::mesh() const
+SMESH::SelectionProxy SMESH::SelectionProxy::mesh() const
 {
-  SMESHGUI_SelectionProxy parent;
-  if ( isValid() )
-    parent = SMESHGUI_SelectionProxy( (SMESH::SMESH_Mesh_var) myObject->GetMesh() ); // cast to var to avoid leaks
+  SMESH::SelectionProxy parent;
+  if ( !isNull() )
+    parent = SMESH::SelectionProxy( (SMESH::SMESH_Mesh_var) myObject->GetMesh() ); // cast to var to avoid leaks
   return parent;
 }
 
@@ -300,17 +308,14 @@ SMESHGUI_SelectionProxy SMESHGUI_SelectionProxy::mesh() const
   \return \c true if Parent mesh is built on a shape; \c false otherwise.
   \note For group or submesh, this method checks that parent mesh has a shape.
 */
-bool SMESHGUI_SelectionProxy::hasShapeToMesh() const
+bool SMESH::SelectionProxy::hasShapeToMesh() const
 {
   bool result = false;
   if ( !isNull() )
   {
-    SMESHGUI_SelectionProxy parent = mesh();
-    if ( parent )
-    {
-      SMESH::SMESH_Mesh_var m = SMESH::SMESH_Mesh::_narrow( (SMESH::SMESH_IDSource_var)parent.object() ); // cast to var to avoid leaks
-      result = m->HasShapeToMesh();
-    }
+    SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
+    if ( !CORBA::is_nil( mesh ) )
+      result = mesh->HasShapeToMesh();
   }
   return result;
 }
@@ -322,7 +327,7 @@ bool SMESHGUI_SelectionProxy::hasShapeToMesh() const
   The result contains valid pointer only if proxy refers to mesh, sub-mesh
   or group created on a geometry.
 */
-GEOM::GEOM_Object_ptr SMESHGUI_SelectionProxy::shape() const
+GEOM::GEOM_Object_ptr SMESH::SelectionProxy::shape() const
 {
   GEOM::GEOM_Object_var shape;
   if ( !isNull() )
@@ -347,7 +352,7 @@ GEOM::GEOM_Object_ptr SMESHGUI_SelectionProxy::shape() const
   The result contains non-empty name only if proxy refers to mesh, sub-mesh
   or group created on a geometry, and if that geometry has valid name.
 */
-QString SMESHGUI_SelectionProxy::shapeName() const
+QString SMESH::SelectionProxy::shapeName() const
 {
   QString name;
   if ( !isNull() )
@@ -367,7 +372,7 @@ QString SMESHGUI_SelectionProxy::shapeName() const
   The result contains valid type only if proxy refers to mesh, sub-mesh
   or group created on a geometry.
 */
-int SMESHGUI_SelectionProxy::shapeType() const
+int SMESH::SelectionProxy::shapeType() const
 {
   int type = -1;
   if ( !isNull() )
@@ -383,10 +388,10 @@ int SMESHGUI_SelectionProxy::shapeType() const
   \brief Check if mesh has been loaded from study file.
   \return \c true if mesh was loaded; \c false otherwise.
 */
-bool SMESHGUI_SelectionProxy::isMeshLoaded() const
+bool SMESH::SelectionProxy::isMeshLoaded() const
 {
   bool result = true; // set default to true to avoid side effects
-  if ( isValid() )
+  if ( !isNull() )
   {
     SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
     if ( !CORBA::is_nil( mesh ) )
@@ -395,6 +400,527 @@ bool SMESHGUI_SelectionProxy::isMeshLoaded() const
   return result;
 }
 
+/*!
+  \brief Check if node with given ID is present in the mesh.
+  \param id Mesh node ID.
+  \return \c true if mesh contains node; \c false otherwise.
+*/
+bool SMESH::SelectionProxy::hasNode( int id )
+{
+  bool result = false;
+  if ( !isNull() )
+  {
+    if ( actor() )
+    {
+      const SMDS_MeshNode* node = actor()->GetObject()->GetMesh()->FindNode( id );
+      result = node != 0;
+    }
+    else
+    {
+      SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
+      if ( !CORBA::is_nil( mesh ) )
+      {
+        SMESH::double_array_var coords = mesh->GetNodeXYZ( id );
+        result = coords->length() >= 3;
+      }
+    }
+  }
+  return result; 
+}
+
+/*!
+  \brief Get node coordinates.
+  \param id Mesh node ID.
+  \param xyz Returned node coordinates.
+  \return \c true if result is valid; \c false otherwise.
+*/
+bool SMESH::SelectionProxy::nodeCoordinates( int id, SMESH::XYZ& xyz )
+{
+  bool result = false;
+  xyz = SMESH::XYZ();
+  
+  if ( !isNull() )
+  {
+    if ( actor() )
+    {
+      const SMDS_MeshNode* node = actor()->GetObject()->GetMesh()->FindNode( id );
+      if ( node )
+      {
+       xyz = SMESH::XYZ( node->X(), node->Y(), node->Z() );
+        result = true;
+      }
+    }
+    else
+    {
+      SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
+      if ( !CORBA::is_nil( mesh ) )
+      {
+        SMESH::double_array_var coords = mesh->GetNodeXYZ( id );
+        if ( coords->length() >= 3 )
+        {
+          xyz = SMESH::XYZ( coords[0], coords[1], coords[2] );
+          result = true;
+        }
+      }
+    }
+  }
+  return result;
+}
+
+/*!
+  \brief Get node connectivity.
+  \param id Mesh node ID.
+  \param connectivity Returned node connectivity.
+  \return \c true if result is valid; \c false otherwise.
+*/
+bool SMESH::SelectionProxy::nodeConnectivity( int id, SMESH::Connectivity& connectivity )
+{
+  bool result = false;
+  connectivity.clear();
+  if ( !isNull() )
+  {
+    if ( actor() )
+    {
+      const SMDS_MeshNode* node = actor()->GetObject()->GetMesh()->FindNode( id );
+      if ( node )
+      {
+        SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
+        while ( it && it->more() )
+        {
+          const SMDS_MeshElement* ne = it->next();
+          connectivity[ ne->GetType() ] << ne->GetID();
+        }
+        result = true;
+      }
+    }
+    else
+    {
+      SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
+      if ( !CORBA::is_nil( mesh ) )
+      {
+        SMESH::long_array_var elements = mesh->GetNodeInverseElements( id );
+        for ( int i = 0, n = elements->length(); i < n; i++ )
+        {
+          SMESH::ElementType type = mesh->GetElementType( elements[i], true );
+          connectivity[ type ] << elements[i];
+        }
+        result = true;
+      }
+    }
+  }
+  return result;
+}
+
+/*!
+  \brief Get node position on a shape.
+  \param id Mesh node ID.
+  \param position Returned node position.
+  \return \c true if result is valid; \c false otherwise.
+*/
+bool SMESH::SelectionProxy::nodePosition( int id, Position& position )
+{
+  bool result = false;
+  position = Position();
+  if ( !isNull() )
+  {
+    SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
+    if ( !CORBA::is_nil( mesh ) )
+    {
+      SMESH::NodePosition_var pos = mesh->GetNodePosition( id );
+      position.setShapeId( pos->shapeID );
+      if ( pos->shapeID > 0 )
+      {
+        position.setShapeType( pos->shapeType );
+        if ( pos->shapeType == GEOM::EDGE && pos->params.length() > 0 )
+        {
+          position.setU( pos->params[0] );
+        }
+        if ( pos->shapeType == GEOM::FACE && pos->params.length() > 1 )
+        {
+          position.setU( pos->params[0] );
+          position.setV( pos->params[1] );
+        }
+        result = true;
+      }
+    }
+  }
+  return result;
+}
+
+/*!
+  \brief Get groups given node belongs to.
+  \param id Mesh node ID.
+  \return List of groups containing given node.
+*/
+QList<SMESH::SelectionProxy> SMESH::SelectionProxy::nodeGroups( int id ) const
+{
+  QList<SMESH::SelectionProxy> result;
+  if ( !isNull() )
+  {
+    SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
+    if ( !CORBA::is_nil( mesh ) )
+    {
+      SMESH::ListOfGroups_var groups = mesh->GetGroups();
+      for ( uint i = 0 ; i < groups->length(); i++ )
+      {
+        if ( groups[i]->GetType() == SMESH::NODE && groups[i]->Contains( id ) )
+        {
+          result << SMESH::SelectionProxy( groups[i].in() );
+        }
+      }
+    }
+  }
+  return result;
+}
+
+/*!
+  \brief Check if element with given ID is present in the mesh.
+  \param id Mesh element ID.
+  \return \c true if mesh contains element; \c false otherwise.
+*/
+bool SMESH::SelectionProxy::hasElement( int id )
+{
+  bool result = false;
+  if ( !isNull() )
+  {
+    if ( actor() )
+    {
+      const SMDS_MeshElement* element = actor()->GetObject()->GetMesh()->FindElement( id );
+      result = element != 0;
+    }
+    else
+    {
+      SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
+      if ( !CORBA::is_nil( mesh ) )
+      {
+        SMESH::long_array_var nodes = mesh->GetElemNodes( id );
+        result = nodes->length() > 0;
+      }
+    }
+  }
+  return result; 
+}
+
+/*!
+  \brief Get type of given mesh element.
+  \param id Mesh element ID.
+  \return Element type.
+*/
+SMESH::ElementType SMESH::SelectionProxy::elementType( int id ) const
+{
+  SMESH::ElementType value = SMESH::ALL;
+  if ( !isNull() )
+  {
+    if ( actor() )
+    {
+      const SMDS_MeshElement* element = actor()->GetObject()->GetMesh()->FindElement( id );
+      if ( element )
+      {
+        value = (SMESH::ElementType)element->GetType();
+      }
+    }
+    else
+    {
+      SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
+      if ( !CORBA::is_nil( mesh ) )
+      {
+        value = mesh->GetElementType( id, true );
+      }
+    }
+  }
+  return value;
+}
+
+/*!
+  \brief Get entity type of given mesh element.
+  \param id Mesh element ID.
+  \return Entity type.
+*/
+int SMESH::SelectionProxy::elementEntityType( int id ) const
+{
+  SMESH::EntityType value = SMESH::Entity_Last;
+  if ( !isNull() )
+  {
+    if ( actor() )
+    {
+      const SMDS_MeshElement* element = actor()->GetObject()->GetMesh()->FindElement( id );
+      if ( element )
+      {
+        value = (SMESH::EntityType)element->GetEntityType();
+      }
+    }
+    else
+    {
+      SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
+      if ( !CORBA::is_nil( mesh ) )
+      {
+        value = mesh->GetElementGeomType( id );
+      }
+    }
+  }
+  return value;
+}
+
+/*!
+  \brief Get element connectivity.
+  \param id Mesh element ID.
+  \param connectivity Returned element connectivity.
+  \return \c true if result is valid; \c false otherwise.
+*/
+bool SMESH::SelectionProxy::elementConnectivity( int id, Connectivity& connectivity )
+{
+  bool result = false;
+  connectivity.clear();
+  if ( !isNull() )
+  {
+    if ( actor() )
+    {
+      const SMDS_MeshElement* element = actor()->GetObject()->GetMesh()->FindElement( id );
+      if ( element )
+      {
+        QSet<int> nodes;
+        SMDS_ElemIteratorPtr it = element->nodesIterator();
+        while ( it && it->more() )
+          nodes << static_cast<const SMDS_MeshNode*>( it->next() )->GetID();
+        connectivity[ SMDSAbs_Node ] = nodes.toList();
+        result = true;
+      }
+    }
+    else
+    {
+      SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
+      if ( !CORBA::is_nil( mesh ) )
+      {
+        SMESH::long_array_var nodes = mesh->GetElemNodes( id );
+        for ( int i = 0, n = nodes->length(); i < n; i++ )
+        {
+          connectivity[ SMDSAbs_Node ] << nodes[i];
+        }
+        result = true;
+      }
+    }
+  }
+  return result;
+}
+
+/*!
+  \brief Get element position on a shape.
+  \param id Mesh element ID.
+  \param position Returned element position.
+  \return \c true if result is valid; \c false otherwise.
+*/
+bool SMESH::SelectionProxy::elementPosition( int id, Position& position )
+{
+  bool result = false;
+  position = Position();
+  if ( !isNull() )
+  {
+    SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
+    if ( !CORBA::is_nil( mesh ) )
+    {
+      SMESH::ElementPosition_var pos = mesh->GetElementPosition( id );
+      position.setShapeId( pos->shapeID );
+      if ( pos->shapeID > 0 )
+      {
+        position.setShapeType( pos->shapeType );
+        result = true;
+      }
+    }
+  }
+  return result;
+}
+
+/*!
+  \brief Get gravity center of given element.
+  \param id Mesh element ID.
+  \param xyz Returned gravity center.
+  \return \c true if result is valid; \c false otherwise.
+*/
+bool SMESH::SelectionProxy::elementGravityCenter( int id, SMESH::XYZ& xyz )
+{
+  bool result = false;
+  xyz = SMESH::XYZ();
+  if ( !isNull() )
+  {
+    if ( actor() )
+    {
+      const SMDS_MeshElement* element = actor()->GetObject()->GetMesh()->FindElement( id );
+      if ( element )
+      {
+        SMDS_ElemIteratorPtr it = element->nodesIterator();
+        while ( it->more() )
+        {
+          const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( it->next() );
+          xyz.add( node->X(), node->Y(), node->Z() );
+        }
+        xyz.divide( element->NbNodes() );
+        result = true;
+      }
+    }
+    else
+    {
+      SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
+      if ( !CORBA::is_nil( mesh ) )
+      {
+        SMESH::long_array_var nodes = mesh->GetElemNodes( id );
+        for ( int i = 0, n = nodes->length(); i < n; i++ )
+        {
+          SMESH::double_array_var coords = mesh->GetNodeXYZ( nodes[i]  );
+          if ( coords->length() >= 3 )
+          {
+            xyz.add( coords[0], coords[1], coords[2] );
+          }
+        }
+        xyz.divide( nodes->length() );
+        result = true;
+      }
+    }
+  }
+  return result;
+}
+
+/*!
+  \brief Get normal vector to given element (face).
+  \param id Mesh element ID.
+  \param xyz Returned normal vector.
+  \return \c true if result is valid; \c false otherwise.
+*/
+bool SMESH::SelectionProxy::elementNormal( int id, SMESH::XYZ& xyz )
+{
+  bool result = false;
+  xyz = SMESH::XYZ();
+  if ( !isNull() )
+  {
+    if ( actor() )
+    {
+      const SMDS_MeshElement* element = actor()->GetObject()->GetMesh()->FindElement( id );
+      if ( element && element->GetType() == SMDSAbs_Face )
+      {
+        xyz = SMESH::getNormale( SMDS_Mesh::DownCast<SMDS_MeshFace>( element ) );
+        result = true;
+      }
+    }
+    else
+    {
+      SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
+      if ( !CORBA::is_nil( mesh ) )
+      {
+        SMESH::double_array_var normal = mesh->GetFaceNormal( id, true );
+        if ( normal->length() >= 3 )
+        {
+          xyz = SMESH::XYZ( normal[0], normal[1], normal[2] );
+          result = true;
+        }
+      }
+    }
+  }
+  return result;
+}
+
+/*!
+  \brief Get quality control's value for given element.
+  \param id Mesh element ID.
+  \param control Quality control type.
+  \param precision Precision for control's value.
+  \param value Returned quality control's value.
+  \return \c true if result is valid; \c false otherwise.
+*/
+bool SMESH::SelectionProxy::elementControl( int id, int control, double precision, double& value ) const
+{
+  bool result = false;
+  value = 0.;
+  if ( !isNull() )
+  {
+    if ( actor() )
+    {
+      SMESH::Controls::NumericalFunctorPtr functor;
+      switch ( control )
+      {
+      case SMESH::FT_AspectRatio:
+        functor.reset( new SMESH::Controls::AspectRatio() );
+        break;
+      case SMESH::FT_AspectRatio3D:
+        functor.reset( new SMESH::Controls::AspectRatio3D() );
+        break;
+      case SMESH::FT_Warping:
+        functor.reset( new SMESH::Controls::Warping() );
+        break;
+      case SMESH::FT_MinimumAngle:
+        functor.reset( new SMESH::Controls::MinimumAngle() );
+        break;
+      case SMESH::FT_Taper:
+        functor.reset( new SMESH::Controls::Taper() );
+        break;
+      case SMESH::FT_Skew:
+        functor.reset( new SMESH::Controls::Skew() );
+        break;
+      case SMESH::FT_Area:
+        functor.reset(  new SMESH::Controls::Area() );
+        break;
+      case SMESH::FT_Volume3D:
+        functor.reset(  new SMESH::Controls::Volume() );
+        break;
+      case SMESH::FT_MaxElementLength2D:
+        functor.reset( new SMESH::Controls::MaxElementLength2D() );
+        break;
+      case SMESH::FT_MaxElementLength3D:
+        functor.reset(  new SMESH::Controls::MaxElementLength3D() );
+        break;
+      case SMESH::FT_Length:
+        functor.reset( new SMESH::Controls::Length() );
+        break;
+      case SMESH::FT_Length2D:
+        functor.reset( new SMESH::Controls::Length2D() );
+        break;
+      case SMESH::FT_BallDiameter:
+        functor.reset( new SMESH::Controls::BallDiameter() );
+        break;
+      default:
+        break;
+      }        
+      const SMDS_MeshElement* element = actor()->GetObject()->GetMesh()->FindElement( id );
+      if ( element && functor && element->GetType() == functor->GetType() )
+      {
+        functor->SetMesh( actor()->GetObject()->GetMesh() );
+        functor->SetPrecision( precision );
+        value = functor->GetValue( id );
+        result = true;
+      }
+    }
+    else
+    {
+      //todo
+    }
+  }
+  return result;
+}
+
+/*!
+  \brief Get groups given element belongs to.
+  \param id Mesh element ID.
+  \return List of groups containing element.
+*/
+QList<SMESH::SelectionProxy> SMESH::SelectionProxy::elementGroups( int id ) const
+{
+  QList<SMESH::SelectionProxy> result;
+  if ( !isNull() )
+  {
+    SMESH::SMESH_Mesh_var mesh = myObject->GetMesh();
+    if ( !CORBA::is_nil( mesh ) )
+    {
+      SMESH::ListOfGroups_var groups = mesh->GetGroups();
+      for ( uint i = 0 ; i < groups->length(); i++ )
+      {
+        if ( groups[i]->GetType() != SMESH::NODE && groups[i]->Contains( id ) )
+        {
+          result << SMESH::SelectionProxy( groups[i].in() );
+        }
+      }
+    }
+  }
+  return result;
+}
+
 /*!
   \brief Get MED file information.
   \return MED file information.
@@ -402,9 +928,9 @@ bool SMESHGUI_SelectionProxy::isMeshLoaded() const
   The result contains valid data only if proxy refers to mesh object
   which has been imported from the MED file.
 */
-SMESHGUI_MedFileInfo SMESHGUI_SelectionProxy::medFileInfo() const
+SMESH::MedInfo SMESH::SelectionProxy::medFileInfo() const
 {
-  SMESHGUI_MedFileInfo info;
+  SMESH::MedInfo info;
   if ( !isNull() )
   {
     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( myObject );
@@ -423,9 +949,9 @@ SMESHGUI_MedFileInfo SMESHGUI_SelectionProxy::medFileInfo() const
   \brief Get child sub-meshes.
   \return List of sub-meshes for mesh object; empty list for other types.
 */
-QList<SMESHGUI_SelectionProxy> SMESHGUI_SelectionProxy::submeshes() const
+QList<SMESH::SelectionProxy> SMESH::SelectionProxy::submeshes() const
 {
-  QList<SMESHGUI_SelectionProxy> lst;
+  QList<SMESH::SelectionProxy> lst;
   if ( !isNull() )
   {
     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( myObject );
@@ -433,7 +959,7 @@ QList<SMESHGUI_SelectionProxy> SMESHGUI_SelectionProxy::submeshes() const
     {
       SMESH::submesh_array_var array = mesh->GetSubMeshes();
       for ( uint i = 0 ; i < array->length(); i++ )
-        lst << SMESHGUI_SelectionProxy( array[i].in() );
+        lst << SMESH::SelectionProxy( array[i].in() );
     }
   }
   return lst;
@@ -443,9 +969,9 @@ QList<SMESHGUI_SelectionProxy> SMESHGUI_SelectionProxy::submeshes() const
   \brief Get child groups.
   \return List of groups for mesh object; empty list for other types.
 */
-QList<SMESHGUI_SelectionProxy> SMESHGUI_SelectionProxy::groups() const
+QList<SMESH::SelectionProxy> SMESH::SelectionProxy::groups() const
 {
-  QList<SMESHGUI_SelectionProxy> lst;
+  QList<SMESH::SelectionProxy> lst;
   if ( !isNull() )
   {
     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( myObject );
@@ -453,7 +979,7 @@ QList<SMESHGUI_SelectionProxy> SMESHGUI_SelectionProxy::groups() const
     {
       SMESH::ListOfGroups_var array = mesh->GetGroups();
       for ( uint i = 0 ; i < array->length(); i++ )
-        lst << SMESHGUI_SelectionProxy( array[i].in() );
+        lst << SMESH::SelectionProxy( array[i].in() );
     }
   }
   return lst;
@@ -463,7 +989,7 @@ QList<SMESHGUI_SelectionProxy> SMESHGUI_SelectionProxy::groups() const
   \brief Get element type (for group). For other mesh objects result is undefined.
   \return Group's element type.
 */
-SMESH::ElementType SMESHGUI_SelectionProxy::elementType() const
+SMESH::ElementType SMESH::SelectionProxy::groupElementType() const
 {
   SMESH::ElementType value = SMESH::ALL;
   if ( !isNull() )
@@ -479,7 +1005,7 @@ SMESH::ElementType SMESHGUI_SelectionProxy::elementType() const
   \brief Get color (for group). For other mesh objects result is undefined.
   \return Group's color.
 */
-QColor SMESHGUI_SelectionProxy::color() const
+QColor SMESH::SelectionProxy::color() const
 {
   QColor result;
   if ( !isNull() )
@@ -499,7 +1025,7 @@ QColor SMESHGUI_SelectionProxy::color() const
   \param autoCompute Compute size if it is unavailable. Defaults to \c false.
   \return Group's size.
 */
-int SMESHGUI_SelectionProxy::size( bool autoCompute ) const
+int SMESH::SelectionProxy::size( bool autoCompute ) const
 {
   // note: size is not computed for group on filter for performance reasons, see IPAL52831
   int result = -1;
@@ -527,7 +1053,7 @@ int SMESHGUI_SelectionProxy::size( bool autoCompute ) const
   \param autoCompute Compute size if it is unavailable. Defaults to \c false.
   \return Number of nodes contained in group.
 */
-int SMESHGUI_SelectionProxy::nbNodes( bool autoCompute ) const
+int SMESH::SelectionProxy::nbNodes( bool autoCompute ) const
 {
   // note: nb of nodes is not computed automatically for performance reasons
   int result = -1;
@@ -552,7 +1078,7 @@ int SMESHGUI_SelectionProxy::nbNodes( bool autoCompute ) const
   \brief Get list of nodes / elements IDs for the mesh group.
   \return List of IDs for group object; empty list for other types.
 */
-QSet<uint> SMESHGUI_SelectionProxy::ids() const
+QSet<uint> SMESH::SelectionProxy::ids() const
 {
   QSet<uint> result;
   if ( !isNull() )
@@ -569,14 +1095,14 @@ QSet<uint> SMESHGUI_SelectionProxy::ids() const
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-/// \class SMESHGUI_MeshInfo
+/// \class SMESH::MeshInfo
 /// \brief Store statistics on mesh object.
 ////////////////////////////////////////////////////////////////////////////////
 
 /*!
   \brief Constructor.
 */
-SMESHGUI_MeshInfo::SMESHGUI_MeshInfo()
+SMESH::MeshInfo::MeshInfo()
 {
 }
 
@@ -585,7 +1111,7 @@ SMESHGUI_MeshInfo::SMESHGUI_MeshInfo()
   \param type Entity type.
   \param value Number of entities.
 */
-void SMESHGUI_MeshInfo::addInfo( int type, long value )
+void SMESH::MeshInfo::addInfo( int type, long value )
 {
   myInfo[type] = value;
 }
@@ -595,7 +1121,7 @@ void SMESHGUI_MeshInfo::addInfo( int type, long value )
   \param type Entity type.
   \return Number of entities.
 */
-uint SMESHGUI_MeshInfo::info( int type ) const
+uint SMESH::MeshInfo::info( int type ) const
 {
   return myInfo.value( type, 0U );
 }
@@ -605,7 +1131,7 @@ uint SMESHGUI_MeshInfo::info( int type ) const
   \param type Entity type.
   \return Number of entities.
 */
-uint SMESHGUI_MeshInfo::operator[] ( int type )
+uint SMESH::MeshInfo::operator[] ( int type )
 {
   return (uint)info( type );
 }
@@ -616,7 +1142,7 @@ uint SMESHGUI_MeshInfo::operator[] ( int type )
   \param toType Upper entity type.
   \return Number of entities.
 */
-uint SMESHGUI_MeshInfo::count( int fromType, int toType ) const
+uint SMESH::MeshInfo::count( int fromType, int toType ) const
 {
   uint value = 0;
   for ( int type = fromType; type <= toType; type++ )
@@ -625,14 +1151,14 @@ uint SMESHGUI_MeshInfo::count( int fromType, int toType ) const
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-/// \class SMESHGUI_MedFileInfo
+/// \class SMESH::MedInfo
 /// \brief Provide operations over the selected object
 ////////////////////////////////////////////////////////////////////////////////
 
 /*!
   \brief Constructor.
 */
-SMESHGUI_MedFileInfo::SMESHGUI_MedFileInfo()
+SMESH::MedInfo::MedInfo()
 {
 }
 
@@ -643,7 +1169,7 @@ SMESHGUI_MedFileInfo::SMESHGUI_MedFileInfo()
 
   \return \c true if MED file info is valid; \c false otherwise.
 */
-bool SMESHGUI_MedFileInfo::isValid() const
+bool SMESH::MedInfo::isValid() const
 {
   return !myFileName.isEmpty();
 }
@@ -652,7 +1178,7 @@ bool SMESHGUI_MedFileInfo::isValid() const
   \brief Get file name for mesh imported from MED file.
   \return MED file name.
 */
-QString SMESHGUI_MedFileInfo::fileName() const
+QString SMESH::MedInfo::fileName() const
 {
   return myFileName;
 }
@@ -661,7 +1187,7 @@ QString SMESHGUI_MedFileInfo::fileName() const
   \brief Set file name for mesh imported from MED file.
   \param fileName MED file name.
 */
-void SMESHGUI_MedFileInfo::setFileName( const QString& fileName )
+void SMESH::MedInfo::setFileName( const QString& fileName )
 {
   myFileName = fileName;
 }
@@ -670,7 +1196,7 @@ void SMESHGUI_MedFileInfo::setFileName( const QString& fileName )
   \brief Get file size for mesh imported from MED file.
   \return MED file size.
 */
-uint SMESHGUI_MedFileInfo::size() const
+uint SMESH::MedInfo::size() const
 {
   return mySize;
 }
@@ -679,7 +1205,7 @@ uint SMESHGUI_MedFileInfo::size() const
   \brief Set file size for mesh imported from MED file.
   \param size MED file size.
 */
-void SMESHGUI_MedFileInfo::setSize( uint size )
+void SMESH::MedInfo::setSize( uint size )
 {
   mySize = size;
 }
@@ -688,7 +1214,7 @@ void SMESHGUI_MedFileInfo::setSize( uint size )
   \brief Get version of format for mesh imported from MED file.
   \return MED file format version.
 */
-QString SMESHGUI_MedFileInfo::version() const
+QString SMESH::MedInfo::version() const
 {
   QString v = QString( "%1" ).arg( myMajor );
   if ( myMinor > 0 || myRelease > 0 ) v += QString( ".%1" ).arg( myMinor );
@@ -703,9 +1229,223 @@ QString SMESHGUI_MedFileInfo::version() const
   \param minor Minor version number.
   \param release Release version number.
 */
-void SMESHGUI_MedFileInfo::setVersion( uint major, uint minor, uint release )
+void SMESH::MedInfo::setVersion( uint major, uint minor, uint release )
 {
   myMajor = major;
   myMinor = minor;
   myRelease = release;
 }
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class SMESH::Position
+/// \brief Describes position of mesh node or element on a reference shape.
+////////////////////////////////////////////////////////////////////////////////
+
+/*!
+  \brief Contructor. Creates invalid position.
+*/
+SMESH::Position::Position():
+  myShapeId(-1), myShapeType(-1), myU(0), myV(0), myHasU(false), myHasV(false)
+{
+}
+
+/*!
+  \brief Check if position is valid.
+  \return \c true if position is valid; \c false otherwise.
+*/
+bool SMESH::Position::isValid() const
+{
+  return myShapeId > 0 && myShapeType != -1;
+}
+
+/*!
+  \brief Get reference shape ID.
+  \return Shape / sub-shape ID.
+*/
+int SMESH::Position::shapeId() const
+{
+  return myShapeId;
+}
+
+/*!
+  \brief Set reference shape ID.
+  \param id Shape / sub-shape ID.
+*/
+void SMESH::Position::setShapeId( int id )
+{
+  myShapeId = id;
+}
+
+/*!
+  \brief Get reference shape type.
+  \return Shape type.
+*/
+int SMESH::Position::shapeType() const
+{
+  return myShapeType;
+}
+
+/*!
+  \brief Set reference shape type.
+  \param type Shape type.
+*/
+void SMESH::Position::setShapeType( int type )
+{
+  myShapeType = type;
+}
+
+/*!
+  \brief Check if there is U position on a shape.
+  \return \c true if U position is valid; \c false otherwise.
+*/
+bool SMESH::Position::hasU() const
+{
+  return myHasU;
+}
+
+/*!
+  \brief Get U position on a shape.
+  \return U position.
+*/
+double SMESH::Position::u() const
+{
+  return myU;
+}
+
+/*!
+  \brief Set U position on a shape.
+  \parm u U position.
+*/
+void SMESH::Position::setU( double u )
+{
+  myU = u;
+  myHasU = true;
+}
+
+/*!
+  \brief Check if there is V position on a shape.
+  \return \c true if V position is valid; \c false otherwise.
+*/
+bool SMESH::Position::hasV() const
+{
+  return myHasV;
+}
+
+/*!
+  \brief Get V position on a shape.
+  \return V position.
+*/
+double SMESH::Position::v() const
+{
+  return myV;
+}
+
+/*!
+  \brief Set V position on a shape.
+  \parm v V position.
+*/
+void SMESH::Position::setV( double v)
+{
+  myV = v;
+  myHasV = true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class SMESH::XYZ
+/// \brief Simple structure to manage 3D coordinate.
+////////////////////////////////////////////////////////////////////////////////
+
+/*!
+  \brief Default constructor.
+*/
+SMESH::XYZ::XYZ()
+{
+  myX = myY = myZ = 0.0;
+}
+
+/*!
+  \brief Base constructor.
+  \param parameter x X coordinate.
+  \param parameter y Y coordinate.
+  \param parameter z Z coordinate.
+*/
+SMESH::XYZ::XYZ( double x, double y, double z )
+{
+  myX = x;
+  myY = y;
+  myZ = z;
+}
+
+/*!
+  \brief Construction from geometrical point.
+  \param parameter p Geometrical point.
+*/
+SMESH::XYZ::XYZ( const gp_XYZ& p )
+{
+  myX = p.X();
+  myY = p.Y();
+  myZ = p.Z();
+}
+
+/*!
+  \brief Add a point.
+  \param parameter x X coordinate.
+  \param parameter y Y coordinate.
+  \param parameter z Z coordinate.
+*/
+void SMESH::XYZ::add( double x, double y, double z )
+{
+  myX += x;
+  myY += y;
+  myZ += z;
+}
+
+/*!
+  \brief Divide point to given coefficient.
+  \param parameter a Divider coefficient.
+*/
+void SMESH::XYZ::divide( double a )
+{
+  if ( a != 0.)
+  {
+    myX /= a;
+    myY /= a;
+    myZ /= a;
+  }
+}
+
+/*!
+  \brief Get X coordinate.
+  \return X coordinate.
+*/
+double SMESH::XYZ::x() const
+{
+  return myX;
+}
+
+/*!
+  \brief Get Y coordinate.
+  \return Y coordinate.
+*/
+double SMESH::XYZ::y() const
+{
+  return myY;
+}
+
+/*!
+  \brief Get Z coordinate.
+  \return Z coordinate.
+*/
+double SMESH::XYZ::z() const
+{
+  return myZ;
+}
+
+/*!
+  \brief Conversion to geometrical point.
+  \return Geometrical point.
+*/
+SMESH::XYZ::operator gp_XYZ() const
+{
+  return gp_XYZ( myX, myY, myZ );
+}
index 8301c2576a292015655e4afa24662ff2d2bb55e9..63d479de007d3c499e6700b8e9ee3fad2809e6c5 100644 (file)
@@ -20,8 +20,8 @@
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
-#ifndef SMESHGUI_OBJECTPROXY_H
-#define SMESHGUI_OBJECTPROXY_H
+#ifndef SMESHGUI_SELECTIONPROXY_H
+#define SMESHGUI_SELECTIONPROXY_H
 
 #include "SMESH_SMESHGUI.hxx"
 
 #include CORBA_SERVER_HEADER(GEOM_Gen)
 
 #include <QColor>
+#include <QList>
 #include <QMap>
 #include <QSet>
 #include <QString>
 
-class SMESH_Actor;
-
-class SMESHGUI_EXPORT SMESHGUI_MeshInfo
-{
-  QMap<int, long> myInfo;
+#include <gp_XYZ.hxx>
 
-public:
-  SMESHGUI_MeshInfo();
-
-  void addInfo( int, long );
-  uint info( int ) const;
-  uint operator[] ( int );
-  uint count( int, int ) const;
-};
+class SMESH_Actor;
 
-class SMESHGUI_EXPORT SMESHGUI_MedFileInfo
+namespace SMESH
 {
-  QString myFileName;
-  uint mySize;
-  uint myMajor, myMinor, myRelease;
-
-public:
-  SMESHGUI_MedFileInfo();
-
-  bool isValid() const;
-  QString fileName() const;
-  void setFileName( const QString& );
-  uint size() const;
-  void setSize( uint );
-  QString version() const;
-  void setVersion( uint, uint, uint );
-};
-
-class SMESHGUI_EXPORT SMESHGUI_SelectionProxy
-{
-  Handle(SALOME_InteractiveObject) myIO;
-  SMESH::SMESH_IDSource_var myObject;
-  SMESH_Actor* myActor;
-  bool myDirty;
-
-public:
-  enum Type
+  class SMESHGUI_EXPORT MeshInfo
   {
-    Unknown,
-    Mesh,
-    Submesh,
-    Group,
-    GroupStd,
-    GroupGeom,
-    GroupFilter
+    QMap<int, long> myInfo;
+  public:
+    MeshInfo();
+    uint info( int ) const;
+    uint operator[] ( int );
+    uint count( int, int ) const;
+  private:
+    void addInfo( int, long );
+    friend class SelectionProxy;
   };
 
-  SMESHGUI_SelectionProxy();
-  SMESHGUI_SelectionProxy( const Handle(SALOME_InteractiveObject)& );
-  SMESHGUI_SelectionProxy( SMESH::SMESH_IDSource_ptr );
-  SMESHGUI_SelectionProxy( const SMESHGUI_SelectionProxy& );
-
-  SMESHGUI_SelectionProxy& operator= ( const SMESHGUI_SelectionProxy& );
-  bool operator== ( const SMESHGUI_SelectionProxy& );
-
-  void refresh();
-
-  bool isNull() const;
-  operator bool() const;
-
-  SMESH::SMESH_IDSource_ptr object() const;
-  const Handle(SALOME_InteractiveObject)& io() const;
-  SMESH_Actor* actor() const;
-
-  bool isValid() const;
-  void load();
+  class SMESHGUI_EXPORT MedInfo
+  {
+    QString myFileName;
+    uint mySize;
+    uint myMajor, myMinor, myRelease;
+  public:
+    MedInfo();
+    bool isValid() const;
+    QString fileName() const;
+    uint size() const;
+    QString version() const;
+  private:
+    void setFileName( const QString& );
+    void setSize( uint );
+    void setVersion( uint, uint, uint );
+    friend class SelectionProxy;
+  };
 
-  QString name() const;
-  Type type() const;
-  SMESHGUI_MeshInfo meshInfo() const;
-  SMESHGUI_SelectionProxy mesh() const;
-  bool hasShapeToMesh() const;
-  GEOM::GEOM_Object_ptr shape() const;
-  QString shapeName() const;
-  int shapeType() const;
+  class SMESHGUI_EXPORT Position
+  {
+    int myShapeId;
+    int myShapeType;
+    double myU, myV;
+    bool myHasU, myHasV;
+  public:
+    Position();
+    bool isValid() const;
+    int shapeId() const;
+    int shapeType() const;
+    bool hasU() const;
+    double u() const;
+    bool hasV() const;
+    double v() const;
+  private:
+    void setShapeId( int );
+    void setShapeType( int );
+    void setU( double );
+    void setV( double );
+    friend class SelectionProxy;
+  };
 
-  bool isMeshLoaded() const;
-  SMESHGUI_MedFileInfo medFileInfo() const;
-  QList<SMESHGUI_SelectionProxy> submeshes() const;
-  QList<SMESHGUI_SelectionProxy> groups() const;
+  class XYZ
+  {
+    double myX, myY, myZ;
+  public:
+    XYZ();
+    XYZ( double, double, double );
+    XYZ( const gp_XYZ& );
+    void add( double, double, double );
+    void divide( double );
+    double x() const;
+    double y() const;
+    double z() const;
+    operator gp_XYZ() const;
+  };
 
-  SMESH::ElementType elementType() const;
-  QColor color() const;
-  int size( bool = false ) const;
-  int nbNodes( bool = false ) const;
-  QSet<uint> ids() const;
+  typedef QMap< int, QList<int> > Connectivity;
 
-private:
-  void init();
-};
+  class SMESHGUI_EXPORT SelectionProxy
+  {
+    Handle(SALOME_InteractiveObject) myIO;
+    SMESH::SMESH_IDSource_var myObject;
+    SMESH_Actor* myActor;
+    bool myDirty;
+
+  public:
+    enum Type
+    {
+      Unknown,
+      Mesh,
+      Submesh,
+      Group,
+      GroupStd,
+      GroupGeom,
+      GroupFilter
+    };
+
+    // construction
+    SelectionProxy();
+    SelectionProxy( const Handle(SALOME_InteractiveObject)& );
+    SelectionProxy( SMESH::SMESH_IDSource_ptr );
+    SelectionProxy( const SelectionProxy& );
+
+    SelectionProxy& operator= ( const SelectionProxy& );
+
+    // comparison
+    bool operator== ( const SelectionProxy& );
+
+    // general purpose methods
+    void refresh();
+
+    bool isNull() const;
+    operator bool() const;
+
+    SMESH::SMESH_IDSource_ptr object() const;
+    const Handle(SALOME_InteractiveObject)& io() const;
+    SMESH_Actor* actor() const;
+
+    bool isValid() const;
+    void load();
+
+    // methods common to all types of proxy
+    QString name() const;
+    Type type() const;
+    MeshInfo meshInfo() const;
+    SelectionProxy mesh() const;
+    bool hasShapeToMesh() const;
+    GEOM::GEOM_Object_ptr shape() const;
+    QString shapeName() const;
+    int shapeType() const;
+    bool isMeshLoaded() const;
+
+    bool hasNode( int );
+    bool nodeCoordinates( int, XYZ& );
+    bool nodeConnectivity( int, Connectivity& );
+    bool nodePosition( int, Position& );
+    QList<SelectionProxy> nodeGroups( int ) const;
+
+    bool hasElement( int );
+    SMESH::ElementType elementType( int ) const;
+    int elementEntityType( int ) const;
+    bool elementConnectivity( int, Connectivity& );
+    bool elementPosition( int, Position& );
+    bool elementGravityCenter( int, XYZ& );
+    bool elementNormal( int, XYZ& );
+    bool elementControl( int, int, double, double& ) const;
+    QList<SelectionProxy> elementGroups( int ) const;
+
+    // methods that work for mesh only
+    MedInfo medFileInfo() const;
+    QList<SelectionProxy> submeshes() const;
+    QList<SelectionProxy> groups() const;
+
+    // methods that work for group only
+    SMESH::ElementType groupElementType() const;
+    QColor color() const;
+    int size( bool = false ) const;
+    int nbNodes( bool = false ) const;
+    QSet<uint> ids() const;
+
+  private:
+    void init();
+  };
+}
 
-#endif // SMESHGUI_OBJECTPROXY_H
+#endif // SMESHGUI_SELECTIONPROXY_H
index 86901755b64926b85906c8b08da00d5615f72ff9..6cd28bc452f53e9b7ff8e96de3a99d12f602321b 100644 (file)
@@ -1924,7 +1924,7 @@ add the exported data to its contents?</translation>
         <translation>Height:</translation>
     </message>
     <message>
-        <source>SMESH_HEXAS</source>
+        <source>SMESH_HEXAHEDRON</source>
         <translation>Hexahedron</translation>
     </message>
     <message>
@@ -2770,7 +2770,7 @@ Check algorithm documentation for supported geometry</translation>
         <translation>Symmetry</translation>
     </message>
     <message>
-        <source>SMESH_TETRAS</source>
+        <source>SMESH_TETRAHEDRON</source>
         <translation>Tetrahedron</translation>
     </message>
     <message>
@@ -4523,6 +4523,10 @@ It can&apos;t be deleted </translation>
         <source>SMESH_3D_ALGO_GROUP_ADVANCED</source>
         <translation>Advanced</translation>
     </message>
+    <message>
+        <source>SMESH_HEX_PRISM</source>
+        <translation>Hexagonal Prism</translation>
+    </message>
 </context>
 <context>
     <name>SMESHGUI_FieldSelectorWdg</name>
index 655ad7565bb1c5c1f9904a10f5a5db938bbd32b1..205af6c8aaf4b897a63605e01b72a7058f42cc2f 100755 (executable)
@@ -1895,7 +1895,7 @@ les données exportées ?</translation>
         <translation>Hauteur :</translation>
     </message>
     <message>
-        <source>SMESH_HEXAS</source>
+        <source>SMESH_HEXAHEDRON</source>
         <translation>Hexaèdre</translation>
     </message>
     <message>
@@ -2733,7 +2733,7 @@ Référez-vous à la documentation sur l&apos;algorithme et la géométrie suppo
         <translation>Symétrie</translation>
     </message>
     <message>
-        <source>SMESH_TETRAS</source>
+        <source>SMESH_TETRAHEDRON</source>
         <translation>Tétraèdre</translation>
     </message>
     <message>
@@ -4471,6 +4471,10 @@ Il ne peut pas être supprimé.</translation>
         <source>SMESH_3D_ALGO_GROUP_ADVANCED</source>
         <translation>Avancé</translation>
     </message>
+    <message>
+        <source>SMESH_HEX_PRISM</source>
+        <translation>Prisme hexagonal</translation>
+    </message>
 </context>
 <context>
     <name>SMESHGUI_FieldSelectorWdg</name>
index a5dfc977dc4c44062f5ece815c1f5405de44c4b8..ca15aebf9f0f41993c20c84542e5bb1ac6beaeb5 100644 (file)
       <translation>高さ:</translation>
     </message>
     <message>
-      <source>SMESH_HEXAS</source>
+      <source>SMESH_HEXAHEDRON</source>
       <translation>六面体</translation>
     </message>
     <message>
       <translation>オブジェクトの反転</translation>
     </message>
     <message>
-      <source>SMESH_TETRAS</source>
+      <source>SMESH_TETRAHEDRON</source>
       <translation>四面体</translation>
     </message>
     <message>
       <source>SMESH_3D_ALGO_GROUP_ADVANCED</source>
       <translation>アドバンス</translation>
     </message>
+    <message>
+      <source>SMESH_HEX_PRISM</source>
+      <translation>六角形プリズム</translation>
+    </message>
   </context>
   <context>
     <name>SMESHGUI_FieldSelectorWdg</name>