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