Salome HOME
Merge remote branch 'origin/gdd/translations'
[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       break;
331     }
332   }
333   QApplication::instance()->processEvents();
334   myMainFrame->hide();
335   myMainFrame->show();
336   updateGeometry();
337   resize(minimumSizeHint());
338 }
339
340 //================================================================================
341 /*!
342  * \brief Constructor
343 */
344 //================================================================================
345
346 SMESHGUI_MakeNodeAtPointOp::SMESHGUI_MakeNodeAtPointOp()
347 {
348   mySimulation = 0;
349   myDlg = new SMESHGUI_MakeNodeAtPointDlg;
350   myFilter = 0;
351   myHelpFileName = "mesh_through_point_page.html";
352
353   myNoPreview = false;
354   myUpdateDestination = false;
355   myDestCoordChanged = true;
356
357   // connect signals and slots
358   connect(myDlg->myDestinationX, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
359   connect(myDlg->myDestinationY, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
360   connect(myDlg->myDestinationZ, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
361   connect(myDlg->myDestDX, SIGNAL (valueChanged(double)), this, SLOT(onDestCoordChanged()));
362   connect(myDlg->myDestDY, SIGNAL (valueChanged(double)), this, SLOT(onDestCoordChanged()));
363   connect(myDlg->myDestDZ, SIGNAL (valueChanged(double)), this, SLOT(onDestCoordChanged()));
364   connect(myDlg->myId,SIGNAL (textChanged(const QString&)),SLOT(redisplayPreview()));
365   connect(myDlg->myPreviewChkBox,   SIGNAL (toggled(bool)),SLOT(redisplayPreview()));
366
367   // IPAL22913: TC6.5.0: selected in "Move node" dialog box node is not highlighted
368   // note: this slot seems to be lost together with removed obsolete SMESHGUI_MoveNodesDlg class
369   connect(myDlg->myId,SIGNAL (textChanged(const QString&)),SLOT(onTextChange(const QString&)));
370   connect(myDlg->myUpdateBtn, SIGNAL (clicked()), this, SLOT(onUpdateDestination()));
371 }
372
373 void SMESHGUI_MakeNodeAtPointOp::onUpdateDestination()
374 {
375   myUpdateDestination = true;
376   redisplayPreview();
377   myUpdateDestination = false;
378 }
379
380 void SMESHGUI_MakeNodeAtPointOp::onDestCoordChanged()
381 {
382   myDestCoordChanged = false;
383   redisplayPreview();
384   myDestCoordChanged = true;
385 }
386
387 //=======================================================================
388 // function : startOperation()
389 // purpose  : Init dialog fields, connect signals and slots, show dialog
390 //=======================================================================
391 void SMESHGUI_MakeNodeAtPointOp::startOperation()
392 {
393   myNoPreview = false;
394   myMeshActor = 0;
395
396   // init simulation with a current View
397   if ( mySimulation ) delete mySimulation;
398   mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( getSMESHGUI() ));
399   vtkProperty* aProp = vtkProperty::New();
400   aProp->SetRepresentationToWireframe();
401   aProp->SetColor(250, 0, 250);
402   aProp->SetPointSize(5);
403   aProp->SetLineWidth( SMESH::GetFloat("SMESH:element_width",1) + 1);
404   mySimulation->GetActor()->SetProperty(aProp);
405   aProp->Delete();
406
407   // SalomeApp_TypeFilter depends on a current study
408   if ( myFilter ) delete myFilter;
409   QList<SUIT_SelectionFilter*> filters;
410   filters.append( new SalomeApp_TypeFilter((SalomeApp_Study*)study(), "SMESH" ));
411   TColStd_MapOfInteger vertexType;
412   vertexType.Add( TopAbs_VERTEX );
413   filters.append( new SMESH_NumberFilter("GEOM", TopAbs_VERTEX, 1, vertexType ));
414   myFilter = new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR );
415
416   // IPAL19360
417   SMESHGUI_SelectionOp::startOperation(); // this method should be called only after filter creation
418   //activateSelection(); // set filters   // called inside of previous statement
419   myDlg->myId->setText("");
420   myDlg->myDestinationX->SetValue(0);
421   myDlg->myDestinationY->SetValue(0);
422   myDlg->myDestinationZ->SetValue(0);
423   myDlg->myDestDX->SetValue(0);
424   myDlg->myDestDY->SetValue(0);
425   myDlg->myDestDZ->SetValue(0);
426   myDlg->myCurrentX->SetValue(0);
427   myDlg->myCurrentY->SetValue(0);
428   myDlg->myCurrentZ->SetValue(0);
429   myDlg->myDestDX->setReadOnly(true);
430   myDlg->myDestDY->setReadOnly(true);
431   myDlg->myDestDZ->setReadOnly(true);
432   myDlg->myRButNodeToMove->setChecked(true);
433
434   myDlg->ConstructorsClicked(GetConstructorId());
435
436   myDlg->show();
437
438   onSelectionDone(); // init myMeshActor
439
440   if ( myMeshActor ) {
441 //     myMeshActor->SetRepresentation( VTK_WIREFRAME );
442     myMeshActor->SetPointRepresentation(true);
443     SMESH::RepaintCurrentView();
444     redisplayPreview();
445   }
446 }
447
448 //=================================================================================
449 // function : GetConstructorId()
450 // purpose  :
451 //=================================================================================
452 int SMESHGUI_MakeNodeAtPointOp::GetConstructorId()
453 {
454   return myDlg->myButtonGroup->checkedId();
455 }
456
457 //================================================================================
458 /*!
459  * \brief Stops operation
460  */
461 //================================================================================
462
463 void SMESHGUI_MakeNodeAtPointOp::stopOperation()
464 {
465   myNoPreview = true;
466   mySimulation->SetVisibility(false);
467   if ( myMeshActor ) {
468     myMeshActor->SetPointRepresentation(false);
469     SMESH::RepaintCurrentView();
470     myMeshActor = 0;
471   }
472   selectionMgr()->removeFilter( myFilter );
473   SMESHGUI_SelectionOp::stopOperation();
474 }
475
476 //================================================================================
477 /*!
478  * \brief perform it's intention action: move or create a node
479  */
480 //================================================================================
481
482 bool SMESHGUI_MakeNodeAtPointOp::onApply()
483 {
484   if( isStudyLocked() )
485     return false;
486
487   if ( !myMeshActor ) {
488     SUIT_MessageBox::warning( dlg(), tr( "SMESH_WRN_WARNING" ),
489                               tr("INVALID_MESH") );
490     dlg()->show();
491     return false;
492   }
493
494   QString msg;
495   if ( !isValid( msg ) ) { // node id is invalid
496     if( !msg.isEmpty() )
497       SUIT_MessageBox::warning( dlg(), tr( "SMESH_WRN_WARNING" ),
498                                 tr("INVALID_ID") );
499     dlg()->show();
500     return false;
501   }
502
503   QStringList aParameters;
504   aParameters << myDlg->myDestinationX->text();
505   aParameters << myDlg->myDestinationY->text();
506   aParameters << myDlg->myDestinationZ->text();
507
508   try {
509     SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(myMeshActor->getIO());
510     if (aMesh->_is_nil()) {
511       SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_ERROR"),
512                                    tr("SMESHG_NO_MESH") );
513       return true;
514     }
515     SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
516     if (aMeshEditor->_is_nil())
517       return true;
518
519     aMesh->SetParameters( aParameters.join(":").toLatin1().constData() );
520
521     bool ok;
522     int anId = myDlg->myId->text().toInt( &ok );
523     if( !ok || anId < 1 )
524       anId = aMeshEditor->FindNodeClosestTo(myDlg->myDestinationX->GetValue(),
525                                             myDlg->myDestinationY->GetValue(),
526                                             myDlg->myDestinationZ->GetValue());
527
528     int aResult = aMeshEditor->MoveNode(anId,
529                                         myDlg->myDestinationX->GetValue(),
530                                         myDlg->myDestinationY->GetValue(),
531                                         myDlg->myDestinationZ->GetValue() );
532
533     if (aResult)
534     {
535       myDlg->myCurrentX->SetValue(0);
536       myDlg->myCurrentY->SetValue(0);
537       myDlg->myCurrentZ->SetValue(0);
538       myDlg->myDestDX->SetValue(0);
539       myDlg->myDestDY->SetValue(0);
540       myDlg->myDestDZ->SetValue(0);
541
542       SALOME_ListIO aList;
543       selectionMgr()->setSelectedObjects(aList,false);
544       aList.Append(myMeshActor->getIO());
545       selectionMgr()->setSelectedObjects(aList,false);
546       SMESH::UpdateView();
547       SMESHGUI::Modified();
548     }
549   }
550   catch (const SALOME::SALOME_Exception& S_ex) {
551     SalomeApp_Tools::QtCatchCorbaException(S_ex);
552   }
553   catch (...) {
554   }
555
556   return true;
557 }
558
559 //================================================================================
560 /*!
561  * \brief Check selected node id validity
562  */
563 //================================================================================
564
565 bool SMESHGUI_MakeNodeAtPointOp::isValid( QString& msg )
566 {
567   bool ok = true;
568   if ( myMeshActor && myDlg->myRButNodeToMove->isChecked() )
569   {
570     ok = false;
571     int id = myDlg->myId->text().toInt();
572     if ( id > 0 )
573       if (SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh())
574         ok = aMesh->FindNode( id );
575     if( !ok )
576       msg += tr("INVALID_ID") + "\n";
577   }
578
579   ok = myDlg->myDestinationX->isValid( msg, !myNoPreview ) && ok;
580   ok = myDlg->myDestinationY->isValid( msg, !myNoPreview ) && ok;
581   ok = myDlg->myDestinationZ->isValid( msg, !myNoPreview ) && ok;
582
583   return ok;
584 }
585
586 //================================================================================
587 /*!
588  * \brief SLOT called when selection changed
589  */
590 //================================================================================
591
592 void SMESHGUI_MakeNodeAtPointOp::onSelectionDone()
593 {
594   if ( !myDlg->isVisible() || !myDlg->isEnabled() )
595     return;
596   try {
597     SALOME_ListIO aList;
598     selectionMgr()->selectedObjects(aList, SVTK_Viewer::Type());
599     if (aList.Extent() != 1)
600       return;
601     Handle(SALOME_InteractiveObject) anIO = aList.First();
602     SMESH_Actor* aMeshActor = SMESH::FindActorByEntry(anIO->getEntry());
603
604     if (!aMeshActor) { // coord by geom
605       if ( myDlg->myDestBtn->isChecked() ) {
606         GEOM::GEOM_Object_var geom = SMESH::IObjectToInterface<GEOM::GEOM_Object>(anIO);
607         if ( !geom->_is_nil() ) {
608           TopoDS_Vertex aShape;
609           if ( GEOMBase::GetShape(geom, aShape) &&
610                aShape.ShapeType() == TopAbs_VERTEX ) {
611             gp_Pnt P = BRep_Tool::Pnt(aShape);
612             myNoPreview = true;
613             myDlg->myDestinationX->SetValue(P.X());
614             myDlg->myDestinationY->SetValue(P.Y());
615             myDlg->myDestinationZ->SetValue(P.Z());
616             myNoPreview = false;
617             redisplayPreview();
618           }
619         }
620         return;
621       }
622     }
623
624     if ( !myMeshActor )
625       myMeshActor = aMeshActor;
626
627     QString aString;
628     int nbElems = SMESH::GetNameOfSelectedElements(selector(),anIO, aString);
629     if (nbElems == 1) {
630       if (SMDS_Mesh* aMesh = aMeshActor->GetObject()->GetMesh()) {
631         if (const SMDS_MeshNode* aNode = aMesh->FindNode(aString.toInt())) {
632           myNoPreview = true;
633           if ( myDlg->myDestBtn->isChecked() ) { // set coord
634             myDlg->myDestinationX->SetValue(aNode->X());
635             myDlg->myDestinationY->SetValue(aNode->Y());
636             myDlg->myDestinationZ->SetValue(aNode->Z());
637             myNoPreview = false;
638             redisplayPreview();
639           }
640           else if ( myDlg->myIdBtn->isChecked() &&
641                     myDlg->myIdBtn->isEnabled() ) { // set node to move
642             myDlg->myId->setText(aString);
643             myNoPreview = false;
644             redisplayPreview();
645           }
646
647           if (const SMDS_MeshNode* aCurrentNode = aMesh->FindNode(myDlg->myId->text().toInt())) {
648             double x = aCurrentNode->X();
649             double y = aCurrentNode->Y();
650             double z = aCurrentNode->Z();
651             double dx = myDlg->myDestinationX->GetValue() - x;
652             double dy = myDlg->myDestinationY->GetValue() - y;
653             double dz = myDlg->myDestinationZ->GetValue() - z;
654             myDlg->myCurrentX->SetValue(x);
655             myDlg->myCurrentY->SetValue(y);
656             myDlg->myCurrentZ->SetValue(z);
657             myDlg->myDestDX->SetValue(dx);
658             myDlg->myDestDY->SetValue(dy);
659             myDlg->myDestDZ->SetValue(dz);
660             myDlg->myDestDX->setReadOnly(false);
661             myDlg->myDestDY->setReadOnly(false);
662             myDlg->myDestDZ->setReadOnly(false);
663           }
664         }
665       }
666     }
667   } catch (...) {
668   }
669 }
670
671 //================================================================================
672 /*!
673  * \brief update preview
674  */
675 //================================================================================
676
677 void SMESHGUI_MakeNodeAtPointOp::redisplayPreview()
678 {
679   if ( myNoPreview )
680     return;
681   myNoPreview = true;
682
683   SMESH::MeshPreviewStruct_var aMeshPreviewStruct;
684
685   bool moveShown = false;
686   if ( myMeshActor)
687   {
688     const bool isPreview = myDlg->myPreviewChkBox->isChecked();
689     const bool isMoveNode = myDlg->myRButMoveWithoutNode->isChecked();
690     QString msg;
691     if ( isValid( msg ) )
692     {
693       try {
694         SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(myMeshActor->getIO());
695         if (!aMesh->_is_nil()) {
696           SMESH::SMESH_MeshEditor_var aPreviewer = aMesh->GetMeshEditPreviewer();
697           if (!aPreviewer->_is_nil())
698           {
699             SUIT_OverrideCursor aWaitCursor;
700
701             int anId = myDlg->myId->text().toInt();
702
703             SMESH::double_array_var aXYZ = aMesh->GetNodeXYZ( anId );
704             if( &aXYZ.in() && aXYZ->length() >= 3 )
705             {
706               double x = aXYZ[0];
707               double y = aXYZ[1];
708               double z = aXYZ[2];
709               double dx = 0;
710               double dy = 0;
711               double dz = 0;
712
713               if ( myUpdateDestination ) {
714                 myDlg->myDestinationX->SetValue(x);
715                 myDlg->myDestinationY->SetValue(y);
716                 myDlg->myDestinationZ->SetValue(z);
717               }
718               if ( myDestCoordChanged ) {
719                 dx = myDlg->myDestinationX->GetValue() - x;
720                 dy = myDlg->myDestinationY->GetValue() - y;
721                 dz = myDlg->myDestinationZ->GetValue() - z;
722                 myDlg->myDestDX->SetValue(dx);
723                 myDlg->myDestDY->SetValue(dy);
724                 myDlg->myDestDZ->SetValue(dz);
725               }
726               else {
727                 dx = myDlg->myDestDX->GetValue() + x;
728                 dy = myDlg->myDestDY->GetValue() + y;
729                 dz = myDlg->myDestDZ->GetValue() + z;
730                 myDlg->myDestinationX->SetValue(dx);
731                 myDlg->myDestinationY->SetValue(dy);
732                 myDlg->myDestinationZ->SetValue(dz);
733               }
734               myDlg->myCurrentX->SetValue(x);
735               myDlg->myCurrentY->SetValue(y);
736               myDlg->myCurrentZ->SetValue(z);
737               myDlg->myDestDX->setReadOnly(false);
738               myDlg->myDestDY->setReadOnly(false);
739               myDlg->myDestDZ->setReadOnly(false);
740             }
741             else {
742               myDlg->myCurrentX->SetValue(0);
743               myDlg->myCurrentY->SetValue(0);
744               myDlg->myCurrentZ->SetValue(0);
745               myDlg->myDestDX->SetValue(0);
746               myDlg->myDestDY->SetValue(0);
747               myDlg->myDestDZ->SetValue(0);
748               myDlg->myDestDX->setReadOnly(true);
749               myDlg->myDestDY->setReadOnly(true);
750               myDlg->myDestDZ->setReadOnly(true);
751             }
752             if ( isPreview && isMoveNode && anId == 0 )
753               anId = aPreviewer->FindNodeClosestTo(myDlg->myDestinationX->GetValue(),
754                                                    myDlg->myDestinationY->GetValue(),
755                                                    myDlg->myDestinationZ->GetValue());
756             // find id and/or just compute preview
757             aPreviewer->MoveNode(anId,
758                                  myDlg->myDestinationX->GetValue(),
759                                  myDlg->myDestinationY->GetValue(),
760                                  myDlg->myDestinationZ->GetValue());
761
762             if ( isPreview ) { // fill preview data
763               aMeshPreviewStruct = aPreviewer->GetPreviewData();
764               moveShown = ( anId > 0 );
765             }
766           }
767         }
768       }catch (...) {
769       }
770     }
771   }
772
773   if ( !moveShown )
774   {
775     aMeshPreviewStruct = new SMESH::MeshPreviewStruct();
776
777     aMeshPreviewStruct->nodesXYZ.length(1);
778     aMeshPreviewStruct->nodesXYZ[0].x = myDlg->myDestinationX->GetValue();
779     aMeshPreviewStruct->nodesXYZ[0].y = myDlg->myDestinationY->GetValue();
780     aMeshPreviewStruct->nodesXYZ[0].z = myDlg->myDestinationZ->GetValue();
781
782     aMeshPreviewStruct->elementTypes.length(1);
783     aMeshPreviewStruct->elementTypes[0].SMDS_ElementType = SMESH::NODE;
784     aMeshPreviewStruct->elementTypes[0].isPoly = false;
785     aMeshPreviewStruct->elementTypes[0].nbNodesInElement = 1;
786
787     aMeshPreviewStruct->elementConnectivities.length(1);
788     aMeshPreviewStruct->elementConnectivities[0] = 0;
789   }
790
791   // display data
792   if ( aMeshPreviewStruct.operator->() )
793   {
794     mySimulation->SetData(aMeshPreviewStruct._retn());
795   }
796   else
797   {
798     mySimulation->SetVisibility(false);
799   }
800
801   myNoPreview = false;
802 }
803
804 //================================================================================
805 /*!
806  * \brief SLOT called when the node id is manually changed
807  */
808 //================================================================================
809
810 void SMESHGUI_MakeNodeAtPointOp::onTextChange( const QString& theText )
811 {
812   if( myMeshActor )
813   {
814     if( SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh() )
815     {
816       Handle(SALOME_InteractiveObject) anIO = myMeshActor->getIO();
817       SALOME_ListIO aList;
818       aList.Append( anIO );
819       selectionMgr()->setSelectedObjects( aList, false );
820
821       if( const SMDS_MeshNode* aNode = aMesh->FindNode( theText.toInt() ) )
822       {
823         TColStd_MapOfInteger aListInd;
824         aListInd.Add( aNode->GetID() );
825         selector()->AddOrRemoveIndex( anIO, aListInd, false );
826         if( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( SMESHGUI::GetSMESHGUI() ) )
827           aViewWindow->highlight( anIO, true, true );
828       }
829     }
830   }
831 }
832
833 //================================================================================
834 /*!
835  * \brief Activate Node selection
836  */
837 //================================================================================
838
839 void SMESHGUI_MakeNodeAtPointOp::activateSelection()
840 {
841   selectionMgr()->clearFilters();
842   SMESH::SetPointRepresentation(false);
843   selectionMgr()->installFilter( myFilter );
844   setSelectionMode( NodeSelection );
845 }
846
847 //================================================================================
848 /*!
849  * \brief Destructor
850 */
851 //================================================================================
852
853 SMESHGUI_MakeNodeAtPointOp::~SMESHGUI_MakeNodeAtPointOp()
854 {
855   if ( myDlg )        delete myDlg;
856   if ( mySimulation ) delete mySimulation;
857   if ( myFilter )     delete myFilter;
858 }
859
860 //================================================================================
861 /*!
862  * \brief Gets dialog of this operation
863  * \retval LightApp_Dialog* - pointer to dialog of this operation
864  */
865 //================================================================================
866
867 LightApp_Dialog* SMESHGUI_MakeNodeAtPointOp::dlg() const
868 {
869   return myDlg;
870 }
871