Salome HOME
23189: EDF 11603 - Dyssymetry in meshing
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_MakeNodeAtPointDlg.cxx
1 // Copyright (C) 2007-2015  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, or (at your option) any later version.
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
23 // File   : SMESHGUI_MakeNodeAtPointDlg.cxx
24 // Author : Edward AGAPOV, Open CASCADE S.A.S.
25 // SMESH includes
26 //
27 #include "SMESHGUI_MakeNodeAtPointDlg.h"
28
29 #include "SMESHGUI.h"
30 #include "SMESHGUI_IdValidator.h"
31 #include "SMESHGUI_MeshUtils.h"
32 #include "SMESHGUI_VTKUtils.h"
33 #include "SMESHGUI_SpinBox.h"
34 #include "SMESHGUI_MeshEditPreview.h"
35
36 #include <SMDS_Mesh.hxx>
37 #include <SMESH_Actor.h>
38 #include <SMESH_ActorUtils.h>
39 #include <SMESH_NumberFilter.hxx>
40 #include <SMESH_LogicalFilter.hxx>
41
42 // SALOME GEOM includes
43 #include <GEOMBase.h>
44
45 // SALOME GUI includes
46 #include <LightApp_SelectionMgr.h>
47 #include <SALOME_ListIO.hxx>
48 #include <SUIT_Desktop.h>
49 #include <SVTK_ViewModel.h>
50 #include <SVTK_ViewWindow.h>
51 #include <SalomeApp_Tools.h>
52 #include <SalomeApp_TypeFilter.h>
53 #include <SUIT_ResourceMgr.h>
54 #include <SUIT_OverrideCursor.h>
55 #include <SUIT_MessageBox.h>
56
57 // OCCT includes
58 #include <TColStd_MapOfInteger.hxx>
59 #include <TopoDS_Vertex.hxx>
60 #include <BRep_Tool.hxx>
61 #include <gp_Pnt.hxx>
62
63 // Qt includes
64 #include <QApplication>
65 #include <QGroupBox>
66 #include <QGridLayout>
67 #include <QHBoxLayout>
68 #include <QVBoxLayout>
69 #include <QLineEdit>
70 #include <QPushButton>
71 #include <QLabel>
72 #include <QRadioButton>
73 #include <QCheckBox>
74 #include <QButtonGroup>
75
76 // VTK includes
77 #include <vtkProperty.h>
78
79 // IDL includes
80 #include <SALOMEconfig.h>
81 #include CORBA_SERVER_HEADER(SMESH_Mesh)
82 #include CORBA_SERVER_HEADER(SMESH_MeshEditor)
83
84 #define SPACING 6
85 #define MARGIN  11
86
87 /*!
88  * \brief Dialog to publish a sub-shape of the mesh main shape
89  *        by selecting mesh elements
90  */
91 SMESHGUI_MakeNodeAtPointDlg::SMESHGUI_MakeNodeAtPointDlg()
92   : SMESHGUI_Dialog( 0, false, true )
93 {
94   setWindowTitle(tr("CAPTION"));
95
96   QVBoxLayout* aDlgLay = new QVBoxLayout (mainFrame());
97   aDlgLay->setMargin(0);
98   aDlgLay->setSpacing(SPACING);
99   myMainFrame = createMainFrame(mainFrame());
100
101   aDlgLay->addWidget(myMainFrame);
102
103   aDlgLay->setStretchFactor(myMainFrame, 1);
104 }
105
106 //=======================================================================
107 // function : createMainFrame()
108 // purpose  : Create frame containing dialog's input fields
109 //=======================================================================
110 QWidget* SMESHGUI_MakeNodeAtPointDlg::createMainFrame (QWidget* theParent)
111 {
112   QWidget* aFrame = new QWidget(theParent);
113
114   SUIT_ResourceMgr* rm = SMESH::GetResourceMgr( SMESHGUI::GetSMESHGUI() );
115   QPixmap iconMoveNode        (rm->loadPixmap("SMESH", tr("ICON_DLG_MOVE_NODE")));
116   QPixmap iconMoveWithoutNode (rm->loadPixmap("SMESH", tr("ICON_DLG_MOVE_WITHOUT_NODE")));
117   QPixmap iconSelect          (rm->loadPixmap("SMESH", tr("ICON_SELECT")));
118
119   // constructor
120   QGroupBox* aPixGrp = new QGroupBox(tr("MOVE_NODE"), this);
121   aPixGrp->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
122   myButtonGroup = new QButtonGroup(this);
123   QHBoxLayout* aPixGrpLayout = new QHBoxLayout(aPixGrp);
124   aPixGrpLayout->setMargin(MARGIN);
125   aPixGrpLayout->setSpacing(SPACING);
126
127   myRButNodeToMove = new QRadioButton(aPixGrp);
128   myRButMoveWithoutNode = new QRadioButton(aPixGrp);
129   myRButNodeToMove->setIcon(iconMoveNode);
130   myRButMoveWithoutNode->setIcon(iconMoveWithoutNode);
131   myRButNodeToMove->setChecked(true);
132
133   aPixGrpLayout->addWidget(myRButNodeToMove);
134   aPixGrpLayout->addWidget(myRButMoveWithoutNode);
135   myButtonGroup->addButton(myRButNodeToMove, 0);
136   myButtonGroup->addButton(myRButMoveWithoutNode, 1);
137
138   // Node to move
139
140   myNodeToMoveGrp = new QGroupBox(tr("NODE_2MOVE"), aFrame);
141   myNodeToMoveGrp->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
142   QLabel* idLabel = new QLabel(tr("NODE_2MOVE_ID"), myNodeToMoveGrp);
143   myIdBtn = new QPushButton(myNodeToMoveGrp);
144   myIdBtn->setIcon(iconSelect);
145   myIdBtn->setCheckable(true);
146   myId = new QLineEdit(myNodeToMoveGrp);
147   myId->setValidator(new SMESHGUI_IdValidator(this, 1));
148
149   myUpdateBtn = new QPushButton(tr("UPDATE_DESTINATION"), myNodeToMoveGrp);
150   myUpdateBtn->setAutoDefault(true);
151
152   QWidget* aCoordWidget = new QWidget(myNodeToMoveGrp);
153
154   QLabel* aCurrentXLabel = new QLabel(tr("SMESH_X"), aCoordWidget);
155   myCurrentX = new SMESHGUI_SpinBox(aCoordWidget);
156   myCurrentX->setButtonSymbols(QAbstractSpinBox::NoButtons);
157   myCurrentX->setReadOnly(true);
158
159   QLabel* aCurrentYLabel = new QLabel(tr("SMESH_Y"), aCoordWidget);
160   myCurrentY = new SMESHGUI_SpinBox(aCoordWidget);
161   myCurrentY->setButtonSymbols(QAbstractSpinBox::NoButtons);
162   myCurrentY->setReadOnly(true);
163
164   QLabel* aCurrentZLabel = new QLabel(tr("SMESH_Z"), aCoordWidget);
165   myCurrentZ = new SMESHGUI_SpinBox(aCoordWidget);
166   myCurrentZ->setButtonSymbols(QAbstractSpinBox::NoButtons);
167   myCurrentZ->setReadOnly(true);
168
169   myCurrentX->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
170   myCurrentY->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
171   myCurrentZ->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
172
173   QGridLayout* aCoordLayout = new QGridLayout(aCoordWidget);
174   aCoordLayout->setMargin(0);
175   aCoordLayout->setSpacing(SPACING);
176   aCoordLayout->addWidget(aCurrentXLabel, 0, 0);
177   aCoordLayout->addWidget(myCurrentX,     0, 1);
178   aCoordLayout->addWidget(aCurrentYLabel, 0, 2);
179   aCoordLayout->addWidget(myCurrentY,     0, 3);
180   aCoordLayout->addWidget(aCurrentZLabel, 0, 4);
181   aCoordLayout->addWidget(myCurrentZ,     0, 5);
182   aCoordLayout->setColumnStretch(1, 1);
183   aCoordLayout->setColumnStretch(3, 1);
184   aCoordLayout->setColumnStretch(5, 1);
185
186   QGridLayout* myNodeToMoveGrpLayout = new QGridLayout(myNodeToMoveGrp);
187   myNodeToMoveGrpLayout->setSpacing(SPACING);
188   myNodeToMoveGrpLayout->setMargin(MARGIN);
189
190   myNodeToMoveGrpLayout->addWidget( idLabel, 0, 0 );
191   myNodeToMoveGrpLayout->addWidget( myIdBtn, 0, 1 );
192   myNodeToMoveGrpLayout->addWidget( myId,    0, 2 );
193   myNodeToMoveGrpLayout->addWidget( myUpdateBtn, 0, 3 );
194   myNodeToMoveGrpLayout->addWidget( aCoordWidget,       1, 0, 1, 4 );
195
196   // Destination
197
198   myDestinationGrp = new QGroupBox(tr("DESTINATION"), aFrame);
199   myDestinationGrp->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
200
201   myDestBtn = new QPushButton(myDestinationGrp);
202   myDestBtn->setIcon(iconSelect);
203   myDestBtn->setCheckable(true);
204
205   QLabel* aDestinationXLabel = new QLabel(tr("SMESH_X"), myDestinationGrp);
206   myDestinationX = new SMESHGUI_SpinBox(myDestinationGrp);
207
208   QLabel* aDestinationYLabel = new QLabel(tr("SMESH_Y"), myDestinationGrp);
209   myDestinationY = new SMESHGUI_SpinBox(myDestinationGrp);
210
211   QLabel* aDestinationZLabel = new QLabel(tr("SMESH_Z"), myDestinationGrp);
212   myDestinationZ = new SMESHGUI_SpinBox(myDestinationGrp);
213
214   myDestDXLabel = new QLabel(tr("SMESH_DX"), myDestinationGrp);
215   myDestDX = new SMESHGUI_SpinBox(myDestinationGrp);
216   myDestDX->setReadOnly(true);
217
218   myDestDYLabel = new QLabel(tr("SMESH_DY"), myDestinationGrp);
219   myDestDY = new SMESHGUI_SpinBox(myDestinationGrp);
220   myDestDY->setReadOnly(true);
221
222   myDestDZLabel = new QLabel(tr("SMESH_DZ"), myDestinationGrp);
223   myDestDZ = new SMESHGUI_SpinBox(myDestinationGrp);
224   myDestDZ->setReadOnly(true);
225
226   myDestinationX->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
227   myDestinationY->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
228   myDestinationZ->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
229   myDestDX->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
230   myDestDY->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
231   myDestDZ->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
232
233   QGridLayout* aDestLayout = new QGridLayout(myDestinationGrp);
234   aDestLayout->setMargin(MARGIN);
235   aDestLayout->setSpacing(SPACING);
236   aDestLayout->addWidget(myDestBtn, 0, 0);
237   aDestLayout->addWidget(aDestinationXLabel, 0, 1);
238   aDestLayout->addWidget(myDestinationX,     0, 2);
239   aDestLayout->addWidget(aDestinationYLabel, 0, 3);
240   aDestLayout->addWidget(myDestinationY,     0, 4);
241   aDestLayout->addWidget(aDestinationZLabel, 0, 5);
242   aDestLayout->addWidget(myDestinationZ,     0, 6);
243   aDestLayout->addWidget(myDestDXLabel,      1, 1);
244   aDestLayout->addWidget(myDestDX,           1, 2);
245   aDestLayout->addWidget(myDestDYLabel,      1, 3);
246   aDestLayout->addWidget(myDestDY,           1, 4);
247   aDestLayout->addWidget(myDestDZLabel,      1, 5);
248   aDestLayout->addWidget(myDestDZ,           1, 6);
249   aDestLayout->setColumnStretch(2, 1);
250   aDestLayout->setColumnStretch(4, 1);
251   aDestLayout->setColumnStretch(6, 1);
252
253   // Preview
254
255   myPreviewChkBox = new QCheckBox( tr("PREVIEW"), aFrame);
256
257   QVBoxLayout* aLay = new QVBoxLayout(aFrame);
258   aLay->addWidget(aPixGrp);
259   aLay->addWidget(myNodeToMoveGrp);
260   aLay->addWidget(myDestinationGrp);
261   aLay->addWidget(myPreviewChkBox);
262
263   connect(myDestBtn,          SIGNAL (toggled(bool)), this, SLOT(ButtonToggled(bool)));
264   connect(myIdBtn,            SIGNAL (toggled(bool)), this, SLOT(ButtonToggled(bool)));
265   connect(myButtonGroup,      SIGNAL (buttonClicked(int)),  SLOT(ConstructorsClicked(int)));
266
267   myIdBtn->setChecked(true);
268
269   return aFrame;
270 }
271
272 //================================================================================
273 /*!
274  * \brief SLOT called when any button is toggled
275   * \param bool - on or off
276  */
277 //================================================================================
278
279 void SMESHGUI_MakeNodeAtPointDlg::ButtonToggled (bool on)
280 {
281   const QObject* aSender = sender();
282   if ( on ) {
283     if ( aSender == myDestBtn ) // button to set coord by node selection
284     {
285       if ( myIdBtn->isEnabled() )
286         myIdBtn->setChecked( !on );
287     }
288     else if ( aSender == myIdBtn ) // button to select a node to move
289     {
290       myDestBtn->setChecked( !on );
291     }
292   }      
293 }
294 //================================================================================
295 /*!
296  * \brief SLOT called when clicked radio button
297   * \param int - number of the button
298  */
299 //================================================================================
300 void SMESHGUI_MakeNodeAtPointDlg::ConstructorsClicked (int constructorId)
301 {
302   switch (constructorId) {
303   case 0:
304     {
305       myDestDXLabel->show();
306       myDestDYLabel->show();
307       myDestDZLabel->show();
308       myDestDX->show();
309       myDestDY->show();
310       myDestDZ->show();
311       myCurrentX->SetValue(0);
312       myCurrentY->SetValue(0);
313       myCurrentZ->SetValue(0);
314       if (!myNodeToMoveGrp->isVisible()) myNodeToMoveGrp->show();
315       break;
316     }
317   case 1:
318     {
319       myId->setText("");
320       myCurrentX->SetValue(0);
321       myCurrentY->SetValue(0);
322       myCurrentZ->SetValue(0);
323       myDestDXLabel->hide();
324       myDestDYLabel->hide();
325       myDestDZLabel->hide();
326       myDestDX->hide();
327       myDestDY->hide();
328       myDestDZ->hide();
329       if (myNodeToMoveGrp->isVisible()) myNodeToMoveGrp->hide();
330       myDestBtn->setChecked( true );
331       break;
332     }
333   }
334   QApplication::instance()->processEvents();
335   myMainFrame->hide();
336   myMainFrame->show();
337   updateGeometry();
338   resize(minimumSizeHint());
339 }
340
341 //================================================================================
342 /*!
343  * \brief Constructor
344 */
345 //================================================================================
346
347 SMESHGUI_MakeNodeAtPointOp::SMESHGUI_MakeNodeAtPointOp()
348 {
349   mySimulation = 0;
350   mySMESHGUI = 0;
351   myDlg = new SMESHGUI_MakeNodeAtPointDlg;
352   myFilter = 0;
353   myHelpFileName = "mesh_through_point_page.html";
354
355   myNoPreview = false;
356   myUpdateDestination = false;
357   myDestCoordChanged = true;
358
359   // connect signals and slots
360   connect(myDlg->myDestinationX,  SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
361   connect(myDlg->myDestinationY,  SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
362   connect(myDlg->myDestinationZ,  SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
363   connect(myDlg->myDestDX,        SIGNAL (valueChanged(double)), this, SLOT(onDestCoordChanged()));
364   connect(myDlg->myDestDY,        SIGNAL (valueChanged(double)), this, SLOT(onDestCoordChanged()));
365   connect(myDlg->myDestDZ,        SIGNAL (valueChanged(double)), this, SLOT(onDestCoordChanged()));
366   connect(myDlg->myId,            SIGNAL (textChanged(const QString&)),SLOT(redisplayPreview()));
367   connect(myDlg->myPreviewChkBox, SIGNAL (toggled(bool)),              SLOT(redisplayPreview()));
368   connect(myDlg->myButtonGroup,   SIGNAL (buttonClicked(int)),         SLOT(redisplayPreview()));
369
370   // IPAL22913: TC6.5.0: selected in "Move node" dialog box node is not highlighted
371   // note: this slot seems to be lost together with removed obsolete SMESHGUI_MoveNodesDlg class
372   connect(myDlg->myId,SIGNAL (textChanged(const QString&)),SLOT(onTextChange(const QString&)));
373   connect(myDlg->myUpdateBtn, SIGNAL (clicked()), this, SLOT(onUpdateDestination()));
374 }
375
376 void SMESHGUI_MakeNodeAtPointOp::onUpdateDestination()
377 {
378   myUpdateDestination = true;
379   redisplayPreview();
380   myUpdateDestination = false;
381 }
382
383 void SMESHGUI_MakeNodeAtPointOp::onDestCoordChanged()
384 {
385   myDestCoordChanged = false;
386   redisplayPreview();
387   myDestCoordChanged = true;
388 }
389
390 //=======================================================================
391 // function : startOperation()
392 // purpose  : Init dialog fields, connect signals and slots, show dialog
393 //=======================================================================
394 void SMESHGUI_MakeNodeAtPointOp::startOperation()
395 {
396   myNoPreview = false;
397   myMeshActor = 0;
398
399   // init simulation with a current View
400   if ( mySimulation ) delete mySimulation;
401   mySMESHGUI = getSMESHGUI();
402   mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI ) );
403   connect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView()));
404   connect(mySMESHGUI, SIGNAL (SignalCloseView()), this, SLOT(onCloseView()));
405   vtkProperty* aProp = vtkProperty::New();
406   aProp->SetRepresentationToWireframe();
407   aProp->SetColor(250, 0, 250);
408   aProp->SetPointSize(5);
409   aProp->SetLineWidth( SMESH::GetFloat("SMESH:element_width",1) + 1);
410   mySimulation->GetActor()->SetProperty(aProp);
411   aProp->Delete();
412
413   // SalomeApp_TypeFilter depends on a current study
414   if ( myFilter ) delete myFilter;
415   QList<SUIT_SelectionFilter*> filters;
416   filters.append( new SalomeApp_TypeFilter((SalomeApp_Study*)study(), "SMESH" ));
417   TColStd_MapOfInteger vertexType;
418   vertexType.Add( TopAbs_VERTEX );
419   filters.append( new SMESH_NumberFilter("GEOM", TopAbs_VERTEX, 1, vertexType ));
420   myFilter = new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR );
421
422   // IPAL19360
423   SMESHGUI_SelectionOp::startOperation(); // this method should be called only after filter creation
424   //activateSelection(); // set filters   // called inside of previous statement
425   myDlg->myId->setText("");
426   myDlg->myDestinationX->SetValue(0);
427   myDlg->myDestinationY->SetValue(0);
428   myDlg->myDestinationZ->SetValue(0);
429   myDlg->myDestDX->SetValue(0);
430   myDlg->myDestDY->SetValue(0);
431   myDlg->myDestDZ->SetValue(0);
432   myDlg->myCurrentX->SetValue(0);
433   myDlg->myCurrentY->SetValue(0);
434   myDlg->myCurrentZ->SetValue(0);
435   myDlg->myDestDX->setReadOnly(true);
436   myDlg->myDestDY->setReadOnly(true);
437   myDlg->myDestDZ->setReadOnly(true);
438   myDlg->myRButNodeToMove->setChecked(true);
439
440   myDlg->ConstructorsClicked(GetConstructorId());
441
442   myDlg->show();
443
444   onSelectionDone(); // init myMeshActor
445 }
446
447 //=================================================================================
448 // function : GetConstructorId()
449 // purpose  :
450 //=================================================================================
451 int SMESHGUI_MakeNodeAtPointOp::GetConstructorId()
452 {
453   return myDlg->myButtonGroup->checkedId();
454 }
455
456 //================================================================================
457 /*!
458  * \brief Stops operation
459  */
460 //================================================================================
461
462 void SMESHGUI_MakeNodeAtPointOp::stopOperation()
463 {
464   myNoPreview = true;
465   if ( mySimulation )
466   {
467     mySimulation->SetVisibility(false);
468     delete mySimulation;
469     mySimulation = 0;
470   }
471   if ( myMeshActor ) {
472     myMeshActor->SetPointRepresentation(false);
473     SMESH::RepaintCurrentView();
474     myMeshActor = 0;
475   }
476   disconnect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView()));
477   disconnect(mySMESHGUI, SIGNAL (SignalCloseView()), this, SLOT(onCloseView()));
478   selectionMgr()->removeFilter( myFilter );
479   SMESHGUI_SelectionOp::stopOperation();
480 }
481
482 //================================================================================
483 /*!
484  * \brief perform it's intention action: move or create a node
485  */
486 //================================================================================
487
488 bool SMESHGUI_MakeNodeAtPointOp::onApply()
489 {
490   if( isStudyLocked() )
491     return false;
492
493   if ( !myMeshActor ) {
494     SUIT_MessageBox::warning( dlg(), tr( "SMESH_WRN_WARNING" ),
495                               tr("INVALID_MESH") );
496     dlg()->show();
497     return false;
498   }
499
500   QString msg;
501   if ( !isValid( msg ) ) { // node id is invalid
502     if( !msg.isEmpty() )
503       SUIT_MessageBox::warning( dlg(), tr( "SMESH_WRN_WARNING" ),
504                                 tr("INVALID_ID") );
505     dlg()->show();
506     return false;
507   }
508
509   QStringList aParameters;
510   aParameters << myDlg->myDestinationX->text();
511   aParameters << myDlg->myDestinationY->text();
512   aParameters << myDlg->myDestinationZ->text();
513
514   try {
515     SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(myMeshActor->getIO());
516     if (aMesh->_is_nil()) {
517       SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_ERROR"),
518                                    tr("SMESHG_NO_MESH") );
519       return true;
520     }
521     SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
522     if (aMeshEditor->_is_nil())
523       return true;
524
525     aMesh->SetParameters( aParameters.join(":").toLatin1().constData() );
526
527     bool ok;
528     int anId = myDlg->myId->text().toInt( &ok );
529     if( !ok || anId < 1 )
530       anId = aMeshEditor->FindNodeClosestTo(myDlg->myDestinationX->GetValue(),
531                                             myDlg->myDestinationY->GetValue(),
532                                             myDlg->myDestinationZ->GetValue());
533
534     int aResult = aMeshEditor->MoveNode(anId,
535                                         myDlg->myDestinationX->GetValue(),
536                                         myDlg->myDestinationY->GetValue(),
537                                         myDlg->myDestinationZ->GetValue() );
538
539     if (aResult)
540     {
541       myDlg->myCurrentX->SetValue(0);
542       myDlg->myCurrentY->SetValue(0);
543       myDlg->myCurrentZ->SetValue(0);
544       myDlg->myDestDX->SetValue(0);
545       myDlg->myDestDY->SetValue(0);
546       myDlg->myDestDZ->SetValue(0);
547
548       SALOME_ListIO aList;
549       selectionMgr()->setSelectedObjects(aList,false);
550       aList.Append(myMeshActor->getIO());
551       selectionMgr()->setSelectedObjects(aList,false);
552       SMESH::UpdateView();
553       SMESHGUI::Modified();
554     }
555   }
556   catch (const SALOME::SALOME_Exception& S_ex) {
557     SalomeApp_Tools::QtCatchCorbaException(S_ex);
558   }
559   catch (...) {
560   }
561
562   return true;
563 }
564
565 //================================================================================
566 /*!
567  * \brief Check selected node id validity
568  */
569 //================================================================================
570
571 bool SMESHGUI_MakeNodeAtPointOp::isValid( QString& msg )
572 {
573   bool ok = true;
574   if ( myMeshActor && myDlg->myRButNodeToMove->isChecked() )
575   {
576     ok = false;
577     int id = myDlg->myId->text().toInt();
578     if ( id > 0 )
579       if (SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh())
580         ok = aMesh->FindNode( id );
581     if( !ok )
582       msg += tr("INVALID_ID") + "\n";
583   }
584
585   ok = myDlg->myDestinationX->isValid( msg, !myNoPreview ) && ok;
586   ok = myDlg->myDestinationY->isValid( msg, !myNoPreview ) && ok;
587   ok = myDlg->myDestinationZ->isValid( msg, !myNoPreview ) && ok;
588
589   return ok;
590 }
591
592 //================================================================================
593 /*!
594  * \brief SLOT called when selection changed
595  */
596 //================================================================================
597
598 void SMESHGUI_MakeNodeAtPointOp::onSelectionDone()
599 {
600   if ( !myDlg->isVisible() || !myDlg->isEnabled() )
601     return;
602
603   myNoPreview = true;
604   try {
605     SALOME_ListIO aList;
606     selectionMgr()->selectedObjects(aList, SVTK_Viewer::Type());
607     if (aList.Extent() != 1)
608       return;
609     Handle(SALOME_InteractiveObject) anIO = aList.First();
610     SMESH_Actor* aMeshActor = SMESH::FindActorByEntry(anIO->getEntry());
611
612     if (( myDlg->myIdBtn->isChecked() && myDlg->myIdBtn->isEnabled() ) ||
613         ( !myDlg->myNodeToMoveGrp->isVisible() ))
614       myMeshActor = aMeshActor;
615
616     if (!aMeshActor) { // coord by geom
617       if ( myDlg->myDestBtn->isChecked() ) {
618         GEOM::GEOM_Object_var geom = SMESH::IObjectToInterface<GEOM::GEOM_Object>(anIO);
619         if ( !geom->_is_nil() ) {
620           TopoDS_Vertex aShape;
621           if ( GEOMBase::GetShape(geom, aShape) &&
622                aShape.ShapeType() == TopAbs_VERTEX ) {
623             gp_Pnt P = BRep_Tool::Pnt(aShape);
624             myDlg->myDestinationX->SetValue(P.X());
625             myDlg->myDestinationY->SetValue(P.Y());
626             myDlg->myDestinationZ->SetValue(P.Z());
627           }
628         }
629         myNoPreview = false;
630         redisplayPreview();
631         return;
632       }
633     }
634
635     QString aString;
636     int nbElems = SMESH::GetNameOfSelectedElements(selector(),anIO, aString);
637     if (nbElems == 1) {
638       if (SMDS_Mesh* aMesh = aMeshActor->GetObject()->GetMesh()) {
639         if (const SMDS_MeshNode* aNode = aMesh->FindNode(aString.toInt())) {
640           if ( myDlg->myDestBtn->isChecked() ) { // set coord
641             myDlg->myDestinationX->SetValue(aNode->X());
642             myDlg->myDestinationY->SetValue(aNode->Y());
643             myDlg->myDestinationZ->SetValue(aNode->Z());
644           }
645           else if ( myDlg->myIdBtn->isChecked() &&
646                     myDlg->myIdBtn->isEnabled() ) { // set node to move
647             myDlg->myId->setText(aString);
648             myDlg->myCurrentX->SetValue( aNode->X() );
649             myDlg->myCurrentY->SetValue( aNode->Y() );
650             myDlg->myCurrentZ->SetValue( aNode->Z() );
651             redisplayPreview();
652           }
653
654           double x = myDlg->myCurrentX->GetValue();
655           double y = myDlg->myCurrentY->GetValue();
656           double z = myDlg->myCurrentZ->GetValue();
657           double dx = myDlg->myDestinationX->GetValue() - x;
658           double dy = myDlg->myDestinationY->GetValue() - y;
659           double dz = myDlg->myDestinationZ->GetValue() - z;
660           myDlg->myDestDX->SetValue(dx);
661           myDlg->myDestDY->SetValue(dy);
662           myDlg->myDestDZ->SetValue(dz);
663           myDlg->myDestDX->setReadOnly(false);
664           myDlg->myDestDY->setReadOnly(false);
665           myDlg->myDestDZ->setReadOnly(false);
666         }
667       }
668     }
669   } catch (...) {
670   }
671
672   myNoPreview = false;
673   redisplayPreview();
674 }
675
676 //================================================================================
677 /*!
678  * \brief update preview
679  */
680 //================================================================================
681
682 void SMESHGUI_MakeNodeAtPointOp::redisplayPreview()
683 {
684   if ( myNoPreview )
685     return;
686   myNoPreview = true;
687
688   SMESH::MeshPreviewStruct_var aMeshPreviewStruct;
689
690   bool moveShown = false;
691   if ( myMeshActor)
692   {
693     const bool  isPreview = myDlg->myPreviewChkBox->isChecked();
694     const bool isMoveNode = myDlg->myRButMoveWithoutNode->isChecked();
695     QString msg;
696     if ( isValid( msg ) )
697     {
698       try {
699         SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(myMeshActor->getIO());
700         if (!aMesh->_is_nil()) {
701           SMESH::SMESH_MeshEditor_var aPreviewer = aMesh->GetMeshEditPreviewer();
702           if (!aPreviewer->_is_nil())
703           {
704             SUIT_OverrideCursor aWaitCursor;
705
706             int anId = myDlg->myId->text().toInt();
707
708             SMESH::double_array_var aXYZ = aMesh->GetNodeXYZ( anId );
709             if( &aXYZ.in() && aXYZ->length() >= 3 )
710             {
711               double x = aXYZ[0];
712               double y = aXYZ[1];
713               double z = aXYZ[2];
714               double dx = 0;
715               double dy = 0;
716               double dz = 0;
717
718               if ( myUpdateDestination ) {
719                 myDlg->myDestinationX->SetValue(x);
720                 myDlg->myDestinationY->SetValue(y);
721                 myDlg->myDestinationZ->SetValue(z);
722                 myDlg->myDestDX->SetValue(dx);
723                 myDlg->myDestDY->SetValue(dy);
724                 myDlg->myDestDZ->SetValue(dz);
725               }
726               else
727               {
728                 if ( myDestCoordChanged ) {
729                   dx = myDlg->myDestinationX->GetValue() - x;
730                   dy = myDlg->myDestinationY->GetValue() - y;
731                   dz = myDlg->myDestinationZ->GetValue() - z;
732                   myDlg->myDestDX->SetValue(dx);
733                   myDlg->myDestDY->SetValue(dy);
734                   myDlg->myDestDZ->SetValue(dz);
735                 }
736                 else {
737                   dx = myDlg->myDestDX->GetValue() + x;
738                   dy = myDlg->myDestDY->GetValue() + y;
739                   dz = myDlg->myDestDZ->GetValue() + z;
740                   myDlg->myDestinationX->SetValue(dx);
741                   myDlg->myDestinationY->SetValue(dy);
742                   myDlg->myDestinationZ->SetValue(dz);
743                 }
744               }
745               myDlg->myCurrentX->SetValue(x);
746               myDlg->myCurrentY->SetValue(y);
747               myDlg->myCurrentZ->SetValue(z);
748               myDlg->myDestDX->setReadOnly(false);
749               myDlg->myDestDY->setReadOnly(false);
750               myDlg->myDestDZ->setReadOnly(false);
751             }
752             else {
753               myDlg->myCurrentX->SetValue(0);
754               myDlg->myCurrentY->SetValue(0);
755               myDlg->myCurrentZ->SetValue(0);
756               myDlg->myDestDX->SetValue(0);
757               myDlg->myDestDY->SetValue(0);
758               myDlg->myDestDZ->SetValue(0);
759               myDlg->myDestDX->setReadOnly(true);
760               myDlg->myDestDY->setReadOnly(true);
761               myDlg->myDestDZ->setReadOnly(true);
762             }
763             if ( isPreview && isMoveNode && anId == 0 )
764               anId = aPreviewer->FindNodeClosestTo(myDlg->myDestinationX->GetValue(),
765                                                    myDlg->myDestinationY->GetValue(),
766                                                    myDlg->myDestinationZ->GetValue());
767             // find id and/or just compute preview
768             aPreviewer->MoveNode(anId,
769                                  myDlg->myDestinationX->GetValue(),
770                                  myDlg->myDestinationY->GetValue(),
771                                  myDlg->myDestinationZ->GetValue());
772
773             if ( isPreview ) { // fill preview data
774               aMeshPreviewStruct = aPreviewer->GetPreviewData();
775               moveShown = ( anId > 0 );
776             }
777           }
778         }
779       }catch (...) {
780       }
781     }
782   }
783
784   if ( !moveShown )
785   {
786     aMeshPreviewStruct = new SMESH::MeshPreviewStruct();
787
788     aMeshPreviewStruct->nodesXYZ.length(1);
789     aMeshPreviewStruct->nodesXYZ[0].x = myDlg->myDestinationX->GetValue();
790     aMeshPreviewStruct->nodesXYZ[0].y = myDlg->myDestinationY->GetValue();
791     aMeshPreviewStruct->nodesXYZ[0].z = myDlg->myDestinationZ->GetValue();
792
793     aMeshPreviewStruct->elementTypes.length(1);
794     aMeshPreviewStruct->elementTypes[0].SMDS_ElementType = SMESH::NODE;
795     aMeshPreviewStruct->elementTypes[0].isPoly = false;
796     aMeshPreviewStruct->elementTypes[0].nbNodesInElement = 1;
797
798     aMeshPreviewStruct->elementConnectivities.length(1);
799     aMeshPreviewStruct->elementConnectivities[0] = 0;
800   }
801   if (!mySimulation)
802     mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI ));
803   // display data
804   if ( aMeshPreviewStruct.operator->() )
805   {
806     mySimulation->SetData(aMeshPreviewStruct._retn());
807   }
808   else
809   {
810     mySimulation->SetVisibility(false);
811   }
812
813   myNoPreview = false;
814 }
815
816 //=================================================================================
817 /*!
818  * \brief SLOT called when the viewer opened
819  */
820 //=================================================================================
821 void SMESHGUI_MakeNodeAtPointOp::onOpenView()
822 {
823   if ( mySimulation ) {
824     mySimulation->SetVisibility(false);
825     SMESH::SetPointRepresentation(false);
826   }
827   else {
828     mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI ));
829   }
830 }
831
832 //=================================================================================
833 /*!
834  * \brief SLOT called when the viewer closed
835  */
836 //=================================================================================
837 void SMESHGUI_MakeNodeAtPointOp::onCloseView()
838 {
839   delete mySimulation;
840   mySimulation = 0;
841 }
842
843 //================================================================================
844 /*!
845  * \brief SLOT called when the node id is manually changed
846  */
847 //================================================================================
848
849 void SMESHGUI_MakeNodeAtPointOp::onTextChange( const QString& theText )
850 {
851   if( myMeshActor )
852   {
853     if( SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh() )
854     {
855       Handle(SALOME_InteractiveObject) anIO = myMeshActor->getIO();
856       SALOME_ListIO aList;
857       aList.Append( anIO );
858       selectionMgr()->setSelectedObjects( aList, false );
859
860       if( const SMDS_MeshNode* aNode = aMesh->FindNode( theText.toInt() ) )
861       {
862         TColStd_MapOfInteger aListInd;
863         aListInd.Add( aNode->GetID() );
864         selector()->AddOrRemoveIndex( anIO, aListInd, false );
865         if( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( SMESHGUI::GetSMESHGUI() ) )
866           aViewWindow->highlight( anIO, true, true );
867       }
868     }
869   }
870 }
871
872 //================================================================================
873 /*!
874  * \brief Activate Node selection
875  */
876 //================================================================================
877
878 void SMESHGUI_MakeNodeAtPointOp::activateSelection()
879 {
880   selectionMgr()->clearFilters();
881   SMESH::SetPointRepresentation( true );
882   selectionMgr()->installFilter( myFilter );
883   setSelectionMode( NodeSelection );
884 }
885
886 //================================================================================
887 /*!
888  * \brief Destructor
889 */
890 //================================================================================
891
892 SMESHGUI_MakeNodeAtPointOp::~SMESHGUI_MakeNodeAtPointOp()
893 {
894   if ( myDlg )        delete myDlg;
895   if ( mySimulation ) delete mySimulation;
896   if ( myFilter )     delete myFilter;
897 }
898
899 //================================================================================
900 /*!
901  * \brief Gets dialog of this operation
902  * \retval LightApp_Dialog* - pointer to dialog of this operation
903  */
904 //================================================================================
905
906 LightApp_Dialog* SMESHGUI_MakeNodeAtPointOp::dlg() const
907 {
908   return myDlg;
909 }
910