Salome HOME
1. Implementation of new pattern mapping algorthm (mesh refinement)
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_MeshPatternDlg.cxx
1 //  SMESH SMESHGUI : GUI for SMESH component
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : SMESHGUI_MeshPatternDlg.cxx
25 //  Author : Sergey LITONIN
26 //  Module : SMESH
27
28 #include "SMESHGUI_MeshPatternDlg.h"
29
30 #include "QAD_Desktop.h"
31 #include "QAD_FileDlg.h"
32
33 #include "SMESHGUI_SpinBox.h"
34 #include "SMESHGUI.h"
35 #include "SALOME_Selection.h"
36 #include "SMESH_NumberFilter.hxx"
37 #include "SMESHGUI_Utils.h"
38 #include "SMESHGUI_VTKUtils.h"
39 #include "SMESHGUI_CreatePatternDlg.h"
40 #include "SMESHGUI_PatternWidget.h"
41 #include "SMESH_Actor.h"
42 #include "SALOMEGUI_QtCatchCorbaException.hxx"
43 #include "VTKViewer_ViewFrame.h"
44 #include "SMESHGUI_PatternUtils.h"
45 #include "SMESH_ActorUtils.h"
46 #include "SMDS_MeshElement.hxx"
47 #include "SMDS_Mesh.hxx"
48
49 #include "QAD_Config.h"
50
51 #include <TColStd_MapOfInteger.hxx>
52
53 #include <qframe.h>
54 #include <qlayout.h>
55 #include <qlineedit.h>
56 #include <qpushbutton.h>
57 #include <qgroupbox.h>
58 #include <qlabel.h>
59 #include <qradiobutton.h>
60 #include <qcheckbox.h>
61 #include <qbuttongroup.h>
62 #include <qmessagebox.h>
63 #include <qcstring.h>
64 #include <qspinbox.h>
65 #include <qvaluelist.h>
66
67 #include <vtkCell.h>
68 #include <vtkIdList.h>
69 #include <vtkIntArray.h>
70 #include <vtkCellArray.h>
71 #include <vtkUnsignedCharArray.h>
72 #include <vtkUnstructuredGrid.h>
73 #include <vtkDataSetMapper.h>
74
75 #define SPACING 5
76 #define MARGIN  10
77
78 /*
79   Class       : SMESHGUI_MeshPatternDlg
80   Description : Dialog to specify filters for VTK viewer
81 */
82
83 //=======================================================================
84 // name    : SMESHGUI_MeshPatternDlg::SMESHGUI_MeshPatternDlg
85 // Purpose : Constructor
86 //=======================================================================
87 SMESHGUI_MeshPatternDlg::SMESHGUI_MeshPatternDlg( QWidget*          theParent,
88                                             SALOME_Selection* theSelection,
89                                             const char*       theName )
90 : QDialog( theParent, theName, false,
91           WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu ),
92   myBusy( false )
93 {
94   setCaption( tr( "CAPTION" ) );
95
96   QVBoxLayout* aDlgLay = new QVBoxLayout( this, MARGIN, SPACING );
97
98   QFrame* aMainFrame = createMainFrame  ( this );
99   QFrame* aBtnFrame  = createButtonFrame( this );
100
101
102
103
104   aDlgLay->addWidget( aMainFrame );
105   aDlgLay->addWidget( aBtnFrame );
106
107   aDlgLay->setStretchFactor( aMainFrame, 1 );
108
109   myCreationDlg = 0;
110   Init( theSelection );
111 }
112
113 //=======================================================================
114 // name    : SMESHGUI_MeshPatternDlg::createMainFrame
115 // Purpose : Create frame containing dialog's input fields
116 //=======================================================================
117 QFrame* SMESHGUI_MeshPatternDlg::createMainFrame( QWidget* theParent )
118 {
119   QPixmap iconSlct( QAD_Desktop::getResourceManager()->loadPixmap( "SMESH", tr( "ICON_SELECT" ) ) );
120   QPixmap icon2d  ( QAD_Desktop::getResourceManager()->loadPixmap( "SMESH", tr( "ICON_PATTERN_2d" ) ) );
121   QPixmap icon3d  ( QAD_Desktop::getResourceManager()->loadPixmap( "SMESH", tr( "ICON_PATTERN_3d" ) ) );
122   QPixmap iconOpen( QAD_Desktop::getResourceManager()->loadPixmap( "SMESH", tr( "ICON_FILE_OPEN" ) ) );
123
124   QPixmap iconSample2d( QAD_Desktop::getResourceManager()->loadPixmap( "SMESH", tr( "ICON_PATTERN_SAMPLE_2D" ) ) );
125   QPixmap iconSample3d( QAD_Desktop::getResourceManager()->loadPixmap( "SMESH", tr( "ICON_PATTERN_SAMPLE_3D" ) ) );
126
127   QGroupBox* aMainGrp = new QGroupBox( 1, Qt::Horizontal, theParent );
128   aMainGrp->setFrameStyle( QFrame::NoFrame );
129   aMainGrp->setInsideMargin( 0 );
130
131   // Pattern type group
132   
133   myTypeGrp = new QButtonGroup( 1, Qt::Vertical, tr( "PATTERN_TYPE" ), aMainGrp );
134   mySwitch2d = new QRadioButton( myTypeGrp );
135   mySwitch3d = new QRadioButton( myTypeGrp );
136   mySwitch2d->setPixmap( icon2d );
137   mySwitch3d->setPixmap( icon3d );
138   myTypeGrp->insert( mySwitch2d, Type_2d );
139   myTypeGrp->insert( mySwitch3d, Type_3d );
140
141
142   // Mesh group
143   
144   QGroupBox* aMeshGrp = new QGroupBox( 1, Qt::Vertical, tr( "SMESH_MESH" ), aMainGrp );
145   new QLabel( tr( "SMESH_MESH" ), aMeshGrp );
146   mySelBtn[ Mesh ] = new QPushButton( aMeshGrp );
147   mySelBtn[ Mesh ]->setPixmap( iconSlct );
148   mySelEdit[ Mesh ] = new QLineEdit( aMeshGrp );
149   mySelEdit[ Mesh ]->setReadOnly( true );
150
151   // Pattern group
152   
153   QGroupBox* aPatGrp = new QGroupBox( 1, Qt::Horizontal, tr( "PATTERN" ), aMainGrp );
154
155   // pattern name
156   QGroupBox* aNameGrp = new QGroupBox( 1, Qt::Vertical, aPatGrp );
157   aNameGrp->setFrameStyle( QFrame::NoFrame );
158   aNameGrp->setInsideMargin( 0 );
159   new QLabel( tr( "PATTERN" ), aNameGrp );
160   myName = new QLineEdit( aNameGrp );
161   myName->setReadOnly( true );
162   myOpenBtn = new QPushButton( aNameGrp );
163   myOpenBtn->setPixmap( iconOpen );
164   myNewBtn = new QPushButton( tr( "NEW" ), aNameGrp );
165
166   // Mode selection check box
167   myRefine = new QCheckBox( tr( "REFINE" ), aPatGrp );
168
169   // selection widgets for Apply to geom mode
170   myGeomGrp = new QGroupBox( 3, Qt::Horizontal, aPatGrp );
171   myGeomGrp->setFrameStyle( QFrame::NoFrame );
172   myGeomGrp->setInsideMargin( 0 );
173
174   for ( int i = Object; i <= Vertex2; i++ )
175   {
176     mySelLbl[ i ] = new QLabel( myGeomGrp );
177     mySelBtn[ i ] = new QPushButton( myGeomGrp );
178     mySelBtn[ i ]->setPixmap( iconSlct );
179     mySelEdit[ i ] = new QLineEdit( myGeomGrp );
180     mySelEdit[ i ]->setReadOnly( true );
181   }
182
183   // Widgets for refinement of existing mesh elements
184   myRefineGrp = new QFrame( aPatGrp );
185   myRefineGrp->setFrameStyle( QFrame::NoFrame );
186   QGridLayout* aRefGrid = new QGridLayout( myRefineGrp, 3, 3, 0, 5 );
187
188   mySelLbl[ Ids ] = new QLabel( myRefineGrp );
189   mySelBtn[ Ids ] = new QPushButton( myRefineGrp );
190   mySelBtn[ Ids ]->setPixmap( iconSlct );
191   mySelEdit[ Ids ] = new QLineEdit( myRefineGrp );
192
193   QLabel* aNodeLbl = new QLabel( tr( "NODE_1" ), myRefineGrp );
194   myNode1          = new QSpinBox( myRefineGrp );
195   myNode2Lbl       = new QLabel( tr( "NODE_2" ), myRefineGrp );
196   myNode2          = new QSpinBox( myRefineGrp );
197
198   aRefGrid->addWidget( mySelLbl [ Ids ], 0, 0 );
199   aRefGrid->addWidget( mySelBtn [ Ids ], 0, 1 );
200   aRefGrid->addWidget( mySelEdit[ Ids ], 0, 2 );
201   aRefGrid->addWidget( aNodeLbl, 1, 0 );
202   aRefGrid->addMultiCellWidget( myNode1, 1, 1, 1, 2 );
203   aRefGrid->addWidget( myNode2Lbl, 2, 0 );
204   aRefGrid->addMultiCellWidget( myNode2, 2, 2, 1, 2 );
205
206   // reverse check box
207   myReverseChk = new QCheckBox( tr( "REVERSE" ), aPatGrp );
208
209   // Pictures 2d and 3d
210   for ( int i = 0; i < 2; i++ )
211   {
212     if ( i == 0 )
213     {
214       myPicture2d = new SMESHGUI_PatternWidget( aPatGrp ),
215       myPicture2d->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
216     }
217     else
218     {
219       myPicture3d = new QFrame( aPatGrp ),
220       myPreview3d = new QLabel( myPicture3d );
221       myPreview3d->setPixmap( iconSample3d );
222       QGridLayout* aLay = new QGridLayout( myPicture3d, 3, 3, 0, 0 );
223       QSpacerItem* aSpacerH1 = new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum );
224       QSpacerItem* aSpacerH2 = new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum );
225       QSpacerItem* aSpacerV1 = new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding );
226       QSpacerItem* aSpacerV2 = new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding );
227       aLay->addItem( aSpacerH1, 1, 0 );
228       aLay->addItem( aSpacerH2, 1, 2 );
229       aLay->addItem( aSpacerV1, 0, 1 );
230       aLay->addItem( aSpacerV2, 2, 1 );
231       aLay->addWidget( myPreview3d, 1, 1 );
232     }
233   }
234
235   myPreviewChk = new QCheckBox( tr( "PREVIEW" ), aPatGrp );
236
237   // Connect signals and slots
238
239   connect( myTypeGrp,      SIGNAL( clicked( int )  ),               SLOT( onTypeChanged( int ) ) );
240   connect( myOpenBtn,      SIGNAL( clicked()       ),               SLOT( onOpen()             ) );
241   connect( myNewBtn,       SIGNAL( clicked()       ),               SLOT( onNew()              ) );
242   connect( myReverseChk,   SIGNAL( toggled( bool ) ),               SLOT( onReverse( bool )    ) );
243   connect( myPreviewChk,   SIGNAL( toggled( bool ) ),               SLOT( onPreview( bool )    ) );
244   connect( myRefine,       SIGNAL( toggled( bool ) ),               SLOT( onModeToggled( bool ) ) );
245   connect( myNode1,        SIGNAL( valueChanged( int ) ),           SLOT( onNodeChanged( int ) ) );
246   connect( myNode2,        SIGNAL( valueChanged( int ) ),           SLOT( onNodeChanged( int ) ) );
247   connect( mySelEdit[Ids], SIGNAL( textChanged( const QString& ) ), SLOT( onTextChanged( const QString& ) ) );
248
249   QMap< int, QPushButton* >::iterator anIter;
250   for ( anIter = mySelBtn.begin(); anIter != mySelBtn.end(); ++anIter )
251     connect( *anIter, SIGNAL( clicked() ), SLOT( onSelInputChanged() ) );
252
253   return aMainGrp;
254 }
255
256 //=======================================================================
257
258 // name    : SMESHGUI_MeshPatternDlg::createButtonFrame
259 // Purpose : Create frame containing buttons
260 //=======================================================================
261 QFrame* SMESHGUI_MeshPatternDlg::createButtonFrame( QWidget* theParent )
262 {
263   QFrame* aFrame = new QFrame( theParent );
264   aFrame->setFrameStyle( QFrame::Box | QFrame::Sunken );
265
266   myOkBtn     = new QPushButton( tr( "SMESH_BUT_OK"    ), aFrame );
267   myApplyBtn  = new QPushButton( tr( "SMESH_BUT_APPLY" ), aFrame );
268   myCloseBtn  = new QPushButton( tr( "SMESH_BUT_CLOSE" ), aFrame );
269
270   QSpacerItem* aSpacer = new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum );
271
272   QHBoxLayout* aLay = new QHBoxLayout( aFrame, MARGIN, SPACING );
273
274   aLay->addWidget( myOkBtn );
275   aLay->addWidget( myApplyBtn );
276   aLay->addItem( aSpacer);
277   aLay->addWidget( myCloseBtn );
278
279   connect( myOkBtn,    SIGNAL( clicked() ), SLOT( onOk() ) );
280   connect( myCloseBtn, SIGNAL( clicked() ), SLOT( onClose() ) ) ;
281   connect( myApplyBtn, SIGNAL( clicked() ), SLOT( onApply() ) );
282
283   return aFrame;
284 }
285
286 //=======================================================================
287 // name    : SMESHGUI_MeshPatternDlg::~SMESHGUI_MeshPatternDlg
288 // Purpose : Destructor
289 //=======================================================================
290 SMESHGUI_MeshPatternDlg::~SMESHGUI_MeshPatternDlg()
291 {
292 }
293
294 //=======================================================================
295 // name    : SMESHGUI_MeshPatternDlg::Init
296 // Purpose : Init dialog fields, connect signals and slots, show dialog
297 //=======================================================================
298 void SMESHGUI_MeshPatternDlg::Init( SALOME_Selection* theSelection )
299 {
300   myPattern = SMESH::GetPattern();
301   myPreviewActor = 0;
302   myIsCreateDlgOpen = false;
303   mySelInput = Mesh;
304   myType = -1;
305   myNbPoints = -1;
306   mySelection = theSelection;
307   SMESHGUI* aSMESHGUI = SMESHGUI::GetSMESHGUI();
308   aSMESHGUI->SetActiveDialogBox( ( QDialog* )this );
309   myMesh = SMESH::SMESH_Mesh::_nil();
310
311   myMeshShape = GEOM::GEOM_Object::_nil();
312   myGeomObj[ Object  ] = GEOM::GEOM_Object::_nil();
313   myGeomObj[ Vertex1 ] = GEOM::GEOM_Object::_nil();
314   myGeomObj[ Vertex2 ] = GEOM::GEOM_Object::_nil();
315
316   // selection and SMESHGUI
317   connect( mySelection, SIGNAL( currentSelectionChanged() ), SLOT( onSelectionDone() ) );
318   connect( aSMESHGUI, SIGNAL( SignalDeactivateActiveDialog() ), SLOT( onDeactivate() ) );
319   connect( aSMESHGUI, SIGNAL( SignalCloseAllDialogs() ), SLOT( onClose() ) );
320
321   myTypeGrp->setButton( Type_2d );
322   onTypeChanged( Type_2d );
323   onModeToggled( isRefine() );
324
325   updateGeometry();
326
327   resize( minimumSize() );
328
329   activateSelection();
330   onSelectionDone();
331
332   int x, y ;
333   aSMESHGUI->DefineDlgPosition( this, x, y );
334   this->move( x, y );
335   this->show();
336 }
337
338 //=======================================================================
339 // name    : SMESHGUI_MeshPatternDlg::isValid
340 // Purpose : Verify validity of entry data
341 //=======================================================================
342 bool SMESHGUI_MeshPatternDlg::isValid( const bool theMess )
343 {
344   QValueList<int> ids;
345   if ( ( isRefine() && ( myMesh->_is_nil() || !getIds( ids ) || getNode( false ) < 0 || myType == Type_3d && ( getNode( true ) < 0 || getNode( false ) == getNode( true ) ) ) ) 
346        || ( !isRefine() && ( myMesh->_is_nil() || myMeshShape->_is_nil() || myGeomObj[ Object ]->_is_nil() ||
347        myGeomObj[ Vertex1 ]->_is_nil() || myType == Type_3d && myGeomObj[ Vertex2 ]->_is_nil() ) ) )
348   {
349     if ( theMess )
350       QMessageBox::information( SMESHGUI::GetSMESHGUI()->GetDesktop(),
351         tr( "SMESH_INSUFFICIENT_DATA" ), tr( "SMESHGUI_INVALID_PARAMETERS" ), QMessageBox::Ok );
352     return false;
353   }
354   else
355     return true;
356 }
357
358 //=======================================================================
359 // name    : SMESHGUI_MeshPatternDlg::onApply
360 // Purpose : SLOT called when "Apply" button pressed.
361 //=======================================================================
362 bool SMESHGUI_MeshPatternDlg::onApply()
363 {
364   try
365   {
366     if ( !isValid() )
367       return false;
368
369     erasePreview();
370
371     if ( isRefine() ) { // Refining existing mesh elements
372       QValueList<int> ids;
373       getIds( ids );
374       SMESH::long_array_var varIds = new SMESH::long_array();
375       varIds->length( ids.count() );
376       int i = 0;
377       for ( QValueList<int>::iterator it = ids.begin(); it != ids.end(); ++it )
378         varIds[i++] = *it;
379       myType == Type_2d
380         ? myPattern->ApplyToMeshFaces  ( myMesh, varIds, getNode( false ), myReverseChk->isChecked() )
381         : myPattern->ApplyToHexahedrons( myMesh, varIds, getNode( false ), getNode( true ) );
382     }
383     else { // Applying a pattern to geometrical object
384     if ( myType == Type_2d )
385       myPattern->ApplyToFace(
386         myGeomObj[ Object ], myGeomObj[ Vertex1 ], myReverseChk->isChecked() );
387     else
388       myPattern->ApplyTo3DBlock(
389         myGeomObj[ Object ], myGeomObj[ Vertex1 ], myGeomObj[ Vertex2 ] );
390     }
391
392     if ( myPattern->MakeMesh( myMesh ) )
393     {
394       mySelection->ClearIObjects();
395       SMESHGUI* aCompGUI = SMESHGUI::GetSMESHGUI();
396       if ( !isRefine() && !QAD_CONFIG->getSetting( "SMESH:AutomaticUpdate" ).compare( "true" ) ) {
397         SALOMEDS::SObject_var aSO = SMESH::FindSObject( myMesh.in() );
398         SMESH_Actor* anActor = SMESH::FindActorByEntry( aSO->GetID() );
399         if(!anActor){
400           anActor = SMESH::CreateActor( aSO->GetStudy(), aSO->GetID() );
401           if(anActor){
402             SMESH::DisplayActor( aCompGUI->GetActiveStudy()->getActiveStudyFrame(), anActor );
403             SMESH::FitAll();
404           }
405         }
406       }
407       SMESH::UpdateView();
408
409       aCompGUI->GetActiveStudy()->updateObjBrowser( true );
410       return true;
411     }
412     else
413     {
414       QMessageBox::information( SMESHGUI::GetSMESHGUI()->GetDesktop(),
415         tr( "SMESH_ERROR" ), tr( "SMESH_OPERATION_FAILED" ), QMessageBox::Ok );
416       return false;
417     }
418   }
419   catch( const SALOME::SALOME_Exception& S_ex )
420   {
421     QtCatchCorbaException( S_ex );    
422   }
423   catch( ... )
424   {
425   }
426
427   return false;
428 }
429
430 //=======================================================================
431 // name    : SMESHGUI_MeshPatternDlg::onOk
432 // Purpose : SLOT called when "Ok" button pressed.
433 //=======================================================================
434 void SMESHGUI_MeshPatternDlg::onOk()
435 {
436   if ( onApply() )
437     onClose();
438 }
439
440 //=======================================================================
441 // name    : SMESHGUI_MeshPatternDlg::onClose
442 // Purpose : SLOT called when "Close" button pressed. Close dialog
443 //=======================================================================
444 void SMESHGUI_MeshPatternDlg::onClose()
445 {
446   mySelection->ClearFilters();
447   SMESH::SetPickable();
448   QAD_Application::getDesktop()->SetSelectionMode( ActorSelection );
449   disconnect( mySelection, 0, this, 0 );
450   disconnect( SMESHGUI::GetSMESHGUI(), 0, this, 0 );
451   SMESHGUI::GetSMESHGUI()->ResetState();
452   erasePreview();
453   reject();
454 }
455
456
457
458 //=======================================================================
459 // name    : SMESHGUI_MeshPatternDlg::onSelectionDone
460 // Purpose : SLOT called when selection changed
461 //=======================================================================
462 void SMESHGUI_MeshPatternDlg::onSelectionDone()
463 {
464   if ( myBusy )
465     return;
466   
467   try
468   {
469     if ( mySelInput == Mesh )
470     {
471       if ( mySelection->IObjectCount() != 1 )
472         return;
473
474       // Retrieve mesh from selection
475       Handle(SALOME_InteractiveObject) anIO = mySelection->firstIObject();
476       SMESH::SMESH_Mesh_var aMesh = SMESH::IObjectToInterface<SMESH::SMESH_Mesh>( anIO );
477       if ( aMesh->_is_nil() )
478         return;
479
480       // Get geom object corresponding to the mesh
481       SALOMEDS::Study_var aStudy =
482         SMESHGUI::GetSMESHGUI()->GetActiveStudy()->getStudyDocument();
483
484       SALOMEDS::SObject_var aSO = SMESH::FindSObject( aMesh.in() );
485       if ( aSO->_is_nil() )
486         return;
487
488       bool isFound = false;
489       SALOMEDS::ChildIterator_var anIter = aStudy->NewChildIterator( aSO );
490       for( ; anIter->More(); anIter->Next() )
491       {
492         SALOMEDS::SObject_var aSO = anIter->Value();
493         SALOMEDS::SObject_var aRefSO;
494
495         GEOM::GEOM_Object_var aMeshShape = GEOM::GEOM_Object::_narrow(
496           aSO->ReferencedObject( aRefSO )? aRefSO->GetObject() : aSO->GetObject() );
497
498         if ( !aMeshShape->_is_nil() )
499         {
500           isFound = true;
501           myMeshShape = aMeshShape;
502           break;
503
504         }
505       }
506
507       if ( !isFound )
508         myMeshShape = GEOM::GEOM_Object::_nil();
509
510       // Clear fields of geom objects if mesh was changed
511       if ( myMesh != aMesh )
512       {
513         for ( int i = Object; i <= Ids; i++ )
514         {
515           myGeomObj[ i ] = GEOM::GEOM_Object::_nil();
516           mySelEdit[ i ]->setText( "" );
517         }
518       }
519
520       myMesh = aMesh;
521
522       // Set name of mesh in line edit
523       QString aName;
524       SMESH::GetNameOfSelectedIObjects( mySelection, aName );
525       mySelEdit[ Mesh ]->setText( aName );
526     }
527     else if ( mySelInput == Ids ) {
528       QString anIds;
529       if ( !SMESH::GetNameOfSelectedElements( mySelection, anIds ) )
530         anIds = "";
531  
532       myBusy = true;
533       mySelEdit[ Ids ]->setText( anIds );
534       myBusy = false;
535     }
536     else
537     {
538       if ( mySelection->IObjectCount() != 1 )
539         return;
540
541       // Get geom object from selection
542       Handle(SALOME_InteractiveObject) anIO = mySelection->firstIObject();
543       GEOM::GEOM_Object_var anObj = SMESH::IObjectToInterface<GEOM::GEOM_Object>( anIO );
544       if ( anObj->_is_nil() )
545         return;
546
547       // Clear fields of vertexes if face or 3d block was changed
548       if ( anObj != myGeomObj[ mySelInput ] && mySelInput == Object )
549       {
550         for ( int i = Vertex1; i <= Vertex2; i++ )
551         {
552           myGeomObj[ i ] = GEOM::GEOM_Object::_nil();
553           mySelEdit[ i ]->setText( "" );
554         }
555       }
556
557       myGeomObj[ mySelInput ] = anObj;
558
559       // Set name of geom object in line edit
560       QString aName;
561       SMESH::GetNameOfSelectedIObjects( mySelection, aName );
562       mySelEdit[ mySelInput ]->setText( aName );
563     }
564   }
565   catch( const SALOME::SALOME_Exception& S_ex )
566   {
567     QtCatchCorbaException( S_ex );
568     resetSelInput();
569   }
570   catch( ... )
571   {
572     resetSelInput();
573   }
574
575   updateWgState();
576   displayPreview();
577 }
578
579 //=======================================================================
580 // name    : SMESHGUI_MeshPatternDlg::resetSelInput
581 // Purpose : Reset fields corresponding to the current selection input
582 //=======================================================================
583 void SMESHGUI_MeshPatternDlg::resetSelInput()
584 {
585   if ( mySelInput == Mesh )
586   {
587     myMesh = SMESH::SMESH_Mesh::_nil();
588     myMeshShape = GEOM::GEOM_Object::_nil();
589   }
590
591   else
592     myGeomObj[ mySelInput ] = GEOM::GEOM_Object::_nil();
593
594   mySelEdit[ mySelInput ]->setText( "" );
595 }
596
597 //=======================================================================
598 // name    : SMESHGUI_MeshPatternDlg::onDeactivate
599 // Purpose : SLOT called when dialog must be deativated
600 //=======================================================================
601 void SMESHGUI_MeshPatternDlg::onDeactivate()
602 {
603   mySelection->ClearFilters();
604   //if ( myReverseChk->isChecked() )
605   //  erasePreview();
606   disconnect( mySelection, 0, this, 0 );
607   setEnabled( false );
608 }
609
610 //=======================================================================
611 // name    : SMESHGUI_MeshPatternDlg::enterEvent
612 // Purpose : Event filter
613 //=======================================================================
614 void SMESHGUI_MeshPatternDlg::enterEvent( QEvent* )
615 {
616   if ( myIsCreateDlgOpen )
617     return;
618     
619   if ( myReverseChk->isChecked() )
620     displayPreview();
621   SMESHGUI::GetSMESHGUI()->EmitSignalDeactivateDialog() ;
622   setEnabled( true );
623   activateSelection();
624   connect( mySelection, SIGNAL( currentSelectionChanged() ), SLOT( onSelectionDone() ) );
625   onTextChanged( mySelEdit[Ids]->text() );
626 }
627
628
629 //=================================================================================
630 // function : closeEvent()
631 // purpose  :
632 //=================================================================================
633 void SMESHGUI_MeshPatternDlg::closeEvent( QCloseEvent* e )
634 {
635   onClose() ;
636 }
637
638 //=======================================================================
639 // name    : SMESHGUI_MeshPatternDlg::onSelInputChanged
640 // Purpose : SLOT. Called when -> button clicked.
641 //           Change current selection input field
642 //=======================================================================
643 void SMESHGUI_MeshPatternDlg::onSelInputChanged()
644 {
645   const QObject* aSender = sender();
646   for ( int i = Mesh; i <= Ids; i++ )
647     if ( aSender == mySelBtn[ i ] )
648       mySelInput = i;
649
650   activateSelection();
651   onSelectionDone();
652 }
653
654 //=======================================================================
655 // name    : SMESHGUI_MeshPatternDlg::prepareFilters
656 // Purpose : Prepare filters for dialog
657 //=======================================================================
658
659 QStringList SMESHGUI_MeshPatternDlg::prepareFilters() const
660 {
661   static QStringList aList;
662   if ( aList.isEmpty() )
663   {
664     aList.append( tr( "PATTERN_FILT" ) );
665     //aList.append( tr( "ALL_FILES_FILTER" ) );
666   }
667
668   return aList;
669 }
670
671 //================================================================
672
673 // Function : SMESHGUI_MeshPatternDlg::autoExtension
674 // Purpose  : Append extension to the file name
675 //================================================================
676 QString SMESHGUI_MeshPatternDlg::autoExtension( const QString& theFileName ) const
677 {
678   QString anExt = theFileName.section( '.', -1 );
679   return anExt != "smp" && anExt != "SMP" ? theFileName + ".smp" : theFileName;
680 }
681
682 //=======================================================================
683 // name    : SMESHGUI_MeshPatternDlg::onOpen
684 // Purpose : SLOT. Called when "Open" button clicked.
685 //           Displays file open dialog
686 //=======================================================================
687 void SMESHGUI_MeshPatternDlg::onOpen()
688 {
689   QAD_FileDlg* aDlg = new QAD_FileDlg( this, true );
690   aDlg->setCaption( tr( "LOAD_PATTERN" ) );
691   aDlg->setMode( QFileDialogP::ExistingFile );
692   aDlg->setFilters( prepareFilters() );
693   if ( myName->text() != "" )
694     aDlg->setSelection( myName->text() + ".smp" );
695   QPushButton* anOkBtn = ( QPushButton* )aDlg->child( "OK", "QPushButton" );
696   if ( anOkBtn != 0 )
697     anOkBtn->setText( tr( "SMESH_BUT_OK" ) );
698
699   if ( aDlg->exec() != Accepted )
700     return;
701
702   QString fName = aDlg->selectedFile();
703   if ( fName.isEmpty() )
704     return;
705
706   if ( QFileInfo( fName ).extension().isEmpty() )
707     fName = autoExtension( fName );
708
709   fName = QDir::convertSeparators( fName );
710   
711   QString prev = QDir::convertSeparators( myName->text() );
712   if ( prev == fName )
713     return;
714
715   // Read string from file
716   QFile aFile( fName );
717   if ( !aFile.open( IO_ReadOnly ) )
718   {
719     QMessageBox::information( SMESHGUI::GetSMESHGUI()->GetDesktop(),
720       tr( "SMESH_ERROR" ), tr( "ERROR_OF_OPENING" ), QMessageBox::Ok );
721     return;
722   }
723   
724   QByteArray aDataArray = aFile.readAll();
725   const char* aData = aDataArray.data();
726   if ( aData == 0 )
727   {
728     QMessageBox::information( SMESHGUI::GetSMESHGUI()->GetDesktop(),
729       tr( "SMESH_ERROR" ), tr( "ERROR_OF_READING" ), QMessageBox::Ok );
730     return;
731   }
732   
733   if ( loadFromFile( aData ) )
734     myName->setText( QFileInfo( fName ).baseName() );
735     
736   updateWgState();
737   displayPreview();
738 }
739
740 //=======================================================================
741 // name    : SMESHGUI_MeshPatternDlg::onCloseCreationDlg
742 // Purpose : SLOT. Called when "Pattern creation" dialog closed with "Close"
743 //=======================================================================
744 void SMESHGUI_MeshPatternDlg::onCloseCreationDlg()
745 {
746   setEnabled( true );
747   myIsCreateDlgOpen = false;
748 }
749
750
751 //=======================================================================
752 // name    : SMESHGUI_MeshPatternDlg::onOkCreationDlg
753 // Purpose : SLOT. Called when "Pattern creation" dialog closed with OK
754 //           or SAVE buttons. Initialize myPattern field. Redisplay preview
755 //=======================================================================
756 void SMESHGUI_MeshPatternDlg::onOkCreationDlg()
757 {
758   myPattern = SMESH::SMESH_Pattern::_duplicate( myCreationDlg->GetPattern() );
759   myName->setText( myCreationDlg->GetPatternName() );
760   displayPreview();
761   setEnabled( true );
762   myIsCreateDlgOpen = false;
763 }
764
765
766 //=======================================================================
767 // name    : SMESHGUI_MeshPatternDlg::onNew
768 // Purpose : SLOT. Called when "New..." button clicked. Create new pattern
769 //=======================================================================
770 void SMESHGUI_MeshPatternDlg::onNew()
771 {
772   setEnabled( false );
773   myIsCreateDlgOpen = true;
774   if ( myCreationDlg == 0 )
775   {
776     myCreationDlg = new SMESHGUI_CreatePatternDlg( this, mySelection, myType );
777     connect( myCreationDlg, SIGNAL( NewPattern() ), SLOT( onOkCreationDlg() ) );
778     connect( myCreationDlg, SIGNAL( Close() ), SLOT( onCloseCreationDlg() ) );
779   }
780   else
781     myCreationDlg->Init( mySelection, myType );
782
783   myCreationDlg->SetMesh( myMesh );
784   myCreationDlg->show();
785 }
786
787 //=======================================================================
788 // name    : SMESHGUI_MeshPatternDlg::onReverse
789 // Purpose : SLOT. Called when state of "Reverse order..." checkbox chaged
790 //           Calculate new points of the mesh to be created. Redisplay preview
791 //=======================================================================
792 void SMESHGUI_MeshPatternDlg::onReverse( bool )
793 {
794   displayPreview();
795 }
796
797 //=======================================================================
798
799 // name    : SMESHGUI_MeshPatternDlg::onPreview
800 // Purpose : SLOT. Called when state of "Preview" checkbox changed
801 //           Display/Erase preview
802 //=======================================================================
803 void SMESHGUI_MeshPatternDlg::onPreview( bool )
804 {
805   displayPreview();
806 }
807
808 //=======================================================================
809 // name    : SMESHGUI_MeshPatternDlg::displayPreview
810 // Purpose : Display preview
811 //=======================================================================
812 void SMESHGUI_MeshPatternDlg::displayPreview()
813 {
814   try
815   {
816     // Redisplay preview in dialog
817
818     SMESH::point_array_var pnts = myPattern->GetPoints();
819     SMESH::long_array_var keyPoints = myPattern->GetKeyPoints();
820     SMESH::array_of_long_array_var elemPoints = myPattern->GetElementPoints(false);
821
822     if ( pnts->length()       == 0 ||
823          keyPoints->length()  == 0 ||
824          elemPoints->length() == 0 )
825     {
826       erasePreview();
827       return;
828     }
829
830     else
831     {
832       PointVector aPoints( pnts->length() );
833       QValueVector<int> aKeyPoints( keyPoints->length() );
834       ConnectivityVector anElemPoints( elemPoints->length() );
835
836       for ( int i = 0, n = pnts->length(); i < n; i++ )
837         aPoints[ i ] = pnts[ i ];
838
839       for ( int i2 = 0, n2 = keyPoints->length(); i2 < n2; i2++ )
840         aKeyPoints[ i2 ] = keyPoints[ i2 ];
841
842       for ( int i3 = 0, n3 = elemPoints->length(); i3 < n3; i3++ )
843       {
844         QValueVector<int> aVec( elemPoints[ i3 ].length() );
845         for ( int i4 = 0, n4 = elemPoints[ i3 ].length(); i4 < n4; i4++ )
846           aVec[ i4 ] = elemPoints[ i3 ][ i4 ];
847
848         anElemPoints[ i3 ] = aVec;
849       }
850
851       myPicture2d->SetPoints( aPoints, aKeyPoints, anElemPoints );
852     }
853
854
855     // Redisplay preview in 3D viewer
856
857     if ( myPreviewActor != 0 )
858     {
859       if ( VTKViewer_ViewFrame* vf = SMESH::GetCurrentVtkView() )
860       {
861         vf->RemoveActor(myPreviewActor);
862         vf->Repaint();
863       }
864       myPreviewActor->Delete();
865       myPreviewActor = 0;
866     }
867
868     if ( !myPreviewChk->isChecked() || !isValid( false ) )
869       return;
870
871     vtkUnstructuredGrid* aGrid = getGrid();
872     if ( aGrid == 0 )
873       return;
874
875     // Create and display actor
876     vtkDataSetMapper* aMapper = vtkDataSetMapper::New();
877     aMapper->SetInput( aGrid );
878
879     myPreviewActor = SALOME_Actor::New();
880     myPreviewActor->PickableOff();
881     myPreviewActor->SetMapper( aMapper );
882
883     vtkProperty* aProp = vtkProperty::New();
884     aProp->SetRepresentationToWireframe();
885     aProp->SetColor( 250, 0, 250 );
886     if ( SMESH::FindActorByObject( myMesh ) )
887       aProp->SetLineWidth( SMESH::GetFloat( "SMESH:SettingsWidth", 1 ) +1 );
888     else
889       aProp->SetLineWidth( 1 );
890     myPreviewActor->SetProperty( aProp );
891
892     myPreviewActor->SetRepresentation( 3 );
893
894     SMESH::GetCurrentVtkView()->AddActor( myPreviewActor );
895     SMESH::GetCurrentVtkView()->Repaint();
896
897     aProp->Delete();
898     aGrid->Delete();
899   }
900   catch( const SALOME::SALOME_Exception& S_ex )
901   {
902     QtCatchCorbaException( S_ex );
903     erasePreview();
904   }
905   catch( ... )
906   {
907     erasePreview();
908   }
909 }
910
911 //=======================================================================
912 // name    : SMESHGUI_MeshPatternDlg::erasePreview
913 // Purpose : Erase preview
914 //=======================================================================
915 void SMESHGUI_MeshPatternDlg::erasePreview()
916 {
917   // Erase preview in 2D viewer
918   myPicture2d->SetPoints( PointVector(), QValueVector<int>(), ConnectivityVector() );
919
920   // Erase preview in 3D viewer
921   if ( myPreviewActor == 0 )
922     return;
923
924
925   if ( VTKViewer_ViewFrame* vf = SMESH::GetCurrentVtkView() )
926   {
927     vf->RemoveActor(myPreviewActor);
928     vf->Repaint();
929   }
930   myPreviewActor->Delete();
931   myPreviewActor = 0;
932 }
933
934 //=======================================================================
935 // name    : SMESHGUI_MeshPatternDlg::updateWgState
936 // Purpose : Enable/disable selection widgets
937 //=======================================================================
938 void SMESHGUI_MeshPatternDlg::updateWgState()
939 {
940   if ( myMesh->_is_nil() )
941   {
942     for ( int i = Object; i <= Ids; i++ )
943     {
944       mySelBtn [ i ]->setEnabled( false );
945       mySelEdit[ i ]->setEnabled( false );
946       mySelEdit[ i ]->setText( "" );
947     }
948     myNode1->setEnabled( false );
949     myNode2->setEnabled( false );
950     myNode1->setRange( 0, 0 );
951     myNode2->setRange( 0, 0 );
952   }
953   else
954   {
955     mySelBtn [ Object ]->setEnabled( true );
956     mySelEdit[ Object ]->setEnabled( true );
957     mySelBtn [ Ids ]   ->setEnabled( true );
958     mySelEdit[ Ids ]   ->setEnabled( true );
959     
960     if ( myGeomObj[ Object ]->_is_nil() )
961     {
962       for ( int i = Vertex1; i <= Vertex2; i++ )
963       {
964         mySelBtn [ i ]->setEnabled( false );
965         mySelEdit[ i ]->setEnabled( false );
966         mySelEdit[ i ]->setText( "" );
967       }
968     }
969     else
970     {
971       for ( int i = Object; i <= Vertex2; i++ )
972       {
973         mySelBtn [ i ]->setEnabled( true );
974         mySelEdit[ i ]->setEnabled( true );
975       }
976     }
977
978     QValueList<int> ids;
979     if ( !CORBA::is_nil( myPattern ) && getIds( ids ) ) {
980       SMESH::long_array_var keyPoints = myPattern->GetKeyPoints();
981       if ( keyPoints->length() ) {
982         myNode1->setEnabled( true );
983         myNode2->setEnabled( true );
984         myNode1->setRange( 1, keyPoints->length() );
985         myNode2->setRange( 1, keyPoints->length() );
986         return;
987       }
988     }
989
990     myNode1->setEnabled( false );
991     myNode2->setEnabled( false );
992     myNode1->setRange( 0, 0 );
993     myNode2->setRange( 0, 0 );
994   }
995 }
996
997 //=======================================================================
998 // name    : SMESHGUI_MeshPatternDlg::activateSelection
999 // Purpose : Activate selection in accordance with current selection input
1000 //=======================================================================
1001 void SMESHGUI_MeshPatternDlg::activateSelection()
1002 {
1003   mySelection->ClearFilters();
1004   if ( mySelInput == Ids ) {
1005     SMESH_Actor* anActor = SMESH::FindActorByObject( myMesh );
1006     if ( anActor )
1007       SMESH::SetPickable(anActor);
1008
1009     if ( myType == Type_2d )
1010       QAD_Application::getDesktop()->SetSelectionMode( FaceSelection, true );
1011     else
1012       QAD_Application::getDesktop()->SetSelectionMode( CellSelection, true );
1013   }
1014   else {
1015     SMESH::SetPickable();
1016   QAD_Application::getDesktop()->SetSelectionMode( ActorSelection );
1017   }
1018   
1019   if ( mySelInput == Object && !myMeshShape->_is_nil() )
1020   {
1021     if ( myType == Type_2d )
1022     {
1023       if ( myNbPoints > 0 )
1024         mySelection->AddFilter( new SMESH_NumberFilter( 
1025
1026           "GEOM", TopAbs_VERTEX, myNbPoints, TopAbs_FACE, myMeshShape ) );
1027       else
1028         mySelection->AddFilter( new SMESH_NumberFilter(
1029           "GEOM", TopAbs_SHAPE, myNbPoints, TopAbs_FACE, myMeshShape ) );
1030     }
1031     else
1032     {
1033       TColStd_MapOfInteger aTypes;
1034       aTypes.Add( TopAbs_SHELL );
1035       aTypes.Add( TopAbs_SOLID );
1036       mySelection->AddFilter( new SMESH_NumberFilter(
1037         "GEOM", TopAbs_FACE, 6, aTypes, myMeshShape, true ) );
1038     }
1039   }
1040   else if ( ( mySelInput == Vertex1 || mySelInput == Vertex2 ) && !myGeomObj[ Object ]->_is_nil()  )
1041   {
1042     mySelection->AddFilter( new SMESH_NumberFilter(
1043       "GEOM", TopAbs_SHAPE, 1, TopAbs_VERTEX, myGeomObj[ Object ] ) );
1044   }
1045 }
1046
1047 //=======================================================================
1048 // name    : SMESHGUI_MeshPatternDlg::loadFromFile
1049 // Purpose : Load pattern from file
1050 //=======================================================================
1051 bool SMESHGUI_MeshPatternDlg::loadFromFile( const QString& theName )
1052 {
1053   try
1054   {
1055     SMESH::SMESH_Pattern_var aPattern = SMESH::GetPattern();
1056
1057     if ( !aPattern->LoadFromFile( theName.latin1() ) ||
1058          myType == Type_2d && !aPattern->Is2D())
1059     {
1060       SMESH::SMESH_Pattern::ErrorCode aCode = aPattern->GetErrorCode();
1061       QString aMess;
1062       if      ( aCode == SMESH::SMESH_Pattern::ERR_READ_NB_POINTS      ) aMess = tr( "ERR_READ_NB_POINTS" );
1063       else if ( aCode == SMESH::SMESH_Pattern::ERR_READ_POINT_COORDS   ) aMess = tr( "ERR_READ_POINT_COORDS" );
1064       else if ( aCode == SMESH::SMESH_Pattern::ERR_READ_TOO_FEW_POINTS ) aMess = tr( "ERR_READ_TOO_FEW_POINTS" );
1065       else if ( aCode == SMESH::SMESH_Pattern::ERR_READ_3D_COORD       ) aMess = tr( "ERR_READ_3D_COORD" );
1066       else if ( aCode == SMESH::SMESH_Pattern::ERR_READ_NO_KEYPOINT    ) aMess = tr( "ERR_READ_NO_KEYPOINT" );
1067       else if ( aCode == SMESH::SMESH_Pattern::ERR_READ_BAD_INDEX      ) aMess = tr( "ERR_READ_BAD_INDEX" );
1068       else if ( aCode == SMESH::SMESH_Pattern::ERR_READ_ELEM_POINTS    ) aMess = tr( "ERR_READ_ELEM_POINTS" );
1069       else if ( aCode == SMESH::SMESH_Pattern::ERR_READ_NO_ELEMS       ) aMess = tr( "ERR_READ_NO_ELEMS" );
1070       else if ( aCode == SMESH::SMESH_Pattern::ERR_READ_BAD_KEY_POINT  ) aMess = tr( "ERR_READ_BAD_KEY_POINT" );
1071       else                                                               aMess = tr( "ERROR_OF_LOADING" );
1072
1073       QMessageBox::information( SMESHGUI::GetSMESHGUI()->GetDesktop(),
1074         tr( "SMESH_ERROR" ), aMess, QMessageBox::Ok );
1075       return false;
1076     }
1077     else
1078     {
1079       myPattern = aPattern;
1080       return true;
1081     }
1082   }
1083   catch( const SALOME::SALOME_Exception& S_ex )
1084   {
1085     QtCatchCorbaException( S_ex );
1086     QMessageBox::information( SMESHGUI::GetSMESHGUI()->GetDesktop(),
1087         tr( "SMESH_ERROR" ), tr( "ERROR_OF_LOADING" ), QMessageBox::Ok );
1088       return false;
1089   }
1090 }
1091
1092 //=======================================================================
1093 // name    : SMESHGUI_MeshPatternDlg::onTypeChanged
1094
1095 // Purpose : SLOT. Called when pattern type changed.
1096 //           Change dialog's look and feel
1097 //=======================================================================
1098 void SMESHGUI_MeshPatternDlg::onTypeChanged( int theType )
1099 {
1100   if ( myType == theType )
1101     return;
1102
1103   myType = theType;
1104
1105   myNbPoints = -1;
1106   myGeomObj[ Object  ] = GEOM::GEOM_Object::_nil();
1107   myGeomObj[ Vertex1 ] = GEOM::GEOM_Object::_nil();
1108   myGeomObj[ Vertex2 ] = GEOM::GEOM_Object::_nil();
1109   myPattern = SMESH::GetPattern();
1110
1111   myName->setText( "" );
1112   mySelEdit[ Object  ]->setText( "" );
1113   mySelEdit[ Vertex1 ]->setText( "" );
1114   mySelEdit[ Vertex2 ]->setText( "" );
1115   mySelEdit[ Ids ]    ->setText( "" );
1116
1117   if ( theType == Type_2d )
1118   {
1119     // Geom widgets
1120     mySelLbl [ Vertex2 ]->hide();
1121     mySelBtn [ Vertex2 ]->hide();
1122     mySelEdit[ Vertex2 ]->hide();
1123     myReverseChk->show();
1124     myPicture2d->show();
1125     myPicture3d->hide();
1126     mySelLbl[ Object  ]->setText( tr( "FACE" ) );
1127     mySelLbl[ Vertex1 ]->setText( tr( "VERTEX" ) );
1128     // Refine widgets
1129     mySelLbl[ Ids ]->setText( tr( "MESH_FACES" ) );
1130     myNode2Lbl->hide();
1131     myNode2   ->hide();
1132   }
1133   else
1134   {
1135     // Geom widgets
1136     mySelLbl [ Vertex2 ]->show();
1137     mySelBtn [ Vertex2 ]->show();
1138     mySelEdit[ Vertex2 ]->show();
1139     myReverseChk->hide();
1140     myPicture2d->hide();
1141     myPicture3d->show();
1142     mySelLbl[ Object  ]->setText( tr( "3D_BLOCK" ) );
1143     mySelLbl[ Vertex1 ]->setText( tr( "VERTEX1" ) );
1144     mySelLbl[ Vertex2 ]->setText( tr( "VERTEX2" ) );
1145     // Refine widgets
1146     mySelLbl[ Ids ]->setText( tr( "MESH_VOLUMES" ) );
1147     myNode2Lbl->show();
1148     myNode2   ->show();
1149   }
1150
1151   mySelInput = Mesh;
1152   activateSelection();
1153   updateWgState();
1154   displayPreview();
1155 }
1156
1157 //=======================================================================
1158 // name    : SMESHGUI_MeshPatternDlg::getGrid
1159 // Purpose : Get unstructured grid for pattern
1160 //=======================================================================
1161 vtkUnstructuredGrid* SMESHGUI_MeshPatternDlg::getGrid()
1162 {
1163   try
1164   {
1165     // Get points from pattern
1166     SMESH::point_array_var pnts;
1167     QValueList<int> ids;
1168     if ( isRefine() && getIds( ids ) ) {
1169       SMESH::long_array_var varIds = new SMESH::long_array();
1170       varIds->length( ids.count() );
1171       int i = 0;
1172       for ( QValueList<int>::iterator it = ids.begin(); it != ids.end(); ++it )
1173         varIds[i++] = *it;
1174       pnts = myType == Type_2d
1175         ? myPattern->ApplyToMeshFaces  ( myMesh, varIds, getNode( false ), myReverseChk->isChecked() )
1176         : myPattern->ApplyToHexahedrons( myMesh, varIds, getNode( false ), getNode( true ) );
1177     }
1178     else {
1179       pnts = myType == Type_2d
1180         ? myPattern->ApplyToFace   ( myGeomObj[ Object ], myGeomObj[ Vertex1 ], myReverseChk->isChecked() )
1181       : myPattern->ApplyTo3DBlock( myGeomObj[ Object ], myGeomObj[ Vertex1 ], myGeomObj[ Vertex2 ] );
1182     }
1183
1184     SMESH::array_of_long_array_var elemPoints = myPattern->GetElementPoints(true);
1185
1186     if ( pnts->length() == 0 || elemPoints->length() == 0 )
1187       return 0;
1188
1189     
1190
1191     // to do : to be removed /////////////////////////////////////////////
1192
1193 #ifdef DEB_SLN
1194     for ( int i1 = 0, n1 = pnts->length(); i1 < n1; i1++ )
1195       printf( "%d: %g %g %g\n", i1, pnts[ i1 ].x, pnts[ i1 ].y, pnts[ i1 ].z );
1196
1197     printf( "\nELEMENTS : \n" );
1198     for ( int i2 = 0, n2 = elemPoints->length(); i2 < n2; i2++ )
1199     {
1200
1201       printf( "%d: ", i2 );
1202       for ( int i3 = 0, n3 = elemPoints[ i2 ].length(); i3 < n3; i3++ )
1203         printf( "%d ", elemPoints[ i2 ][ i3 ] );
1204
1205       printf( "\n" );
1206
1207     }
1208 #endif
1209     //////////////////////////////////////////////////////////////////////
1210
1211     // Calculate number of points used for cell
1212     vtkIdType aNbCells = elemPoints->length();
1213     vtkIdType aCellsSize = 0;
1214     for ( int i = 0, n = elemPoints->length(); i < n; i++ )
1215       aCellsSize += elemPoints[ i ].length();
1216
1217     // Create unstructured grid and other  usefull arrays
1218     vtkUnstructuredGrid* aGrid = vtkUnstructuredGrid::New();
1219
1220     vtkCellArray* aConnectivity = vtkCellArray::New();
1221     aConnectivity->Allocate( aCellsSize, 0 );
1222
1223     vtkPoints* aPoints = vtkPoints::New();
1224     aPoints->SetNumberOfPoints( pnts->length() );
1225
1226     vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
1227     aCellTypesArray->SetNumberOfComponents( 1 );
1228     aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
1229
1230     vtkIdList *anIdList = vtkIdList::New();
1231
1232     // Fill array of points
1233     for ( int p = 0, nbPnt = pnts->length(); p < nbPnt; p++ )
1234       aPoints->SetPoint( p, pnts[ p ].x, pnts[ p ].y, pnts[ p ].z );
1235
1236     for ( int e = 0, nbElem = elemPoints->length(); e < nbElem; e++ )
1237     {
1238       int nbPoints = elemPoints[ e ].length();
1239       anIdList->SetNumberOfIds( nbPoints );
1240       for ( int i = 0; i < nbPoints; i++ )
1241         anIdList->SetId( i, elemPoints[ e ][ i ] );
1242
1243       aConnectivity->InsertNextCell( anIdList );
1244
1245       if      ( nbPoints == 3 ) aCellTypesArray->InsertNextValue( VTK_TRIANGLE );
1246       else if ( nbPoints == 5 ) aCellTypesArray->InsertNextValue( VTK_PYRAMID );
1247       else if ( nbPoints == 6 ) aCellTypesArray->InsertNextValue( VTK_WEDGE );
1248       else if ( nbPoints == 8 ) aCellTypesArray->InsertNextValue( VTK_HEXAHEDRON );
1249       else if ( nbPoints == 4 && myType == Type_2d ) aCellTypesArray->InsertNextValue( VTK_QUAD );
1250       else if ( nbPoints == 4 && myType == Type_3d ) aCellTypesArray->InsertNextValue( VTK_TETRA );
1251       else aCellTypesArray->InsertNextValue( VTK_EMPTY_CELL );
1252     }
1253
1254     vtkIntArray* aCellLocationsArray = vtkIntArray::New();
1255     aCellLocationsArray->SetNumberOfComponents( 1 );
1256     aCellLocationsArray->SetNumberOfTuples( aNbCells );
1257
1258     aConnectivity->InitTraversal();
1259     for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
1260       aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
1261
1262     aGrid->SetPoints( aPoints );
1263     aGrid->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
1264
1265     aConnectivity->Delete();
1266     aPoints->Delete();
1267     aCellTypesArray->Delete();
1268     anIdList->Delete();
1269     aCellLocationsArray->Delete();
1270
1271     return aGrid;
1272   }
1273   catch( ... )
1274   {
1275     return 0;
1276   }
1277 }
1278
1279 //=======================================================================
1280 // name    : onModeToggled
1281 // Purpose : 
1282 //=======================================================================
1283 void SMESHGUI_MeshPatternDlg::onModeToggled( bool on )
1284 {
1285   on ? myRefineGrp->show() : myRefineGrp->hide();
1286   on ? myGeomGrp->hide()   : myGeomGrp->show();
1287
1288   displayPreview();
1289 }
1290
1291 //=======================================================================
1292 // name    : isRefine
1293 // Purpose : 
1294 //=======================================================================
1295 bool SMESHGUI_MeshPatternDlg::isRefine() const
1296 {
1297   return myRefine->isChecked();
1298 }
1299
1300 //=======================================================================
1301 //function : onTextChanged
1302 //purpose  : 
1303 //=======================================================================
1304 void SMESHGUI_MeshPatternDlg::onTextChanged(const QString& theNewText)
1305 {
1306   if ( myBusy || !isRefine() )
1307     return;
1308
1309   myBusy = true;
1310
1311   if ( mySelInput != Ids ) {
1312     mySelInput = Ids;
1313     activateSelection();
1314   }
1315
1316   // hilight entered elements/nodes
1317   SMDS_Mesh* aMesh = 0;
1318   SMESH_Actor* anActor = SMESH::FindActorByObject( myMesh );
1319   if ( anActor )
1320     aMesh = anActor->GetObject()->GetMesh();
1321
1322   if ( aMesh ) {
1323     mySelection->ClearIObjects();
1324     mySelection->AddIObject( anActor->getIO() );
1325
1326     QStringList aListId = QStringList::split( " ", theNewText, false);
1327
1328     for ( int i = 0; i < aListId.count(); i++ ) {
1329       const SMDS_MeshElement * e = aMesh->FindElement( aListId[ i ].toInt() );
1330       if ( e && e->GetType() == ( myType == Type_2d ? SMDSAbs_Face : SMDSAbs_Volume ) ) {
1331         if ( !mySelection->IsIndexSelected( anActor->getIO(), e->GetID() ) )
1332           mySelection->AddOrRemoveIndex( anActor->getIO(), e->GetID(), true );
1333       }
1334     }
1335   }
1336
1337   myBusy = false;
1338 }
1339
1340 //=======================================================================
1341 //function : onNodeChanged
1342 //purpose  : 
1343 //=======================================================================
1344 void SMESHGUI_MeshPatternDlg::onNodeChanged( int value )
1345 {
1346   if ( myType == Type_3d ) {
1347     QSpinBox* first = (QSpinBox*)sender();
1348     QSpinBox* second = first == myNode1 ? myNode2 : myNode1;
1349     int secondVal = second->value();
1350     if ( secondVal == value ) {
1351       secondVal = value == second->maxValue() ? second->minValue() : value + 1;
1352       bool blocked = second->signalsBlocked();
1353       second->blockSignals( true );
1354       second->setValue( secondVal );
1355       second->blockSignals( blocked );
1356     }
1357   }
1358
1359   displayPreview();
1360 }
1361
1362 //=======================================================================
1363 //function : getIds
1364 //purpose  : 
1365 //=======================================================================
1366 bool SMESHGUI_MeshPatternDlg::getIds( QValueList<int>& ids ) const
1367 {
1368   ids.clear();
1369   QStringList strIds = QStringList::split( " ", mySelEdit[Ids]->text() );
1370   bool isOk;
1371   int val;
1372   for ( QStringList::iterator it = strIds.begin(); it != strIds.end(); ++it ) {
1373     val = (*it).toInt( &isOk );
1374     if ( isOk )
1375       ids.append( val );
1376   }
1377
1378   return ids.count();
1379 }
1380
1381 //=======================================================================
1382 //function : getNode1
1383 //purpose  : 
1384 //=======================================================================
1385 int SMESHGUI_MeshPatternDlg::getNode( bool second ) const
1386 {
1387   return second ? myNode2->value() - 1 : myNode1->value() - 1;
1388 }
1389