Salome HOME
3b8ffef6514829c822f274c022c9d3f8eb0ea98a
[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   mySMESHGUI = 0;
350   myDlg = new SMESHGUI_MakeNodeAtPointDlg;
351   myFilter = 0;
352   myHelpFileName = "mesh_through_point_page.html";
353
354   myNoPreview = false;
355   myUpdateDestination = false;
356   myDestCoordChanged = true;
357
358   // connect signals and slots
359   connect(myDlg->myDestinationX, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
360   connect(myDlg->myDestinationY, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
361   connect(myDlg->myDestinationZ, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
362   connect(myDlg->myDestDX, SIGNAL (valueChanged(double)), this, SLOT(onDestCoordChanged()));
363   connect(myDlg->myDestDY, SIGNAL (valueChanged(double)), this, SLOT(onDestCoordChanged()));
364   connect(myDlg->myDestDZ, SIGNAL (valueChanged(double)), this, SLOT(onDestCoordChanged()));
365   connect(myDlg->myId,SIGNAL (textChanged(const QString&)),SLOT(redisplayPreview()));
366   connect(myDlg->myPreviewChkBox,   SIGNAL (toggled(bool)),SLOT(redisplayPreview()));
367
368   // IPAL22913: TC6.5.0: selected in "Move node" dialog box node is not highlighted
369   // note: this slot seems to be lost together with removed obsolete SMESHGUI_MoveNodesDlg class
370   connect(myDlg->myId,SIGNAL (textChanged(const QString&)),SLOT(onTextChange(const QString&)));
371   connect(myDlg->myUpdateBtn, SIGNAL (clicked()), this, SLOT(onUpdateDestination()));
372 }
373
374 void SMESHGUI_MakeNodeAtPointOp::onUpdateDestination()
375 {
376   myUpdateDestination = true;
377   redisplayPreview();
378   myUpdateDestination = false;
379 }
380
381 void SMESHGUI_MakeNodeAtPointOp::onDestCoordChanged()
382 {
383   myDestCoordChanged = false;
384   redisplayPreview();
385   myDestCoordChanged = true;
386 }
387
388 //=======================================================================
389 // function : startOperation()
390 // purpose  : Init dialog fields, connect signals and slots, show dialog
391 //=======================================================================
392 void SMESHGUI_MakeNodeAtPointOp::startOperation()
393 {
394   myNoPreview = false;
395   myMeshActor = 0;
396
397   // init simulation with a current View
398   if ( mySimulation ) delete mySimulation;
399   mySMESHGUI = getSMESHGUI();
400   mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI ) );
401   connect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView()));
402   connect(mySMESHGUI, SIGNAL (SignalCloseView()), this, SLOT(onCloseView()));
403   vtkProperty* aProp = vtkProperty::New();
404   aProp->SetRepresentationToWireframe();
405   aProp->SetColor(250, 0, 250);
406   aProp->SetPointSize(5);
407   aProp->SetLineWidth( SMESH::GetFloat("SMESH:element_width",1) + 1);
408   mySimulation->GetActor()->SetProperty(aProp);
409   aProp->Delete();
410
411   // SalomeApp_TypeFilter depends on a current study
412   if ( myFilter ) delete myFilter;
413   QList<SUIT_SelectionFilter*> filters;
414   filters.append( new SalomeApp_TypeFilter((SalomeApp_Study*)study(), "SMESH" ));
415   TColStd_MapOfInteger vertexType;
416   vertexType.Add( TopAbs_VERTEX );
417   filters.append( new SMESH_NumberFilter("GEOM", TopAbs_VERTEX, 1, vertexType ));
418   myFilter = new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR );
419
420   // IPAL19360
421   SMESHGUI_SelectionOp::startOperation(); // this method should be called only after filter creation
422   //activateSelection(); // set filters   // called inside of previous statement
423   myDlg->myId->setText("");
424   myDlg->myDestinationX->SetValue(0);
425   myDlg->myDestinationY->SetValue(0);
426   myDlg->myDestinationZ->SetValue(0);
427   myDlg->myDestDX->SetValue(0);
428   myDlg->myDestDY->SetValue(0);
429   myDlg->myDestDZ->SetValue(0);
430   myDlg->myCurrentX->SetValue(0);
431   myDlg->myCurrentY->SetValue(0);
432   myDlg->myCurrentZ->SetValue(0);
433   myDlg->myDestDX->setReadOnly(true);
434   myDlg->myDestDY->setReadOnly(true);
435   myDlg->myDestDZ->setReadOnly(true);
436   myDlg->myRButNodeToMove->setChecked(true);
437
438   myDlg->ConstructorsClicked(GetConstructorId());
439
440   myDlg->show();
441
442   onSelectionDone(); // init myMeshActor
443
444   if ( myMeshActor ) {
445 //     myMeshActor->SetRepresentation( VTK_WIREFRAME );
446     myMeshActor->SetPointRepresentation(true);
447     SMESH::RepaintCurrentView();
448     redisplayPreview();
449   }
450 }
451
452 //=================================================================================
453 // function : GetConstructorId()
454 // purpose  :
455 //=================================================================================
456 int SMESHGUI_MakeNodeAtPointOp::GetConstructorId()
457 {
458   return myDlg->myButtonGroup->checkedId();
459 }
460
461 //================================================================================
462 /*!
463  * \brief Stops operation
464  */
465 //================================================================================
466
467 void SMESHGUI_MakeNodeAtPointOp::stopOperation()
468 {
469   myNoPreview = true;
470   if ( mySimulation )
471   {
472     mySimulation->SetVisibility(false);
473     delete mySimulation;
474     mySimulation = 0;
475   }
476   if ( myMeshActor ) {
477     myMeshActor->SetPointRepresentation(false);
478     SMESH::RepaintCurrentView();
479     myMeshActor = 0;
480   }
481   disconnect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView()));
482   disconnect(mySMESHGUI, SIGNAL (SignalCloseView()), this, SLOT(onCloseView()));
483   selectionMgr()->removeFilter( myFilter );
484   SMESHGUI_SelectionOp::stopOperation();
485 }
486
487 //================================================================================
488 /*!
489  * \brief perform it's intention action: move or create a node
490  */
491 //================================================================================
492
493 bool SMESHGUI_MakeNodeAtPointOp::onApply()
494 {
495   if( isStudyLocked() )
496     return false;
497
498   if ( !myMeshActor ) {
499     SUIT_MessageBox::warning( dlg(), tr( "SMESH_WRN_WARNING" ),
500                               tr("INVALID_MESH") );
501     dlg()->show();
502     return false;
503   }
504
505   QString msg;
506   if ( !isValid( msg ) ) { // node id is invalid
507     if( !msg.isEmpty() )
508       SUIT_MessageBox::warning( dlg(), tr( "SMESH_WRN_WARNING" ),
509                                 tr("INVALID_ID") );
510     dlg()->show();
511     return false;
512   }
513
514   QStringList aParameters;
515   aParameters << myDlg->myDestinationX->text();
516   aParameters << myDlg->myDestinationY->text();
517   aParameters << myDlg->myDestinationZ->text();
518
519   try {
520     SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(myMeshActor->getIO());
521     if (aMesh->_is_nil()) {
522       SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_ERROR"),
523                                    tr("SMESHG_NO_MESH") );
524       return true;
525     }
526     SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
527     if (aMeshEditor->_is_nil())
528       return true;
529
530     aMesh->SetParameters( aParameters.join(":").toLatin1().constData() );
531
532     bool ok;
533     int anId = myDlg->myId->text().toInt( &ok );
534     if( !ok || anId < 1 )
535       anId = aMeshEditor->FindNodeClosestTo(myDlg->myDestinationX->GetValue(),
536                                             myDlg->myDestinationY->GetValue(),
537                                             myDlg->myDestinationZ->GetValue());
538
539     int aResult = aMeshEditor->MoveNode(anId,
540                                         myDlg->myDestinationX->GetValue(),
541                                         myDlg->myDestinationY->GetValue(),
542                                         myDlg->myDestinationZ->GetValue() );
543
544     if (aResult)
545     {
546       myDlg->myCurrentX->SetValue(0);
547       myDlg->myCurrentY->SetValue(0);
548       myDlg->myCurrentZ->SetValue(0);
549       myDlg->myDestDX->SetValue(0);
550       myDlg->myDestDY->SetValue(0);
551       myDlg->myDestDZ->SetValue(0);
552
553       SALOME_ListIO aList;
554       selectionMgr()->setSelectedObjects(aList,false);
555       aList.Append(myMeshActor->getIO());
556       selectionMgr()->setSelectedObjects(aList,false);
557       SMESH::UpdateView();
558       SMESHGUI::Modified();
559     }
560   }
561   catch (const SALOME::SALOME_Exception& S_ex) {
562     SalomeApp_Tools::QtCatchCorbaException(S_ex);
563   }
564   catch (...) {
565   }
566
567   return true;
568 }
569
570 //================================================================================
571 /*!
572  * \brief Check selected node id validity
573  */
574 //================================================================================
575
576 bool SMESHGUI_MakeNodeAtPointOp::isValid( QString& msg )
577 {
578   bool ok = true;
579   if ( myMeshActor && myDlg->myRButNodeToMove->isChecked() )
580   {
581     ok = false;
582     int id = myDlg->myId->text().toInt();
583     if ( id > 0 )
584       if (SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh())
585         ok = aMesh->FindNode( id );
586     if( !ok )
587       msg += tr("INVALID_ID") + "\n";
588   }
589
590   ok = myDlg->myDestinationX->isValid( msg, !myNoPreview ) && ok;
591   ok = myDlg->myDestinationY->isValid( msg, !myNoPreview ) && ok;
592   ok = myDlg->myDestinationZ->isValid( msg, !myNoPreview ) && ok;
593
594   return ok;
595 }
596
597 //================================================================================
598 /*!
599  * \brief SLOT called when selection changed
600  */
601 //================================================================================
602
603 void SMESHGUI_MakeNodeAtPointOp::onSelectionDone()
604 {
605   if ( !myDlg->isVisible() || !myDlg->isEnabled() )
606     return;
607   try {
608     SALOME_ListIO aList;
609     selectionMgr()->selectedObjects(aList, SVTK_Viewer::Type());
610     if (aList.Extent() != 1)
611       return;
612     Handle(SALOME_InteractiveObject) anIO = aList.First();
613     SMESH_Actor* aMeshActor = SMESH::FindActorByEntry(anIO->getEntry());
614
615     if (!aMeshActor) { // coord by geom
616       if ( myDlg->myDestBtn->isChecked() ) {
617         GEOM::GEOM_Object_var geom = SMESH::IObjectToInterface<GEOM::GEOM_Object>(anIO);
618         if ( !geom->_is_nil() ) {
619           TopoDS_Vertex aShape;
620           if ( GEOMBase::GetShape(geom, aShape) &&
621                aShape.ShapeType() == TopAbs_VERTEX ) {
622             gp_Pnt P = BRep_Tool::Pnt(aShape);
623             myNoPreview = true;
624             myDlg->myDestinationX->SetValue(P.X());
625             myDlg->myDestinationY->SetValue(P.Y());
626             myDlg->myDestinationZ->SetValue(P.Z());
627             myNoPreview = false;
628             redisplayPreview();
629           }
630         }
631         return;
632       }
633     }
634
635     if ( !myMeshActor )
636       myMeshActor = aMeshActor;
637
638     QString aString;
639     int nbElems = SMESH::GetNameOfSelectedElements(selector(),anIO, aString);
640     if (nbElems == 1) {
641       if (SMDS_Mesh* aMesh = aMeshActor->GetObject()->GetMesh()) {
642         if (const SMDS_MeshNode* aNode = aMesh->FindNode(aString.toInt())) {
643           myNoPreview = true;
644           if ( myDlg->myDestBtn->isChecked() ) { // set coord
645             myDlg->myDestinationX->SetValue(aNode->X());
646             myDlg->myDestinationY->SetValue(aNode->Y());
647             myDlg->myDestinationZ->SetValue(aNode->Z());
648             myNoPreview = false;
649             redisplayPreview();
650           }
651           else if ( myDlg->myIdBtn->isChecked() &&
652                     myDlg->myIdBtn->isEnabled() ) { // set node to move
653             myDlg->myId->setText(aString);
654             myNoPreview = false;
655             redisplayPreview();
656           }
657
658           if (const SMDS_MeshNode* aCurrentNode = aMesh->FindNode(myDlg->myId->text().toInt())) {
659             double x = aCurrentNode->X();
660             double y = aCurrentNode->Y();
661             double z = aCurrentNode->Z();
662             double dx = myDlg->myDestinationX->GetValue() - x;
663             double dy = myDlg->myDestinationY->GetValue() - y;
664             double dz = myDlg->myDestinationZ->GetValue() - z;
665             myDlg->myCurrentX->SetValue(x);
666             myDlg->myCurrentY->SetValue(y);
667             myDlg->myCurrentZ->SetValue(z);
668             myDlg->myDestDX->SetValue(dx);
669             myDlg->myDestDY->SetValue(dy);
670             myDlg->myDestDZ->SetValue(dz);
671             myDlg->myDestDX->setReadOnly(false);
672             myDlg->myDestDY->setReadOnly(false);
673             myDlg->myDestDZ->setReadOnly(false);
674           }
675         }
676       }
677     }
678   } catch (...) {
679   }
680 }
681
682 //================================================================================
683 /*!
684  * \brief update preview
685  */
686 //================================================================================
687
688 void SMESHGUI_MakeNodeAtPointOp::redisplayPreview()
689 {
690   if ( myNoPreview )
691     return;
692   myNoPreview = true;
693
694   SMESH::MeshPreviewStruct_var aMeshPreviewStruct;
695
696   bool moveShown = false;
697   if ( myMeshActor)
698   {
699     const bool isPreview = myDlg->myPreviewChkBox->isChecked();
700     const bool isMoveNode = myDlg->myRButMoveWithoutNode->isChecked();
701     QString msg;
702     if ( isValid( msg ) )
703     {
704       try {
705         SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(myMeshActor->getIO());
706         if (!aMesh->_is_nil()) {
707           SMESH::SMESH_MeshEditor_var aPreviewer = aMesh->GetMeshEditPreviewer();
708           if (!aPreviewer->_is_nil())
709           {
710             SUIT_OverrideCursor aWaitCursor;
711
712             int anId = myDlg->myId->text().toInt();
713
714             SMESH::double_array_var aXYZ = aMesh->GetNodeXYZ( anId );
715             if( &aXYZ.in() && aXYZ->length() >= 3 )
716             {
717               double x = aXYZ[0];
718               double y = aXYZ[1];
719               double z = aXYZ[2];
720               double dx = 0;
721               double dy = 0;
722               double dz = 0;
723
724               if ( myUpdateDestination ) {
725                 myDlg->myDestinationX->SetValue(x);
726                 myDlg->myDestinationY->SetValue(y);
727                 myDlg->myDestinationZ->SetValue(z);
728               }
729               if ( myDestCoordChanged ) {
730                 dx = myDlg->myDestinationX->GetValue() - x;
731                 dy = myDlg->myDestinationY->GetValue() - y;
732                 dz = myDlg->myDestinationZ->GetValue() - z;
733                 myDlg->myDestDX->SetValue(dx);
734                 myDlg->myDestDY->SetValue(dy);
735                 myDlg->myDestDZ->SetValue(dz);
736               }
737               else {
738                 dx = myDlg->myDestDX->GetValue() + x;
739                 dy = myDlg->myDestDY->GetValue() + y;
740                 dz = myDlg->myDestDZ->GetValue() + z;
741                 myDlg->myDestinationX->SetValue(dx);
742                 myDlg->myDestinationY->SetValue(dy);
743                 myDlg->myDestinationZ->SetValue(dz);
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(false);
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