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