--- /dev/null
+// Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File : SMESHGUI_Measurements.cxx
+// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+
+#include "SMESHGUI_Measurements.h"
+
+#include "SMESH_Actor.h"
+#include "SMESHGUI.h"
+#include "SMESHGUI_IdValidator.h"
+#include "SMESHGUI_Utils.h"
+#include "SMESHGUI_VTKUtils.h"
+#include <SMESH_TypeFilter.hxx>
+#include <SMESH_LogicalFilter.hxx>
+
+#include <LightApp_SelectionMgr.h>
+#include <SUIT_OverrideCursor.h>
+#include <SUIT_ResourceMgr.h>
+#include <SVTK_ViewWindow.h>
+#include <SALOME_ListIteratorOfListIO.hxx>
+
+#include <QButtonGroup>
+#include <QGridLayout>
+#include <QGroupBox>
+#include <QHBoxLayout>
+#include <QKeyEvent>
+#include <QLabel>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QRadioButton>
+#include <QTabWidget>
+#include <QVBoxLayout>
+
+#include <SALOMEconfig.h>
+#include CORBA_SERVER_HEADER(SMESH_MeshEditor)
+#include CORBA_SERVER_HEADER(SMESH_Measurements)
+
+const int SPACING = 6; // layout spacing
+const int MARGIN = 9; // layout margin
+const int MAX_NB_FOR_EDITOR = 40; // max nb of items in the ID list editor field
+
+// Uncomment as soon as elements are supported by Min Distance operation
+//#define MINDIST_ENABLE_ELEMENT
+
+// Uncomment as soon as objects are supported by Min Distance operation
+//#define MINDIST_ENABLE_OBJECT
+
+/*!
+ \class SMESHGUI_MinDistance
+ \brief Minimum distance measurement widget.
+
+ Widget to calculate minimum distance between two objects.
+*/
+
+/*!
+ \brief Constructor.
+ \param parent parent widget
+*/
+SMESHGUI_MinDistance::SMESHGUI_MinDistance( QWidget* parent )
+: QWidget( parent ), myCurrentTgt( FirstTgt ), myFirstActor( 0 ), mySecondActor( 0 )
+{
+ QGroupBox* aFirstTgtGrp = new QGroupBox( tr( "FIRST_TARGET" ), this );
+ QRadioButton* aFNode = new QRadioButton( tr( "NODE" ), aFirstTgtGrp );
+ QRadioButton* aFElem = new QRadioButton( tr( "ELEMENT" ), aFirstTgtGrp );
+ QRadioButton* aFObject = new QRadioButton( tr( "OBJECT" ), aFirstTgtGrp );
+ myFirstTgt = new QLineEdit( aFirstTgtGrp );
+
+ QGridLayout* fl = new QGridLayout( aFirstTgtGrp );
+ fl->setMargin( MARGIN );
+ fl->setSpacing( SPACING );
+ fl->addWidget( aFNode, 0, 0 );
+ fl->addWidget( aFElem, 0, 1 );
+ fl->addWidget( aFObject, 0, 2 );
+ fl->addWidget( myFirstTgt, 1, 0, 1, 3 );
+
+ myFirst = new QButtonGroup( this );
+ myFirst->addButton( aFNode, NodeTgt );
+ myFirst->addButton( aFElem, ElementTgt );
+ myFirst->addButton( aFObject, ObjectTgt );
+
+ QGroupBox* aSecondTgtGrp = new QGroupBox( tr( "SECOND_TARGET" ), this );
+ QRadioButton* aSOrigin = new QRadioButton( tr( "ORIGIN" ), aSecondTgtGrp );
+ QRadioButton* aSNode = new QRadioButton( tr( "NODE" ), aSecondTgtGrp );
+ QRadioButton* aSElem = new QRadioButton( tr( "ELEMENT" ), aSecondTgtGrp );
+ QRadioButton* aSObject = new QRadioButton( tr( "OBJECT" ), aSecondTgtGrp );
+ mySecondTgt = new QLineEdit( aSecondTgtGrp );
+
+ QGridLayout* sl = new QGridLayout( aSecondTgtGrp );
+ sl->setMargin( MARGIN );
+ sl->setSpacing( SPACING );
+ sl->addWidget( aSOrigin, 0, 0 );
+ sl->addWidget( aSNode, 0, 1 );
+ sl->addWidget( aSElem, 0, 2 );
+ sl->addWidget( aSObject, 0, 3 );
+ sl->addWidget( mySecondTgt, 1, 0, 1, 4 );
+
+ mySecond = new QButtonGroup( this );
+ mySecond->addButton( aSOrigin, OriginTgt );
+ mySecond->addButton( aSNode, NodeTgt );
+ mySecond->addButton( aSElem, ElementTgt );
+ mySecond->addButton( aSObject, ObjectTgt );
+
+ QPushButton* aCompute = new QPushButton( tr( "COMPUTE" ), this );
+
+ QGroupBox* aResults = new QGroupBox( tr( "RESULT" ), this );
+ QLabel* aDxLab = new QLabel( "dX", aResults );
+ myDX = new QLineEdit( aResults );
+ QLabel* aDyLab = new QLabel( "dY", aResults );
+ myDY = new QLineEdit( aResults );
+ QLabel* aDzLab = new QLabel( "dZ", aResults );
+ myDZ = new QLineEdit( aResults );
+ QLabel* aDistLab = new QLabel( tr( "DISTANCE" ), aResults );
+ myDistance = new QLineEdit( aResults );
+
+ QGridLayout* rl = new QGridLayout( aResults );
+ rl->setMargin( MARGIN );
+ rl->setSpacing( SPACING );
+ rl->addWidget( aDxLab, 0, 0 );
+ rl->addWidget( myDX, 0, 1 );
+ rl->addWidget( aDyLab, 1, 0 );
+ rl->addWidget( myDY, 1, 1 );
+ rl->addWidget( aDzLab, 2, 0 );
+ rl->addWidget( myDZ, 2, 1 );
+ rl->addWidget( aDistLab, 0, 2 );
+ rl->addWidget( myDistance, 0, 3 );
+
+ QGridLayout* l = new QGridLayout( this );
+ l->setMargin( MARGIN );
+ l->setSpacing( SPACING );
+
+ l->addWidget( aFirstTgtGrp, 0, 0, 1, 2 );
+ l->addWidget( aSecondTgtGrp, 1, 0, 1, 2 );
+ l->addWidget( aCompute, 2, 0 );
+ l->addWidget( aResults, 3, 0, 1, 2 );
+ l->setColumnStretch( 1, 5 );
+ l->setRowStretch( 4, 5 );
+
+ aFNode->setChecked( true );
+ aSOrigin->setChecked( true );
+#ifndef MINDIST_ENABLE_ELEMENT
+ aFElem->setEnabled( false ); // NOT AVAILABLE YET
+ aSElem->setEnabled( false ); // NOT AVAILABLE YET
+#endif
+#ifndef MINDIST_ENABLE_OBJECT
+ aFObject->setEnabled( false ); // NOT AVAILABLE YET
+ aSObject->setEnabled( false ); // NOT AVAILABLE YET
+#endif
+ myDX->setReadOnly( true );
+ myDY->setReadOnly( true );
+ myDZ->setReadOnly( true );
+ myDistance->setReadOnly( true );
+
+ myValidator = new SMESHGUI_IdValidator( this, 1 );
+
+ myFirstTgt->installEventFilter( this );
+ mySecondTgt->installEventFilter( this );
+
+ connect( myFirst, SIGNAL( buttonClicked( int ) ), this, SLOT( firstChanged() ) );
+ connect( mySecond, SIGNAL( buttonClicked( int ) ), this, SLOT( secondChanged() ) );
+ connect( aCompute, SIGNAL( clicked() ), this, SLOT( compute() ) );
+ connect( myFirstTgt, SIGNAL( textEdited( QString ) ), this, SLOT( firstEdited() ) );
+ connect( mySecondTgt, SIGNAL( textEdited( QString ) ), this, SLOT( secondEdited() ) );
+
+ QList<SUIT_SelectionFilter*> filters;
+ filters.append( new SMESH_TypeFilter( MESHorSUBMESH ) );
+ filters.append( new SMESH_TypeFilter( GROUP ) );
+ myFilter = new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR );
+
+ clear();
+
+ //setTarget( FirstTgt );
+}
+
+/*!
+ \brief Destructor
+*/
+SMESHGUI_MinDistance::~SMESHGUI_MinDistance()
+{
+}
+
+/*!
+ \brief Event filter
+ \param o object
+ \param o event
+ \return \c true if event is filtered or \c false otherwise
+*/
+bool SMESHGUI_MinDistance::eventFilter( QObject* o, QEvent* e )
+{
+ if ( e->type() == QEvent::FocusIn ) {
+ if ( o == myFirstTgt )
+ setTarget( FirstTgt );
+ else if ( o == mySecondTgt )
+ setTarget( SecondTgt );
+ }
+ return QWidget::eventFilter( o, e );
+}
+
+/*!
+ \brief Setup selection mode depending on the current widget state
+*/
+void SMESHGUI_MinDistance::updateSelection()
+{
+ LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
+
+ disconnect( selMgr, 0, this, 0 );
+ selMgr->clearFilters();
+
+ bool nodeMode = ( myCurrentTgt == FirstTgt && myFirst->checkedId() == NodeTgt ) ||
+ ( myCurrentTgt == SecondTgt && mySecond->checkedId() == NodeTgt );
+ bool elemMode = ( myCurrentTgt == FirstTgt && myFirst->checkedId() == ElementTgt ) ||
+ ( myCurrentTgt == SecondTgt && mySecond->checkedId() == ElementTgt );
+ bool objMode = ( myCurrentTgt == FirstTgt && myFirst->checkedId() == ObjectTgt ) ||
+ ( myCurrentTgt == SecondTgt && mySecond->checkedId() == ObjectTgt ) ||
+ ( myCurrentTgt == NoTgt );
+
+ if ( nodeMode ) {
+ SMESH::SetPointRepresentation( true );
+ if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
+ aViewWindow->SetSelectionMode( NodeSelection );
+ }
+ else if ( elemMode ) {
+ SMESH::SetPointRepresentation( false );
+ if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
+ aViewWindow->SetSelectionMode( CellSelection );
+ }
+ else if ( objMode ) {
+ SMESH::SetPointRepresentation( false );
+ if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
+ aViewWindow->SetSelectionMode( ActorSelection );
+ selMgr->installFilter( myFilter );
+ }
+
+ connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( selectionChanged() ) );
+
+ if ( myCurrentTgt == FirstTgt )
+ firstEdited();
+ else if ( myCurrentTgt == SecondTgt )
+ secondEdited();
+
+ //selectionChanged();
+}
+
+/*!
+ \brief Deactivate widget
+*/
+void SMESHGUI_MinDistance::deactivate()
+{
+ disconnect( SMESHGUI::selectionMgr(), 0, this, 0 );
+}
+
+/*!
+ \brief Set current target for selection
+ \param target new target ID
+*/
+void SMESHGUI_MinDistance::setTarget( int target )
+{
+ if ( myCurrentTgt != target ) {
+ myCurrentTgt = target;
+ updateSelection();
+ }
+}
+
+/*!
+ \brief Called when selection is changed
+*/
+void SMESHGUI_MinDistance::selectionChanged()
+{
+ SUIT_OverrideCursor wc;
+
+ SALOME_ListIO selected;
+ SMESHGUI::selectionMgr()->selectedObjects( selected );
+
+ if ( selected.Extent() == 1 ) {
+ Handle(SALOME_InteractiveObject) IO = selected.First();
+ SMESH::SMESH_IDSource_var obj = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( IO );
+ if ( !CORBA::is_nil( obj ) ) {
+ if ( myCurrentTgt == FirstTgt ) {
+ myFirstSrc = obj;
+ myFirstActor = SMESH::FindActorByEntry( IO->getEntry() );
+ if ( myFirst->checkedId() == ObjectTgt ) {
+ QString aName;
+ SMESH::GetNameOfSelectedIObjects( SMESHGUI::selectionMgr(), aName );
+ myFirstTgt->setText( aName );
+ }
+ else {
+ SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector();
+ QString ID;
+ int nb = 0;
+ if ( myFirstActor && selector ) {
+ nb = myFirst->checkedId() == NodeTgt ?
+ SMESH::GetNameOfSelectedElements( selector, IO, ID ) :
+ SMESH::GetNameOfSelectedNodes( selector, IO, ID );
+ }
+ if ( nb == 1 )
+ myFirstTgt->setText( ID.trimmed() );
+ else
+ myFirstTgt->clear();
+ }
+ }
+ else if ( myCurrentTgt == SecondTgt ) {
+ mySecondSrc = obj;
+ mySecondActor = SMESH::FindActorByEntry( IO->getEntry() );
+ if ( mySecond->checkedId() == ObjectTgt ) {
+ QString aName;
+ SMESH::GetNameOfSelectedIObjects( SMESHGUI::selectionMgr(), aName );
+ mySecondTgt->setText( aName );
+ }
+ else {
+ SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector();
+ QString ID;
+ int nb = 0;
+ if ( mySecondActor && selector ) {
+ nb = mySecond->checkedId() == NodeTgt ?
+ SMESH::GetNameOfSelectedElements( selector, IO, ID ) :
+ SMESH::GetNameOfSelectedNodes( selector, IO, ID );
+ }
+ if ( nb == 1 )
+ mySecondTgt->setText( ID.trimmed() );
+ else
+ mySecondTgt->clear();
+ }
+ }
+ }
+ }
+}
+
+/*!
+ \brief Called when first target mode is changed by the user
+*/
+void SMESHGUI_MinDistance::firstChanged()
+{
+ myFirstTgt->clear();
+ myFirstTgt->setReadOnly( myFirst->checkedId() == ObjectTgt );
+ myFirstTgt->setValidator( myFirst->checkedId() == ObjectTgt ? 0 : myValidator );
+ setTarget( FirstTgt );
+ updateSelection();
+ clear();
+}
+
+/*!
+ \brief Called when second target mode is changed by the user
+*/
+void SMESHGUI_MinDistance::secondChanged()
+{
+ mySecondTgt->setEnabled( mySecond->checkedId() != OriginTgt );
+ mySecondTgt->setReadOnly( mySecond->checkedId() == ObjectTgt );
+ mySecondTgt->setValidator( mySecond->checkedId() == ObjectTgt ? 0 : myValidator );
+ mySecondTgt->clear();
+ setTarget( mySecond->checkedId() != OriginTgt ? SecondTgt : NoTgt );
+ updateSelection();
+ clear();
+}
+
+/*!
+ \brief Called when first target is edited by the user
+*/
+void SMESHGUI_MinDistance::firstEdited()
+{
+ setTarget( FirstTgt );
+ clear();
+ SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector();
+ if ( myFirstActor && selector ) {
+ Handle(SALOME_InteractiveObject) IO = myFirstActor->getIO();
+ if ( myFirst->checkedId() == NodeTgt || myFirst->checkedId() == ElementTgt ) {
+ TColStd_MapOfInteger ID;
+ ID.Add( myFirstTgt->text().toLong() );
+ selector->AddOrRemoveIndex( IO, ID, false );
+ }
+ if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
+ aViewWindow->highlight( IO, true, true );
+ }
+}
+
+/*!
+ \brief Called when second target is edited by the user
+*/
+void SMESHGUI_MinDistance::secondEdited()
+{
+ setTarget( SecondTgt );
+ clear();
+ SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector();
+ if ( mySecondActor && selector ) {
+ Handle(SALOME_InteractiveObject) IO = mySecondActor->getIO();
+ if ( mySecond->checkedId() == NodeTgt || mySecond->checkedId() == ElementTgt ) {
+ TColStd_MapOfInteger ID;
+ ID.Add( mySecondTgt->text().toLong() );
+ selector->AddOrRemoveIndex( IO, ID, false );
+ }
+ if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
+ aViewWindow->highlight( IO, true, true );
+ }
+}
+
+/*!
+ \brief Compute the minimum distance between targets
+*/
+void SMESHGUI_MinDistance::compute()
+{
+ SUIT_OverrideCursor wc;
+ SMESH::SMESH_IDSource_var s1;
+ SMESH::SMESH_IDSource_var s2;
+ bool isOrigin = mySecond->checkedId() == OriginTgt;
+
+ // process first target
+ if ( !CORBA::is_nil( myFirstSrc ) ) {
+ if ( myFirst->checkedId() == NodeTgt || myFirst->checkedId() == ElementTgt ) {
+ SMESH::SMESH_Mesh_var m = myFirstSrc->GetMesh();
+ long id = myFirstTgt->text().toLong();
+ if ( !CORBA::is_nil( m ) && id ) {
+ SMESH::long_array_var ids = new SMESH::long_array();
+ ids->length( 1 );
+ ids[0] = id;
+ SMESH::SMESH_MeshEditor_var me = m->GetMeshEditor();
+ s1 = me->MakeIDSource( ids.in(), myFirst->checkedId() == NodeTgt ? SMESH::NODE : SMESH::FACE );
+ }
+ }
+ else {
+ s1 = myFirstSrc;
+ }
+ }
+
+ // process second target
+ if ( !CORBA::is_nil( mySecondSrc ) ) {
+ if ( mySecond->checkedId() == NodeTgt || mySecond->checkedId() == ElementTgt ) {
+ SMESH::SMESH_Mesh_var m = mySecondSrc->GetMesh();
+ long id = mySecondTgt->text().toLong();
+ if ( !CORBA::is_nil( m ) && id ) {
+ SMESH::long_array_var ids = new SMESH::long_array();
+ ids->length( 1 );
+ ids[0] = id;
+ SMESH::SMESH_MeshEditor_var me = m->GetMeshEditor();
+ s2 = me->MakeIDSource( ids.in(), mySecond->checkedId() == NodeTgt ? SMESH::NODE : SMESH::FACE );
+ }
+ }
+ else {
+ s2 = mySecondSrc;
+ }
+ }
+
+ if ( !CORBA::is_nil( s1 ) && ( !CORBA::is_nil( s2 ) || isOrigin ) ) {
+ int precision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
+ SMESH::Measurements_var measure = SMESHGUI::GetSMESHGen()->CreateMeasurements();
+ SMESH::Measure result = measure->MinDistance( s1.in(), s2.in() );
+ measure->Destroy();
+ myDX->setText( QString::number( result.minX, precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
+ myDY->setText( QString::number( result.minY, precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
+ myDZ->setText( QString::number( result.minZ, precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
+ myDistance->setText( QString::number( result.value, precision > 0 ? 'f' : 'g', qAbs( precision ) ) );
+ }
+ else {
+ clear();
+ }
+}
+
+/*!
+ \brief Reset the widget to the initial state (nullify result fields)
+*/
+void SMESHGUI_MinDistance::clear()
+{
+ myDX->clear();
+ myDY->clear();
+ myDZ->clear();
+ myDistance->clear();
+}
+
+/*!
+ \class SMESHGUI_BoundingBox
+ \brief Bounding box measurement widget.
+
+ Widget to calculate bounding box of the selected object(s).
+*/
+
+/*!
+ \brief Constructor.
+ \param parent parent widget
+*/
+SMESHGUI_BoundingBox::SMESHGUI_BoundingBox( QWidget* parent )
+: QWidget( parent ), myActor( 0 )
+{
+ QGroupBox* aSourceGrp = new QGroupBox( tr( "SOURCE" ), this );
+ QRadioButton* aObjects = new QRadioButton( tr( "OBJECTS" ), aSourceGrp );
+ QRadioButton* aNodes = new QRadioButton( tr( "NODES" ), aSourceGrp );
+ QRadioButton* aElements = new QRadioButton( tr( "ELEMENTS" ), aSourceGrp );
+ mySource = new QLineEdit( aSourceGrp );
+
+ QGridLayout* fl = new QGridLayout( aSourceGrp );
+ fl->setMargin( MARGIN );
+ fl->setSpacing( SPACING );
+ fl->addWidget( aObjects, 0, 0 );
+ fl->addWidget( aNodes, 0, 1 );
+ fl->addWidget( aElements, 0, 2 );
+ fl->addWidget( mySource, 1, 0, 1, 3 );
+
+ mySourceMode = new QButtonGroup( this );
+ mySourceMode->addButton( aObjects, ObjectsSrc );
+ mySourceMode->addButton( aNodes, NodesSrc );
+ mySourceMode->addButton( aElements, ElementsSrc );
+
+ QPushButton* aCompute = new QPushButton( tr( "COMPUTE" ), this );
+
+ QGroupBox* aResults = new QGroupBox( tr( "RESULT" ), this );
+ QLabel* aXminLab = new QLabel( "Xmin", aResults );
+ myXmin = new QLineEdit( aResults );
+ QLabel* aXmaxLab = new QLabel( "Xmax", aResults );
+ myXmax = new QLineEdit( aResults );
+ QLabel* aDxLab = new QLabel( "dX", aResults );
+ myDX = new QLineEdit( aResults );
+ QLabel* aYminLab = new QLabel( "Ymin", aResults );
+ myYmin = new QLineEdit( aResults );
+ QLabel* aYmaxLab = new QLabel( "Ymax", aResults );
+ myYmax = new QLineEdit( aResults );
+ QLabel* aDyLab = new QLabel( "dY", aResults );
+ myDY = new QLineEdit( aResults );
+ QLabel* aZminLab = new QLabel( "Zmin", aResults );
+ myZmin = new QLineEdit( aResults );
+ QLabel* aZmaxLab = new QLabel( "Zmax", aResults );
+ myZmax = new QLineEdit( aResults );
+ QLabel* aDzLab = new QLabel( "dZ", aResults );
+ myDZ = new QLineEdit( aResults );
+
+ QGridLayout* rl = new QGridLayout( aResults );
+ rl->setMargin( MARGIN );
+ rl->setSpacing( SPACING );
+ rl->addWidget( aXminLab, 0, 0 );
+ rl->addWidget( myXmin, 0, 1 );
+ rl->addWidget( aXmaxLab, 0, 2 );
+ rl->addWidget( myXmax, 0, 3 );
+ rl->addWidget( aDxLab, 0, 4 );
+ rl->addWidget( myDX, 0, 5 );
+ rl->addWidget( aYminLab, 1, 0 );
+ rl->addWidget( myYmin, 1, 1 );
+ rl->addWidget( aYmaxLab, 1, 2 );
+ rl->addWidget( myYmax, 1, 3 );
+ rl->addWidget( aDyLab, 1, 4 );
+ rl->addWidget( myDY, 1, 5 );
+ rl->addWidget( aZminLab, 2, 0 );
+ rl->addWidget( myZmin, 2, 1 );
+ rl->addWidget( aZmaxLab, 2, 2 );
+ rl->addWidget( myZmax, 2, 3 );
+ rl->addWidget( aDzLab, 2, 4 );
+ rl->addWidget( myDZ, 2, 5 );
+
+ QGridLayout* l = new QGridLayout( this );
+ l->setMargin( MARGIN );
+ l->setSpacing( SPACING );
+
+ l->addWidget( aSourceGrp, 0, 0, 1, 2 );
+ l->addWidget( aCompute, 1, 0 );
+ l->addWidget( aResults, 2, 0, 1, 2 );
+ l->setColumnStretch( 1, 5 );
+ l->setRowStretch( 3, 5 );
+
+ aObjects->setChecked( true );
+ myXmin->setReadOnly( true );
+ myXmax->setReadOnly( true );
+ myDX->setReadOnly( true );
+ myYmin->setReadOnly( true );
+ myYmax->setReadOnly( true );
+ myDY->setReadOnly( true );
+ myZmin->setReadOnly( true );
+ myZmax->setReadOnly( true );
+ myDZ->setReadOnly( true );
+
+ myValidator = new SMESHGUI_IdValidator( this );
+
+ connect( mySourceMode, SIGNAL( buttonClicked( int ) ), this, SLOT( sourceChanged() ) );
+ connect( aCompute, SIGNAL( clicked() ), this, SLOT( compute() ) );
+ connect( mySource, SIGNAL( textEdited( QString ) ), this, SLOT( sourceEdited() ) );
+
+ QList<SUIT_SelectionFilter*> filters;
+ filters.append( new SMESH_TypeFilter( MESHorSUBMESH ) );
+ filters.append( new SMESH_TypeFilter( GROUP ) );
+ myFilter = new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR );
+
+ clear();
+}
+
+/*!
+ \brief Destructor
+*/
+SMESHGUI_BoundingBox::~SMESHGUI_BoundingBox()
+{
+}
+
+/*!
+ \brief Setup selection mode depending on the current widget state
+*/
+void SMESHGUI_BoundingBox::updateSelection()
+{
+ LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
+
+ disconnect( selMgr, 0, this, 0 );
+ selMgr->clearFilters();
+
+ bool nodeMode = mySourceMode->checkedId() == NodesSrc;
+ bool elemMode = mySourceMode->checkedId() == ElementsSrc;
+ bool objMode = mySourceMode->checkedId() == ObjectsSrc;
+
+ if ( nodeMode ) {
+ SMESH::SetPointRepresentation( true );
+ if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
+ aViewWindow->SetSelectionMode( NodeSelection );
+ }
+ else if ( elemMode ) {
+ SMESH::SetPointRepresentation( false );
+ if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
+ aViewWindow->SetSelectionMode( CellSelection );
+ }
+ else if ( objMode ) {
+ SMESH::SetPointRepresentation( false );
+ if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
+ aViewWindow->SetSelectionMode( ActorSelection );
+ selMgr->installFilter( myFilter );
+ }
+
+ connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( selectionChanged() ) );
+
+ sourceEdited();
+
+ //selectionChanged();
+}
+
+/*!
+ \brief Deactivate widget
+*/
+void SMESHGUI_BoundingBox::deactivate()
+{
+ disconnect( SMESHGUI::selectionMgr(), 0, this, 0 );
+}
+
+/*!
+ \brief Called when selection is changed
+*/
+void SMESHGUI_BoundingBox::selectionChanged()
+{
+ SUIT_OverrideCursor wc;
+
+ SALOME_ListIO selected;
+ SMESHGUI::selectionMgr()->selectedObjects( selected );
+
+ if ( selected.Extent() == 1 ) {
+ Handle(SALOME_InteractiveObject) IO = selected.First();
+ SMESH::SMESH_IDSource_var obj = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( IO );
+ if ( !CORBA::is_nil( obj ) ) {
+ mySrc.clear();
+ mySrc.append( obj );
+ myActor = SMESH::FindActorByEntry( IO->getEntry() );
+ if ( mySourceMode->checkedId() == ObjectsSrc ) {
+ QString aName;
+ SMESH::GetNameOfSelectedIObjects( SMESHGUI::selectionMgr(), aName );
+ mySource->setText( aName );
+ }
+ else {
+ SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector();
+ QString ID;
+ int nb = 0;
+ if ( myActor && selector ) {
+ nb = mySourceMode->checkedId() == NodesSrc ?
+ SMESH::GetNameOfSelectedElements( selector, IO, ID ) :
+ SMESH::GetNameOfSelectedNodes( selector, IO, ID );
+ }
+ if ( nb > 0 ) {
+ myIDs = ID.trimmed();
+ if ( nb < MAX_NB_FOR_EDITOR ) {
+ mySource->setReadOnly( false );
+ if ( mySource->validator() != myValidator )
+ mySource->setValidator( myValidator );
+ mySource->setText( ID.trimmed() );
+ }
+ else {
+ mySource->setReadOnly( true );
+ mySource->setValidator( 0 );
+ mySource->setText( tr( "SELECTED_NB_OBJ" ).arg( nb )
+ .arg( mySourceMode->checkedId() == NodesSrc ? tr( "NB_NODES" ) : tr( "NB_ELEMENTS") ) );
+ }
+ }
+ else {
+ myIDs = "";
+ mySource->clear();
+ mySource->setReadOnly( false );
+ mySource->setValidator( myValidator );
+ }
+ }
+ }
+ }
+ else if ( selected.Extent() > 1 ) {
+ myIDs = "";
+ SALOME_ListIteratorOfListIO It( selected );
+ mySrc.clear();
+ myActor = 0;
+ if ( mySourceMode->checkedId() == ObjectsSrc ) {
+ for( ; It.More(); It.Next()){
+ Handle(SALOME_InteractiveObject) IO = It.Value();
+ SMESH::SMESH_IDSource_var obj = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( IO );
+ if ( !CORBA::is_nil( obj ) ) {
+ mySrc.append( obj );
+ }
+ }
+ QString aName;
+ SMESH::GetNameOfSelectedIObjects( SMESHGUI::selectionMgr(), aName );
+ mySource->setText( aName );
+ }
+ else {
+ mySource->clear();
+ }
+ }
+}
+
+/*!
+ \brief Called when source mode is changed by the user
+*/
+void SMESHGUI_BoundingBox::sourceChanged()
+{
+ myIDs = "";
+ mySource->clear();
+ mySource->setReadOnly( mySourceMode->checkedId() == ObjectsSrc );
+ mySource->setValidator( mySourceMode->checkedId() == ObjectsSrc ? 0 : myValidator );
+ updateSelection();
+ clear();
+}
+
+/*!
+ \brief Called when source mode is edited by the user
+*/
+void SMESHGUI_BoundingBox::sourceEdited()
+{
+ clear();
+ SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector();
+ if ( myActor && selector ) {
+ Handle(SALOME_InteractiveObject) IO = myActor->getIO();
+ if ( mySourceMode->checkedId() == NodesSrc || mySourceMode->checkedId() == ElementsSrc ) {
+ TColStd_MapOfInteger ID;
+ if ( !mySource->isReadOnly() )
+ myIDs = mySource->text();
+ QStringList ids = mySource->text().split( " ", QString::SkipEmptyParts );
+ foreach ( QString id, ids )
+ ID.Add( id.trimmed().toLong() );
+ selector->AddOrRemoveIndex( IO, ID, false );
+ }
+ if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
+ aViewWindow->highlight( IO, true, true );
+ }
+}
+
+/*!
+ \brief Calculate bounding box of the selected object(s)
+*/
+void SMESHGUI_BoundingBox::compute()
+{
+ SUIT_OverrideCursor wc;
+ if ( mySourceMode->checkedId() == NodesSrc ) {
+ }
+ else {
+ }
+}
+
+/*!
+ \brief Reset the widget to the initial state (nullify result fields)
+*/
+void SMESHGUI_BoundingBox::clear()
+{
+ myXmin->clear();
+ myXmax->clear();
+ myDX->clear();
+ myYmin->clear();
+ myYmax->clear();
+ myDY->clear();
+ myZmin->clear();
+ myZmax->clear();
+ myDZ->clear();
+}
+
+/*!
+ \class SMESHGUI_MeshInfoDlg
+ \brief Centralized dialog box for the measurements
+*/
+
+/*!
+ \brief Constructor
+ \param parent parent widget
+ \param page specifies the dialog page to be shown at the start-up
+*/
+SMESHGUI_MeasureDlg::SMESHGUI_MeasureDlg( QWidget* parent, int page )
+: QDialog( parent )
+{
+ setModal( false );
+ setAttribute( Qt::WA_DeleteOnClose, true );
+ setWindowTitle( tr( "MEASUREMENTS" ) );
+ setSizeGripEnabled( true );
+
+ myTabWidget = new QTabWidget( this );
+
+ // min distance
+
+ myMinDist = new SMESHGUI_MinDistance( myTabWidget );
+ myTabWidget->addTab( myMinDist, tr( "MIN_DIST" ) );
+
+ // bounding box
+
+ myBndBox = new SMESHGUI_BoundingBox( myTabWidget );
+ myTabWidget->addTab( myBndBox, tr( "BND_BOX" ) );
+
+ // buttons
+ QPushButton* okBtn = new QPushButton( tr( "SMESH_BUT_OK" ), this );
+ okBtn->setAutoDefault( true );
+ okBtn->setDefault( true );
+ okBtn->setFocus();
+ QPushButton* helpBtn = new QPushButton( tr( "SMESH_BUT_HELP" ), this );
+ helpBtn->setAutoDefault( true );
+
+ QHBoxLayout* btnLayout = new QHBoxLayout;
+ btnLayout->setSpacing( SPACING );
+ btnLayout->setMargin( 0 );
+ btnLayout->addWidget( okBtn );
+ btnLayout->addStretch( 10 );
+ btnLayout->addWidget( helpBtn );
+
+ QVBoxLayout* l = new QVBoxLayout ( this );
+ l->setMargin( MARGIN );
+ l->setSpacing( SPACING );
+ l->addWidget( myTabWidget );
+ l->addStretch();
+ l->addLayout( btnLayout );
+
+ myTabWidget->setCurrentIndex( qMax( (int)MinDistance, qMin( (int)BoundingBox, page ) ) );
+
+ connect( okBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
+ connect( helpBtn, SIGNAL( clicked() ), this, SLOT( help() ) );
+ connect( myTabWidget, SIGNAL( currentChanged( int ) ), this, SLOT( updateSelection() ) );
+ connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalDeactivateActiveDialog() ), this, SLOT( deactivate() ) );
+ connect( SMESHGUI::GetSMESHGUI(), SIGNAL( SignalCloseAllDialogs() ), this, SLOT( reject() ) );
+
+ updateSelection();
+}
+
+/*!
+ \brief Destructor
+*/
+SMESHGUI_MeasureDlg::~SMESHGUI_MeasureDlg()
+{
+}
+
+/*!
+ \brief Perform clean-up actions on the dialog box closing.
+*/
+void SMESHGUI_MeasureDlg::reject()
+{
+ LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
+ selMgr->clearFilters();
+ SMESH::SetPointRepresentation( false );
+ if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
+ aViewWindow->SetSelectionMode( ActorSelection );
+ QDialog::reject();
+}
+
+/*!
+ \brief Process keyboard event
+ \param e key press event
+*/
+void SMESHGUI_MeasureDlg::keyPressEvent( QKeyEvent* e )
+{
+ QDialog::keyPressEvent( e );
+ if ( !e->isAccepted() && e->key() == Qt::Key_F1 ) {
+ e->accept();
+ help();
+ }
+}
+
+/*!
+ \brief Reactivate dialog box, when mouse pointer goes into it.
+*/
+void SMESHGUI_MeasureDlg::enterEvent( QEvent* )
+{
+ activate();
+}
+
+/*!
+ \brief Setup selection mode depending on the current dialog box state.
+*/
+void SMESHGUI_MeasureDlg::updateSelection()
+{
+ if ( myTabWidget->currentIndex() == MinDistance )
+ myMinDist->updateSelection();
+ else if ( myTabWidget->currentIndex() == BoundingBox )
+ myBndBox->updateSelection();
+
+}
+
+/*!
+ \brief Show help page
+*/
+void SMESHGUI_MeasureDlg::help()
+{
+ SMESH::ShowHelpFile( myTabWidget->currentIndex() == MinDistance ?
+ "measurements_page.html#min_distance_anchor" :
+ "measurements_page.html#bounding_box_anchor" );
+}
+
+/*!
+ \brief Activate dialog box
+*/
+void SMESHGUI_MeasureDlg::activate()
+{
+ SMESHGUI::GetSMESHGUI()->EmitSignalDeactivateDialog();
+ SMESHGUI::GetSMESHGUI()->SetActiveDialogBox( this );
+ myTabWidget->setEnabled( true );
+ updateSelection();
+}
+
+/*!
+ \brief Deactivate dialog box
+*/
+void SMESHGUI_MeasureDlg::deactivate()
+{
+ myMinDist->deactivate();
+ myBndBox->deactivate();
+ myTabWidget->setEnabled( false );
+ disconnect( SMESHGUI::selectionMgr(), SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) );
+}