]> SALOME platform Git repositories - modules/smesh.git/blob - src/SMESHGUI/SMESHGUI_SewingDlg.cxx
Salome HOME
bos #29143 [CEA] Compute takes too much time in polyhedron per solid use case
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_SewingDlg.cxx
1 // Copyright (C) 2007-2021  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_SewingDlg.cxx
25 // Author : Michael ZORIN, Open CASCADE S.A.S.
26 // SMESH includes
27 //
28 #include "SMESHGUI_SewingDlg.h"
29
30 #include "SMESHGUI.h"
31 #include "SMESHGUI_IdPreview.h"
32 #include "SMESHGUI_IdValidator.h"
33 #include "SMESHGUI_MergeDlg.h"
34 #include "SMESHGUI_MeshUtils.h"
35 #include "SMESHGUI_PreVisualObj.h"
36 #include "SMESHGUI_SpinBox.h"
37 #include "SMESHGUI_Utils.h"
38 #include "SMESHGUI_VTKUtils.h"
39
40 #include <SMDS_Mesh.hxx>
41 #include <SMESH_Actor.h>
42 #include <SMESH_TypeDefs.hxx>
43
44 // SALOME GUI includes
45 #include <LightApp_Application.h>
46 #include <LightApp_SelectionMgr.h>
47 #include <SALOMEDSClient_Study.hxx>
48 #include <SALOME_ListIO.hxx>
49 #include <SUIT_Desktop.h>
50 #include <SUIT_MessageBox.h>
51 #include <SUIT_OverrideCursor.h>
52 #include <SUIT_ResourceMgr.h>
53 #include <SUIT_Session.h>
54 #include <SVTK_ViewModel.h>
55 #include <SVTK_ViewWindow.h>
56 #include <SalomeApp_IntSpinBox.h>
57 #include <SalomeApp_Tools.h>
58
59 // OCCT includes
60 #include <TColStd_MapOfInteger.hxx>
61
62 // Qt includes
63 #include <QApplication>
64 #include <QButtonGroup>
65 #include <QCheckBox>
66 #include <QGridLayout>
67 #include <QGroupBox>
68 #include <QHBoxLayout>
69 #include <QKeyEvent>
70 #include <QLabel>
71 #include <QLineEdit>
72 #include <QListWidget>
73 #include <QPushButton>
74 #include <QRadioButton>
75 #include <QToolButton>
76 #include <QVBoxLayout>
77
78 #define SPACING 6
79 #define MARGIN  11
80
81 namespace
82 {
83   enum ActionType { MODE_AUTO=0, MODE_MANUAL,
84                     MOVE_LEFT_1=0, MOVE_RIGHT_1, MOVE_LEFT_2, MOVE_RIGHT_2,
85                     GROUP_COLOR=Qt::UserRole, GROUP_INDEX };
86 }
87
88 //=================================================================================
89 /*!
90  * \brief Dispalayer of free borders
91  */
92 //=================================================================================
93
94 struct SMESHGUI_SewingDlg::BorderGroupDisplayer
95 {
96   const SMESH::ListOfFreeBorders& myBorders;
97   const SMESH::FreeBordersGroup&  myGroup;
98   QColor                          myColor;
99   SMESH::SMESH_Mesh_ptr           myMesh;
100
101   std::vector< SMESH_Actor* >     myPartActors;
102   SVTK_ViewWindow*                myViewWindow;
103   SMESHGUI_IdPreview              myIdPreview;
104
105   BorderGroupDisplayer( const SMESH::CoincidentFreeBorders& borders,
106                         int                                 groupIndex,
107                         QColor                              color,
108                         SMESH::SMESH_Mesh_ptr               mesh);
109   ~BorderGroupDisplayer();
110   void Hide();
111   void ShowGroup( bool wholeBorders );
112   void ShowPart( int partIndex, bool toEdit );
113   void Update();
114
115 private:
116   void getPartEnds( int partIndex, std::vector<int> & ids, std::list<gp_XYZ>& coords);
117 };
118
119 //=================================================================================
120 // class    : SMESHGUI_SewingDlg()
121 // purpose  :
122 //=================================================================================
123 SMESHGUI_SewingDlg::SMESHGUI_SewingDlg( SMESHGUI* theModule )
124   : QDialog( SMESH::GetDesktop( theModule ) ),
125     mySMESHGUI( theModule ),
126     mySelectionMgr( SMESH::GetSelectionMgr( theModule ) )
127 {
128   SUIT_ResourceMgr* mgr = SMESH::GetResourceMgr( mySMESHGUI );
129   QPixmap image0 (mgr->loadPixmap("SMESH", tr("ICON_SMESH_SEWING_FREEBORDERS")));
130   QPixmap image1 (mgr->loadPixmap("SMESH", tr("ICON_SMESH_SEWING_CONFORM_FREEBORDERS")));
131   QPixmap image2 (mgr->loadPixmap("SMESH", tr("ICON_SMESH_SEWING_BORDERTOSIDE")));
132   QPixmap image3 (mgr->loadPixmap("SMESH", tr("ICON_SMESH_SEWING_SIDEELEMENTS")));
133   QPixmap image4 (mgr->loadPixmap("SMESH", tr("ICON_SELECT")));
134   QPixmap IconRemove(mgr->loadPixmap("SMESH", tr("ICON_REMOVE")));
135
136   setModal(false);
137   setAttribute(Qt::WA_DeleteOnClose, true);
138   setWindowTitle(tr("SMESH_SEWING"));
139   setSizeGripEnabled(true);
140
141   QVBoxLayout* SMESHGUI_SewingDlgLayout = new QVBoxLayout(this);
142   SMESHGUI_SewingDlgLayout->setSpacing(SPACING);
143   SMESHGUI_SewingDlgLayout->setMargin(MARGIN);
144
145   /***************************************************************/
146   ConstructorsBox = new QGroupBox(tr("SMESH_SEWING"), this);
147   GroupConstructors = new QButtonGroup(this);
148   QHBoxLayout* ConstructorsBoxLayout = new QHBoxLayout(ConstructorsBox);
149   ConstructorsBoxLayout->setSpacing(SPACING);
150   ConstructorsBoxLayout->setMargin(MARGIN);
151
152   RadioButton1 = new QRadioButton(ConstructorsBox);
153   RadioButton1->setIcon(image0);
154   RadioButton2 = new QRadioButton(ConstructorsBox);
155   RadioButton2->setIcon(image1);
156   RadioButton3 = new QRadioButton(ConstructorsBox);
157   RadioButton3->setIcon(image2);
158   RadioButton4 = new QRadioButton(ConstructorsBox);
159   RadioButton4->setIcon(image3);
160
161   ConstructorsBoxLayout->addWidget(RadioButton1);
162   ConstructorsBoxLayout->addWidget(RadioButton2);
163   ConstructorsBoxLayout->addWidget(RadioButton3);
164   ConstructorsBoxLayout->addWidget(RadioButton4);
165   GroupConstructors->addButton(RadioButton1, 0);
166   GroupConstructors->addButton(RadioButton2, 1);
167   GroupConstructors->addButton(RadioButton3, 2);
168   GroupConstructors->addButton(RadioButton4, 3);
169
170   /***************************************************************/
171   GroupArguments = new QGroupBox(this);
172   QVBoxLayout* GroupArgumentsLayout = new QVBoxLayout(GroupArguments);
173   GroupArgumentsLayout->setSpacing(SPACING);
174   GroupArgumentsLayout->setMargin(MARGIN);
175
176   // First subgroup
177   SubGroup1 = new QGroupBox(GroupArguments);
178   QGridLayout* SubGroup1Layout = new QGridLayout(SubGroup1);
179   SubGroup1Layout->setSpacing(SPACING);
180   SubGroup1Layout->setMargin(MARGIN);
181
182   // Controls of the first subgroup
183   TextLabel1 = new QLabel(SubGroup1);
184   SelectButton1  = new QPushButton(SubGroup1);
185   SelectButton1->setIcon(image4);
186   LineEdit1 = new QLineEdit(SubGroup1);
187
188   TextLabel2 = new QLabel(SubGroup1);
189   SelectButton2  = new QPushButton(SubGroup1);
190   SelectButton2->setIcon(image4);
191   LineEdit2 = new QLineEdit(SubGroup1);
192
193   TextLabel3 = new QLabel(SubGroup1);
194   SelectButton3  = new QPushButton(SubGroup1);
195   SelectButton3->setIcon(image4);
196   LineEdit3 = new QLineEdit(SubGroup1);
197
198   SubGroup1Layout->addWidget(TextLabel1,    0, 0);
199   SubGroup1Layout->addWidget(SelectButton1, 0, 1);
200   SubGroup1Layout->addWidget(LineEdit1,     0, 2);
201   SubGroup1Layout->addWidget(TextLabel2,    1, 0);
202   SubGroup1Layout->addWidget(SelectButton2, 1, 1);
203   SubGroup1Layout->addWidget(LineEdit2,     1, 2);
204   SubGroup1Layout->addWidget(TextLabel3,    2, 0);
205   SubGroup1Layout->addWidget(SelectButton3, 2, 1);
206   SubGroup1Layout->addWidget(LineEdit3,     2, 2);
207
208   // Second subgroup
209   SubGroup2 = new QGroupBox(GroupArguments);
210   QGridLayout* SubGroup2Layout = new QGridLayout(SubGroup2);
211   SubGroup2Layout->setSpacing(SPACING);
212   SubGroup2Layout->setMargin(MARGIN);
213
214   // Controls of the first subgroup
215   TextLabel4 = new QLabel(SubGroup2);
216   SelectButton4  = new QPushButton(SubGroup2);
217   SelectButton4->setIcon(image4);
218   LineEdit4 = new QLineEdit(SubGroup2);
219
220   TextLabel5 = new QLabel(SubGroup2);
221   SelectButton5  = new QPushButton(SubGroup2);
222   SelectButton5->setIcon(image4);
223   LineEdit5 = new QLineEdit(SubGroup2);
224
225   TextLabel6 = new QLabel(SubGroup2);
226   SelectButton6  = new QPushButton(SubGroup2);
227   SelectButton6->setIcon(image4);
228   LineEdit6 = new QLineEdit(SubGroup2);
229
230   SubGroup2Layout->addWidget(TextLabel4,    0, 0);
231   SubGroup2Layout->addWidget(SelectButton4, 0, 1);
232   SubGroup2Layout->addWidget(LineEdit4,     0, 2);
233   SubGroup2Layout->addWidget(TextLabel5,    1, 0);
234   SubGroup2Layout->addWidget(SelectButton5, 1, 1);
235   SubGroup2Layout->addWidget(LineEdit5,     1, 2);
236   SubGroup2Layout->addWidget(TextLabel6,    2, 0);
237   SubGroup2Layout->addWidget(SelectButton6, 2, 1);
238   SubGroup2Layout->addWidget(LineEdit6,     2, 2);
239
240   // Control for the merging equal elements
241   CheckBoxMerge = new QCheckBox(tr("MERGE_EQUAL_ELEMENTS"), GroupArguments);
242
243   // Control for the polygons creation instead of splitting
244   CheckBoxPolygons = new QCheckBox(tr("CREATE_POLYGONS_INSTEAD_SPLITTING"), GroupArguments);
245   
246   // Control for the polyedres creation to obtain conform mesh
247   CheckBoxPolyedrs = new QCheckBox(tr("CREATE_POLYEDRS_NEAR_BOUNDARY"), GroupArguments);
248
249   /***************************************************************/
250   // Controls to switch free borders mode ( auto || manual )
251
252   ModeGroup = new QGroupBox( tr( "SMESH_MODE" ), GroupArguments );
253   ModeButGrp = new QButtonGroup( ModeGroup );
254   QHBoxLayout* aModeGroupLayout = new QHBoxLayout( ModeGroup );
255   aModeGroupLayout->setMargin( MARGIN );
256   aModeGroupLayout->setSpacing( SPACING );
257
258   QRadioButton* rb1 = new QRadioButton( tr( "SMESH_AUTOMATIC" ), ModeGroup );
259   QRadioButton* rb2 = new QRadioButton( tr( "SMESH_MANUAL"    ), ModeGroup );
260   ModeButGrp->addButton( rb1, MODE_AUTO );
261   ModeButGrp->addButton( rb2, MODE_MANUAL );
262   aModeGroupLayout->addWidget( rb1 );
263   aModeGroupLayout->addWidget( rb2 );
264   rb1->setChecked(true);
265
266   /***************************************************************/
267   // Controls for detecting coincident free borders
268
269   SewFreeBordersWidget = new QWidget( GroupArguments );
270   QVBoxLayout* aSewFreeBordersLayout = new QVBoxLayout( SewFreeBordersWidget );
271   aSewFreeBordersLayout->setMargin( 0 );
272   aSewFreeBordersLayout->setSpacing( SPACING );
273
274   // Tolerance
275   QWidget* TolAndAuto = new QWidget(SewFreeBordersWidget);
276   QLabel* TextLabelTolerance = new QLabel(tr("SMESH_TOLERANCE"), TolAndAuto);
277   SpinBoxTolerance = new SMESHGUI_SpinBox(TolAndAuto);
278   SpinBoxTolerance->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
279   SpinBoxTolerance->RangeStepAndValidator(0.0, COORD_MAX, 0.00001, "len_tol_precision");
280   SpinBoxTolerance->SetValue(0.); // auto-tolerance
281
282   // Auto Sewing
283   AutoSewCheck = new QCheckBox(tr("AUTO_SEWING"), TolAndAuto);
284   AutoSewCheck->setChecked( true );
285
286   // mesh
287   QGroupBox* GroupMesh = new QGroupBox(tr("SMESH_MESH"), SewFreeBordersWidget);
288   QHBoxLayout* GroupMeshLayout = new QHBoxLayout(GroupMesh);
289   GroupMeshLayout->setSpacing(SPACING);
290   GroupMeshLayout->setMargin(MARGIN);
291
292   QLabel* TextLabelName = new QLabel(tr("SMESH_NAME"), GroupMesh);
293   //SelectMeshButton = new QPushButton(GroupMesh);
294   //SelectMeshButton->setIcon(IconSelect);
295   LineEditMesh = new QLineEdit(GroupMesh);
296   LineEditMesh->setReadOnly(true);
297
298   GroupMeshLayout->addWidget(TextLabelName);
299   //GroupMeshLayout->addWidget(SelectMeshButton);
300   GroupMeshLayout->addWidget(LineEditMesh);
301
302   QGridLayout* TolAndAutoLayout = new QGridLayout( TolAndAuto );
303   TolAndAutoLayout->setSpacing(SPACING);
304   TolAndAutoLayout->setMargin(0);
305   TolAndAutoLayout->addWidget(GroupMesh,          0, 0, 1, 2 );
306   TolAndAutoLayout->addWidget(TextLabelTolerance, 1, 0 );
307   TolAndAutoLayout->addWidget(SpinBoxTolerance,   1, 1 );
308   TolAndAutoLayout->addWidget(AutoSewCheck,       2, 0 );
309
310   aSewFreeBordersLayout->addWidget( TolAndAuto );
311
312   /******************/
313   // Coincident group
314   GroupCoincidentWidget = new QWidget(SewFreeBordersWidget);
315   QGridLayout* GroupCoincidentLayout = new QGridLayout(GroupCoincidentWidget);
316   GroupCoincidentLayout->setSpacing(SPACING);
317   GroupCoincidentLayout->setMargin(0);
318
319   QGroupBox* GroupCoincident = new QGroupBox(tr("COINCIDENT_FREE_BORDERS"), GroupCoincidentWidget);
320   QGridLayout* aCoincidentLayout = new QGridLayout(GroupCoincident);
321   aCoincidentLayout->setSpacing(SPACING);
322   aCoincidentLayout->setMargin(MARGIN);
323
324   /*******/
325   // borders
326   ListCoincident = new QListWidget(GroupCoincident);
327   ListCoincident->setSelectionMode(QListWidget::ExtendedSelection);
328
329   DetectButton      = new QPushButton(tr("DETECT"),           GroupCoincident);
330   RemoveGroupButton = new QPushButton(tr("SMESH_BUT_REMOVE"), GroupCoincident);
331
332   SelectAllCheck = new QCheckBox(tr("SELECT_ALL"), GroupCoincident);
333
334   aCoincidentLayout->addWidget(ListCoincident,    0, 0, 5, 2);
335   aCoincidentLayout->addWidget(DetectButton,      1, 2);
336   aCoincidentLayout->addWidget(RemoveGroupButton, 3, 2);
337   aCoincidentLayout->addWidget(SelectAllCheck,    5, 0);
338   aCoincidentLayout->setRowMinimumHeight(1, 10);
339   aCoincidentLayout->setRowStretch      (4, 5);
340   aCoincidentLayout->setRowStretch      (5, 0);
341
342   /*****************************************/
343   // Controls for editing the selected group
344
345   QGroupBox* GroupEdit = new QGroupBox(tr("EDIT_SELECTED_GROUP"), GroupCoincidentWidget);
346   QGridLayout* GroupEditLayout = new QGridLayout(GroupEdit);
347   GroupEditLayout->setSpacing(SPACING);
348   GroupEditLayout->setMargin(MARGIN);
349
350   ListEdit = new QListWidget(GroupEdit);
351   ListEdit->setFlow( QListView::LeftToRight );
352   ListEdit->setSelectionMode(QListWidget::ExtendedSelection);
353   SetFirstButton = new QPushButton(GroupEdit);
354   SetFirstButton->setIcon(QPixmap(SMESHGUI_MergeDlg::IconFirst()));
355   RemoveElemButton = new QPushButton(GroupEdit);
356   RemoveElemButton->setIcon(IconRemove);
357
358   MoveBorderEndsButGrp = new QButtonGroup( GroupEdit );
359   QToolButton* moveBut1 = new QToolButton( GroupEdit );
360   QToolButton* moveBut2 = new QToolButton( GroupEdit );
361   QToolButton* moveBut3 = new QToolButton( GroupEdit );
362   QToolButton* moveBut4 = new QToolButton( GroupEdit );
363   moveBut1->setArrowType( Qt::LeftArrow );
364   moveBut2->setArrowType( Qt::RightArrow );
365   moveBut3->setArrowType( Qt::LeftArrow );
366   moveBut4->setArrowType( Qt::RightArrow );
367   MoveBorderEndsButGrp->addButton( moveBut1, MOVE_LEFT_1 );
368   MoveBorderEndsButGrp->addButton( moveBut2, MOVE_RIGHT_1 );
369   MoveBorderEndsButGrp->addButton( moveBut3, MOVE_LEFT_2 );
370   MoveBorderEndsButGrp->addButton( moveBut4, MOVE_RIGHT_2 );
371
372   SwapBut  = new QPushButton( "<->", GroupEdit );
373   BorderEndLine[0] = new QLineEdit( GroupEdit );
374   BorderEndLine[1] = new QLineEdit( GroupEdit );
375   BorderEndLine[0]->setReadOnly(true);
376   BorderEndLine[1]->setReadOnly(true);
377   QLabel* StepLabel = new QLabel(tr("STEP"), GroupEdit );
378   StepSpin = new SalomeApp_IntSpinBox( 1, 100000, 1, GroupEdit,
379                                        /*acceptNames=*/false, /*showTip=*/false );
380   StepSpin->setValue( 1 );
381
382   GroupEditLayout->addWidget(ListEdit,         0, 0, 1, 8);
383   GroupEditLayout->addWidget(SetFirstButton,   0, 8);
384   GroupEditLayout->addWidget(RemoveElemButton, 0, 9);
385   GroupEditLayout->addWidget(moveBut1,         1, 0);
386   GroupEditLayout->addWidget(BorderEndLine[0], 1, 1);
387   GroupEditLayout->addWidget(moveBut2,         1, 2);
388   GroupEditLayout->addWidget(moveBut3,         1, 3);
389   GroupEditLayout->addWidget(BorderEndLine[1], 1, 4);
390   GroupEditLayout->addWidget(moveBut4,         1, 5);
391   GroupEditLayout->setColumnStretch(              6, 5 );
392   GroupEditLayout->addWidget(SwapBut,          1, 7);
393   GroupEditLayout->addWidget(StepLabel,        1, 8);
394   GroupEditLayout->addWidget(StepSpin,         1, 9);
395   GroupEditLayout->setRowStretch( 0, 1 );
396
397   GroupCoincidentLayout->addWidget( GroupCoincident );
398   GroupCoincidentLayout->addWidget( GroupEdit );
399   GroupCoincidentLayout->setRowStretch( 0, 10 );
400   GroupCoincidentLayout->setRowStretch( 1, 1 );
401
402   aSewFreeBordersLayout->addWidget( GroupCoincidentWidget );
403
404   // layout
405   GroupArgumentsLayout->addWidget(ModeGroup);
406   GroupArgumentsLayout->addWidget(SubGroup1);
407   GroupArgumentsLayout->addWidget(SubGroup2);
408   GroupArgumentsLayout->addWidget(SewFreeBordersWidget);
409   GroupArgumentsLayout->addWidget(CheckBoxMerge);
410   GroupArgumentsLayout->addWidget(CheckBoxPolygons);
411   GroupArgumentsLayout->addWidget(CheckBoxPolyedrs);
412
413   /***************************************************************/
414   GroupButtons = new QGroupBox(this);
415   QHBoxLayout* GroupButtonsLayout = new QHBoxLayout(GroupButtons);
416   GroupButtonsLayout->setSpacing(SPACING);
417   GroupButtonsLayout->setMargin(MARGIN);
418
419   buttonOk = new QPushButton(tr("SMESH_BUT_APPLY_AND_CLOSE"), GroupButtons);
420   buttonOk->setAutoDefault(true);
421   buttonOk->setDefault(true);
422   buttonApply = new QPushButton(tr("SMESH_BUT_APPLY"), GroupButtons);
423   buttonApply->setAutoDefault(true);
424   buttonCancel = new QPushButton(tr("SMESH_BUT_CLOSE"), GroupButtons);
425   buttonCancel->setAutoDefault(true);
426   buttonHelp = new QPushButton(tr("SMESH_BUT_HELP"), GroupButtons);
427   buttonHelp->setAutoDefault(true);
428
429   GroupButtonsLayout->addWidget(buttonOk);
430   GroupButtonsLayout->addSpacing(10);
431   GroupButtonsLayout->addWidget(buttonApply);
432   GroupButtonsLayout->addSpacing(10);
433   GroupButtonsLayout->addStretch();
434   GroupButtonsLayout->addWidget(buttonCancel);
435   GroupButtonsLayout->addWidget(buttonHelp);
436
437   /***************************************************************/
438   SMESHGUI_SewingDlgLayout->addWidget(ConstructorsBox);
439   SMESHGUI_SewingDlgLayout->addWidget(GroupArguments);
440   SMESHGUI_SewingDlgLayout->addWidget(GroupButtons);
441   //SMESHGUI_SewingDlgLayout->setStretch( 2, 10 );
442
443   /* Initialisations */
444   RadioButton1->setChecked(true);
445
446   LineEdit2->setValidator(new SMESHGUI_IdValidator(this, 1));
447   LineEdit3->setValidator(new SMESHGUI_IdValidator(this, 1));
448   LineEdit5->setValidator(new SMESHGUI_IdValidator(this, 1));
449   LineEdit6->setValidator(new SMESHGUI_IdValidator(this, 1));
450
451   mySelector = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector();
452
453   mySMESHGUI->SetActiveDialogBox((QDialog*)this);
454
455   myHelpFileName = "sewing_meshes.html";
456
457   myActor = 0;
458   myStoredEntityMode = 0;
459
460   setDisplayMode();
461   Init();
462
463   /* signals and slots connections */
464   connect(buttonOk,     SIGNAL(clicked()), this, SLOT(ClickOnOk()));
465   connect(buttonCancel, SIGNAL(clicked()), this, SLOT(reject()));
466   connect(buttonApply,  SIGNAL(clicked()), this, SLOT(ClickOnApply()));
467   connect(buttonHelp,   SIGNAL(clicked()), this, SLOT(ClickOnHelp()));
468   connect(GroupConstructors, SIGNAL(buttonClicked(int)), SLOT(ConstructorsClicked(int)));
469
470   connect(SelectButton1, SIGNAL (clicked()),   this, SLOT(SetEditCurrentArgument()));
471   connect(SelectButton2, SIGNAL (clicked()),   this, SLOT(SetEditCurrentArgument()));
472   connect(SelectButton3, SIGNAL (clicked()),   this, SLOT(SetEditCurrentArgument()));
473   connect(SelectButton4, SIGNAL (clicked()),   this, SLOT(SetEditCurrentArgument()));
474   connect(SelectButton5, SIGNAL (clicked()),   this, SLOT(SetEditCurrentArgument()));
475   connect(SelectButton6, SIGNAL (clicked()),   this, SLOT(SetEditCurrentArgument()));
476
477   connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog()));
478   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
479   /* to close dialog if study change */
480   connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()),      this, SLOT(reject()));
481   connect(mySMESHGUI, SIGNAL(SignalActivatedViewManager()), this, SLOT(onOpenView()));
482   connect(mySMESHGUI, SIGNAL(SignalCloseView()),            this, SLOT(onCloseView()));
483
484   connect(LineEdit1, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
485   connect(LineEdit2, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
486   connect(LineEdit3, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
487   connect(LineEdit4, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
488   connect(LineEdit5, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
489   connect(LineEdit6, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
490
491   connect(ModeButGrp,           SIGNAL(buttonClicked(int)),     SLOT(onModeChange(int)));
492   connect(AutoSewCheck,         SIGNAL(stateChanged(int)),      SLOT(onAutoSew(int)));
493   connect(DetectButton,         SIGNAL(clicked()),              SLOT(onDetectClicked()));
494   connect(RemoveGroupButton,    SIGNAL(clicked()),              SLOT(onRemoveGroupClicked()));
495   connect(ListCoincident,       SIGNAL(itemSelectionChanged()), SLOT(onSelectGroup()));
496   connect(SelectAllCheck,       SIGNAL(stateChanged(int)),      SLOT(onSelectAll(int)));
497   connect(ListEdit,             SIGNAL(itemSelectionChanged()), SLOT(onSelectBorderPartFromGroup()));
498   connect(SetFirstButton,       SIGNAL(clicked()),              SLOT(onSetFirstClicked()));
499   connect(RemoveElemButton,     SIGNAL(clicked()),              SLOT(onRemoveElemClicked()));
500   connect(MoveBorderEndsButGrp, SIGNAL(buttonClicked(int)),     SLOT(onMoveBorderEnd(int)));
501   connect(SwapBut,              SIGNAL(clicked()),              SLOT(onSwapClicked()));
502
503   ConstructorsClicked(0);
504 }
505
506 //=================================================================================
507 // function : ~SMESHGUI_SewingDlg()
508 // purpose  : Destroys the object and frees any allocated resources
509 //=================================================================================
510 SMESHGUI_SewingDlg::~SMESHGUI_SewingDlg()
511 {
512   for ( size_t i = 0; i < myBorderDisplayers.size(); ++i )
513   {
514     delete myBorderDisplayers[ i ];
515     myBorderDisplayers[ i ] = 0;
516   }
517   myBorderDisplayers.clear();
518 }
519
520 //=================================================================================
521 // function : Init()
522 // purpose  :
523 //=================================================================================
524 void SMESHGUI_SewingDlg::Init()
525 {
526   myBusy = false;
527
528   if ( LineEdit1->isVisible() )
529     myEditCurrentArgument = LineEdit1;
530   else
531     myEditCurrentArgument = LineEditMesh;
532   myEditCurrentArgument->setFocus();
533   //myActor = 0;
534   myMesh = SMESH::SMESH_Mesh::_nil();
535   // CheckBoxMerge->setChecked(false);
536   // CheckBoxPolygons->setChecked(false);
537   // CheckBoxPolyedrs->setChecked(false);
538   SelectionIntoArgument();
539 }
540
541 //=================================================================================
542 // function : ConstructorsClicked()
543 // purpose  : Radio button management
544 //=================================================================================
545 void SMESHGUI_SewingDlg::ConstructorsClicked (int constructorId)
546 {
547   disconnect(mySelectionMgr, 0, this, 0);
548   SALOME_ListIO io;
549   mySelectionMgr->selectedObjects( io );
550   mySelectionMgr->clearSelected();
551   LineEdit1->setText("");
552   LineEdit2->setText("");
553   LineEdit3->setText("");
554   LineEdit4->setText("");
555   LineEdit5->setText("");
556   LineEdit6->setText("");
557   myOk1 = myOk2 = myOk3 = myOk4 = myOk5 = myOk6 = false;
558   myEditCurrentArgument = LineEdit1;
559   myEditCurrentArgument->setFocus();
560
561   if (!TextLabel5->isEnabled()) {
562     TextLabel5->setEnabled(true);
563     SelectButton5->setEnabled(true);
564     LineEdit5->setEnabled(true);
565   } else if (!TextLabel6->isEnabled()) {
566     TextLabel6->setEnabled(true);
567     SelectButton6->setEnabled(true);
568     LineEdit6->setEnabled(true);
569   }
570
571   if (constructorId == 1 || constructorId == 3) {
572     if (CheckBoxPolygons->isVisible())
573       CheckBoxPolygons->hide();
574     if (CheckBoxPolyedrs->isVisible())
575       CheckBoxPolyedrs->hide();
576   }
577
578   CheckBoxMerge->setVisible ( constructorId == 3 );
579
580   if (( !SubGroup1->isVisible() ) &&
581       ( constructorId != 0 || ModeButGrp->checkedId() == MODE_MANUAL ))
582   {
583     SubGroup1->show();
584     SubGroup2->show();
585   }
586
587   if ( constructorId != 0 )
588   {
589     ModeGroup->hide();
590     SewFreeBordersWidget->hide();
591     restoreDisplayMode();
592   }
593
594   bool isNodeSelection = true;
595
596   switch (constructorId) {
597   case 0:
598   {
599     GroupArguments->setTitle(tr("SEW_FREE_BORDERS"));
600     SubGroup1->setTitle(tr("BORDER_1"));
601     SubGroup2->setTitle(tr("BORDER_2"));
602
603     if (!CheckBoxPolygons->isVisible())
604       CheckBoxPolygons->show();
605     if (!CheckBoxPolyedrs->isVisible())
606       CheckBoxPolyedrs->show();
607
608     if ( !ModeGroup->isVisible() )
609     {
610       ModeGroup->show();
611     }
612     onModeChange( ModeButGrp->checkedId() );
613
614     isNodeSelection = ( ModeButGrp->checkedId() == MODE_MANUAL );
615
616     break;
617   }
618   case 1:
619   {
620     GroupArguments->setTitle(tr("SEW_CONFORM_FREE_BORDERS"));
621     SubGroup1->setTitle(tr("BORDER_1"));
622     SubGroup2->setTitle(tr("BORDER_2"));
623
624     TextLabel6->setEnabled(false);
625     SelectButton6->setEnabled(false);
626     LineEdit6->setEnabled(false);
627
628     myOk6 = true;
629
630     break;
631   }
632   case 2:
633   {
634     GroupArguments->setTitle(tr("SEW_BORDER_TO_SIDE"));
635     SubGroup1->setTitle(tr("BORDER"));
636     SubGroup2->setTitle(tr("SIDE"));
637
638     TextLabel5->setEnabled(false);
639     SelectButton5->setEnabled(false);
640     LineEdit5->setEnabled(false);
641
642     if (!CheckBoxPolygons->isVisible())
643       CheckBoxPolygons->show();
644     if (!CheckBoxPolyedrs->isVisible())
645       CheckBoxPolyedrs->show();
646
647     myOk5 = true;
648
649     break;
650   }
651   case 3:
652   {
653     GroupArguments->setTitle(tr("SEW_SIDE_ELEMENTS"));
654     SubGroup1->setTitle(tr("SIDE_1"));
655     SubGroup2->setTitle(tr("SIDE_2"));
656
657     TextLabel1->setText(tr("SMESH_ID_ELEMENTS"));
658     TextLabel2->setText(tr("NODE1_TO_MERGE"));
659     TextLabel3->setText(tr("NODE2_TO_MERGE"));
660     TextLabel4->setText(tr("SMESH_ID_ELEMENTS"));
661     TextLabel5->setText(tr("NODE1_TO_MERGE"));
662     TextLabel6->setText(tr("NODE2_TO_MERGE"));
663
664     LineEdit1->setValidator(new SMESHGUI_IdValidator(this));
665     LineEdit4->setValidator(new SMESHGUI_IdValidator(this));
666
667     isNodeSelection = false;
668     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
669       aViewWindow->SetSelectionMode(CellSelection);
670     break;
671   }
672   }
673
674   if (constructorId != 3) {
675     TextLabel1->setText(tr("FIRST_NODE_ID"));
676     TextLabel2->setText(tr("SECOND_NODE_ID"));
677     TextLabel3->setText(tr("LAST_NODE_ID"));
678     TextLabel4->setText(tr("FIRST_NODE_ID"));
679     TextLabel5->setText(tr("SECOND_NODE_ID"));
680     TextLabel6->setText(tr("LAST_NODE_ID"));
681
682     LineEdit1->setValidator(new SMESHGUI_IdValidator(this, 1));
683     LineEdit4->setValidator(new SMESHGUI_IdValidator(this, 1));
684   }
685
686   if ( myActor )
687     myActor->SetPointRepresentation( isNodeSelection );
688
689   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
690     aViewWindow->SetSelectionMode( isNodeSelection ? NodeSelection : ActorSelection );
691
692   UpdateButtons();
693
694   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
695   mySelectionMgr->setSelectedObjects( io );
696
697   QApplication::instance()->processEvents();
698   updateGeometry();
699
700   resize(100,100);
701 }
702
703 //=======================================================================
704 //function : storeDisplayMode
705 //purpose  : save representation of a mesh and switch it to wireframe mode
706 //=======================================================================
707
708 void SMESHGUI_SewingDlg::setDisplayMode()
709 {
710   if ( myStoredEntityMode )
711     return;
712   myStoredEntityMode = 0;
713   myStoredRepresentation = -1;
714
715   if ( myActor && AutoSewCheck->isVisible() && !AutoSewCheck->isChecked() )
716   {
717     myStoredEntityMode     = myActor->GetEntityMode();
718     myStoredRepresentation = myActor->GetRepresentation();
719
720     myActor->SetEntityMode( myStoredEntityMode & ~SMESH_Actor::eVolumes );
721     myActor->SetRepresentation( SMESH_Actor::eEdge );
722   }
723 }
724
725 //=======================================================================
726 //function : restoreDisplayMode
727 //purpose  : restore representation of a mesh
728 //=======================================================================
729
730 void SMESHGUI_SewingDlg::restoreDisplayMode()
731 {
732   if ( myActor && myStoredEntityMode )
733   {
734     if ( myActor->GetEntityMode() == ( myStoredEntityMode & ~SMESH_Actor::eVolumes ))
735       myActor->SetEntityMode( myStoredEntityMode );
736
737     if ( myActor->GetRepresentation() == SMESH_Actor::eEdge )
738       myActor->SetRepresentation( myStoredRepresentation );
739
740     myStoredEntityMode = 0;
741     myStoredRepresentation = -1;
742   }
743   for ( size_t i = 0; i < myBorderDisplayers.size(); ++i )
744     if ( myBorderDisplayers[ i ])
745       myBorderDisplayers[ i ]->Hide();
746 }
747
748 //=======================================================================
749 //function : onModeChange
750 //purpose  : SLOT called when mode (auto or manual) of Sew free borders change
751 //=======================================================================
752
753 void SMESHGUI_SewingDlg::onModeChange( int mode )
754 {
755   if ( mode == MODE_MANUAL )
756   {
757     myEditCurrentArgument = LineEdit1;
758     if ( !SubGroup1->isVisible() )
759       SubGroup1->show(), SubGroup2->show();
760     SewFreeBordersWidget->hide();
761   }
762   else
763   {
764     myEditCurrentArgument = LineEditMesh;
765     SubGroup1->hide(), SubGroup2->hide();
766     if ( !SewFreeBordersWidget->isVisible() )
767       SewFreeBordersWidget->show();
768   }
769   if ( myActor )
770     myActor->SetPointRepresentation( mode == MODE_MANUAL );
771
772   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetCurrentVtkView() )
773     aViewWindow->SetSelectionMode( mode == MODE_MANUAL ? NodeSelection : ActorSelection );
774
775   onAutoSew( AutoSewCheck->isChecked() );
776
777   QApplication::instance()->processEvents();
778   updateGeometry();
779
780   resize(100,100);
781 }
782
783 //=======================================================================
784 //function : onAutoSew
785 //purpose  : SLOT called when Auto Sewing check box is checked
786 //=======================================================================
787
788 void SMESHGUI_SewingDlg::onAutoSew( int isAuto )
789 {
790   GroupCoincidentWidget->setVisible( !isAuto );
791
792   QApplication::instance()->processEvents();
793
794   SewFreeBordersWidget->hide();
795   if ( ModeButGrp->checkedId() == MODE_AUTO )
796     SewFreeBordersWidget->show();
797
798   if ( isAuto )
799     restoreDisplayMode();
800   else
801     setDisplayMode();
802   SMESH::RepaintCurrentView();
803
804   UpdateButtons();
805
806   updateGeometry();
807   resize(minimumSizeHint());
808 }
809
810 //=======================================================================
811 //function : haveBorders
812 //purpose  : Returns true if myBorders have been initialized
813 //=======================================================================
814
815 bool SMESHGUI_SewingDlg::haveBorders()
816 {
817   return ( & myBorders.in() &&
818            myBorders->borders.length() &&
819            myBorders->coincidentGroups.length() );
820 }
821
822 //=======================================================================
823 //function : getGroupText
824 //purpose  : Returns a text of a given group of coincident free borders
825 //=======================================================================
826
827 QString SMESHGUI_SewingDlg::getPartText(const SMESH::FreeBorderPart& aPART)
828 {
829   typedef CORBA::Long TInt;
830   QString text;
831   if ( 0 <= aPART.border && aPART.border < (TInt)myBorders->borders.length() )
832   {
833     const SMESH::FreeBorder& aBRD = myBorders->borders[ aPART.border ];
834     if ( 0 <= aPART.node1    && aPART.node1    < (TInt)aBRD.nodeIDs.length() &&
835          0 <= aPART.nodeLast && aPART.nodeLast < (TInt)aBRD.nodeIDs.length() )
836     {
837       text += QString("( %1 %2 %3 ) ")
838         .arg( aBRD.nodeIDs[ aPART.node1 ] )
839         .arg( aBRD.nodeIDs[ aPART.node2 ] )
840         .arg( aBRD.nodeIDs[ aPART.nodeLast ] );
841     }
842   }
843   return text;
844 }
845
846 //=======================================================================
847 //function : getGroupText
848 //purpose  : Returns a text of a given group of coincident free borders
849 //=======================================================================
850
851 QString SMESHGUI_SewingDlg::getGroupText(int groupIndex)
852 {
853   QString text;
854
855   if ( haveBorders()   &&
856        groupIndex >= 0 &&
857        groupIndex < (int)myBorders->coincidentGroups.length() )
858   {
859     const SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ groupIndex ];
860
861     for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
862     {
863       QString partText = getPartText( aGRP[ iP ]);
864       if ( partText.isEmpty() )
865         return "";
866       text += partText;
867     }
868   }
869   return text;
870 }
871
872 //=======================================================================
873 //function : onDetectClicked
874 //purpose  : SLOT called when [Detect] is clicked
875 //=======================================================================
876
877 void SMESHGUI_SewingDlg::onDetectClicked()
878 {
879   myBusy = true;
880   ListCoincident->clear();
881
882   if ( myMesh->_is_nil() )
883     return;
884
885   SUIT_OverrideCursor wc;
886
887   SMESH::SMESH_MeshEditor_var editor = myMesh->GetMeshEditor();
888   myBorders = editor->FindCoincidentFreeBorders( SpinBoxTolerance->GetValue() );
889   if ( haveBorders() )
890   {
891     for ( size_t i = 0; i < myBorderDisplayers.size(); ++i )
892     {
893       delete myBorderDisplayers[ i ];
894       myBorderDisplayers[ i ] = 0;
895     }
896     myBorderDisplayers.resize( myBorders->coincidentGroups.length(), 0 );
897
898     for ( uint i = 0; i < myBorders->coincidentGroups.length(); ++i )
899     {
900       QString groupText = getGroupText( i );
901       if ( groupText.isEmpty() )
902         continue;
903
904       QColor groupColor;
905       groupColor.setHsvF( float(i) / myBorders->coincidentGroups.length(), 1., 1. );
906       QPixmap icon( QSize( 20, 20 ));
907       icon.fill( groupColor );
908
909       QListWidgetItem * item = new QListWidgetItem( icon, groupText, ListCoincident );
910       item->setData( GROUP_COLOR, groupColor );
911       item->setData( GROUP_INDEX, i );
912     }
913   }
914   myBusy = false;
915
916   onSelectGroup();
917
918   UpdateButtons();
919 }
920
921 //=======================================================================
922 //function : onRemoveGroupClicked
923 //purpose  :
924 //=======================================================================
925
926 void SMESHGUI_SewingDlg::onRemoveGroupClicked()
927 {
928   myBusy = true;
929   QList<QListWidgetItem*> selItems = ListCoincident->selectedItems();
930   for ( int i = 0; i < selItems.count(); ++i )
931   {
932     QListWidgetItem* item = selItems[ i ];
933     item->setSelected( false );
934     int groupIndex = item->data( GROUP_INDEX ).toInt();
935     delete item;
936     if ( myBorderDisplayers[ groupIndex ])
937       myBorderDisplayers[ groupIndex ]->Hide();
938     SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ groupIndex ];
939     aGRP.length( 0 );
940   }
941   myBusy = false;
942
943   onSelectGroup();
944   UpdateButtons();
945 }
946
947 //=======================================================================
948 //function : showGroup
949 //purpose  : display a group of coincident free borders in the Viewer
950 //=======================================================================
951
952 void SMESHGUI_SewingDlg::showGroup( QListWidgetItem* item )
953 {
954   if ( !item ||
955        item->listWidget() != ListCoincident ||
956        !haveBorders())
957     return;
958
959   int    groupIndex = item->data( GROUP_INDEX ).toInt();
960   QColor groupColor = item->data( GROUP_COLOR ).value<QColor>();
961   if ( groupIndex >= 0       &&
962        groupIndex < (int)myBorders->coincidentGroups.length() )
963   {
964     if ( !myBorderDisplayers[ groupIndex ] && SMESH::GetCurrentVtkView())
965       myBorderDisplayers[ groupIndex ] = new BorderGroupDisplayer( myBorders, groupIndex, groupColor, myMesh );
966     bool wholeBorders = setCurrentGroup();
967     if ( myBorderDisplayers[ groupIndex ])
968       myBorderDisplayers[ groupIndex ]->ShowGroup( wholeBorders );
969   }
970 }
971
972 //=======================================================================
973 //function : setCurrentGroup
974 //purpose  : set index of a current free border group to myCurGroupIndex
975 //=======================================================================
976
977 bool SMESHGUI_SewingDlg::setCurrentGroup()
978 {
979   if ( !haveBorders() )
980     return false;
981
982   QList<QListWidgetItem*> selItems = ListCoincident->selectedItems();
983   if ( selItems.count() != 1 )
984     return false;
985   
986   myCurGroupIndex = selItems[0]->data( GROUP_INDEX ).toInt();
987
988   return ( myCurGroupIndex >= 0 && myCurGroupIndex < (int)myBorders->coincidentGroups.length() );
989 }
990
991 //=======================================================================
992 //function : setCurrentPart
993 //purpose  : set index of a current free border of a current group to myCurPartIndex
994 //=======================================================================
995
996 bool SMESHGUI_SewingDlg::setCurrentPart()
997 {
998   if ( !setCurrentGroup() )
999     return false;
1000
1001   if ( ListEdit->selectedItems().count() != 1 )
1002     return false;
1003
1004   myCurPartIndex = ListEdit->currentRow();
1005   const SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
1006
1007   return ( myCurPartIndex >= 0 && myCurPartIndex < (int)aGRP.length() );
1008 }
1009
1010 //=======================================================================
1011 //function : onSelectGroup
1012 //purpose  : SLOT called when selection of coincident free borders change
1013 //=======================================================================
1014
1015 void SMESHGUI_SewingDlg::onSelectGroup()
1016 {
1017   if ( myBusy )
1018     return;
1019   ListEdit->clear();
1020   BorderEndLine[0]->clear();
1021   BorderEndLine[1]->clear();
1022   for ( size_t i = 0; i < myBorderDisplayers.size(); ++i )
1023     if ( myBorderDisplayers[ i ])
1024       myBorderDisplayers[ i ]->Hide();
1025
1026   QList<QListWidgetItem*> selItems = ListCoincident->selectedItems();
1027
1028   RemoveGroupButton->setEnabled( selItems.count() > 0 );
1029
1030   onSelectBorderPartFromGroup(); // enable buttons
1031
1032   if ( !haveBorders() )
1033     return;
1034
1035   SelectAllCheck->blockSignals( true );
1036   if ( ListCoincident->count() != selItems.count() )
1037     SelectAllCheck->setChecked( false );
1038   SelectAllCheck->blockSignals( false );
1039
1040   if ( selItems.empty() ) // nothing selected - show all
1041     for ( int i = 0; i < ListCoincident->count(); ++i )
1042       showGroup( ListCoincident->item( i ));
1043   else
1044     for ( int i = 0; i < selItems.count(); ++i )
1045       showGroup( selItems[ i ]);
1046
1047   if ( setCurrentGroup() ) // edit a selected group
1048   {
1049     const SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
1050     for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
1051       new QListWidgetItem( getPartText( aGRP[ iP ]), ListEdit );
1052   }
1053   SMESH::RepaintCurrentView();
1054 }
1055
1056 //=======================================================================
1057 //function : onSelectAll
1058 //purpose  : SLOT called when Select All is checked
1059 //=======================================================================
1060
1061 void SMESHGUI_SewingDlg::onSelectAll(int isOn)
1062 {
1063   if ( isOn )
1064     ListCoincident->selectAll();
1065   else
1066     ListCoincident->clearSelection();
1067 }
1068
1069 //=======================================================================
1070 //function : onSelectBorderPartFromGroup
1071 //purpose  : SLOT called when selection of borders in an edited group changes
1072 //=======================================================================
1073
1074 void SMESHGUI_SewingDlg::onSelectBorderPartFromGroup()
1075 {
1076   if ( myBusy ) return;
1077   BorderEndLine[0]->setText("");
1078   BorderEndLine[1]->setText("");
1079   MoveBorderEndsButGrp->button( MOVE_LEFT_1  )->setEnabled( false );
1080   MoveBorderEndsButGrp->button( MOVE_RIGHT_1 )->setEnabled( false );
1081   MoveBorderEndsButGrp->button( MOVE_LEFT_2  )->setEnabled( false );
1082   MoveBorderEndsButGrp->button( MOVE_RIGHT_2 )->setEnabled( false );
1083   SwapBut->setEnabled( false );
1084   SetFirstButton->setEnabled( false );
1085   RemoveElemButton->setEnabled ( ListEdit->count() > 2 );
1086
1087   if ( !setCurrentGroup() )
1088     return;
1089
1090   if ( !myBorderDisplayers[ myCurGroupIndex ]) return;
1091   myBorderDisplayers[ myCurGroupIndex ]->Hide();
1092
1093   QList<QListWidgetItem*> selItems = ListEdit->selectedItems();
1094   bool editPart = ( setCurrentPart() );
1095   for ( int i = 0; i < selItems.count(); ++i )
1096     myBorderDisplayers[ myCurGroupIndex ]->ShowPart( ListEdit->row( selItems[i] ), editPart );
1097
1098   if ( selItems.isEmpty() )
1099     myBorderDisplayers[ myCurGroupIndex ]->ShowGroup( /*wholeBorders=*/ true );
1100
1101   if ( editPart )
1102   {
1103     SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
1104     SMESH::FreeBorderPart&   aPRT = aGRP[ myCurPartIndex ];
1105     SMESH::FreeBorder&       aBRD = myBorders->borders[ aPRT.border ];
1106
1107     BorderEndLine[0]->setText( QString::number( aBRD.nodeIDs[ aPRT.node1 ]));
1108     BorderEndLine[1]->setText( QString::number( aBRD.nodeIDs[ aPRT.nodeLast ]));
1109     SwapBut->setEnabled( true );
1110     SetFirstButton->setEnabled( myCurPartIndex > 0 );
1111
1112     int      size = (int) aBRD.nodeIDs.length();
1113     bool isClosed = ( aBRD.nodeIDs[0] == aBRD.nodeIDs[ size-1 ]);
1114     if ( !isClosed )
1115     {
1116       bool isFwd = ( Abs( aPRT.node2 - aPRT.node1 ) == 1 ) ? aPRT.node2 > aPRT.node1 : aPRT.node2 < aPRT.node1;
1117       int dn     = ( isFwd ? +1 : -1 ) * StepSpin->value();
1118       MoveBorderEndsButGrp->button( MOVE_LEFT_1  )->
1119         setEnabled( 0 <= aPRT.node1-dn && aPRT.node1-dn < size );
1120       MoveBorderEndsButGrp->button( MOVE_RIGHT_1 )->
1121         setEnabled( 0 <= aPRT.node1+dn && aPRT.node1+dn < size );
1122       MoveBorderEndsButGrp->button( MOVE_LEFT_2  )->
1123         setEnabled( 0 <= aPRT.nodeLast-dn && aPRT.nodeLast-dn < size );
1124       MoveBorderEndsButGrp->button( MOVE_RIGHT_2  )->
1125         setEnabled( 0 <= aPRT.nodeLast+dn && aPRT.nodeLast+dn < size );
1126     }
1127     else
1128     {
1129       MoveBorderEndsButGrp->button( MOVE_LEFT_1  )->setEnabled( true );
1130       MoveBorderEndsButGrp->button( MOVE_RIGHT_1 )->setEnabled( true );
1131       MoveBorderEndsButGrp->button( MOVE_LEFT_2  )->setEnabled( true );
1132       MoveBorderEndsButGrp->button( MOVE_RIGHT_2 )->setEnabled( true );
1133     }
1134   }
1135   SMESH::RepaintCurrentView();
1136 }
1137
1138 //=======================================================================
1139 //function : onGroupChange
1140 //purpose  : Update after modification of a current group by the user
1141 //=======================================================================
1142
1143 void SMESHGUI_SewingDlg::onGroupChange( bool partChange )
1144 {
1145   ListCoincident->currentItem()->setText( getGroupText( myCurGroupIndex ));
1146
1147   const SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
1148   for ( int i = 0; i < ListEdit->count(); ++i )
1149     ListEdit->item( i )->setText( getPartText( aGRP[ i ]));
1150
1151   if ( myBorderDisplayers[ myCurGroupIndex ])
1152     myBorderDisplayers[ myCurGroupIndex ]->Update();
1153
1154   if ( partChange )
1155     onSelectBorderPartFromGroup();
1156 }
1157
1158 //=======================================================================
1159 //function : onSetFirstClicked
1160 //purpose  : STOL called when |<< is clicked
1161 //=======================================================================
1162
1163 void SMESHGUI_SewingDlg::onSetFirstClicked()
1164 {
1165   if ( !setCurrentPart() || myCurPartIndex == 0 || ListEdit->count() == 0 )
1166     return;
1167
1168   SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
1169
1170   SMESH::FreeBorderPart new1st = aGRP[ myCurPartIndex ];
1171   for ( ; myCurPartIndex > 0; --myCurPartIndex )
1172     aGRP[ myCurPartIndex ] = aGRP[ myCurPartIndex - 1 ];
1173
1174   aGRP[ 0 ] = new1st;
1175
1176   onGroupChange();
1177
1178   myBusy = true;
1179   ListEdit->clearSelection();
1180   myBusy = false;
1181   ListEdit->setCurrentItem( ListEdit->item(0) );//ListEdit->item(0)->setSelected(true);
1182 }
1183
1184 //=======================================================================
1185 //function : onRemoveElemClicked
1186 //purpose  : 
1187 //=======================================================================
1188
1189 void SMESHGUI_SewingDlg::onRemoveElemClicked()
1190 {
1191   if ( !setCurrentGroup() )
1192     return;
1193
1194   SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
1195
1196   myBusy = true;
1197   QList<QListWidgetItem*> selItems = ListEdit->selectedItems();
1198   for ( int i = 0; i < selItems.count(); ++i )
1199   {
1200     int part = ListEdit->row( selItems[i] );
1201     for ( ; part + 1 < (int)aGRP.length(); ++part )
1202       aGRP[ part ] = aGRP[ part + 1 ];
1203     if ( aGRP.length() > 0 )
1204       aGRP.length( aGRP.length() - 1 );
1205     delete selItems[i];
1206   }
1207   myBusy = false;
1208
1209   if ( aGRP.length() == 0 )
1210     onRemoveGroupClicked();
1211   else
1212     onGroupChange( /*partChange=*/true );
1213 }
1214
1215 //=======================================================================
1216 //function : onMoveBorderEnd
1217 //purpose  : 
1218 //=======================================================================
1219
1220 void SMESHGUI_SewingDlg::onMoveBorderEnd(int button)
1221 {
1222   if ( !setCurrentPart() )
1223     return;
1224
1225   SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
1226   SMESH::FreeBorderPart&   aPRT = aGRP[ myCurPartIndex ];
1227   SMESH::FreeBorder&       aBRD = myBorders->borders[ aPRT.border ];
1228   int size = (int) aBRD.nodeIDs.length();
1229
1230   bool isClosed = ( aBRD.nodeIDs[0] == aBRD.nodeIDs[ size-1 ]);
1231   if ( isClosed ) --size;
1232
1233   bool isFwd = ( Abs( aPRT.node2 - aPRT.node1 ) == 1 ) ? aPRT.node2 > aPRT.node1 : aPRT.node2 < aPRT.node1;
1234   int dn     = ( isFwd ? +1 : -1 ) * StepSpin->value();
1235   if ( button == MOVE_LEFT_1 || button == MOVE_LEFT_2 )
1236     dn *= -1;
1237
1238   switch ( button ) {
1239   case MOVE_LEFT_1:
1240   case MOVE_RIGHT_1:
1241     if (( isClosed ) ||
1242         ( 0 <= aPRT.node1+dn && aPRT.node1+dn < size ))
1243     {
1244       aPRT.node1 = ( aPRT.node1 + size + dn ) % size;
1245       aPRT.node2 = ( aPRT.node2 + size + dn ) % size;
1246     }
1247     break;
1248   case MOVE_LEFT_2:
1249   case MOVE_RIGHT_2:
1250     if (( isClosed ) ||
1251         ( 0 <= aPRT.nodeLast+dn && aPRT.nodeLast+dn < size ))
1252     {
1253       aPRT.nodeLast = ( aPRT.nodeLast + size + dn ) % size;
1254     }
1255     break;
1256   default:
1257     return; // impossible to move
1258   }
1259   
1260   onGroupChange( /*partChange=*/true );
1261 }
1262
1263 //=======================================================================
1264 //function : onSwapClicked
1265 //purpose  : SLOT called when <-> is clicked
1266 //=======================================================================
1267
1268 void SMESHGUI_SewingDlg::onSwapClicked()
1269 {
1270   if ( !setCurrentPart() )
1271     return;
1272
1273   SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
1274   SMESH::FreeBorderPart&   aPRT = aGRP[ myCurPartIndex ];
1275   SMESH::FreeBorder&       aBRD = myBorders->borders[ aPRT.border ];
1276   int size = (int) aBRD.nodeIDs.length();
1277
1278   bool isClosed = ( aBRD.nodeIDs[0] == aBRD.nodeIDs[ size-1 ]);
1279   if ( isClosed ) --size;
1280
1281   bool isFwd = ( Abs( aPRT.node2 - aPRT.node1 ) == 1 ) ? aPRT.node2 > aPRT.node1 : aPRT.node2 < aPRT.node1;
1282
1283   std::swap( aPRT.nodeLast, aPRT.node1 );
1284
1285   aPRT.node2 = ( aPRT.node1 + ( isFwd ? -1 : +1 ) + size ) % size;
1286
1287   onGroupChange( /*partChange=*/true );
1288 }
1289
1290 //=================================================================================
1291 // function : ClickOnApply()
1292 // purpose  :
1293 //=================================================================================
1294 bool SMESHGUI_SewingDlg::ClickOnApply()
1295 {
1296   if (SMESHGUI::isStudyLocked())
1297     return false;
1298
1299   bool aResult = false;
1300
1301   if (IsValid())
1302   {
1303     bool toMerge          = CheckBoxMerge->isChecked();
1304     bool toCreatePolygons = CheckBoxPolygons->isChecked();
1305     bool toCreatePolyedrs = CheckBoxPolyedrs->isChecked();
1306     try {
1307       SUIT_OverrideCursor aWaitCursor;
1308       SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor();
1309
1310       int aConstructorId = GetConstructorId();
1311       SMESH::SMESH_MeshEditor::Sew_Error anError = SMESH::SMESH_MeshEditor::SEW_OK;
1312
1313       if (aConstructorId == 0)
1314       {
1315         if ( ModeButGrp->checkedId() == MODE_MANUAL )
1316         {
1317           anError = aMeshEditor->SewFreeBorders(LineEdit1->text().toLong(),
1318                                                 LineEdit2->text().toLong(),
1319                                                 LineEdit3->text().toLong(),
1320                                                 LineEdit4->text().toLong(),
1321                                                 LineEdit5->text().toLong(),
1322                                                 LineEdit6->text().toLong(),
1323                                                 toCreatePolygons,
1324                                                 toCreatePolyedrs);
1325         }
1326         else
1327         {
1328           int nbCoincGroups = ListCoincident->count();
1329           if ( AutoSewCheck->isChecked() )
1330           {
1331             myBorders     = aMeshEditor->FindCoincidentFreeBorders( SpinBoxTolerance->GetValue() );
1332             nbCoincGroups = myBorders->coincidentGroups.length();
1333           }
1334           CORBA::Short nbSewed = aMeshEditor->SewCoincidentFreeBorders( myBorders.inout(),
1335                                                                         toCreatePolygons,
1336                                                                         toCreatePolyedrs);
1337           QString msg;
1338           if ( nbCoincGroups == 0 )
1339             msg = tr("NO_BORDERS_TO_SEW");
1340           else if ( nbSewed < nbCoincGroups )
1341             msg = tr("NOT_ALL_BORDERS_SEWED").arg( nbSewed ).arg( nbCoincGroups );
1342           else
1343             msg = tr("ALL_BORDERS_SEWED").arg( nbSewed );
1344           SUIT_MessageBox::information( this, tr("SMESH_INFORMATION"), msg );
1345
1346           anError = SMESH::SMESH_MeshEditor::SEW_OK;
1347         }
1348       }
1349       else if (aConstructorId == 1)
1350       {
1351         anError = aMeshEditor->SewConformFreeBorders(LineEdit1->text().toLong(),
1352                                                      LineEdit2->text().toLong(),
1353                                                      LineEdit3->text().toLong(),
1354                                                      LineEdit4->text().toLong(),
1355                                                      LineEdit5->text().toLong());
1356       }
1357       else if (aConstructorId == 2)
1358       {
1359         anError = aMeshEditor->SewBorderToSide(LineEdit1->text().toLong(),
1360                                                LineEdit2->text().toLong(),
1361                                                LineEdit3->text().toLong(),
1362                                                LineEdit4->text().toLong(),
1363                                                LineEdit6->text().toLong(),
1364                                                toCreatePolygons,
1365                                                toCreatePolyedrs);
1366       }
1367       else if (aConstructorId == 3) {
1368         QStringList aListElementsId1 = LineEdit1->text().split(" ", QString::SkipEmptyParts);
1369         QStringList aListElementsId2 = LineEdit4->text().split(" ", QString::SkipEmptyParts);
1370
1371         SMESH::smIdType_array_var anElementsId1 = new SMESH::smIdType_array;
1372         SMESH::smIdType_array_var anElementsId2 = new SMESH::smIdType_array;
1373
1374         anElementsId1->length(aListElementsId1.count());
1375         anElementsId2->length(aListElementsId2.count());
1376
1377         for (int i = 0; i < aListElementsId1.count(); i++)
1378           anElementsId1[i] = aListElementsId1[i].toInt();
1379         for (int i = 0; i < aListElementsId2.count(); i++)
1380           anElementsId2[i] = aListElementsId2[i].toInt();
1381
1382         anError = aMeshEditor->SewSideElements(anElementsId1.inout(),
1383                                                anElementsId2.inout(),
1384                                                LineEdit2->text().toLong(),
1385                                                LineEdit5->text().toLong(),
1386                                                LineEdit3->text().toLong(),
1387                                                LineEdit6->text().toLong());
1388       }
1389       aResult = (anError == SMESH::SMESH_MeshEditor::SEW_OK);
1390
1391       if (toMerge && aResult)
1392         aMeshEditor->MergeEqualElements();
1393
1394       if (!aResult) {
1395         QString msg = tr(QString("ERROR_%1").arg(anError).toLatin1().data());
1396         SUIT_MessageBox::warning(this, tr("SMESH_WRN_WARNING"), msg);
1397       }
1398     }
1399     catch ( const SALOME::SALOME_Exception& S_ex )
1400     {
1401       SalomeApp_Tools::QtCatchCorbaException( S_ex );
1402       return false;
1403     }
1404
1405     if (aResult) {
1406
1407       if ( myActor )
1408       {
1409         Handle(SALOME_InteractiveObject) anIO = myActor->getIO();
1410         SALOME_ListIO aList;
1411         aList.Append(anIO);
1412         mySelectionMgr->setSelectedObjects(aList, false);
1413         SMESH::UpdateView();
1414       }
1415       Init();
1416       ConstructorsClicked(GetConstructorId());
1417
1418       SMESHGUI::Modified();
1419     }
1420   }
1421
1422   return aResult;
1423 }
1424
1425 //=================================================================================
1426 // function : ClickOnOk()
1427 // purpose  :
1428 //=================================================================================
1429 void SMESHGUI_SewingDlg::ClickOnOk()
1430 {
1431   if (ClickOnApply())
1432     reject();
1433 }
1434
1435 //=================================================================================
1436 // function : onOpenView()
1437 // purpose  :
1438 //=================================================================================
1439 void SMESHGUI_SewingDlg::onOpenView()
1440 {
1441   if ( mySelector ) {
1442     SMESH::SetPointRepresentation(false);
1443   }
1444   else {
1445     mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
1446     ActivateThisDialog();
1447   }
1448 }
1449
1450 //=================================================================================
1451 // function : onCloseView()
1452 // purpose  :
1453 //=================================================================================
1454 void SMESHGUI_SewingDlg::onCloseView()
1455 {
1456   DeactivateActiveDialog();
1457   mySelector = 0;
1458   myActor = 0;
1459
1460   for ( size_t i = 0; i < myBorderDisplayers.size(); ++i )
1461   {
1462     delete myBorderDisplayers[ i ];
1463     myBorderDisplayers[ i ] = 0;
1464   }
1465   myBorderDisplayers.clear();
1466 }
1467
1468 //=================================================================================
1469 // function : reject()
1470 // purpose  :
1471 //=================================================================================
1472 void SMESHGUI_SewingDlg::reject()
1473 {
1474   restoreDisplayMode();
1475   //mySelectionMgr->clearSelected();
1476   SMESH::SetPointRepresentation(false);
1477   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1478     aViewWindow->SetSelectionMode(ActorSelection);
1479   disconnect(mySelectionMgr, 0, this, 0);
1480   mySMESHGUI->ResetState();
1481   QDialog::reject();
1482 }
1483
1484 //=================================================================================
1485 // function : ClickOnHelp()
1486 // purpose  :
1487 //=================================================================================
1488 void SMESHGUI_SewingDlg::ClickOnHelp()
1489 {
1490   LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
1491   if (app) 
1492     app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
1493   else {
1494     QString platform;
1495 #ifdef WIN32
1496     platform = "winapplication";
1497 #else
1498     platform = "application";
1499 #endif
1500     SUIT_MessageBox::warning(this, tr("WRN_WARNING"),
1501                              tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
1502                              arg(app->resourceMgr()->stringValue("ExternalBrowser", 
1503                                                                  platform)).
1504                              arg(myHelpFileName));
1505   }
1506 }
1507
1508 //=======================================================================
1509 //function : onTextChange
1510 //purpose  :
1511 //=======================================================================
1512 void SMESHGUI_SewingDlg::onTextChange (const QString& theNewText)
1513 {
1514   QLineEdit* send = (QLineEdit*)sender();
1515
1516   if (myBusy) return;
1517   myBusy = true;
1518
1519   if (send)
1520     myEditCurrentArgument = send;
1521
1522   if      (send == LineEdit1)
1523     myOk1 = false;
1524   else if (send == LineEdit2)
1525     myOk2 = false;
1526   else if (send == LineEdit3)
1527     myOk3 = false;
1528   else if (send == LineEdit4)
1529     myOk4 = false;
1530   else if (send == LineEdit5)
1531     myOk5 = false;
1532   else if (send == LineEdit6)
1533     myOk6 = false;
1534
1535   // highlight entered elements/nodes
1536   SMDS_Mesh* aMesh = 0;
1537
1538   if (myActor)
1539     aMesh = myActor->GetObject()->GetMesh();
1540   else
1541     send->clear();
1542
1543   if (aMesh) {
1544     SVTK_TVtkIDsMap newIndices;
1545     
1546     if (GetConstructorId() != 3 || (send != LineEdit1 && send != LineEdit4)) {
1547       SMESH::SetPointRepresentation(true);
1548
1549       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1550         aViewWindow->SetSelectionMode(NodeSelection);
1551
1552       const SMDS_MeshNode * n = aMesh->FindNode(theNewText.toInt());
1553       if (n) {
1554         newIndices.Add(n->GetID());
1555         mySelector->AddOrRemoveIndex(myActor->getIO(), newIndices, false);
1556         if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1557           aViewWindow->highlight( myActor->getIO(), true, true );
1558
1559         if      (send == LineEdit1)
1560           myOk1 = true;
1561         else if (send == LineEdit2)
1562           myOk2 = true;
1563         else if (send == LineEdit3)
1564           myOk3 = true;
1565         else if (send == LineEdit4)
1566           myOk4 = true;
1567         else if (send == LineEdit5)
1568           myOk5 = true;
1569         else if (send == LineEdit6)
1570           myOk6 = true;
1571       }
1572     } else {
1573       SMESH::SetPointRepresentation(false);
1574
1575       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1576         aViewWindow->SetSelectionMode(CellSelection);
1577
1578       QStringList aListId = theNewText.split(" ", QString::SkipEmptyParts);
1579
1580       bool atLeastOneExists = false;
1581
1582       for (int i = 0; i < aListId.count(); i++) {
1583         const SMDS_MeshElement * e = aMesh->FindElement(aListId[ i ].toInt());
1584         if (e)
1585         {
1586           newIndices.Add(e->GetID());
1587           atLeastOneExists = true;
1588         }
1589       }
1590
1591       mySelector->AddOrRemoveIndex(myActor->getIO(), newIndices, false);
1592       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1593         aViewWindow->highlight( myActor->getIO(), true, true );
1594
1595       if (atLeastOneExists) {
1596         if (send == LineEdit1)
1597           myOk1 = true;
1598         else if(send == LineEdit4)
1599           myOk4 = true;
1600       } else {
1601         send->clear();
1602       }
1603     }
1604   }
1605
1606   UpdateButtons();
1607
1608   myBusy = false;
1609 }
1610
1611 //=================================================================================
1612 // function : SelectionIntoArgument()
1613 // purpose  : Called when selection as changed or other case
1614 //=================================================================================
1615 void SMESHGUI_SewingDlg::SelectionIntoArgument (bool isSelectionChanged)
1616 {
1617   if (myBusy) return;
1618
1619   // clear
1620   restoreDisplayMode();
1621   if (isSelectionChanged)
1622     myActor = 0;
1623
1624   QString aString = "";
1625
1626   myBusy = true;
1627   myEditCurrentArgument->setText(aString);
1628   ListCoincident->clear();
1629   ListEdit->clear();
1630   myBusy = false;
1631
1632   onSelectGroup(); // erase preview
1633
1634   if (!GroupButtons->isEnabled()) // inactive
1635     return;
1636
1637   buttonOk->setEnabled(false);
1638   buttonApply->setEnabled(false);
1639   DetectButton->setEnabled(false);
1640
1641   // get selected mesh
1642   SALOME_ListIO aList;
1643   mySelectionMgr->selectedObjects(aList);
1644
1645   int nbSel = aList.Extent();
1646   if (nbSel != 1)
1647     return;
1648
1649   Handle(SALOME_InteractiveObject) IO = aList.First();
1650   myMesh  = SMESH::GetMeshByIO(IO);
1651   myActor = SMESH::FindActorByEntry(aList.First()->getEntry());
1652   if (myMesh->_is_nil())
1653     return;
1654
1655   CheckBoxPolyedrs->setEnabled( myMesh->NbVolumes() > 0 );
1656
1657   if ( myEditCurrentArgument == LineEditMesh )
1658   {
1659     if ( _PTR(SObject) meshSO = SMESH::FindSObject( myMesh ))
1660       LineEditMesh->setText( meshSO->GetName().c_str() );
1661     ListCoincident->clear();
1662     if ( AutoSewCheck->isChecked() )
1663     {
1664       buttonOk->setEnabled(true);
1665       buttonApply->setEnabled(true);
1666     }
1667     DetectButton->setEnabled( myMesh->NbFaces() > 0 );
1668     setDisplayMode();
1669     return;
1670   }
1671
1672   if (!myActor)
1673     return;
1674
1675   // get selected elements/nodes
1676   int aNbUnits = 0;
1677   if (( GetConstructorId() != 3 ) ||
1678       ( myEditCurrentArgument != LineEdit1 && myEditCurrentArgument != LineEdit4))
1679   {
1680     aNbUnits = SMESH::GetNameOfSelectedNodes(mySelector, IO, aString);
1681     if (aNbUnits != 1)
1682       return;
1683   }
1684   else {
1685     aNbUnits = SMESH::GetNameOfSelectedElements(mySelector, IO, aString);
1686     if (aNbUnits < 1)
1687       return;
1688   }
1689
1690   myBusy = true;
1691   myEditCurrentArgument->setText(aString);
1692   myBusy = false;
1693
1694   // OK
1695   if (myEditCurrentArgument == LineEdit1)
1696     myOk1 = true;
1697   else if (myEditCurrentArgument == LineEdit2)
1698     myOk2 = true;
1699   else if (myEditCurrentArgument == LineEdit3)
1700     myOk3 = true;
1701   else if (myEditCurrentArgument == LineEdit4)
1702     myOk4 = true;
1703   else if (myEditCurrentArgument == LineEdit5)
1704     myOk5 = true;
1705   else if (myEditCurrentArgument == LineEdit6)
1706     myOk6 = true;
1707
1708   UpdateButtons();
1709 }
1710
1711 //=================================================================================
1712 // function : SetEditCurrentArgument()
1713 // purpose  :
1714 //=================================================================================
1715 void SMESHGUI_SewingDlg::SetEditCurrentArgument()
1716 {
1717   QPushButton* send = (QPushButton*)sender();
1718
1719   disconnect(mySelectionMgr, 0, this, 0);
1720   mySelectionMgr->clearSelected();
1721
1722   if (send == SelectButton1) {
1723     myEditCurrentArgument = LineEdit1;
1724     myOk1 = false;
1725   }
1726   else if (send == SelectButton2) {
1727     myEditCurrentArgument = LineEdit2;
1728     myOk2 = false;
1729   }
1730   else if (send == SelectButton3) {
1731     myEditCurrentArgument = LineEdit3;
1732     myOk3 = false;
1733   }
1734   else if (send == SelectButton4) {
1735     myEditCurrentArgument = LineEdit4;
1736     myOk4 = false;
1737   }
1738   else if (send == SelectButton5) {
1739     myEditCurrentArgument = LineEdit5;
1740     myOk5 = false;
1741   }
1742   else if (send == SelectButton6) {
1743     myEditCurrentArgument = LineEdit6;
1744     myOk6 = false;
1745   }
1746
1747   if (GetConstructorId() != 3 || (send != SelectButton1 && send != SelectButton4)) {
1748     SMESH::SetPointRepresentation(true);
1749
1750     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1751       aViewWindow->SetSelectionMode(NodeSelection);
1752
1753   } else {
1754     SMESH::SetPointRepresentation(false);
1755     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1756       aViewWindow->SetSelectionMode(CellSelection);
1757   }
1758
1759   myEditCurrentArgument->setFocus();
1760   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
1761   SelectionIntoArgument(false);
1762 }
1763
1764 //=================================================================================
1765 // function : DeactivateActiveDialog()
1766 // purpose  :
1767 //=================================================================================
1768 void SMESHGUI_SewingDlg::DeactivateActiveDialog()
1769 {
1770   if (ConstructorsBox->isEnabled()) {
1771     ConstructorsBox->setEnabled(false);
1772     GroupArguments->setEnabled(false);
1773     GroupButtons->setEnabled(false);
1774     mySMESHGUI->ResetState();
1775     mySMESHGUI->SetActiveDialogBox(0);
1776   }
1777 }
1778
1779 //=================================================================================
1780 // function : ActivateThisDialog()
1781 // purpose  :
1782 //=================================================================================
1783 void SMESHGUI_SewingDlg::ActivateThisDialog()
1784 {
1785   /* Emit a signal to deactivate the active dialog */
1786   mySMESHGUI->EmitSignalDeactivateDialog();
1787   ConstructorsBox->setEnabled(true);
1788   GroupArguments->setEnabled(true);
1789   GroupButtons->setEnabled(true);
1790
1791   mySMESHGUI->SetActiveDialogBox((QDialog*)this);
1792
1793   ConstructorsClicked(GetConstructorId());
1794   SelectionIntoArgument();
1795 }
1796
1797 //=================================================================================
1798 // function : enterEvent()
1799 // purpose  :
1800 //=================================================================================
1801 void SMESHGUI_SewingDlg::enterEvent (QEvent* /*e*/)
1802 {
1803   if (!ConstructorsBox->isEnabled()) {
1804     SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
1805     if ( aViewWindow && !mySelector) {
1806       mySelector = aViewWindow->GetSelector();
1807     }
1808     ActivateThisDialog();
1809   }
1810 }
1811
1812 //=================================================================================
1813 // function : GetConstructorId()
1814 // purpose  :
1815 //=================================================================================
1816 int SMESHGUI_SewingDlg::GetConstructorId()
1817 {
1818   return GroupConstructors->checkedId();
1819 }
1820
1821 //=================================================================================
1822 // function : GetConstructorId()
1823 // purpose  :
1824 //=================================================================================
1825 bool SMESHGUI_SewingDlg::IsValid()
1826 {
1827   if ( myMesh->_is_nil() )
1828     return false;
1829
1830   if ( GetConstructorId() == 0 && ModeButGrp->checkedId() == MODE_AUTO )
1831   {
1832     if ( AutoSewCheck->isChecked() )
1833       return true;
1834
1835     int nbGroups = 0;
1836     if ( haveBorders() )
1837       for ( int i = 0; i < ListCoincident->count(); ++i )
1838       {
1839         int groupIndex = ListCoincident->item(i)->data( GROUP_INDEX ).toInt();
1840         nbGroups += ( !getGroupText( groupIndex ).isEmpty() );
1841       }
1842     return nbGroups > 0;
1843   }
1844   return (myOk1 && myOk2 && myOk3 && myOk4 && myOk5 && myOk6);
1845 }
1846
1847 //=======================================================================
1848 //function : UpdateButtons
1849 //purpose  : activate [Apply] buttons
1850 //=======================================================================
1851
1852 void SMESHGUI_SewingDlg::UpdateButtons()
1853 {
1854   bool ok = IsValid();
1855   buttonOk->setEnabled( ok );
1856   buttonApply->setEnabled( ok );
1857 }
1858
1859 //=================================================================================
1860 // function : keyPressEvent()
1861 // purpose  :
1862 //=================================================================================
1863 void SMESHGUI_SewingDlg::keyPressEvent( QKeyEvent* e )
1864 {
1865   QDialog::keyPressEvent( e );
1866   if ( e->isAccepted() )
1867     return;
1868
1869   if ( e->key() == Qt::Key_F1 ) {
1870     e->accept();
1871     ClickOnHelp();
1872   }
1873 }
1874
1875 SMESHGUI_SewingDlg::
1876 BorderGroupDisplayer::BorderGroupDisplayer( const SMESH::CoincidentFreeBorders& borders,
1877                                             int                                 groupIndex,
1878                                             QColor                              color,
1879                                             SMESH::SMESH_Mesh_ptr               mesh):
1880   myBorders   ( borders.borders ),
1881   myGroup     ( borders.coincidentGroups[ groupIndex ]),
1882   myColor     ( color ),
1883   myMesh      ( mesh ),
1884   myViewWindow( SMESH::GetCurrentVtkView() ),
1885   myIdPreview ( myViewWindow )
1886 {
1887   Update();
1888 }
1889
1890 SMESHGUI_SewingDlg::BorderGroupDisplayer::~BorderGroupDisplayer()
1891 {
1892   for ( size_t i = 0; i < myPartActors.size(); ++i )
1893   {
1894     if ( myPartActors[ i ]) {
1895       myViewWindow->RemoveActor( myPartActors[i] );
1896       myPartActors[i]->Delete();
1897     }
1898   }
1899   myIdPreview.SetPointsLabeled(false);
1900 }
1901
1902 void SMESHGUI_SewingDlg::BorderGroupDisplayer::Hide()
1903 {
1904   for ( size_t i = 0; i < myPartActors.size(); ++i )
1905     if ( myPartActors[ i ])
1906       myPartActors[ i ]->SetVisibility(false);
1907
1908   myIdPreview.SetPointsLabeled(false);
1909 }
1910
1911 void SMESHGUI_SewingDlg::BorderGroupDisplayer::ShowGroup( bool wholeBorders )
1912 {
1913   std::vector<int> ids;
1914   std::list<gp_XYZ> coords;
1915   for ( size_t i = 0; i < myPartActors.size(); ++i )
1916     if ( myPartActors[ i ])
1917     {
1918       myPartActors[ i ]->SetPointRepresentation( wholeBorders );
1919       myPartActors[ i ]->SetVisibility( true );
1920       if ( wholeBorders )
1921         getPartEnds( i, ids, coords );
1922     }
1923   if ( wholeBorders )
1924     myIdPreview.SetElemsData( ids, coords );
1925   myIdPreview.SetPointsLabeled( wholeBorders, true );
1926 }
1927
1928 void SMESHGUI_SewingDlg::BorderGroupDisplayer::ShowPart( int partIndex, bool toEdit )
1929 {
1930   if ( partIndex < (int) myPartActors.size() )
1931   {
1932     myPartActors[partIndex]->SetVisibility(true);
1933     myPartActors[partIndex]->SetPointRepresentation(toEdit);
1934
1935     if ( toEdit )
1936     {
1937       std::vector<int> ids;
1938       std::list<gp_XYZ> coords;
1939       getPartEnds( partIndex, ids, coords );
1940
1941       myIdPreview.SetElemsData( ids, coords );
1942       myIdPreview.SetPointsLabeled( true, /*show=*/true );
1943     }
1944   }
1945 }
1946
1947 void SMESHGUI_SewingDlg::BorderGroupDisplayer::getPartEnds( int                partIndex,
1948                                                             std::vector<int> & ids,
1949                                                             std::list<gp_XYZ>& coords)
1950 {
1951   if ( partIndex >= (int)myGroup.length() ) return;
1952   const SMESH::FreeBorderPart& aPART = myGroup  [ partIndex ];
1953   const SMESH::FreeBorder&      aBRD = myBorders[ aPART.border ];
1954
1955   ids.push_back( aBRD.nodeIDs[ aPART.node1 ]);
1956   ids.push_back( aBRD.nodeIDs[ aPART.nodeLast ]);
1957   if ( aPART.node1 == aPART.nodeLast )
1958     ids.push_back( aBRD.nodeIDs[ aPART.node2 ]);
1959
1960   SMDS_Mesh* mesh = myPartActors[ partIndex ]->GetObject()->GetMesh();
1961
1962   coords.push_back( SMESH_TNodeXYZ( mesh->FindNode( aPART.node1+1 )));
1963   coords.push_back( SMESH_TNodeXYZ( mesh->FindNode( aPART.nodeLast+1 )));
1964   if ( aPART.node1 == aPART.nodeLast )
1965     coords.push_back( SMESH_TNodeXYZ( mesh->FindNode( aPART.node2+1 )));
1966 }
1967
1968 void SMESHGUI_SewingDlg::BorderGroupDisplayer::Update()
1969 {
1970   Hide();
1971   myPartActors.resize( myGroup.length(), 0 );
1972
1973   for ( size_t i = 0; i < myPartActors.size(); ++i )
1974   {
1975     TVisualObjPtr obj;
1976     if ( myPartActors[ i ])
1977       obj = myPartActors[ i ]->GetObject();
1978     else
1979       obj = TVisualObjPtr( new SMESHGUI_PreVisualObj() );
1980     SMDS_Mesh* mesh = obj->GetMesh();
1981     mesh->Clear();
1982
1983     // add nodes
1984     const SMESH::FreeBorderPart& aPRT = myGroup[ i ];
1985     const SMESH::FreeBorder&     aBRD = myBorders[ aPRT.border ];
1986     for ( CORBA::ULong iN = 0; iN < aBRD.nodeIDs.length(); ++iN )
1987     {
1988       SMESH::double_array_var xyz = myMesh->GetNodeXYZ( aBRD.nodeIDs[ iN ]);
1989       if ( xyz->length() == 3 )
1990         mesh->AddNode( xyz[0], xyz[1], xyz[2] );
1991     }
1992
1993     // add edges
1994     bool isFwd = ( Abs( aPRT.node2 - aPRT.node1 ) == 1 ) ? aPRT.node2 > aPRT.node1 : aPRT.node2 < aPRT.node1;
1995     int dn     = isFwd ? +1 : -1;
1996     int size   = (int) aBRD.nodeIDs.length();
1997     int n2, n1 = aPRT.node1;
1998     for ( n2 = n1 + dn; ( n2 >= 0 && n2 < size ); n2 += dn )
1999     {
2000       mesh->AddEdgeWithID( n1+1, n2+1, mesh->NbEdges() + 1 );
2001       n1 = n2;
2002       if ( n2 == aPRT.nodeLast )
2003         break;
2004     }
2005     if ( n2 % size != aPRT.nodeLast )
2006     {
2007       if ( n2 < 0 ) n1 = size;
2008       else          n1 = 0;
2009       for ( n2 = n1 + dn; ( n2 >= 0 && n2 < size ); n2 += dn )
2010       {
2011         mesh->AddEdgeWithID( n1+1, n2+1, mesh->NbEdges() + 1 );
2012         n1 = n2;
2013         if ( n2 == aPRT.nodeLast )
2014           break;
2015       }
2016     }
2017
2018     if ( !myPartActors[ i ]) // TVisualObj must be filled before actor creation
2019     {
2020       myPartActors[ i ] = SMESH_Actor::New( obj, "", "", 1 );
2021       myPartActors[ i ]->SetEdgeColor( myColor.redF(), myColor.greenF(), myColor.blueF() );
2022       myPartActors[ i ]->SetLineWidth( 3 * SMESH::GetFloat("SMESH:element_width",1));
2023       myPartActors[ i ]->SetNodeColor( myColor.redF(), myColor.greenF(), myColor.blueF() );
2024       myPartActors[ i ]->SetMarkerStd( VTK::MT_POINT, 13 );
2025       myPartActors[ i ]->SetPickable ( false );
2026       myViewWindow->AddActor( myPartActors[ i ]);
2027     }
2028   }
2029 }
2030