Salome HOME
IMP 22792: EDF 8159 SMESH: Multi-dimensional extrusion/extrusion along a path/revolution
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_ExtrusionAlongPathDlg.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // SMESH SMESHGUI : GUI for SMESH component
24 // File   : SMESHGUI_ExtrusionAlongPathDlg.cxx
25 // Author : Vadim SANDLER, Open CASCADE S.A.S.
26 // SMESH includes
27
28 #include "SMESHGUI_ExtrusionAlongPathDlg.h"
29
30 #include "SMESHGUI.h"
31 #include "SMESHGUI_ExtrusionDlg.h" // for SMESHGUI_3TypesSelector
32 #include "SMESHGUI_FilterDlg.h"
33 #include "SMESHGUI_IdValidator.h"
34 #include "SMESHGUI_MeshEditPreview.h"
35 #include "SMESHGUI_MeshUtils.h"
36 #include "SMESHGUI_SpinBox.h"
37 #include "SMESHGUI_Utils.h"
38 #include "SMESHGUI_VTKUtils.h"
39
40 #include <SMESH_Actor.h>
41 #include <SMESH_TypeFilter.hxx>
42 #include <SMESH_NumberFilter.hxx>
43 #include <SMESH_LogicalFilter.hxx>
44
45 #include <SMDS_Mesh.hxx>
46
47 // SALOME GEOM includes
48 #include <GEOMBase.h>
49
50 // SALOME GUI includes
51 #include <SUIT_ResourceMgr.h>
52 #include <SUIT_OverrideCursor.h>
53 #include <SUIT_Desktop.h>
54 #include <SUIT_MessageBox.h>
55 #include <SUIT_Session.h>
56 #include <LightApp_Application.h>
57 #include <LightApp_SelectionMgr.h>
58 #include <SVTK_ViewWindow.h>
59
60 // OCCT includes
61 #include <BRep_Tool.hxx>
62 #include <TopoDS_Vertex.hxx>
63 #include <gp_Pnt.hxx>
64 #include <TColStd_MapOfInteger.hxx>
65
66 // Qt includes
67 #include <QButtonGroup>
68 #include <QGroupBox>
69 #include <QLabel>
70 #include <QLineEdit>
71 #include <QPushButton>
72 #include <QToolButton>
73 #include <QRadioButton>
74 #include <QCheckBox>
75 #include <QListWidget>
76 #include <QVBoxLayout>
77 #include <QHBoxLayout>
78 #include <QGridLayout>
79 #include <QKeyEvent>
80
81 // IDL includes
82 #include <SALOMEconfig.h>
83 #include CORBA_SERVER_HEADER(SMESH_Group)
84 #include CORBA_SERVER_HEADER(SMESH_MeshEditor)
85
86 #define SPACING 6
87 #define MARGIN  11
88
89 class SMESHGUI_ExtrusionAlongPathDlg::SetBusy
90 {
91 public:
92   SetBusy( SMESHGUI_ExtrusionAlongPathDlg* _dlg )
93   {
94     myDlg = _dlg; 
95     myDlg->myBusy = true;
96   }
97   
98   ~SetBusy()
99   { 
100     myDlg->myBusy = false;
101   }
102   
103 private:
104   SMESHGUI_ExtrusionAlongPathDlg* myDlg;
105 };
106
107 //=================================================================================
108 // function : SMESHGUI_ExtrusionAlongPathDlg()
109 // purpose  : constructor
110 //=================================================================================
111 SMESHGUI_ExtrusionAlongPathDlg::SMESHGUI_ExtrusionAlongPathDlg( SMESHGUI* theModule )
112   : SMESHGUI_PreviewDlg( theModule ),
113     mySelectionMgr( SMESH::GetSelectionMgr( theModule ) )
114 {
115   SUIT_ResourceMgr* mgr = SMESH::GetResourceMgr( mySMESHGUI );
116   QPixmap selectImage ( mgr->loadPixmap("SMESH", tr("ICON_SELECT")));
117   QPixmap addImage    ( mgr->loadPixmap("SMESH", tr("ICON_APPEND")));
118   QPixmap removeImage ( mgr->loadPixmap("SMESH", tr("ICON_REMOVE")));
119
120   setModal( false );
121   setAttribute( Qt::WA_DeleteOnClose, true );
122   setWindowTitle(tr("EXTRUSION_ALONG_PATH"));
123   setSizeGripEnabled(true);
124
125   QVBoxLayout* topLayout = new QVBoxLayout(this);
126   topLayout->setSpacing(SPACING);
127   topLayout->setMargin(MARGIN);
128
129   /***************************************************************/
130   // Arguments group box
131   GroupArguments = new QGroupBox(tr("SMESH_EXTRUSION"), this);
132   QGridLayout* GroupArgumentsLayout = new QGridLayout(GroupArguments);
133   GroupArgumentsLayout->setSpacing(SPACING); GroupArgumentsLayout->setMargin(MARGIN);
134
135   myIdValidator = new SMESHGUI_IdValidator(this);
136
137   // Controls for elements selection
138   SelectorWdg = new SMESHGUI_3TypesSelector( GroupArguments );
139   
140   // Controls for path selection
141   PathGrp = new QGroupBox(tr("SMESH_PATH"), GroupArguments);
142   QGridLayout* PathGrpLayout = new QGridLayout(PathGrp);
143   PathGrpLayout->setSpacing(SPACING); PathGrpLayout->setMargin(MARGIN);
144
145   // Controls for path mesh selection
146   QLabel* PathMeshLab = new QLabel(tr("SMESH_PATH_MESH"), PathGrp);
147
148   SelectPathMeshButton = new QPushButton(PathGrp);
149   SelectPathMeshButton->setIcon(selectImage);
150   SelectPathMeshButton->setCheckable(true);
151
152   PathMeshLineEdit = new QLineEdit(PathGrp);
153   PathMeshLineEdit->setReadOnly(true);
154
155   // Controls for path starting point selection
156   QLabel* StartPointLab = new QLabel(tr("SMESH_PATH_START"), PathGrp);
157
158   SelectStartPointButton = new QPushButton(PathGrp);
159   SelectStartPointButton->setIcon(selectImage);
160   SelectStartPointButton->setCheckable(true);
161
162   StartPointLineEdit = new QLineEdit(PathGrp);
163   StartPointLineEdit->setValidator(new QIntValidator(this));
164
165   // layouting
166   PathGrpLayout->addWidget(PathMeshLab,            0, 0);
167   PathGrpLayout->addWidget(SelectPathMeshButton,   0, 1);
168   PathGrpLayout->addWidget(PathMeshLineEdit,       0, 2);
169   PathGrpLayout->addWidget(StartPointLab,          1, 0);
170   PathGrpLayout->addWidget(SelectStartPointButton, 1, 1);
171   PathGrpLayout->addWidget(StartPointLineEdit,     1, 2);
172
173   BasePointGrp = new QGroupBox(tr("SMESH_BASE_POINT"), GroupArguments);
174   BasePointGrp->setCheckable(true);
175   BasePointGrp->setChecked(false);
176   QHBoxLayout* BasePointGrpLayout = new QHBoxLayout(BasePointGrp);
177   BasePointGrpLayout->setSpacing(SPACING); BasePointGrpLayout->setMargin(MARGIN);
178
179   SelectBasePointButton = new QPushButton(BasePointGrp);
180   SelectBasePointButton->setIcon(selectImage);
181   SelectBasePointButton->setCheckable(true);
182
183   SelectorWdg->GetButtonGroup()->addButton( SelectPathMeshButton );
184   SelectorWdg->GetButtonGroup()->addButton( SelectStartPointButton );
185   SelectorWdg->GetButtonGroup()->addButton( SelectBasePointButton );
186
187   QLabel* XLab  = new QLabel(tr("SMESH_X"), BasePointGrp);
188   XSpin = new SMESHGUI_SpinBox(BasePointGrp);
189   QLabel* YLab  = new QLabel(tr("SMESH_Y"), BasePointGrp);
190   YSpin = new SMESHGUI_SpinBox(BasePointGrp);
191   QLabel* ZLab  = new QLabel(tr("SMESH_Z"), BasePointGrp);
192   ZSpin = new SMESHGUI_SpinBox(BasePointGrp);
193
194   // layouting
195   BasePointGrpLayout->addWidget(SelectBasePointButton);
196   BasePointGrpLayout->addWidget(XLab);
197   BasePointGrpLayout->addWidget(XSpin);
198   BasePointGrpLayout->addWidget(YLab);
199   BasePointGrpLayout->addWidget(YSpin);
200   BasePointGrpLayout->addWidget(ZLab);
201   BasePointGrpLayout->addWidget(ZSpin);
202
203   AnglesGrp = new QGroupBox(tr("SMESH_ANGLES"), GroupArguments);
204   AnglesGrp->setCheckable(true);
205   AnglesGrp->setChecked(false);
206   QGridLayout* AnglesGrpLayout = new QGridLayout(AnglesGrp);
207   AnglesGrpLayout->setSpacing(SPACING); AnglesGrpLayout->setMargin(MARGIN);
208
209   AnglesList = new QListWidget(AnglesGrp);
210   AnglesList->setSelectionMode(QListWidget::ExtendedSelection);
211
212   AddAngleButton = new QToolButton(AnglesGrp);
213   AddAngleButton->setIcon(addImage);
214
215   RemoveAngleButton = new QToolButton(AnglesGrp);
216   RemoveAngleButton->setIcon(removeImage);
217
218   AngleSpin = new SMESHGUI_SpinBox(AnglesGrp);
219
220   LinearAnglesCheck = new QCheckBox(tr("LINEAR_ANGLES"), AnglesGrp);
221
222   // layouting
223   AnglesGrpLayout->addWidget(AnglesList,        0, 0, 4, 1);
224   AnglesGrpLayout->addWidget(AddAngleButton,    0, 1);
225   AnglesGrpLayout->addWidget(RemoveAngleButton, 2, 1);
226   AnglesGrpLayout->addWidget(AngleSpin,         0, 2);
227   AnglesGrpLayout->addWidget(LinearAnglesCheck, 4, 0);
228   AnglesGrpLayout->setRowMinimumHeight(1, 10);
229   AnglesGrpLayout->setRowStretch(3, 10);
230
231   // CheckBox for groups generation
232   MakeGroupsCheck = new QCheckBox(tr("SMESH_MAKE_GROUPS"), GroupArguments);
233   MakeGroupsCheck->setChecked(true);
234
235   //Preview check box
236   myPreviewCheckBox = new QCheckBox(tr("PREVIEW"), GroupArguments);
237
238   // layouting
239   GroupArgumentsLayout->addWidget(SelectorWdg,          0, 0);
240   GroupArgumentsLayout->addWidget(PathGrp,              1, 0);
241   GroupArgumentsLayout->addWidget(BasePointGrp,         2, 0);
242   GroupArgumentsLayout->addWidget(AnglesGrp,            3, 0);
243   GroupArgumentsLayout->addWidget(myPreviewCheckBox,    4, 0);
244   GroupArgumentsLayout->addWidget(MakeGroupsCheck,      5, 0);
245
246   /***************************************************************/
247   // common buttons group box
248   GroupButtons = new QGroupBox(this);
249   QHBoxLayout* GroupButtonsLayout = new QHBoxLayout(GroupButtons);
250   GroupButtonsLayout->setSpacing(SPACING); GroupButtonsLayout->setMargin(MARGIN);
251
252   OkButton = new QPushButton(tr("SMESH_BUT_APPLY_AND_CLOSE"), GroupButtons);
253   OkButton->setAutoDefault(true);
254   OkButton->setDefault(true);
255
256   ApplyButton = new QPushButton(tr("SMESH_BUT_APPLY"), GroupButtons);
257   ApplyButton->setAutoDefault(true);
258
259   CloseButton = new QPushButton(tr("SMESH_BUT_CLOSE"), GroupButtons);
260   CloseButton->setAutoDefault(true);
261
262   HelpButton = new QPushButton(tr("SMESH_BUT_HELP"), GroupButtons);
263   HelpButton->setAutoDefault(true);
264
265   // layouting
266   GroupButtonsLayout->addWidget(OkButton);
267   GroupButtonsLayout->addSpacing(10);
268   GroupButtonsLayout->addWidget(ApplyButton);
269   GroupButtonsLayout->addSpacing(10);
270   GroupButtonsLayout->addStretch();
271   GroupButtonsLayout->addWidget(CloseButton);
272   GroupButtonsLayout->addWidget(HelpButton);
273
274   /***************************************************************/
275   // layouting
276   topLayout->addWidget(GroupArguments);
277   topLayout->addWidget(GroupButtons);
278
279   /***************************************************************/
280   // Initialisations
281   XSpin->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
282   YSpin->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
283   ZSpin->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
284   AngleSpin->RangeStepAndValidator(-180.0, 180.0, 5.0, "angle_precision");
285
286   mySelector = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector();
287
288   mySMESHGUI->SetActiveDialogBox(this);
289
290   myPathMeshFilter = new SMESH_TypeFilter(SMESH::MESHorSUBMESH);
291
292   myHelpFileName = "extrusion_along_path_page.html";
293
294   Init();
295
296   /***************************************************************/
297   // signals-slots connections
298   connect(OkButton,     SIGNAL(clicked()), this, SLOT(ClickOnOk()));
299   connect(CloseButton,  SIGNAL(clicked()), this, SLOT(reject()));
300   connect(ApplyButton,  SIGNAL(clicked()), this, SLOT(ClickOnApply()));
301   connect(HelpButton,   SIGNAL(clicked()), this, SLOT(ClickOnHelp()));
302
303   connect(AddAngleButton,    SIGNAL(clicked()), this, SLOT(OnAngleAdded()));
304   connect(RemoveAngleButton, SIGNAL(clicked()), this, SLOT(OnAngleRemoved()));
305
306   connect(SelectPathMeshButton,   SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
307   connect(SelectStartPointButton, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
308   connect(SelectBasePointButton,  SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
309   connect(BasePointGrp,       SIGNAL(toggled(bool)), this, SLOT(SetEditCurrentArgument()));
310
311   connect(mySMESHGUI,  SIGNAL(SignalCloseAllDialogs()),        SLOT(reject()));
312   connect(mySMESHGUI,  SIGNAL(SignalDeactivateActiveDialog()), SLOT(DeactivateActiveDialog()));
313   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()),   SLOT(SelectionIntoArgument()));
314   connect(SelectorWdg,    SIGNAL(selectionChanged()), this,    SLOT(toDisplaySimulation()));
315   connect(SelectorWdg,    SIGNAL(selectionChanged()), this,    SLOT(CheckIsEnable()));
316
317   connect(StartPointLineEdit, SIGNAL(textChanged(const QString&)),
318           SLOT(onTextChange(const QString&)));
319
320   connect(XSpin,  SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
321   connect(YSpin,  SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
322   connect(ZSpin,  SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
323   connect(AddAngleButton,    SIGNAL(clicked()), this, SLOT(toDisplaySimulation()));
324   connect(RemoveAngleButton, SIGNAL(clicked()), this, SLOT(toDisplaySimulation()));
325   //connect(LinearAnglesCheck, SIGNAL(toggled(bool)), SLOT(onSelectMesh()));
326
327
328   //To Connect preview check box
329   connectPreviewControl();
330
331   AnglesList        ->installEventFilter(this);
332   StartPointLineEdit->installEventFilter(this);
333   XSpin->editor()   ->installEventFilter(this);
334   YSpin->editor()   ->installEventFilter(this);
335   ZSpin->editor()   ->installEventFilter(this);
336
337   CheckIsEnable();
338 }
339
340 //=================================================================================
341 // function : ~SMESHGUI_ExtrusionAlongPathDlg()
342 // purpose  : destructor
343 //=================================================================================
344 SMESHGUI_ExtrusionAlongPathDlg::~SMESHGUI_ExtrusionAlongPathDlg()
345 {
346   // no need to delete child widgets, Qt does it all for us
347 }
348
349 //=================================================================================
350 // function : Init()
351 // purpose  : initialization
352 //=================================================================================
353 void SMESHGUI_ExtrusionAlongPathDlg::Init (bool ResetControls)
354 {
355   myBusy = false;
356   myEditCurrentArgument = 0;
357
358   myPath = SMESH::SMESH_IDSource::_nil();
359
360   SelectorWdg->Clear();
361   PathMeshLineEdit->clear();
362   StartPointLineEdit->clear();
363
364   if (ResetControls) {
365     XSpin->SetValue(0.0);
366     YSpin->SetValue(0.0);
367     ZSpin->SetValue(0.0);
368
369     AngleSpin->SetValue(45);
370     myPreviewCheckBox->setChecked(false);
371     onDisplaySimulation(false);
372   }
373   SetEditCurrentArgument(0);
374 }
375
376 //=================================================================================
377 // function : CheckIsEnable()
378 // purpose  : Check whether the Ok and Apply buttons should be enabled or not
379 //=================================================================================
380
381 void SMESHGUI_ExtrusionAlongPathDlg::CheckIsEnable()
382 {  
383   bool anIsEnable = SelectorWdg->IsAnythingSelected() && isValuesValid();
384
385   OkButton->setEnabled(anIsEnable);
386   ApplyButton->setEnabled(anIsEnable);
387 }
388
389 //=================================================================================
390 // function : ClickOnApply()
391 // purpose  : Called when user presses <Apply> button
392 //=================================================================================
393 bool SMESHGUI_ExtrusionAlongPathDlg::ClickOnApply()
394 {
395   if (mySMESHGUI->isActiveStudyLocked())
396     return false;
397
398   if ( !SelectorWdg->IsAnythingSelected() || myPath->_is_nil() )
399     return false;
400
401   if (!isValid())
402     return false;
403
404   if (StartPointLineEdit->text().trimmed().isEmpty()) {
405     return false;
406   }
407   
408   bool bOk;
409   long aNodeStart = StartPointLineEdit->text().toLong(&bOk);
410   if (!bOk) {
411     return false;
412   }
413
414   QStringList aParameters;
415   
416   //get angles
417   SMESH::double_array_var anAngles = getAngles();
418   
419   for (int i = 0; i < myAnglesList.count(); i++)
420     aParameters << AnglesList->item(i)->text();
421
422
423   // get base point
424   SMESH::PointStruct aBasePoint;
425   if (BasePointGrp->isChecked()) {
426     aBasePoint.x = XSpin->GetValue();
427     aBasePoint.y = YSpin->GetValue();
428     aBasePoint.z = ZSpin->GetValue();
429   }
430   aParameters << XSpin->text();
431   aParameters << YSpin->text();
432   aParameters << ZSpin->text();
433
434   bool meshHadNewTypeBefore = true;
435   int  maxSelType = 0;
436   const bool makeGroups = ( MakeGroupsCheck->isEnabled() && MakeGroupsCheck->isChecked() );
437
438   try {
439     SUIT_OverrideCursor wc;
440
441     SMESH::SMESH_Mesh_var mesh = SelectorWdg->GetMesh();
442
443     mesh->SetParameters( aParameters.join(":").toLatin1().constData() );
444
445       SMESH::ListOfIDSources_var nodes = new SMESH::ListOfIDSources();
446       SMESH::ListOfIDSources_var edges = new SMESH::ListOfIDSources();
447       SMESH::ListOfIDSources_var faces = new SMESH::ListOfIDSources();
448       maxSelType = SelectorWdg->GetSelected( nodes, edges, faces );
449
450       // is it necessary to switch on the next Display Mode?
451       SMESH::ElementType newType = (SMESH::ElementType)( maxSelType + 1 );
452       SMESH::array_of_ElementType_var oldTypes = mesh->GetTypes();
453       meshHadNewTypeBefore = false;
454       for ( size_t i = 0; i < oldTypes->length() && !meshHadNewTypeBefore; ++i )
455         meshHadNewTypeBefore = ( oldTypes[i] >= newType );
456
457       SMESH::SMESH_MeshEditor_var aMeshEditor = mesh->GetMeshEditor();
458       SMESH::SMESH_MeshEditor::Extrusion_Error retVal;
459
460       SMESH::ListOfGroups_var groups =
461         aMeshEditor->ExtrusionAlongPathObjects( nodes, edges, faces, myPath,
462                                                 GEOM::GEOM_Object::_nil(),
463                                                 aNodeStart, AnglesGrp->isChecked(),
464                                                 anAngles, LinearAnglesCheck->isChecked(),
465                                                 BasePointGrp->isChecked(), aBasePoint,
466                                                 makeGroups, retVal );
467
468       wc.suspend();
469       switch (retVal) {
470       case SMESH::SMESH_MeshEditor::EXTR_NO_ELEMENTS:
471         SUIT_MessageBox::warning(this,
472                                  tr("SMESH_ERROR"),
473                                  tr("NO_ELEMENTS_SELECTED"));
474         return false; break;
475       case SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE:
476         SUIT_MessageBox::warning(this,
477                                  tr("SMESH_ERROR"),
478                                  tr("SELECTED_PATH_IS_NOT_EDGE"));
479         return false; break;
480       case SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE:
481         SUIT_MessageBox::warning(this,
482                                  tr("SMESH_ERROR"),
483                                  tr("BAD_SHAPE_TYPE"));
484         return false; break;
485       case SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE:
486         SUIT_MessageBox::warning(this,
487                                  tr("SMESH_ERROR"),
488                                  tr("EXTR_BAD_STARTING_NODE"));
489         return false; break;
490       case SMESH::SMESH_MeshEditor::EXTR_BAD_ANGLES_NUMBER:
491         SUIT_MessageBox::warning(this,
492                                  tr("SMESH_ERROR"),
493                                  tr("WRONG_ANGLES_NUMBER"));
494         return false; break;
495       case SMESH::SMESH_MeshEditor::EXTR_CANT_GET_TANGENT:
496         SUIT_MessageBox::warning(this,
497                                  tr("SMESH_ERROR"),
498                                  tr("CANT_GET_TANGENT"));
499         return false; break;
500       case SMESH::SMESH_MeshEditor::EXTR_OK:
501         break;
502       }
503   } catch (...) {
504     return false;
505   }
506
507   SMESH_Actor* actor = SelectorWdg->GetActor();
508   if ( actor && !meshHadNewTypeBefore )
509   {
510     unsigned int aMode = actor->GetEntityMode();
511     switch ( maxSelType ) {
512     case SMESH::NODE: // extrude node -> edges
513       actor->SetRepresentation(SMESH_Actor::eEdge);
514       actor->SetEntityMode( aMode |= SMESH_Actor::eEdges ); break;
515     case SMESH::EDGE: // edge -> faces
516       actor->SetRepresentation(SMESH_Actor::eSurface);
517       actor->SetEntityMode( aMode |= SMESH_Actor::eFaces ); break;
518     case SMESH::FACE: // faces -> volumes
519       actor->SetRepresentation(SMESH_Actor::eSurface);
520       actor->SetEntityMode( aMode |= SMESH_Actor::eVolumes ); break;
521     }
522   }
523   if ( actor )
524     SMESH::Update( actor->getIO(), actor->GetVisibility() );
525   if ( makeGroups )
526     mySMESHGUI->updateObjBrowser(true); // new groups may appear
527   Init(false);
528   mySelectionMgr->clearSelected();
529   SelectorWdg->Clear();
530
531   SMESHGUI::Modified();
532   return true;
533 }
534
535 //=================================================================================
536 // function : ClickOnOk()
537 // purpose  : Called when user presses <OK> button
538 //=================================================================================
539 void SMESHGUI_ExtrusionAlongPathDlg::ClickOnOk()
540 {
541   if (ClickOnApply())
542     reject();
543 }
544
545 //=================================================================================
546 // function : ClickOnHelp()
547 // purpose  :
548 //=================================================================================
549 void SMESHGUI_ExtrusionAlongPathDlg::ClickOnHelp()
550 {
551   LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
552   if (app) 
553     app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
554   else {
555     QString platform;
556 #ifdef WIN32
557     platform = "winapplication";
558 #else
559     platform = "application";
560 #endif
561     SUIT_MessageBox::warning(this, tr("WRN_WARNING"),
562                              tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
563                              arg(app->resourceMgr()->stringValue("ExternalBrowser", 
564                                                                  platform)).
565                              arg(myHelpFileName));
566   }
567 }
568
569 //=================================================================================
570 // function : reject()
571 // purpose  : Called when dialog box is closed
572 //=================================================================================
573 void SMESHGUI_ExtrusionAlongPathDlg::reject()
574 {
575   disconnect(mySelectionMgr, 0, this, 0);
576   mySelectionMgr->clearFilters();
577   //mySelectionMgr->clearSelected();
578   if (SMESH::GetCurrentVtkView()) {
579     SMESH::RemoveFilters(); // PAL6938 -- clean all mesh entity filters
580     SMESH::SetPointRepresentation(false);
581     SMESH::SetPickable();
582   }
583   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
584     aViewWindow->SetSelectionMode(ActorSelection);
585   mySMESHGUI->ResetState();
586
587   QDialog::reject();
588 }
589
590 //=======================================================================
591 // function : onTextChange()
592 // purpose  :
593 //=======================================================================
594 void SMESHGUI_ExtrusionAlongPathDlg::onTextChange (const QString& theNewText)
595 {
596   QLineEdit* send = (QLineEdit*)sender();
597
598   // return if busy
599   if (myBusy) return;
600
601   // set busy flag
602   SetBusy sb (this);
603
604   if (send == StartPointLineEdit &&
605       myEditCurrentArgument == StartPointLineEdit)
606   {
607     if (!myPath->_is_nil()) {
608       SMESH_Actor* aPathActor = SMESH::FindActorByObject(myPath);
609       SMDS_Mesh* aMesh = aPathActor ? aPathActor->GetObject()->GetMesh() : 0;
610       if (aMesh) {
611         SALOME_ListIO aList;
612         aList.Append(aPathActor->getIO());
613         mySelectionMgr->setSelectedObjects(aList, false);
614
615         bool bOk;
616         long ind = theNewText.toLong(&bOk);
617         if (bOk) {
618           const SMDS_MeshNode* n = aMesh->FindNode(ind);
619           if (n) {
620             TColStd_MapOfInteger newIndices;
621             newIndices.Add(n->GetID());
622             mySelector->AddOrRemoveIndex( aPathActor->getIO(), newIndices, false );
623             if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
624               aViewWindow->highlight( aPathActor->getIO(), true, true );
625           }
626         }
627       }
628     }
629   }
630   CheckIsEnable();
631   onDisplaySimulation(true);
632 }
633
634 //=================================================================================
635 // function : SelectionIntoArgument()
636 // purpose  : Called when selection as changed or other case
637 //=================================================================================
638 void SMESHGUI_ExtrusionAlongPathDlg::SelectionIntoArgument()
639 {
640   if (myBusy) return;
641
642   // return if dialog box is inactive
643   if (!GroupButtons->isEnabled())
644     return;
645
646   // selected objects count
647   const SALOME_ListIO& aList = mySelector->StoredIObjects();
648   int nbSel = aList.Extent();
649   if (nbSel != 1)
650     return;
651
652   // set busy flag
653   SetBusy sb (this);
654
655   const bool isPathDef = ( SelectPathMeshButton->isChecked() ||
656                            SelectStartPointButton->isChecked() );
657
658   if (myEditCurrentArgument == PathMeshLineEdit && isPathDef)
659   {
660     // we are now selecting path mesh
661     // reset
662     PathMeshLineEdit->clear();
663     myPath = SMESH::SMESH_IDSource::_nil();
664     StartPointLineEdit->clear();
665
666     // try to get mesh from selection
667     Handle(SALOME_InteractiveObject) IO = aList.First();
668     myPath = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>(IO);
669     if( myPath->_is_nil() )
670       return;
671
672     QString aString;
673     SMESH::GetNameOfSelectedIObjects(mySelectionMgr, aString);
674     PathMeshLineEdit->setText(aString);
675   }
676   else if (myEditCurrentArgument == StartPointLineEdit && isPathDef )
677   {
678     // we are now selecting start point of path
679     // reset
680     StartPointLineEdit->clear();
681
682     // return if path mesh or path shape is not yet selected
683     if( myPath->_is_nil() )
684       return;
685
686     // try to get shape from selection
687     Handle(SALOME_InteractiveObject) IO = aList.First();
688
689     SMESH_Actor* aPathActor = SMESH::FindActorByObject(myPath);
690     if ( !aPathActor )
691       return;
692
693     QString aString;
694     int aNbUnits = SMESH::GetNameOfSelectedElements(mySelector, aPathActor->getIO(), aString);
695     if (aNbUnits == 1)
696       StartPointLineEdit->setText(aString.trimmed());
697   }
698   else if ( myEditCurrentArgument == XSpin &&
699             SelectBasePointButton->isChecked() )
700   {
701     // we are now selecting base point
702     // reset is not performed here!
703
704     // return if is not enabled
705     if (!BasePointGrp->isChecked())
706       return;
707
708     // try to get shape from selection
709     Handle(SALOME_InteractiveObject) IO = aList.First();
710
711     // check if geom vertex is selected
712     GEOM::GEOM_Object_var aGeomObj = SMESH::IObjectToInterface<GEOM::GEOM_Object>(IO);
713     TopoDS_Vertex aVertex;
714     if (!aGeomObj->_is_nil()) {
715       if (aGeomObj->IsShape() && GEOMBase::GetShape(aGeomObj, aVertex) && !aVertex.IsNull()) {
716         gp_Pnt aPnt = BRep_Tool::Pnt(aVertex);
717         XSpin->SetValue(aPnt.X());
718         YSpin->SetValue(aPnt.Y());
719         ZSpin->SetValue(aPnt.Z());
720       }
721       return;
722     }
723
724     // check if smesh node is selected
725     SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(IO);
726     if (aMesh->_is_nil())
727       return;
728
729     QString aString;
730     int aNbUnits = SMESH::GetNameOfSelectedNodes(mySelector, IO, aString);
731     // return if more than one node is selected
732     if (aNbUnits != 1)
733       return;
734
735     SMESH_Actor* aMeshActor = SMESH::FindActorByObject(aMesh);
736     if (!aMeshActor)
737       return;
738
739     SMDS_Mesh* mesh = aMeshActor->GetObject()->GetMesh();
740     if (!mesh)
741       return;
742
743     const SMDS_MeshNode* n = mesh->FindNode(aString.toLong());
744     if (!n)
745       return;
746
747     XSpin->SetValue(n->X());
748     YSpin->SetValue(n->Y());
749     ZSpin->SetValue(n->Z());
750   }
751   else
752   {
753     return;
754   }
755
756   onDisplaySimulation(true);
757   CheckIsEnable();
758 }
759
760 //=================================================================================
761 // function : SetEditCurrentArgument()
762 // purpose  :
763 //=================================================================================
764 void SMESHGUI_ExtrusionAlongPathDlg::SetEditCurrentArgument()
765 {
766   QPushButton* send = (QPushButton*)sender();
767   if ( sender() == BasePointGrp )
768     send = SelectBasePointButton;
769   if (send != SelectPathMeshButton   &&
770       send != SelectStartPointButton &&
771       send != SelectBasePointButton)
772     return;
773   SetEditCurrentArgument(send);
774 }
775
776 //=================================================================================
777 // function : SetEditCurrentArgument()
778 // purpose  :
779 //=================================================================================
780 void SMESHGUI_ExtrusionAlongPathDlg::SetEditCurrentArgument (QPushButton* button)
781 {
782   disconnect(mySelectionMgr, 0, this, 0);
783   //  mySelectionMgr->clearSelected();
784   mySelectionMgr->clearFilters();
785   SMESH::SetPickable();
786
787   myEditCurrentArgument = 0;
788   if (button == SelectPathMeshButton)
789   {
790     myEditCurrentArgument = PathMeshLineEdit;
791     SMESH::SetPointRepresentation(false);
792     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
793       aViewWindow->SetSelectionMode(ActorSelection);
794     mySelectionMgr->installFilter(myPathMeshFilter);
795   }
796   else if (button == SelectStartPointButton)
797   {
798     myEditCurrentArgument = StartPointLineEdit;
799     if (!myPath->_is_nil()) {
800       SMESH_Actor* aPathActor = SMESH::FindActorByObject(myPath);
801       if (aPathActor) {
802         SMESH::SetPointRepresentation(true);
803         if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
804           aViewWindow->SetSelectionMode(NodeSelection);
805         SMESH::SetPickable(aPathActor);
806       }
807     }
808   }
809   else if (button == SelectBasePointButton)
810   {
811     myEditCurrentArgument = XSpin;
812     SMESH::SetPointRepresentation(true);
813     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
814       aViewWindow->SetSelectionMode(NodeSelection);
815
816     SMESH_TypeFilter* aMeshOrSubMeshFilter = new SMESH_TypeFilter(SMESH::IDSOURCE);
817     SMESH_NumberFilter* aVertexFilter      = new SMESH_NumberFilter ("GEOM", TopAbs_SHAPE,
818                                                                      -1, TopAbs_VERTEX);
819     QList<SUIT_SelectionFilter*> aListOfFilters;
820     if (aMeshOrSubMeshFilter) aListOfFilters.append(aMeshOrSubMeshFilter);
821     if (aVertexFilter)        aListOfFilters.append(aVertexFilter);
822
823     mySelectionMgr->installFilter(new SMESH_LogicalFilter
824                                   (aListOfFilters, SMESH_LogicalFilter::LO_OR, true));
825   }
826
827   if (myEditCurrentArgument && !myEditCurrentArgument->hasFocus())
828     myEditCurrentArgument->setFocus();
829
830   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
831   SelectionIntoArgument();
832 }
833
834 //=================================================================================
835 // function : DeactivateActiveDialog()
836 // purpose  : Deactivates this dialog
837 //=================================================================================
838 void SMESHGUI_ExtrusionAlongPathDlg::DeactivateActiveDialog()
839 {
840   if (GroupButtons->isEnabled())
841   {
842     GroupArguments->setEnabled(false);
843     GroupButtons->setEnabled(false);
844     SelectorWdg->setEnabled(false);
845     mySMESHGUI->ResetState();
846     mySMESHGUI->SetActiveDialogBox(0);
847   }
848 }
849
850 //=================================================================================
851 // function : ActivateThisDialog()
852 // purpose  : Activates this dialog
853 //=================================================================================
854 void SMESHGUI_ExtrusionAlongPathDlg::ActivateThisDialog()
855 {
856   // Emit a signal to deactivate the active dialog
857   mySMESHGUI->EmitSignalDeactivateDialog();
858   GroupArguments->setEnabled(true);
859   GroupButtons->setEnabled(true);
860   SelectorWdg->setEnabled(true);
861
862   mySMESHGUI->SetActiveDialogBox(this);
863   SelectionIntoArgument();
864 }
865
866 //=================================================================================
867 // function : enterEvent()
868 // purpose  : Mouse enter event
869 //=================================================================================
870 void SMESHGUI_ExtrusionAlongPathDlg::enterEvent (QEvent*)
871 {
872   if (!GroupButtons->isEnabled())
873     ActivateThisDialog();
874 }
875
876 //=======================================================================
877 // function : OnAngleAdded()
878 // purpose  : Called when user adds angle to the list
879 //=======================================================================
880 void SMESHGUI_ExtrusionAlongPathDlg::OnAngleAdded()
881 {
882   QString msg;
883   if( !AngleSpin->isValid( msg, true ) ) {
884     QString str( tr( "SMESH_INCORRECT_INPUT" ) );
885     if ( !msg.isEmpty() )
886       str += "\n" + msg;
887     SUIT_MessageBox::critical( this, tr( "SMESH_ERROR" ), str );
888     return;
889   }
890   AnglesList->addItem(AngleSpin->text());
891   myAnglesList.append(AngleSpin->GetValue());
892
893   updateLinearAngles();
894 }
895
896 //=======================================================================
897 // function : OnAngleRemoved()
898 // purpose  : Called when user removes angle(s) from the list
899 //=======================================================================
900 void SMESHGUI_ExtrusionAlongPathDlg::OnAngleRemoved()
901 {
902   QList<QListWidgetItem*> aList = AnglesList->selectedItems();
903   QListWidgetItem* anItem;
904   foreach(anItem, aList) {
905     myAnglesList.removeAt(AnglesList->row(anItem));
906     delete anItem;
907   }
908
909   updateLinearAngles();
910 }
911
912 //=================================================================================
913 // function : eventFilter()
914 // purpose  : event filter ???
915 //=================================================================================
916 bool SMESHGUI_ExtrusionAlongPathDlg::eventFilter (QObject* object, QEvent* event)
917 {
918   if (event->type() == QEvent::KeyPress) {
919     QKeyEvent* ke = (QKeyEvent*)event;
920     if (object == AnglesList) {
921       if (ke->key() == Qt::Key_Delete)
922         OnAngleRemoved();
923     }
924   }
925   else if (event->type() == QEvent::FocusIn) {
926     if (object == StartPointLineEdit) {
927       if (myEditCurrentArgument != StartPointLineEdit)
928         SetEditCurrentArgument(SelectStartPointButton);
929     }
930     else if (object == XSpin->editor() || object == YSpin->editor() || object == ZSpin->editor()) {
931       if (myEditCurrentArgument != XSpin)
932         SetEditCurrentArgument(SelectBasePointButton);
933     }
934   }
935   return QDialog::eventFilter(object, event);
936 }
937
938 //=================================================================================
939 // function : keyPressEvent()
940 // purpose  :
941 //=================================================================================
942 void SMESHGUI_ExtrusionAlongPathDlg::keyPressEvent( QKeyEvent* e )
943 {
944   QDialog::keyPressEvent( e );
945   if ( e->isAccepted() )
946     return;
947
948   if ( e->key() == Qt::Key_F1 ) {
949     e->accept();
950     ClickOnHelp();
951   }
952 }
953
954 //=================================================================================
955 // function : isValid
956 // purpose  :
957 //=================================================================================
958 bool SMESHGUI_ExtrusionAlongPathDlg::isValid()
959 {
960   QString msg;
961   bool ok = true;
962   ok = XSpin->isValid( msg, true ) && ok;
963   ok = YSpin->isValid( msg, true ) && ok;
964   ok = ZSpin->isValid( msg, true ) && ok;
965
966   if( !ok ) {
967     QString str( tr( "SMESH_INCORRECT_INPUT" ) );
968     if ( !msg.isEmpty() )
969       str += "\n" + msg;
970     SUIT_MessageBox::critical( this, tr( "SMESH_ERROR" ), str );
971     return false;
972   }
973   return true;
974 }
975
976 //=================================================================================
977 // function : updateLinearAngles
978 // purpose  :
979 //=================================================================================
980 void SMESHGUI_ExtrusionAlongPathDlg::updateLinearAngles()
981 {
982   bool enableLinear = true;
983   for( int row = 0, nbRows = AnglesList->count(); row < nbRows; row++ ) {
984     if( QListWidgetItem* anItem = AnglesList->item( row ) ) {
985       enableLinear = false;
986       anItem->text().toDouble(&enableLinear);
987       if( !enableLinear )
988         break;
989     }
990   }
991   if( !enableLinear )
992     LinearAnglesCheck->setChecked( false );
993   LinearAnglesCheck->setEnabled( enableLinear );
994 }
995
996 //=================================================================================
997 // function : isValuesValid()
998 // purpose  : Return true in case if values entered into dialog are valid
999 //=================================================================================
1000
1001 bool SMESHGUI_ExtrusionAlongPathDlg::isValuesValid()
1002
1003   if ( myPath->_is_nil() )
1004     return false;
1005   
1006   bool bOk;
1007   long aNodeStart = StartPointLineEdit->text().toLong(&bOk);
1008   if ( !bOk || aNodeStart < 1 )
1009     return false;
1010
1011   SMESH::SMESH_Mesh_var mesh = myPath->GetMesh();
1012   if ( mesh->_is_nil() )
1013     return false;
1014
1015   SMESH::ElementType type = mesh->GetElementType( aNodeStart, false );
1016   if ( type != SMESH::NODE )
1017     return false;
1018
1019   SMESH::long_array_var elems = mesh->GetNodeInverseElements( aNodeStart );
1020   if ( elems->length() != 1 ||
1021        mesh->GetElementType( elems[0], true ) != SMESH::EDGE )
1022     return false;
1023
1024   return true;
1025 }
1026
1027 //=================================================================================
1028 // function : onDisplaySimulation
1029 // purpose  : Show/Hide preview
1030 //=================================================================================
1031
1032 void SMESHGUI_ExtrusionAlongPathDlg::onDisplaySimulation( bool toDisplayPreview )
1033 {
1034   if ( myPreviewCheckBox->isChecked() && toDisplayPreview ) {
1035     if ( SelectorWdg->IsAnythingSelected() && isValid() && isValuesValid())
1036     {
1037       // get angles
1038       SMESH::double_array_var anAngles = getAngles();
1039       
1040       // get base point
1041       SMESH::PointStruct aBasePoint;
1042       if (BasePointGrp->isChecked()) {
1043         aBasePoint.x = XSpin->GetValue();
1044         aBasePoint.y = YSpin->GetValue();
1045         aBasePoint.z = ZSpin->GetValue();
1046       }
1047       bool bOk;
1048       long aNodeStart = StartPointLineEdit->text().toLong(&bOk);
1049       if (bOk) {
1050
1051         try {
1052           SUIT_OverrideCursor wc;
1053
1054           SMESH::SMESH_MeshEditor::Extrusion_Error retVal;
1055           SMESH::SMESH_Mesh_var             mesh = SelectorWdg->GetMesh();
1056           SMESH::SMESH_MeshEditor_var meshEditor = mesh->GetMeshEditPreviewer();
1057
1058           SMESH::ListOfIDSources_var nodes = new SMESH::ListOfIDSources();
1059           SMESH::ListOfIDSources_var edges = new SMESH::ListOfIDSources();
1060           SMESH::ListOfIDSources_var faces = new SMESH::ListOfIDSources();
1061           SelectorWdg->GetSelected( nodes, edges, faces );
1062           const bool makeGroups = false;
1063
1064           SMESH::ListOfGroups_var groups =
1065             meshEditor->ExtrusionAlongPathObjects( nodes, edges, faces, myPath,
1066                                                    GEOM::GEOM_Object::_nil(),
1067                                                    aNodeStart, AnglesGrp->isChecked(),
1068                                                    anAngles, LinearAnglesCheck->isChecked(),
1069                                                    BasePointGrp->isChecked(), aBasePoint,
1070                                                    makeGroups, retVal );
1071
1072           if( retVal == SMESH::SMESH_MeshEditor::EXTR_OK )
1073           {
1074             SMESH::MeshPreviewStruct_var aMeshPreviewStruct = meshEditor->GetPreviewData();
1075             mySimulation->SetData( aMeshPreviewStruct._retn() );
1076           }
1077           else {
1078             hidePreview();
1079           }
1080
1081         } catch (...) {
1082           hidePreview();
1083         }
1084       } else {
1085         hidePreview();
1086       }
1087
1088     } else {
1089       hidePreview();
1090     }
1091   } else {
1092     hidePreview();
1093   }
1094 }
1095
1096 SMESH::double_array_var SMESHGUI_ExtrusionAlongPathDlg::getAngles()
1097 {
1098   SMESH::double_array_var anAngles = new SMESH::double_array;
1099   if (AnglesGrp->isChecked())
1100   {
1101     anAngles->length(myAnglesList.count());
1102     int j = 0;
1103     for (int i = 0; i < myAnglesList.count(); i++) {
1104       double angle = myAnglesList[i];
1105       anAngles[ j++ ] = angle*M_PI/180.;
1106     }
1107     anAngles->length(j);
1108   }
1109   return anAngles;
1110 }