Salome HOME
Merge from OCC_development_generic_2006
[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   int x, y;
228   mySMESHGUI->DefineDlgPosition(this, x, y);
229   this->move(x, y);
230   this->show();
231
232   // set selection mode
233   SMESH::SetPointRepresentation(true);
234   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
235     aViewWindow->SetSelectionMode(NodeSelection);
236
237   onSelectionDone();
238 }
239
240 //=======================================================================
241 // name    : SMESHGUI_MoveNodesDlg::isValid
242 // Purpose : Verify validity of entry information
243 //=======================================================================
244 bool SMESHGUI_MoveNodesDlg::isValid (const bool theMess) const
245 {
246   if (myId->text().isEmpty()) {
247     if (theMess)
248       QMessageBox::information(SMESHGUI::desktop(), tr("SMESH_WARNING"),
249                                tr("NODE_ID_IS_NOT_DEFINED"), QMessageBox::Ok);
250     return false;
251   }
252   return true;
253 }
254
255 //=======================================================================
256 // name    : SMESHGUI_MoveNodesDlg::reset
257 // Purpose : Reset the dialog state
258 //=======================================================================
259 void SMESHGUI_MoveNodesDlg::reset()
260 {
261   myId->clear();
262   myX->SetValue(0);
263   myY->SetValue(0);
264   myZ->SetValue(0);
265   redisplayPreview();
266   updateButtons();
267 }
268
269 //=======================================================================
270 // name    : SMESHGUI_MoveNodesDlg::onApply
271 // Purpose : SLOT called when "Apply" button pressed.
272 //=======================================================================
273 bool SMESHGUI_MoveNodesDlg::onApply()
274 {
275   if (mySMESHGUI->isActiveStudyLocked())
276     return false;
277
278   if (!isValid(true))
279     return false;
280
281   SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(myMeshActor->getIO());
282   if (aMesh->_is_nil()) {
283     QMessageBox::information(SMESHGUI::desktop(), tr("SMESH_ERROR"),
284                              tr("SMESHG_NO_MESH"), QMessageBox::Ok);
285     return false;
286   }
287
288   SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
289   if (aMeshEditor->_is_nil())
290     return false;
291
292   int anId = myId->text().toInt();
293   bool aResult = false;
294   try {
295     aResult = aMeshEditor->MoveNode(anId, myX->GetValue(), myY->GetValue(), myZ->GetValue());
296   } catch (...) {
297   }
298
299   if (aResult) {
300     SALOME_ListIO aList;
301     aList.Append(myMeshActor->getIO());
302     mySelectionMgr->setSelectedObjects(aList,false);
303     SMESH::UpdateView();
304     reset();
305   }
306
307   return aResult;
308 }
309
310 //=======================================================================
311 // name    : SMESHGUI_MoveNodesDlg::onOk
312 // Purpose : SLOT called when "Ok" button pressed.
313 //=======================================================================
314 void SMESHGUI_MoveNodesDlg::onOk()
315 {
316   if (onApply())
317     onClose();
318 }
319
320 //=======================================================================
321 // name    : SMESHGUI_MoveNodesDlg::onClose
322 // Purpose : SLOT called when "Close" button pressed. Close dialog
323 //=======================================================================
324 void SMESHGUI_MoveNodesDlg::onClose()
325 {
326   //mySelectionMgr->clearSelected();
327   SMESH::SetPointRepresentation(false);
328   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
329     aViewWindow->SetSelectionMode(ActorSelection);
330   disconnect(mySelectionMgr, 0, this, 0);
331   disconnect(mySMESHGUI, 0, this, 0);
332   erasePreview();
333   mySMESHGUI->ResetState();
334   reject();
335 }
336
337 //=======================================================================
338 // name    : SMESHGUI_MoveNodesDlg::onTextChange
339 // Purpose :
340 //=======================================================================
341 void SMESHGUI_MoveNodesDlg::onTextChange (const QString& theNewText)
342 {
343   if (myBusy) return;
344
345   myOkBtn->setEnabled(false);
346   myApplyBtn->setEnabled(false);
347   erasePreview();
348
349   // select entered node
350   if(myMeshActor){
351     if(SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh()){
352       myBusy = true;
353       Handle(SALOME_InteractiveObject) anIO = myMeshActor->getIO();
354       SALOME_ListIO aList;
355       aList.Append(anIO);
356       mySelectionMgr->setSelectedObjects(aList,false);
357       myBusy = false;
358
359       if(const SMDS_MeshElement *anElem = aMesh->FindElement(theNewText.toInt())) {
360         TColStd_MapOfInteger aListInd;
361         aListInd.Add(anElem->GetID());
362         mySelector->AddOrRemoveIndex(anIO,aListInd, false);
363         if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
364           aViewWindow->highlight(anIO,true,true);
365         
366         onSelectionDone();
367       }
368     }
369   }
370 }
371
372 //=======================================================================
373 // name    : SMESHGUI_MoveNodesDlg::onSelectionDone
374 // Purpose : SLOT called when selection changed
375 //=======================================================================
376 void SMESHGUI_MoveNodesDlg::onSelectionDone()
377 {
378   if (myBusy) return;
379   myMeshActor = 0;
380
381   SALOME_ListIO aList;
382   mySelectionMgr->selectedObjects(aList,SVTK_Viewer::Type());
383
384   if (aList.Extent() == 1) {
385     Handle(SALOME_InteractiveObject) anIO = aList.First();
386     myMeshActor = SMESH::FindActorByEntry(anIO->getEntry());
387     if(myMeshActor){
388       QString aText;
389       if (SMESH::GetNameOfSelectedNodes(mySelector,anIO,aText) == 1) {
390         if(SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh()) {
391           if(const SMDS_MeshNode* aNode = aMesh->FindNode(aText.toInt())) {
392             myBusy = true;
393             myId->setText(aText);
394             myX->SetValue(aNode->X());
395             myY->SetValue(aNode->Y());
396             myZ->SetValue(aNode->Z());
397             myBusy = false;
398             erasePreview(); // avoid overlapping of a selection and a preview
399             updateButtons();
400             return;
401           }
402         }
403       }
404     }
405   }
406
407   reset();
408 }
409
410 //=======================================================================
411 // name    : SMESHGUI_MoveNodesDlg::onDeactivate
412 // Purpose : SLOT called when dialog must be deativated
413 //=======================================================================
414 void SMESHGUI_MoveNodesDlg::onDeactivate()
415 {
416   setEnabled(false);
417   erasePreview();
418 }
419
420 //=======================================================================
421 // name    : SMESHGUI_MoveNodesDlg::enterEvent
422 // Purpose : Event filter
423 //=======================================================================
424 void SMESHGUI_MoveNodesDlg::enterEvent (QEvent*)
425 {
426   if (!isEnabled()) {
427     mySMESHGUI->EmitSignalDeactivateDialog();
428
429     // set selection mode
430     SMESH::SetPointRepresentation(true);
431     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
432       aViewWindow->SetSelectionMode(NodeSelection);
433
434     redisplayPreview();
435
436     setEnabled(true);
437   }
438 }
439
440 //=======================================================================
441 // name    : SMESHGUI_MoveNodesDlg::closeEvent
442 // Purpose :
443 //=======================================================================
444 void SMESHGUI_MoveNodesDlg::closeEvent (QCloseEvent*)
445 {
446   onClose();
447   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
448     aViewWindow->Repaint();
449 }
450
451 //=======================================================================
452 // name    : SMESHGUI_MoveNodesDlg::hideEvent
453 // Purpose : may be caused by ESC key
454 //=======================================================================
455 void SMESHGUI_MoveNodesDlg::hideEvent (QHideEvent*)
456 {
457   if (!isMinimized())
458     onClose();
459 }
460
461 //=======================================================================
462 // name    : SMESHGUI_MoveNodesDlg::updateButtons
463 // Purpose : Update buttons state
464 //=======================================================================
465 void SMESHGUI_MoveNodesDlg::updateButtons()
466 {
467   bool isEnabled = isValid(false);
468   myOkBtn->setEnabled(isEnabled);
469   myApplyBtn->setEnabled(isEnabled);
470 }
471
472 //=======================================================================
473 // name    : SMESHGUI_MoveNodesDlg::erasePreview
474 // Purpose : Erase preview
475 //=======================================================================
476 void  SMESHGUI_MoveNodesDlg::erasePreview()
477 {
478   if (myPreviewActor == 0)
479     return;
480
481   SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
482   if (aViewWindow)
483     aViewWindow->RemoveActor(myPreviewActor);
484   myPreviewActor->Delete();
485   myPreviewActor = 0;
486   if (aViewWindow)
487     aViewWindow->Repaint();
488 }
489
490 //=======================================================================
491 // name    : SMESHGUI_MoveNodesDlg::redisplayPreview
492 // Purpose : Redisplay preview
493 //=======================================================================
494 void SMESHGUI_MoveNodesDlg::redisplayPreview()
495 {
496   if (myBusy)
497     return;
498
499   if (myPreviewActor != 0)
500     erasePreview();
501
502   if (!isValid(false))
503     return;
504
505   vtkUnstructuredGrid* aGrid = vtkUnstructuredGrid::New();
506
507   vtkPoints* aPoints = vtkPoints::New();
508   aPoints->SetNumberOfPoints(1);
509   aPoints->SetPoint(0, myX->GetValue(), myY->GetValue(), myZ->GetValue());
510
511   // Create cells
512
513   vtkIdList *anIdList = vtkIdList::New();
514   anIdList->SetNumberOfIds(1);
515
516   vtkCellArray *aCells = vtkCellArray::New();
517   aCells->Allocate(2, 0);
518
519   vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
520   aCellTypesArray->SetNumberOfComponents(1);
521   aCellTypesArray->Allocate(1);
522
523   anIdList->SetId(0, 0);
524   aCells->InsertNextCell(anIdList);
525   aCellTypesArray->InsertNextValue(VTK_VERTEX);
526   anIdList->Delete();
527
528   vtkIntArray* aCellLocationsArray = vtkIntArray::New();
529   aCellLocationsArray->SetNumberOfComponents(1);
530   aCellLocationsArray->SetNumberOfTuples(1);
531
532   aCells->InitTraversal();
533   vtkIdType npts;
534   aCellLocationsArray->SetValue(0, aCells->GetTraversalLocation(npts));
535
536   aGrid->SetPoints(aPoints);
537   aPoints->Delete();
538
539   aGrid->SetCells(aCellTypesArray,aCellLocationsArray,aCells);
540   aCellLocationsArray->Delete();
541   aCellTypesArray->Delete();
542   aCells->Delete();
543
544   // Create and display actor
545   vtkDataSetMapper* aMapper = vtkDataSetMapper::New();
546   aMapper->SetInput(aGrid);
547   aGrid->Delete();
548
549   myPreviewActor = SALOME_Actor::New();
550   myPreviewActor->PickableOff();
551   myPreviewActor->SetMapper(aMapper);
552   aMapper->Delete();
553
554   vtkProperty* aProp = vtkProperty::New();
555   aProp->SetRepresentationToWireframe();
556   aProp->SetColor(250, 0, 250);
557   aProp->SetPointSize(5);
558   myPreviewActor->SetProperty(aProp);
559   aProp->Delete();
560
561   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
562     {
563       aViewWindow->AddActor(myPreviewActor);
564       aViewWindow->Repaint();
565     }
566 }