Salome HOME
Join modifications from branch OCC_development_for_3_2_0a2
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_MoveNodesDlg.cxx
1 //  SMESH SMESHGUI : GUI for SMESH component
2 //
3 //  Copyright (C) 2003  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.
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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
21 //
22 //
23 //
24 //  File   : SMESHGUI_MoveNodesDlg.cxx
25 //  Author : Nicolas REJNERI
26 //  Module : SMESH
27 //  $Header$
28
29 #include "SMESHGUI_MoveNodesDlg.h"
30
31 #include "SMESHGUI.h"
32 #include "SMESHGUI_SpinBox.h"
33 #include "SMESHGUI_IdValidator.h"
34 #include "SMESHGUI_Utils.h"
35 #include "SMESHGUI_VTKUtils.h"
36 #include "SMESHGUI_MeshUtils.h"
37
38 #include "SMESH_Actor.h"
39 #include "SMDS_Mesh.hxx"
40 #include "SMDS_MeshNode.hxx"
41
42 #include "LightApp_SelectionMgr.h"
43 #include "SUIT_ResourceMgr.h"
44 #include "SUIT_Desktop.h"
45
46 #include "SVTK_Selector.h"
47 #include "SVTK_ViewModel.h"
48 #include "SVTK_ViewWindow.h"
49 #include "SALOME_ListIO.hxx"
50
51 #include "SVTK_ViewWindow.h"
52
53 #include "utilities.h"
54
55 // OCCT includes
56 #include <TColStd_MapOfInteger.hxx>
57
58 // VTK includes
59 #include <vtkCell.h>
60 #include <vtkIdList.h>
61 #include <vtkIntArray.h>
62 #include <vtkCellArray.h>
63 #include <vtkUnsignedCharArray.h>
64 #include <vtkUnstructuredGrid.h>
65 #include <vtkDataSetMapper.h>
66 #include <vtkProperty.h>
67
68 // QT includes
69 #include <qgroupbox.h>
70 #include <qlabel.h>
71 #include <qlineedit.h>
72 #include <qpushbutton.h>
73 #include <qradiobutton.h>
74 #include <qlayout.h>
75 #include <qpixmap.h>
76 #include <qmessagebox.h>
77 #include <qbuttongroup.h>
78
79 // IDL Headers
80 #include <SALOMEconfig.h>
81 #include CORBA_SERVER_HEADER(SMESH_Mesh)
82
83 #define MARGIN  10
84 #define SPACING 5
85
86
87 //=================================================================================
88 // name    : SMESHGUI_MoveNodesDlg::SMESHGUI_MoveNodesDlg
89 // Purpose :
90 //=================================================================================
91 SMESHGUI_MoveNodesDlg::SMESHGUI_MoveNodesDlg (SMESHGUI* theModule, 
92                                               const char* theName):
93   QDialog(SMESH::GetDesktop(theModule), 
94           theName, 
95           false,
96           WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu),
97   mySelectionMgr(SMESH::GetSelectionMgr(theModule)),
98   mySMESHGUI(theModule)
99 {
100   myPreviewActor = 0;
101   myBusy = false;
102
103   setCaption(tr("CAPTION"));
104
105   QVBoxLayout* aDlgLay = new QVBoxLayout (this, MARGIN, SPACING);
106
107   QFrame* aMainFrame = createMainFrame  (this);
108   QFrame* aBtnFrame  = createButtonFrame(this);
109
110   aDlgLay->addWidget(aMainFrame);
111   aDlgLay->addWidget(aBtnFrame);
112
113   aDlgLay->setStretchFactor(aMainFrame, 1);
114
115   mySelector = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector();
116
117   Init();
118 }
119
120 //=======================================================================
121 // name    : SMESHGUI_MoveNodesDlg::createButtonFrame
122 // Purpose : Create frame containing buttons
123 //=======================================================================
124 QFrame* SMESHGUI_MoveNodesDlg::createButtonFrame (QWidget* theParent)
125 {
126   QFrame* aFrame = new QFrame(theParent);
127   aFrame->setFrameStyle(QFrame::Box | QFrame::Sunken);
128
129   myOkBtn     = new QPushButton(tr("SMESH_BUT_OK"   ), aFrame);
130   myApplyBtn  = new QPushButton(tr("SMESH_BUT_APPLY"), aFrame);
131   myCloseBtn  = new QPushButton(tr("SMESH_BUT_CLOSE"), aFrame);
132
133   QSpacerItem* aSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
134
135   QHBoxLayout* aLay = new QHBoxLayout(aFrame, MARGIN, SPACING);
136
137   aLay->addWidget(myOkBtn);
138   aLay->addWidget(myApplyBtn);
139   aLay->addItem(aSpacer);
140   aLay->addWidget(myCloseBtn);
141
142   connect(myOkBtn,    SIGNAL(clicked()), SLOT(onOk()));
143   connect(myCloseBtn, SIGNAL(clicked()), SLOT(onClose()));
144   connect(myApplyBtn, SIGNAL(clicked()), SLOT(onApply()));
145
146   return aFrame;
147 }
148
149 //=======================================================================
150 // name    : SMESHGUI_MoveNodesDlg::createMainFrame
151 // Purpose : Create frame containing dialog's input fields
152 //=======================================================================
153 QFrame* SMESHGUI_MoveNodesDlg::createMainFrame (QWidget* theParent)
154 {
155   QFrame* aFrame = new QFrame(theParent);
156
157   QPixmap iconMoveNode (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_DLG_MOVE_NODE")));
158   QPixmap iconSelect   (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_SELECT")));
159
160   QButtonGroup* aPixGrp = new QButtonGroup(1, Qt::Vertical, tr("MESH_NODE"), aFrame);
161   aPixGrp->setExclusive(TRUE);
162   QRadioButton* aRBut = new QRadioButton(aPixGrp);
163   aRBut->setPixmap(iconMoveNode);
164   aRBut->setChecked(TRUE);
165
166   QGroupBox* anIdGrp = new QGroupBox(1, Qt::Vertical, tr("SMESH_MOVE"), aFrame);
167   new QLabel(tr("NODE_ID"), anIdGrp);
168   (new QPushButton(anIdGrp))->setPixmap(iconSelect);
169   myId = new QLineEdit(anIdGrp);
170   myId->setValidator(new SMESHGUI_IdValidator(this, "validator", 1));
171
172   QGroupBox* aCoordGrp = new QGroupBox(1, Qt::Vertical, tr("SMESH_COORDINATES"), aFrame);
173   new QLabel(tr("SMESH_X"), aCoordGrp);
174   myX = new SMESHGUI_SpinBox(aCoordGrp);
175   new QLabel(tr("SMESH_Y"), aCoordGrp);
176   myY = new SMESHGUI_SpinBox(aCoordGrp);
177   new QLabel(tr("SMESH_Z"), aCoordGrp);
178   myZ = new SMESHGUI_SpinBox(aCoordGrp);
179
180   myX->RangeStepAndValidator(-999999.999, +999999.999, 25.0, 3);
181   myY->RangeStepAndValidator(-999999.999, +999999.999, 25.0, 3);
182   myZ->RangeStepAndValidator(-999999.999, +999999.999, 25.0, 3);
183
184   QVBoxLayout* aLay = new QVBoxLayout(aFrame);
185   aLay->addWidget(aPixGrp);
186   aLay->addWidget(anIdGrp);
187   aLay->addWidget(aCoordGrp);
188
189   // connect signale and slots
190   connect(myX, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
191   connect(myY, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
192   connect(myZ, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
193   connect(myId, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
194
195   return aFrame;
196 }
197
198 //=======================================================================
199 // name    : SMESHGUI_MoveNodesDlg::~SMESHGUI_MoveNodesDlg
200 // Purpose :
201 //=======================================================================
202 SMESHGUI_MoveNodesDlg::~SMESHGUI_MoveNodesDlg()
203 {
204   erasePreview();
205 }
206
207 //=======================================================================
208 // name    : SMESHGUI_MoveNodesDlg::Init
209 // Purpose : Init dialog fields
210 //=======================================================================
211 void SMESHGUI_MoveNodesDlg::Init()
212 {
213   myPreviewActor = 0;
214   myMeshActor = 0;
215   myBusy = false;
216
217   mySMESHGUI->SetActiveDialogBox((QDialog*)this);
218
219   // selection and SMESHGUI
220   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionDone()));
221   connect(mySMESHGUI, SIGNAL(SignalDeactivateActiveDialog()), SLOT(onDeactivate()));
222   connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()), SLOT(onClose()));
223
224   reset();
225   setEnabled(true);
226
227   this->show();
228
229   // set selection mode
230   SMESH::SetPointRepresentation(true);
231   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
232     aViewWindow->SetSelectionMode(NodeSelection);
233
234   onSelectionDone();
235 }
236
237 //=======================================================================
238 // name    : SMESHGUI_MoveNodesDlg::isValid
239 // Purpose : Verify validity of entry information
240 //=======================================================================
241 bool SMESHGUI_MoveNodesDlg::isValid (const bool theMess) const
242 {
243   if (myId->text().isEmpty()) {
244     if (theMess)
245       QMessageBox::information(SMESHGUI::desktop(), tr("SMESH_WARNING"),
246                                tr("NODE_ID_IS_NOT_DEFINED"), QMessageBox::Ok);
247     return false;
248   }
249   return true;
250 }
251
252 //=======================================================================
253 // name    : SMESHGUI_MoveNodesDlg::reset
254 // Purpose : Reset the dialog state
255 //=======================================================================
256 void SMESHGUI_MoveNodesDlg::reset()
257 {
258   myId->clear();
259   myX->SetValue(0);
260   myY->SetValue(0);
261   myZ->SetValue(0);
262   redisplayPreview();
263   updateButtons();
264 }
265
266 //=======================================================================
267 // name    : SMESHGUI_MoveNodesDlg::onApply
268 // Purpose : SLOT called when "Apply" button pressed.
269 //=======================================================================
270 bool SMESHGUI_MoveNodesDlg::onApply()
271 {
272   if (mySMESHGUI->isActiveStudyLocked())
273     return false;
274
275   if (!isValid(true))
276     return false;
277
278   SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(myMeshActor->getIO());
279   if (aMesh->_is_nil()) {
280     QMessageBox::information(SMESHGUI::desktop(), tr("SMESH_ERROR"),
281                              tr("SMESHG_NO_MESH"), QMessageBox::Ok);
282     return false;
283   }
284
285   SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
286   if (aMeshEditor->_is_nil())
287     return false;
288
289   int anId = myId->text().toInt();
290   bool aResult = false;
291   try {
292     aResult = aMeshEditor->MoveNode(anId, myX->GetValue(), myY->GetValue(), myZ->GetValue());
293   } catch (...) {
294   }
295
296   if (aResult) {
297     SALOME_ListIO aList;
298     aList.Append(myMeshActor->getIO());
299     mySelectionMgr->setSelectedObjects(aList,false);
300     SMESH::UpdateView();
301     reset();
302   }
303
304   return aResult;
305 }
306
307 //=======================================================================
308 // name    : SMESHGUI_MoveNodesDlg::onOk
309 // Purpose : SLOT called when "Ok" button pressed.
310 //=======================================================================
311 void SMESHGUI_MoveNodesDlg::onOk()
312 {
313   if (onApply())
314     onClose();
315 }
316
317 //=======================================================================
318 // name    : SMESHGUI_MoveNodesDlg::onClose
319 // Purpose : SLOT called when "Close" button pressed. Close dialog
320 //=======================================================================
321 void SMESHGUI_MoveNodesDlg::onClose()
322 {
323   //mySelectionMgr->clearSelected();
324   SMESH::SetPointRepresentation(false);
325   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
326     aViewWindow->SetSelectionMode(ActorSelection);
327   disconnect(mySelectionMgr, 0, this, 0);
328   disconnect(mySMESHGUI, 0, this, 0);
329   erasePreview();
330   mySMESHGUI->ResetState();
331   reject();
332 }
333
334 //=======================================================================
335 // name    : SMESHGUI_MoveNodesDlg::onTextChange
336 // Purpose :
337 //=======================================================================
338 void SMESHGUI_MoveNodesDlg::onTextChange (const QString& theNewText)
339 {
340   if (myBusy) return;
341
342   myOkBtn->setEnabled(false);
343   myApplyBtn->setEnabled(false);
344   erasePreview();
345
346   // select entered node
347   if(myMeshActor){
348     if(SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh()){
349       myBusy = true;
350       Handle(SALOME_InteractiveObject) anIO = myMeshActor->getIO();
351       SALOME_ListIO aList;
352       aList.Append(anIO);
353       mySelectionMgr->setSelectedObjects(aList,false);
354       myBusy = false;
355
356       if(const SMDS_MeshElement *anElem = aMesh->FindElement(theNewText.toInt())) {
357         TColStd_MapOfInteger aListInd;
358         aListInd.Add(anElem->GetID());
359         mySelector->AddOrRemoveIndex(anIO,aListInd, false);
360         if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
361           aViewWindow->highlight(anIO,true,true);
362         
363         onSelectionDone();
364       }
365     }
366   }
367 }
368
369 //=======================================================================
370 // name    : SMESHGUI_MoveNodesDlg::onSelectionDone
371 // Purpose : SLOT called when selection changed
372 //=======================================================================
373 void SMESHGUI_MoveNodesDlg::onSelectionDone()
374 {
375   if (myBusy) return;
376   myMeshActor = 0;
377
378   SALOME_ListIO aList;
379   mySelectionMgr->selectedObjects(aList,SVTK_Viewer::Type());
380
381   if (aList.Extent() == 1) {
382     Handle(SALOME_InteractiveObject) anIO = aList.First();
383     myMeshActor = SMESH::FindActorByEntry(anIO->getEntry());
384     if(myMeshActor){
385       QString aText;
386       if (SMESH::GetNameOfSelectedNodes(mySelector,anIO,aText) == 1) {
387         if(SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh()) {
388           if(const SMDS_MeshNode* aNode = aMesh->FindNode(aText.toInt())) {
389             myBusy = true;
390             myId->setText(aText);
391             myX->SetValue(aNode->X());
392             myY->SetValue(aNode->Y());
393             myZ->SetValue(aNode->Z());
394             myBusy = false;
395             erasePreview(); // avoid overlapping of a selection and a preview
396             updateButtons();
397             return;
398           }
399         }
400       }
401     }
402   }
403
404   reset();
405 }
406
407 //=======================================================================
408 // name    : SMESHGUI_MoveNodesDlg::onDeactivate
409 // Purpose : SLOT called when dialog must be deativated
410 //=======================================================================
411 void SMESHGUI_MoveNodesDlg::onDeactivate()
412 {
413   setEnabled(false);
414   erasePreview();
415 }
416
417 //=======================================================================
418 // name    : SMESHGUI_MoveNodesDlg::enterEvent
419 // Purpose : Event filter
420 //=======================================================================
421 void SMESHGUI_MoveNodesDlg::enterEvent (QEvent*)
422 {
423   if (!isEnabled()) {
424     mySMESHGUI->EmitSignalDeactivateDialog();
425
426     // set selection mode
427     SMESH::SetPointRepresentation(true);
428     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
429       aViewWindow->SetSelectionMode(NodeSelection);
430
431     redisplayPreview();
432
433     setEnabled(true);
434   }
435 }
436
437 //=======================================================================
438 // name    : SMESHGUI_MoveNodesDlg::closeEvent
439 // Purpose :
440 //=======================================================================
441 void SMESHGUI_MoveNodesDlg::closeEvent (QCloseEvent*)
442 {
443   onClose();
444   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
445     aViewWindow->Repaint();
446 }
447
448 //=======================================================================
449 // name    : SMESHGUI_MoveNodesDlg::hideEvent
450 // Purpose : may be caused by ESC key
451 //=======================================================================
452 void SMESHGUI_MoveNodesDlg::hideEvent (QHideEvent*)
453 {
454   if (!isMinimized())
455     onClose();
456 }
457
458 //=======================================================================
459 // name    : SMESHGUI_MoveNodesDlg::updateButtons
460 // Purpose : Update buttons state
461 //=======================================================================
462 void SMESHGUI_MoveNodesDlg::updateButtons()
463 {
464   bool isEnabled = isValid(false);
465   myOkBtn->setEnabled(isEnabled);
466   myApplyBtn->setEnabled(isEnabled);
467 }
468
469 //=======================================================================
470 // name    : SMESHGUI_MoveNodesDlg::erasePreview
471 // Purpose : Erase preview
472 //=======================================================================
473 void  SMESHGUI_MoveNodesDlg::erasePreview()
474 {
475   if (myPreviewActor == 0)
476     return;
477
478   SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
479   if (aViewWindow)
480     aViewWindow->RemoveActor(myPreviewActor);
481   myPreviewActor->Delete();
482   myPreviewActor = 0;
483   if (aViewWindow)
484     aViewWindow->Repaint();
485 }
486
487 //=======================================================================
488 // name    : SMESHGUI_MoveNodesDlg::redisplayPreview
489 // Purpose : Redisplay preview
490 //=======================================================================
491 void SMESHGUI_MoveNodesDlg::redisplayPreview()
492 {
493   if (myBusy)
494     return;
495
496   if (myPreviewActor != 0)
497     erasePreview();
498
499   if (!isValid(false))
500     return;
501
502   vtkUnstructuredGrid* aGrid = vtkUnstructuredGrid::New();
503
504   vtkPoints* aPoints = vtkPoints::New();
505   aPoints->SetNumberOfPoints(1);
506   aPoints->SetPoint(0, myX->GetValue(), myY->GetValue(), myZ->GetValue());
507
508   // Create cells
509
510   vtkIdList *anIdList = vtkIdList::New();
511   anIdList->SetNumberOfIds(1);
512
513   vtkCellArray *aCells = vtkCellArray::New();
514   aCells->Allocate(2, 0);
515
516   vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
517   aCellTypesArray->SetNumberOfComponents(1);
518   aCellTypesArray->Allocate(1);
519
520   anIdList->SetId(0, 0);
521   aCells->InsertNextCell(anIdList);
522   aCellTypesArray->InsertNextValue(VTK_VERTEX);
523   anIdList->Delete();
524
525   vtkIntArray* aCellLocationsArray = vtkIntArray::New();
526   aCellLocationsArray->SetNumberOfComponents(1);
527   aCellLocationsArray->SetNumberOfTuples(1);
528
529   aCells->InitTraversal();
530   vtkIdType npts;
531   aCellLocationsArray->SetValue(0, aCells->GetTraversalLocation(npts));
532
533   aGrid->SetPoints(aPoints);
534   aPoints->Delete();
535
536   aGrid->SetCells(aCellTypesArray,aCellLocationsArray,aCells);
537   aCellLocationsArray->Delete();
538   aCellTypesArray->Delete();
539   aCells->Delete();
540
541   // Create and display actor
542   vtkDataSetMapper* aMapper = vtkDataSetMapper::New();
543   aMapper->SetInput(aGrid);
544   aGrid->Delete();
545
546   myPreviewActor = SALOME_Actor::New();
547   myPreviewActor->PickableOff();
548   myPreviewActor->SetMapper(aMapper);
549   aMapper->Delete();
550
551   vtkProperty* aProp = vtkProperty::New();
552   aProp->SetRepresentationToWireframe();
553   aProp->SetColor(250, 0, 250);
554   aProp->SetPointSize(5);
555   myPreviewActor->SetProperty(aProp);
556   aProp->Delete();
557
558   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
559     {
560       aViewWindow->AddActor(myPreviewActor);
561       aViewWindow->Repaint();
562     }
563 }