Salome HOME
Additional fix for issue 0020614: EDF 1133 SMESH : Put new added elements and nodes...
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_AddMeshElementDlg.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  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.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 // SMESH SMESHGUI : GUI for SMESH component
23 // File   : SMESHGUI_AddMeshElementDlg.cxx
24 // Author : Nicolas REJNERI, Open CASCADE S.A.S.
25
26 //  SMESH includes
27 #include "SMESHGUI_AddMeshElementDlg.h"
28
29 #include "SMESHGUI.h"
30 #include "SMESHGUI_Utils.h"
31 #include "SMESHGUI_VTKUtils.h"
32 #include "SMESHGUI_MeshUtils.h"
33 #include "SMESHGUI_GroupUtils.h"
34 #include "SMESHGUI_IdValidator.h"
35
36 #include <SMESH_Actor.h>
37 #include <SMESH_ActorUtils.h>
38 #include <SMESH_FaceOrientationFilter.h>
39 #include <SMDS_Mesh.hxx>
40
41 // SALOME GUI inclues
42 #include <SUIT_Desktop.h>
43 #include <SUIT_Session.h>
44 #include <SUIT_ResourceMgr.h>
45 #include <SUIT_MessageBox.h>
46 #include <SUIT_ViewManager.h>
47 #include <LightApp_SelectionMgr.h>
48 #include <SALOME_ListIO.hxx>
49 #include <SalomeApp_Application.h>
50 #include <SVTK_ViewModel.h>
51 #include <SVTK_ViewWindow.h>
52
53 // IDL incldues
54 #include CORBA_SERVER_HEADER(SMESH_MeshEditor)
55
56 // OCCT includes
57 #include <TColStd_MapOfInteger.hxx>
58
59 // VTK includes
60 #include <vtkCell.h>
61 #include <vtkIdList.h>
62 #include <vtkUnstructuredGrid.h>
63 #include <vtkDataSetMapper.h>
64 #include <vtkPolyDataMapper.h>
65 #include <vtkProperty.h>
66
67 // Qt includes
68 #include <QComboBox>
69 #include <QGroupBox>
70 #include <QLabel>
71 #include <QLineEdit>
72 #include <QPushButton>
73 #include <QRadioButton>
74 #include <QHBoxLayout>
75 #include <QVBoxLayout>
76 #include <QGridLayout>
77 #include <QVariant>
78 #include <QCheckBox>
79 #include <QKeyEvent>
80 #include <QButtonGroup>
81
82 #define SPACING 6
83 #define MARGIN  11
84
85 namespace SMESH
86 {
87   class TElementSimulation
88   {
89     SalomeApp_Application* myApplication;
90     SUIT_ViewWindow* myViewWindow;
91     SVTK_ViewWindow* myVTKViewWindow;
92
93     SALOME_Actor* myPreviewActor;
94     vtkDataSetMapper* myMapper;
95     vtkUnstructuredGrid* myGrid;
96
97     SALOME_Actor* myFaceOrientation;
98     vtkPolyDataMapper* myFaceOrientationDataMapper;
99     SMESH_FaceOrientationFilter* myFaceOrientationFilter;
100
101   public:
102     TElementSimulation (SalomeApp_Application* theApplication)
103     {
104       myApplication = theApplication;
105       SUIT_ViewManager* mgr = theApplication->activeViewManager();
106       if (!mgr) return;
107       myViewWindow = mgr->getActiveView();
108       myVTKViewWindow = GetVtkViewWindow(myViewWindow);
109
110       myGrid = vtkUnstructuredGrid::New();
111
112       // Create and display actor
113       myMapper = vtkDataSetMapper::New();
114       myMapper->SetInput(myGrid);
115
116       myPreviewActor = SALOME_Actor::New();
117       myPreviewActor->PickableOff();
118       myPreviewActor->VisibilityOff();
119       myPreviewActor->SetMapper(myMapper);
120
121       vtkFloatingPointType anRGB[3];
122       vtkProperty* aProp = vtkProperty::New();
123       GetColor( "SMESH", "fill_color", anRGB[0], anRGB[1], anRGB[2], QColor( 0, 170, 255 ) );
124       aProp->SetColor( anRGB[0], anRGB[1], anRGB[2] );
125       myPreviewActor->SetProperty( aProp );
126       aProp->Delete();
127
128       vtkProperty* aBackProp = vtkProperty::New();
129       GetColor( "SMESH", "backface_color", anRGB[0], anRGB[1], anRGB[2], QColor( 0, 0, 255 ) );
130       aBackProp->SetColor( anRGB[0], anRGB[1], anRGB[2] );
131       myPreviewActor->SetBackfaceProperty( aBackProp );
132       aBackProp->Delete();
133
134       myVTKViewWindow->AddActor(myPreviewActor);
135
136       // Orientation of faces
137       myFaceOrientationFilter = SMESH_FaceOrientationFilter::New();
138       myFaceOrientationFilter->SetInput(myGrid);
139
140       myFaceOrientationDataMapper = vtkPolyDataMapper::New();
141       myFaceOrientationDataMapper->SetInput(myFaceOrientationFilter->GetOutput());
142
143       myFaceOrientation = SALOME_Actor::New();
144       myFaceOrientation->PickableOff();
145       myFaceOrientation->VisibilityOff();
146       myFaceOrientation->SetMapper(myFaceOrientationDataMapper);
147
148       vtkProperty* anOrientationProp = vtkProperty::New();
149       GetColor( "SMESH", "orientation_color", anRGB[0], anRGB[1], anRGB[2], QColor( 255, 255, 255 ) );
150       anOrientationProp->SetColor( anRGB[0], anRGB[1], anRGB[2] );
151       myFaceOrientation->SetProperty( anOrientationProp );
152       anOrientationProp->Delete();
153
154       myVTKViewWindow->AddActor(myFaceOrientation);
155     }
156
157     typedef std::vector<vtkIdType> TVTKIds;
158     void SetPosition (SMESH_Actor* theActor,
159                       vtkIdType theType,
160                       const TVTKIds& theIds)
161     {
162       vtkUnstructuredGrid *aGrid = theActor->GetUnstructuredGrid();
163       myGrid->SetPoints(aGrid->GetPoints());
164
165       const int* aConn = NULL;
166       switch (theType) {
167       case VTK_TETRA:
168         {
169           static int anIds[] = {0,2,1,3};
170           aConn = anIds;
171           break;
172         }
173       case VTK_PYRAMID:
174         {
175           static int anIds[] = {0,3,2,1,4};
176           aConn = anIds;
177           break;
178         }
179       case VTK_HEXAHEDRON:
180         {
181           static int anIds[] = {0,3,2,1,4,7,6,5};
182           aConn = anIds;
183           break;
184         }
185       }
186
187       myGrid->Reset();
188       vtkIdList *anIds = vtkIdList::New();
189
190       if(aConn)
191         for (int i = 0, iEnd = theIds.size(); i < iEnd; i++)
192           anIds->InsertId(i,theIds[aConn[i]]);
193       else
194         for (int i = 0, iEnd = theIds.size(); i < iEnd; i++)
195           anIds->InsertId(i,theIds[i]);
196
197       myGrid->InsertNextCell(theType,anIds);
198       anIds->Delete();
199
200       myGrid->Modified();
201
202       SetVisibility(true, theActor->GetFacesOriented());
203     }
204
205
206     void SetVisibility (bool theVisibility, bool theShowOrientation = false)
207     {
208       myPreviewActor->SetVisibility(theVisibility);
209       myFaceOrientation->SetVisibility(theShowOrientation);
210       RepaintCurrentView();
211     }
212
213
214     ~TElementSimulation()
215     {
216       if (FindVtkViewWindow(myApplication->activeViewManager(), myViewWindow)) {
217         myVTKViewWindow->RemoveActor(myPreviewActor);
218         myVTKViewWindow->RemoveActor(myFaceOrientation);
219       }
220       myPreviewActor->Delete();
221       myFaceOrientation->Delete();
222
223       myMapper->RemoveAllInputs();
224       myMapper->Delete();
225
226       myFaceOrientationFilter->Delete();
227
228       myFaceOrientationDataMapper->RemoveAllInputs();
229       myFaceOrientationDataMapper->Delete();
230
231       myGrid->Delete();
232     }
233   };
234 }
235
236 //=================================================================================
237 // function : SMESHGUI_AddMeshElementDlg()
238 // purpose  : constructor
239 //=================================================================================
240 SMESHGUI_AddMeshElementDlg::SMESHGUI_AddMeshElementDlg( SMESHGUI* theModule,
241                                                         SMDSAbs_ElementType ElementType,
242                                                         int nbNodes )
243   : QDialog( SMESH::GetDesktop( theModule ) ),
244     mySMESHGUI( theModule ),
245     mySelectionMgr( SMESH::GetSelectionMgr( theModule ) )
246 {
247   setModal( false );
248   setAttribute( Qt::WA_DeleteOnClose, true );
249
250   SalomeApp_Application* anApp = dynamic_cast<SalomeApp_Application*>
251     (SUIT_Session::session()->activeApplication());
252   myIsPoly = false;
253   mySimulation = new SMESH::TElementSimulation (anApp);
254   mySelector = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector();
255
256   // verify nb nodes and type
257   myNbNodes = nbNodes;
258   myElementType = ElementType;
259   switch (ElementType) {
260   case SMDSAbs_0DElement:
261     if (myNbNodes != 1)
262       myNbNodes = 1;
263     break;
264   case SMDSAbs_Face:
265     //     if (myNbNodes != 3 && myNbNodes != 4)
266     //       myNbNodes = 3;
267     //     break;
268   case SMDSAbs_Volume:
269     //     if (myNbNodes != 4 && myNbNodes != 8) //(nbNodes < 4 || nbNodes > 8 || nbNodes == 7)
270     //       myNbNodes = 4;
271     break;
272   default:
273     myElementType = SMDSAbs_Edge;
274     myNbNodes = 2;
275   }
276
277   QString elemName;
278   if (myNbNodes == 1) {
279     elemName = "ELEM0D";
280     myHelpFileName = "adding_nodes_and_elements_page.html#adding_0delems_anchor";
281   }
282   else if (myNbNodes == 2) {
283     elemName = "EDGE";
284     myHelpFileName = "adding_nodes_and_elements_page.html#adding_edges_anchor";
285   }
286   else if (myNbNodes == 3) {
287     elemName = "TRIANGLE";
288     myHelpFileName = "adding_nodes_and_elements_page.html#adding_triangles_anchor";
289   }
290   else if (myNbNodes == 4) {
291     if (myElementType == SMDSAbs_Face) {
292       elemName = "QUADRANGLE";
293       myHelpFileName = "adding_nodes_and_elements_page.html#adding_quadrangles_anchor";
294     }
295     else {
296       elemName = "TETRAS";
297       myHelpFileName = "adding_nodes_and_elements_page.html#adding_tetrahedrons_anchor";
298     }
299   }
300   else if (myNbNodes == 8) {
301     elemName = "HEXAS";
302     myHelpFileName = "adding_nodes_and_elements_page.html#adding_hexahedrons_anchor";
303   }
304   else if (myElementType == SMDSAbs_Face) {
305     elemName = "POLYGON";
306     myIsPoly = true;
307     myHelpFileName = "adding_nodes_and_elements_page.html#adding_polygons_anchor";
308   }
309   else if (myElementType == SMDSAbs_Volume) {
310     myHelpFileName = "adding_nodes_and_elements_page.html#adding_polyhedrons_anchor";
311   }
312
313   QString iconName      = tr(QString("ICON_DLG_%1").arg(elemName).toLatin1().data());
314   QString buttonGrTitle = tr(QString("SMESH_%1").arg(elemName).toLatin1().data());
315   QString caption       = tr(QString("SMESH_ADD_%1_TITLE").arg(elemName).toLatin1().data());
316   QString grBoxTitle    = tr(QString("SMESH_ADD_%1").arg(elemName).toLatin1().data());
317
318   QPixmap image0 (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", iconName));
319   QPixmap image1 (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_SELECT")));
320
321   setWindowTitle(caption);
322   setSizeGripEnabled(true);
323
324   QVBoxLayout* aTopLayout = new QVBoxLayout(this);
325   aTopLayout->setSpacing(SPACING);
326   aTopLayout->setMargin(MARGIN);
327
328   /***************************************************************/
329   GroupConstructors = new QGroupBox(buttonGrTitle, this);
330   QButtonGroup* ButtonGroup = new QButtonGroup(this);
331   QHBoxLayout* GroupConstructorsLayout = new QHBoxLayout(GroupConstructors);
332   GroupConstructorsLayout->setSpacing(SPACING);
333   GroupConstructorsLayout->setMargin(MARGIN);
334
335   Constructor1 = new QRadioButton(GroupConstructors);
336   Constructor1->setIcon(image0);
337   Constructor1->setChecked(true);
338
339   GroupConstructorsLayout->addWidget(Constructor1);
340   ButtonGroup->addButton( Constructor1, 0 );
341
342   /***************************************************************/
343   GroupC1 = new QGroupBox(grBoxTitle, this);
344   QGridLayout* GroupC1Layout = new QGridLayout(GroupC1);
345   GroupC1Layout->setSpacing(SPACING);
346   GroupC1Layout->setMargin(MARGIN);
347
348   TextLabelC1A1 = new QLabel(tr("SMESH_ID_NODES"), GroupC1);
349   SelectButtonC1A1 = new QPushButton(GroupC1);
350   SelectButtonC1A1->setIcon(image1);
351   LineEditC1A1 = new QLineEdit(GroupC1);
352   //  LineEditC1A1->setReadOnly(true);
353   if (!myIsPoly)
354     LineEditC1A1->setValidator(new SMESHGUI_IdValidator(this, myNbNodes));
355
356   Reverse = myElementType == SMDSAbs_Face ? new QCheckBox(tr("SMESH_REVERSE"), GroupC1) : 0;
357
358   GroupC1Layout->addWidget(TextLabelC1A1,    0, 0);
359   GroupC1Layout->addWidget(SelectButtonC1A1, 0, 1);
360   GroupC1Layout->addWidget(LineEditC1A1,     0, 2);
361   if ( Reverse ) GroupC1Layout->addWidget(Reverse, 1, 0, 1, 3);
362
363   /***************************************************************/
364   GroupGroups = new QGroupBox( tr( "SMESH_ADD_TO_GROUP" ), this );
365   GroupGroups->setCheckable( true );
366   QHBoxLayout* GroupGroupsLayout = new QHBoxLayout(GroupGroups);
367   GroupGroupsLayout->setSpacing(SPACING);
368   GroupGroupsLayout->setMargin(MARGIN);
369
370   TextLabel_GroupName = new QLabel( tr( "SMESH_GROUP" ), GroupGroups );
371   ComboBox_GroupName = new QComboBox( GroupGroups );
372   ComboBox_GroupName->setEditable( true );
373
374   GroupGroupsLayout->addWidget( TextLabel_GroupName );
375   GroupGroupsLayout->addWidget( ComboBox_GroupName, 1 );
376
377   /***************************************************************/
378   GroupButtons = new QGroupBox(this);
379   QHBoxLayout* GroupButtonsLayout = new QHBoxLayout(GroupButtons);
380   GroupButtonsLayout->setSpacing(SPACING);
381   GroupButtonsLayout->setMargin(MARGIN);
382
383   buttonOk = new QPushButton(tr("SMESH_BUT_APPLY_AND_CLOSE"), GroupButtons);
384   buttonOk->setAutoDefault(true);
385   buttonOk->setDefault(true);
386   buttonApply = new QPushButton(tr("SMESH_BUT_APPLY"), GroupButtons);
387   buttonApply->setAutoDefault(true);
388   buttonCancel = new QPushButton(tr("SMESH_BUT_CLOSE"), GroupButtons);
389   buttonCancel->setAutoDefault(true);
390   buttonHelp = new QPushButton(tr("SMESH_BUT_HELP"), GroupButtons);
391   buttonHelp->setAutoDefault(true);
392
393   GroupButtonsLayout->addWidget(buttonOk);
394   GroupButtonsLayout->addSpacing(10);
395   GroupButtonsLayout->addWidget(buttonApply);
396   GroupButtonsLayout->addSpacing(10);
397   GroupButtonsLayout->addStretch();
398   GroupButtonsLayout->addWidget(buttonCancel);
399   GroupButtonsLayout->addWidget(buttonHelp);
400
401   /***************************************************************/
402   aTopLayout->addWidget(GroupConstructors);
403   aTopLayout->addWidget(GroupC1);
404   aTopLayout->addWidget(GroupGroups);
405   aTopLayout->addWidget(GroupButtons);
406
407   Init(); /* Initialisations */
408 }
409
410 //=================================================================================
411 // function : ~SMESHGUI_AddMeshElementDlg()
412 // purpose  : Destroys the object and frees any allocated resources
413 //=================================================================================
414 SMESHGUI_AddMeshElementDlg::~SMESHGUI_AddMeshElementDlg()
415 {
416   delete mySimulation;
417 }
418
419 //=================================================================================
420 // function : Init()
421 // purpose  :
422 //=================================================================================
423 void SMESHGUI_AddMeshElementDlg::Init()
424 {
425   GroupC1->show();
426   Constructor1->setChecked(true);
427   myEditCurrentArgument = LineEditC1A1;
428   mySMESHGUI->SetActiveDialogBox((QDialog*)this);
429
430   /* reset "Add to group" control */
431   GroupGroups->setChecked( false );
432   GroupGroups->setVisible( myElementType != SMDSAbs_0DElement );
433
434   myNbOkNodes = 0;
435   myActor = 0;
436
437   /* signals and slots connections */
438   connect(buttonOk, SIGNAL(clicked()),     SLOT(ClickOnOk()));
439   connect(buttonCancel, SIGNAL(clicked()), SLOT(ClickOnCancel()));
440   connect(buttonApply, SIGNAL(clicked()),  SLOT(ClickOnApply()));
441   connect(buttonHelp, SIGNAL(clicked()),   SLOT(ClickOnHelp()));
442
443   connect(SelectButtonC1A1, SIGNAL(clicked()), SLOT(SetEditCurrentArgument()));
444   connect(LineEditC1A1, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
445   connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), SLOT(DeactivateActiveDialog()));
446   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(SelectionIntoArgument()));
447   /* to close dialog if study frame change */
448   connect(mySMESHGUI, SIGNAL (SignalStudyFrameChanged()), SLOT(ClickOnCancel()));
449
450   if (Reverse)
451     connect(Reverse, SIGNAL(stateChanged(int)), SLOT(CheckBox(int)));
452
453   // set selection mode
454   SMESH::SetPointRepresentation(true);
455
456   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
457     aViewWindow->SetSelectionMode( NodeSelection );
458
459   myBusy = false;
460
461   SelectionIntoArgument();
462 }
463
464 //=================================================================================
465 // function : ClickOnApply()
466 // purpose  :
467 //=================================================================================
468 void SMESHGUI_AddMeshElementDlg::ClickOnApply()
469 {
470   if( !isValid() )
471     return;
472
473   if (myNbOkNodes && !mySMESHGUI->isActiveStudyLocked()) {
474     myBusy = true;
475     SMESH::long_array_var anArrayOfIndices = new SMESH::long_array;
476     anArrayOfIndices->length(myNbNodes);
477     bool reverse = (Reverse && Reverse->isChecked());
478     QStringList aListId = myEditCurrentArgument->text().split(" ", QString::SkipEmptyParts);
479     for (int i = 0; i < aListId.count(); i++)
480       if (reverse)
481         anArrayOfIndices[i] = aListId[ myNbNodes - i - 1 ].toInt();
482       else
483         anArrayOfIndices[i] = aListId[ i ].toInt();
484
485     long anElemId = -1;
486     SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor();
487     switch (myElementType) {
488     case SMDSAbs_0DElement:
489       anElemId = aMeshEditor->Add0DElement(anArrayOfIndices[0]); break;
490     case SMDSAbs_Edge:
491       anElemId = aMeshEditor->AddEdge(anArrayOfIndices.inout()); break;
492     case SMDSAbs_Face: {
493       if(myIsPoly)
494         anElemId = aMeshEditor->AddPolygonalFace(anArrayOfIndices.inout());
495       else
496         anElemId = aMeshEditor->AddFace(anArrayOfIndices.inout());
497       break;
498     }
499     case SMDSAbs_Volume:
500       anElemId = aMeshEditor->AddVolume(anArrayOfIndices.inout()); break;
501     default:;
502     }
503
504     if( anElemId != -1 && GroupGroups->isChecked() ) {
505       SMESH::SMESH_Group_var aGroup;
506       QString aGroupName = ComboBox_GroupName->currentText();
507       SMESH::ListOfGroups aListOfGroups = *myMesh->GetGroups();
508       for( int i = 0, n = aListOfGroups.length(); i < n; i++ ) {
509         SMESH::SMESH_GroupBase_var aGroupBase = aListOfGroups[i];
510         if( !aGroupBase->_is_nil() ) {
511           SMESH::SMESH_Group_var aRefGroup = SMESH::SMESH_Group::_narrow( aGroupBase );
512           if( !aRefGroup->_is_nil() ) {
513             QString aRefGroupName( aRefGroup->GetName() );
514             if( aRefGroupName == aGroupName ) {
515               aGroup = aRefGroup; // // add node to existing group
516               break;
517             }
518           }
519         }
520       }
521       if( aGroup->_is_nil() ) // create new group
522         aGroup = SMESH::AddGroup( myMesh, (SMESH::ElementType)myElementType, aGroupName );
523
524       if( !aGroup->_is_nil() ) {
525         SMESH::long_array_var anIdList = new SMESH::long_array;
526         anIdList->length( 1 );
527         anIdList[0] = anElemId;
528         aGroup->Add( anIdList.inout() );
529       }
530     }
531
532     SALOME_ListIO aList; aList.Append( myActor->getIO() );
533     mySelector->ClearIndex();
534     mySelectionMgr->setSelectedObjects( aList, false );
535
536     SMESH::UpdateView();
537     mySimulation->SetVisibility(false);
538
539     buttonOk->setEnabled(false);
540     buttonApply->setEnabled(false);
541
542     myEditCurrentArgument->setText("");
543
544     myBusy = false;
545   }
546 }
547
548 //=================================================================================
549 // function : ClickOnOk()
550 // purpose  :
551 //=================================================================================
552 void SMESHGUI_AddMeshElementDlg::ClickOnOk()
553 {
554   ClickOnApply();
555   ClickOnCancel();
556 }
557
558 //=================================================================================
559 // function : ClickOnCancel()
560 // purpose  :
561 //=================================================================================
562 void SMESHGUI_AddMeshElementDlg::ClickOnCancel()
563 {
564   //mySelectionMgr->clearSelected();
565   mySimulation->SetVisibility(false);
566   SMESH::SetPointRepresentation(false);
567   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
568     aViewWindow->SetSelectionMode( ActorSelection );
569   disconnect(mySelectionMgr, 0, this, 0);
570   mySMESHGUI->ResetState();
571   reject();
572 }
573
574 //=================================================================================
575 // function : ClickOnHelp()
576 // purpose  :
577 //=================================================================================
578 void SMESHGUI_AddMeshElementDlg::ClickOnHelp()
579 {
580   LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
581   if (app)
582     app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""),
583                              myHelpFileName);
584   else {
585     QString platform;
586 #ifdef WIN32
587     platform = "winapplication";
588 #else
589     platform = "application";
590 #endif
591     SUIT_MessageBox::warning(this, tr("WRN_WARNING"),
592                              tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
593                              arg(app->resourceMgr()->stringValue("ExternalBrowser",
594                                                                  platform)).
595                              arg(myHelpFileName));
596   }
597 }
598
599 //=================================================================================
600 // function : onTextChange()
601 // purpose  :
602 //=================================================================================
603 void SMESHGUI_AddMeshElementDlg::onTextChange (const QString& theNewText)
604 {
605   if (myBusy) return;
606   myBusy = true;
607
608   myNbOkNodes = 0;
609
610   buttonOk->setEnabled(false);
611   buttonApply->setEnabled(false);
612
613   mySimulation->SetVisibility(false);
614
615   // hilight entered nodes
616   SMDS_Mesh* aMesh = 0;
617   if (myActor)
618     aMesh = myActor->GetObject()->GetMesh();
619
620   if (aMesh) {
621     TColStd_MapOfInteger newIndices;
622
623     QStringList aListId = theNewText.split(" ", QString::SkipEmptyParts);
624     bool allOk = true;
625     for (int i = 0; i < aListId.count(); i++) {
626       if( const SMDS_MeshNode * n = aMesh->FindNode( aListId[ i ].toInt() ) )
627         {
628           newIndices.Add( n->GetID() );
629           myNbOkNodes++;
630         }
631       else
632         allOk = false;  
633     }
634
635     mySelector->AddOrRemoveIndex( myActor->getIO(), newIndices, false );
636     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
637       aViewWindow->highlight( myActor->getIO(), true, true );
638
639     myNbOkNodes = ( allOk && myNbNodes == aListId.count() );
640
641     if (myIsPoly)
642       {
643         if ( !allOk || myElementType != SMDSAbs_Face || aListId.count() < 3 )
644           myNbOkNodes = 0;
645         else
646           myNbOkNodes = aListId.count();
647       }
648   }
649
650   if(myNbOkNodes) {
651     buttonOk->setEnabled(true);
652     buttonApply->setEnabled(true);
653     displaySimulation();
654   }
655
656   myBusy = false;
657 }
658
659 //=================================================================================
660 // function : SelectionIntoArgument()
661 // purpose  : Called when selection has changed
662 //=================================================================================
663 void SMESHGUI_AddMeshElementDlg::SelectionIntoArgument()
664 {
665   if (myBusy) return;
666
667   // clear
668   myNbOkNodes = 0;
669   myActor = 0;
670
671   myBusy = true;
672   myEditCurrentArgument->setText("");
673   myBusy = false;
674
675   if (!GroupButtons->isEnabled()) // inactive
676     return;
677
678   buttonOk->setEnabled(false);
679   buttonApply->setEnabled(false);
680
681   mySimulation->SetVisibility(false);
682   //  SMESH::SetPointRepresentation(true);
683
684   QString aCurrentEntry = myEntry;
685
686   // get selected mesh
687   SALOME_ListIO aList;
688   mySelectionMgr->selectedObjects(aList,SVTK_Viewer::Type());
689
690   if (aList.Extent() != 1)
691     return;
692
693   Handle(SALOME_InteractiveObject) anIO = aList.First();
694   myEntry = anIO->getEntry();
695   myMesh = SMESH::GetMeshByIO(anIO);
696   if (myMesh->_is_nil())
697     return;
698
699   // process groups
700   if ( !myMesh->_is_nil() && myEntry != aCurrentEntry ) {
701     ComboBox_GroupName->clear();
702     ComboBox_GroupName->addItem( QString() );
703     SMESH::ListOfGroups aListOfGroups = *myMesh->GetGroups();
704     for ( int i = 0, n = aListOfGroups.length(); i < n; i++ ) {
705       SMESH::SMESH_GroupBase_var aGroupBase = aListOfGroups[i];
706       if ( !aGroupBase->_is_nil() && aGroupBase->GetType() == (SMESH::ElementType)myElementType ) {
707         SMESH::SMESH_Group_var aGroup = SMESH::SMESH_Group::_narrow( aGroupBase );
708         if ( !aGroup->_is_nil() ) {
709           QString aGroupName( aGroup->GetName() );
710           if ( !aGroupName.isEmpty() )
711             ComboBox_GroupName->addItem( aGroupName );
712         }
713       }
714     }
715   }
716
717   myActor = SMESH::FindActorByEntry(anIO->getEntry());
718   if (!myActor)
719     return;
720
721   // get selected nodes
722   QString aString = "";
723   int nbNodes = SMESH::GetNameOfSelectedNodes(mySelector,myActor->getIO(),aString);
724   myBusy = true;
725   myEditCurrentArgument->setText(aString);
726   myBusy = false;
727   if (myIsPoly && myElementType == SMDSAbs_Face && nbNodes >= 3 ) {
728     myNbNodes = nbNodes;
729   } else if (myNbNodes != nbNodes) {
730     return;
731   }
732
733   // OK
734   myNbOkNodes = nbNodes;
735
736   buttonOk->setEnabled(true);
737   buttonApply->setEnabled(true);
738
739   displaySimulation();
740 }
741
742 //=================================================================================
743 // function : displaySimulation()
744 // purpose  :
745 //=================================================================================
746 void SMESHGUI_AddMeshElementDlg::displaySimulation()
747 {
748   if (myNbOkNodes && GroupButtons->isEnabled()) {
749     SMESH::TElementSimulation::TVTKIds anIds;
750     QStringList aListId = myEditCurrentArgument->text().split(" ", QString::SkipEmptyParts);
751     for (int i = 0; i < aListId.count(); i++)
752       anIds.push_back(myActor->GetObject()->GetNodeVTKId(aListId[ i ].toInt()));
753
754     if (Reverse && Reverse->isChecked())
755       reverse(anIds.begin(),anIds.end());
756
757     vtkIdType aType = 0;
758     if (myIsPoly)
759       switch ( myElementType ) {
760       case SMDSAbs_Face  : aType = VTK_POLYGON; break;
761       default: return;
762       }
763     else {
764       switch (myNbNodes) {
765       case 2: aType = VTK_LINE; break;
766       case 3: aType = VTK_TRIANGLE; break;
767       case 4: aType = myElementType == SMDSAbs_Face ? VTK_QUAD : VTK_TETRA; break;
768       case 8: aType = VTK_HEXAHEDRON; break;
769       default: return;
770       }
771     }
772
773     mySimulation->SetPosition(myActor,aType,anIds);
774     SMESH::UpdateView();
775   }
776 }
777
778 //=================================================================================
779 // function : SetEditCurrentArgument()
780 // purpose  :
781 //=================================================================================
782 void SMESHGUI_AddMeshElementDlg::SetEditCurrentArgument()
783 {
784   QPushButton* send = (QPushButton*)sender();
785   if (send == SelectButtonC1A1) {
786     LineEditC1A1->setFocus();
787     myEditCurrentArgument = LineEditC1A1;
788   }
789   SelectionIntoArgument();
790 }
791
792 //=================================================================================
793 // function : DeactivateActiveDialog()
794 // purpose  :
795 //=================================================================================
796 void SMESHGUI_AddMeshElementDlg::DeactivateActiveDialog()
797 {
798   if (GroupConstructors->isEnabled()) {
799     GroupConstructors->setEnabled(false);
800     GroupC1->setEnabled(false);
801     GroupButtons->setEnabled(false);
802     mySimulation->SetVisibility(false);
803     mySMESHGUI->ResetState();
804     mySMESHGUI->SetActiveDialogBox(0);
805   }
806 }
807
808 //=================================================================================
809 // function : ActivateThisDialog()
810 // purpose  :
811 //=================================================================================
812 void SMESHGUI_AddMeshElementDlg::ActivateThisDialog()
813 {
814   /* Emit a signal to deactivate the active dialog */
815   mySMESHGUI->EmitSignalDeactivateDialog();
816
817   GroupConstructors->setEnabled(true);
818   GroupC1->setEnabled(true);
819   GroupButtons->setEnabled(true);
820
821   SMESH::SetPointRepresentation(true);
822
823   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
824     aViewWindow->SetSelectionMode( NodeSelection );
825   SelectionIntoArgument();
826 }
827
828 //=================================================================================
829 // function : enterEvent()
830 // purpose  :
831 //=================================================================================
832 void SMESHGUI_AddMeshElementDlg::enterEvent (QEvent*)
833 {
834   if (GroupConstructors->isEnabled())
835     return;
836   ActivateThisDialog();
837 }
838
839 //=================================================================================
840 // function : closeEvent()
841 // purpose  :
842 //=================================================================================
843 void SMESHGUI_AddMeshElementDlg::closeEvent (QCloseEvent*)
844 {
845   /* same than click on cancel button */
846   ClickOnCancel();
847 }
848
849 //=================================================================================
850 // function : hideEvent()
851 // purpose  : caused by ESC key
852 //=================================================================================
853 void SMESHGUI_AddMeshElementDlg::hideEvent (QHideEvent*)
854 {
855   if (!isMinimized())
856     ClickOnCancel();
857 }
858
859 //=================================================================================
860 // function : CheckBox()
861 // purpose  :
862 //=================================================================================
863 void SMESHGUI_AddMeshElementDlg::CheckBox (int state)
864 {
865   if (!myNbOkNodes)
866     return;
867
868   if (state >= 0) {
869     mySimulation->SetVisibility(false);
870     displaySimulation();
871   }
872 }
873
874 //=================================================================================
875 // function : keyPressEvent()
876 // purpose  :
877 //=================================================================================
878 void SMESHGUI_AddMeshElementDlg::keyPressEvent( QKeyEvent* e )
879 {
880   QDialog::keyPressEvent( e );
881   if ( e->isAccepted() )
882     return;
883
884   if ( e->key() == Qt::Key_F1 ) {
885     e->accept();
886     ClickOnHelp();
887   }
888 }
889
890 //=================================================================================
891 // function : isValid
892 // purpose  :
893 //=================================================================================
894 bool SMESHGUI_AddMeshElementDlg::isValid()
895 {
896   if( GroupGroups->isChecked() && ComboBox_GroupName->currentText().isEmpty() ) {
897     SUIT_MessageBox::warning( this, tr( "SMESH_WRN_WARNING" ), tr( "GROUP_NAME_IS_EMPTY" ) );
898     return false;
899   }
900   return true;
901 }