Salome HOME
To implement issue 0019962: MakePipeBiNormalAlongAxis implementation.
[modules/geom.git] / src / BlocksGUI / BlocksGUI_TrsfDlg.cxx
1 // GEOM GEOMGUI : GUI for Geometry component
2 //
3 // Copyright (C) 2003  CEA
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 //
19 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 //
21 // File   : BlocksGUI_TrsfDlg.cxx
22 // Author : Julia DOROVSKIKH, Open CASCADE S.A.S. (julia.dorovskikh@opencascade.com)
23 //
24
25 #include "BlocksGUI_TrsfDlg.h"
26
27 #include <DlgRef.h>
28 #include <GeometryGUI.h>
29 #include <GEOMBase.h>
30
31 #include <SUIT_Session.h>
32 #include <SUIT_Desktop.h>
33 #include <SUIT_ResourceMgr.h>
34 #include <SUIT_ViewWindow.h>
35 #include <SUIT_ViewManager.h>
36 #include <SalomeApp_Application.h>
37 #include <LightApp_SelectionMgr.h>
38 #include <OCCViewer_ViewModel.h>
39
40 // OCCT Includes
41 #include <TColStd_IndexedMapOfInteger.hxx>
42
43 //=================================================================================
44 // class    : BlocksGUI_TrsfDlg()
45 // purpose  : Constructs a BlocksGUI_TrsfDlg which is a child of 'parent'.
46 //=================================================================================
47 BlocksGUI_TrsfDlg::BlocksGUI_TrsfDlg (GeometryGUI* theGeometryGUI, QWidget* parent)
48   : GEOMBase_Skeleton(theGeometryGUI, parent),
49     myInitial(true)
50 {
51   SUIT_ResourceMgr* aResMgr = myGeomGUI->getApp()->resourceMgr();
52   QPixmap image1 (aResMgr->loadPixmap("GEOM", tr("ICON_DLG_BLOCK_MULTITRSF_SIMPLE")));
53   QPixmap image2 (aResMgr->loadPixmap("GEOM", tr("ICON_DLG_BLOCK_MULTITRSF_DOUBLE")));
54   QPixmap imageS (aResMgr->loadPixmap("GEOM", tr("ICON_SELECT")));
55
56   setWindowTitle(tr("GEOM_BLOCK_MULTITRSF_TITLE"));
57
58   /***************************************************************/
59   mainFrame()->GroupConstructors->setTitle(tr("GEOM_BLOCK_MULTITRSF"));
60
61   mainFrame()->RadioButton1->setIcon(image1);
62   mainFrame()->RadioButton2->setIcon(image2);
63   mainFrame()->RadioButton3->setAttribute(Qt::WA_DeleteOnClose);
64   mainFrame()->RadioButton3->close();
65
66   // Create first group
67   myGrp1 = new QGroupBox(tr("GEOM_BLOCK_MULTITRSF_SIMPLE"), centralWidget());
68
69   createSelWg(tr("GEOM_MAIN_OBJECT"), imageS, myGrp1, MainObj1);
70   createSelWg(tr("FACE_1"),           imageS, myGrp1, Face1);
71   createSelWg(tr("FACE_2"),           imageS, myGrp1, Face2);
72   createSpinWg(tr("GEOM_NB_TIMES"),           myGrp1, SpinBox1);
73
74   // Create second group
75   myGrp2 = new QGroupBox(tr("GEOM_BLOCK_MULTITRSF_DOUBLE"), centralWidget());
76
77   createSelWg(tr("GEOM_MAIN_OBJECT"), imageS, myGrp2, MainObj2);
78   createSelWg(tr("FACE_1U"),          imageS, myGrp2, Face1U);
79   createSelWg(tr("FACE_2U"),          imageS, myGrp2, Face2U);
80   createSpinWg(tr("GEOM_NB_TIMES_U"),         myGrp2, SpinBox2U);
81   createSelWg(tr("FACE_1V"),          imageS, myGrp2, Face1V);
82   createSelWg(tr("FACE_2V"),          imageS, myGrp2, Face2V);
83   createSpinWg(tr("GEOM_NB_TIMES_V"),         myGrp2, SpinBox2V);
84
85   // Add groups to layout
86   QVBoxLayout* layout = new QVBoxLayout(centralWidget());
87   layout->setMargin(0); layout->setSpacing(6);
88   layout->addWidget(myGrp1);
89   layout->addWidget(myGrp2);
90   /***************************************************************/
91
92   setHelpFileName("multi_transformation_operation_page.html");
93
94   Init();
95 }
96
97 //=================================================================================
98 // function : ~BlocksGUI_TrsfDlg()
99 // purpose  : Destroys the object and frees any allocated resources
100 //=================================================================================
101 BlocksGUI_TrsfDlg::~BlocksGUI_TrsfDlg()
102 {
103   // no need to delete child widgets, Qt does it all for us
104 }
105
106 //=================================================================================
107 // function : Init()
108 // purpose  :
109 //=================================================================================
110 void BlocksGUI_TrsfDlg::Init()
111 {
112   // Set range of spinboxes
113   double SpecificStep = 1.0;
114   QMap<int, QDoubleSpinBox*>::iterator anIter;
115   for (anIter = mySpinBox.begin(); anIter != mySpinBox.end(); ++anIter) {
116     //anIter.data()->RangeStepAndValidator(1.0, 999.999, SpecificStep, 3);
117     initSpinBox(anIter.value(), 1.0, MAX_NUMBER, SpecificStep, 3);
118   }
119
120   // signals and slots connections
121   connect(buttonOk(),    SIGNAL(clicked()), this, SLOT(ClickOnOk()));
122   connect(buttonApply(), SIGNAL(clicked()), this, SLOT(ClickOnApply()));
123
124   connect(this, SIGNAL(constructorsClicked(int)), this, SLOT(ConstructorsClicked(int)));
125
126   QMap<int, QPushButton*>::iterator anIterBtn;
127   for (anIterBtn = mySelBtn.begin(); anIterBtn != mySelBtn.end(); ++anIterBtn)
128     connect(anIterBtn.value(), SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
129
130   QMap<int, QDoubleSpinBox*>::iterator anIterSpin;
131   for (anIterSpin = mySpinBox.begin(); anIterSpin != mySpinBox.end(); ++anIterSpin)
132     connect(anIterSpin.value(), SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double)));
133
134   // init controls and fields
135   initName(tr("GEOM_BLOCK_MULTITRSF"));
136
137   myConstructorId = -1;
138   ConstructorsClicked(0);
139 }
140
141 //=================================================================================
142 // function : ConstructorsClicked()
143 // purpose  : Radio button management
144 //=================================================================================
145 void BlocksGUI_TrsfDlg::ConstructorsClicked (int constructorId)
146 {
147   if (myConstructorId == constructorId)
148     return;
149
150   myConstructorId = constructorId;
151
152   // init fields
153   myShape = GEOM::GEOM_Object::_nil();
154   myFaces[Face1] = myFaces[Face2] = -1;
155   myFaces[Face1U] = myFaces[Face2U] = -1;
156   myFaces[Face1V] = myFaces[Face2V] = -1;
157
158   // clear line edits
159   QMap<int, QLineEdit*>::iterator anIterLE;
160   for (anIterLE = mySelName.begin(); anIterLE != mySelName.end(); ++anIterLE)
161     anIterLE.value()->setText("");
162
163   switch (constructorId) {
164   case 0:
165     myGrp2->hide();
166     myGrp1->show();
167     mySpinBox[SpinBox1]->setValue(2.0);
168     mySelBtn[MainObj1]->click();
169     break;
170   case 1:
171     myGrp1->hide();
172     myGrp2->show();
173     mySpinBox[SpinBox2U]->setValue(2.0);
174     mySpinBox[SpinBox2V]->setValue(2.0);
175     mySelBtn[MainObj2]->click();
176     break;
177   default:
178     break;
179   }
180
181   qApp->processEvents();
182   updateGeometry();
183   resize(minimumSize());
184
185   // on dialog initialization we init the first field with a selected object (if any)
186   SelectionIntoArgument();
187 }
188
189 //=================================================================================
190 // function : ClickOnOk()
191 // purpose  :
192 //=================================================================================
193 void BlocksGUI_TrsfDlg::ClickOnOk()
194 {
195   if (ClickOnApply())
196     ClickOnCancel();
197 }
198
199 //=================================================================================
200 // function : ClickOnApply()
201 // purpose  :
202 //=================================================================================
203 bool BlocksGUI_TrsfDlg::ClickOnApply()
204 {
205   if (!onAccept())
206     return false;
207
208   initName();
209   return true;
210 }
211
212 //=================================================================================
213 // function : SelectionIntoArgument()
214 // purpose  : Called when selection is changed or on dialog initialization or activation
215 //=================================================================================
216 void BlocksGUI_TrsfDlg::SelectionIntoArgument()
217 {
218   erasePreview();
219   myEditCurrentArgument->setText("");
220
221   // Get index of current selection focus
222   int aCurrFocus = -1;
223   QMap<int, QLineEdit*>::iterator anIter;
224   for (anIter = mySelName.begin(); anIter != mySelName.end(); ++anIter) {
225     if (myEditCurrentArgument == anIter.value()) {
226       aCurrFocus = anIter.key();
227       break;
228     }
229   }
230
231   LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
232   SALOME_ListIO aSelList;
233   aSelMgr->selectedObjects(aSelList);
234
235   QString aName;
236   GEOM::GEOM_Object_var anObj = GEOM::GEOM_Object::_nil();
237
238   if (aCurrFocus == MainObj1 || aCurrFocus == MainObj2)
239   {
240     // If selection of main object is activated
241     if (aSelList.Extent() == 1) {
242       Standard_Boolean aResult = Standard_False;
243       anObj = GEOMBase::ConvertIOinGEOMObject(aSelList.First(), aResult);
244
245       if (aResult && !anObj->_is_nil() && GEOMBase::IsShape(anObj)) {
246         aName = GEOMBase::GetName(anObj);
247       }
248     }
249     myEditCurrentArgument->setText(aName);
250     myShape = anObj;
251     enableWidgets();
252   }
253   else if (aCurrFocus == Face1  || aCurrFocus == Face2  ||
254            aCurrFocus == Face1U || aCurrFocus == Face2U ||
255            aCurrFocus == Face1V || aCurrFocus == Face2V) {
256     // If face selection is activated
257     int anIndex = -1;
258     if (aSelList.Extent() == 1) {
259       Standard_Boolean aResult = Standard_False;
260       anObj = GEOMBase::ConvertIOinGEOMObject(aSelList.First(), aResult);
261       if (aResult && !anObj->_is_nil() && GEOMBase::IsShape(anObj)) {
262         aName = GEOMBase::GetName(anObj);
263         TColStd_IndexedMapOfInteger anIndexes;
264         aSelMgr->GetIndexes(aSelList.First(), anIndexes);
265
266         if (anIndexes.Extent() == 1) {
267           anIndex = anIndexes(1);
268           aName += QString(":face_%1").arg(anIndex);
269         }
270       }
271     }
272     myEditCurrentArgument->setText(aName);
273     myFaces[aCurrFocus] = anIndex;
274     displayPreview();
275   }
276
277   switch (aCurrFocus) {
278     // 1D
279   case MainObj1:
280     if (!myShape->_is_nil() && myFaces[Face1] == -1)
281       mySelBtn[Face1]->click();
282     break;
283   case Face1:
284     if (myFaces[Face1] != -1 && myFaces[Face2] == -1)
285       mySelBtn[Face2]->click();
286     break;
287   case Face2:
288     if (myFaces[Face2] != -1 && myShape->_is_nil())
289       mySelBtn[MainObj1]->click();
290     break;
291
292     // 2D
293   case MainObj2:
294     if (!myShape->_is_nil() && myFaces[Face1U] == -1)
295       mySelBtn[Face1U]->click();
296     break;
297   case Face1U:
298     if (myFaces[Face1U] != -1 && myFaces[Face2U] == -1)
299       mySelBtn[Face2U]->click();
300     break;
301   case Face2U:
302     if (myFaces[Face2U] != -1 && myFaces[Face1V] == -1)
303       mySelBtn[Face1V]->click();
304     break;
305   case Face1V:
306     if (myFaces[Face1V] != -1 && myFaces[Face2V] == -1)
307       mySelBtn[Face2V]->click();
308     break;
309   case Face2V:
310     if (myFaces[Face2V] != -1 && myShape->_is_nil())
311       mySelBtn[MainObj1]->click();
312     break;
313
314   default:
315     break;
316   }
317 }
318
319 //=================================================================================
320 // function : SetEditCurrentArgument()
321 // purpose  :
322 //=================================================================================
323 void BlocksGUI_TrsfDlg::SetEditCurrentArgument()
324 {
325   QPushButton* aSender = (QPushButton*)sender();
326
327   // clear selection
328   disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0);
329   if (myInitial)
330     myInitial = false;
331   else
332     myGeomGUI->getApp()->selectionMgr()->clearSelected();
333
334   // disable all
335   switch (myConstructorId) {
336   case 0:
337     mySelBtn[MainObj1]->setDown(false);
338     mySelBtn[Face1]->setDown(false);
339     mySelBtn[Face2]->setDown(false);
340
341     mySelName[MainObj1]->setEnabled(false);
342     mySelName[Face1]->setEnabled(false);
343     mySelName[Face2]->setEnabled(false);
344     break;
345   case 1:
346     mySelBtn[MainObj2]->setDown(false);
347     mySelBtn[Face1U]->setDown(false);
348     mySelBtn[Face2U]->setDown(false);
349     mySelBtn[Face1V]->setDown(false);
350     mySelBtn[Face2V]->setDown(false);
351
352     mySelName[MainObj2]->setEnabled(false);
353     mySelName[Face1U]->setEnabled(false);
354     mySelName[Face2U]->setEnabled(false);
355     mySelName[Face1V]->setEnabled(false);
356     mySelName[Face2V]->setEnabled(false);
357     break;
358   default:
359     break;
360   }
361
362   // set line edit as current argument
363   QMap<int, QPushButton*>::iterator anIter;
364   for (anIter = mySelBtn.begin(); anIter != mySelBtn.end(); ++anIter) {
365     if (anIter.value() == aSender) {
366       myEditCurrentArgument = mySelName[anIter.key()];
367       break;
368     }
369   }
370
371   // enable line edit
372   myEditCurrentArgument->setEnabled(true);
373   myEditCurrentArgument->setFocus();
374
375   // enable push button
376   // after setFocus(), because it will be setDown(false) when loses focus
377   aSender->setDown(true);
378
379   activateSelection();
380 }
381
382 //=================================================================================
383 // function : ActivateThisDialog()
384 // purpose  :
385 //=================================================================================
386 void BlocksGUI_TrsfDlg::ActivateThisDialog()
387 {
388   GEOMBase_Skeleton::ActivateThisDialog();
389   activateSelection();
390
391   // ??
392   displayPreview();
393 }
394
395 //=================================================================================
396 // function : enterEvent()
397 // purpose  :
398 //=================================================================================
399 void BlocksGUI_TrsfDlg::enterEvent (QEvent*)
400 {
401   if (!mainFrame()->GroupConstructors->isEnabled())
402     ActivateThisDialog();
403 }
404
405 //=================================================================================
406 // function : ValueChangedInSpinBox()
407 // purpose  :
408 //=================================================================================
409 void BlocksGUI_TrsfDlg::ValueChangedInSpinBox(double)
410 {
411   displayPreview();
412 }
413
414 //=================================================================================
415 // function : createSelWg()
416 // purpose  :
417 //=================================================================================
418 void BlocksGUI_TrsfDlg::createSelWg (const QString& theLbl,
419                                      QPixmap&       thePix,
420                                      QWidget*       theParent,
421                                      const int      theId)
422 {
423   QLabel* lab = new QLabel(theLbl, theParent);
424   mySelBtn[theId] = new QPushButton(theParent);
425   mySelBtn[theId]->setIcon(thePix);
426   mySelBtn[theId]->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
427   mySelName[theId] = new QLineEdit(theParent);
428   mySelName[theId]->setReadOnly(true);
429   QGridLayout* l = 0;
430   if (!theParent->layout()) {
431     l = new QGridLayout(theParent);
432     l->setMargin(9); l->setSpacing(6);
433   }
434   else {
435     l = qobject_cast<QGridLayout*>(theParent->layout());
436   }
437   int row = l->rowCount();
438   l->addWidget(lab,              row, 0);
439   l->addWidget(mySelBtn[theId],  row, 1);
440   l->addWidget(mySelName[theId], row, 2);
441 }
442
443 //=================================================================================
444 // function : createSpinWg()
445 // purpose  :
446 //=================================================================================
447 void BlocksGUI_TrsfDlg::createSpinWg (const QString& theLbl,
448                                       QWidget*       theParent,
449                                       const int      theId)
450 {
451   QLabel* lab = new QLabel(theLbl, theParent);
452   mySpinBox[theId] = new QDoubleSpinBox(theParent);
453   QGridLayout* l = 0;
454   if (!theParent->layout()) {
455     l = new QGridLayout(theParent);
456     l->setMargin(9); l->setSpacing(6);
457   }
458   else {
459     l = qobject_cast<QGridLayout*>(theParent->layout());
460   }
461   int row = l->rowCount();
462   l->addWidget(lab,              row, 0);
463   l->addWidget(mySpinBox[theId], row, 2);
464 }
465
466 //=================================================================================
467 // function : activateSelection
468 // purpose  : Activate selection in accordance with myEditCurrentArgument
469 //=================================================================================
470 void BlocksGUI_TrsfDlg::activateSelection()
471 {
472   globalSelection(GEOM_ALLSHAPES);
473   if (!myShape->_is_nil() &&
474       (myEditCurrentArgument == mySelName[Face1 ] ||
475        myEditCurrentArgument == mySelName[Face2 ] ||
476        myEditCurrentArgument == mySelName[Face1U] ||
477        myEditCurrentArgument == mySelName[Face2U] ||
478        myEditCurrentArgument == mySelName[Face1V] ||
479        myEditCurrentArgument == mySelName[Face2V]))
480   {
481     // Local selection is available only in the OCC Viewer
482     if (getDesktop()->activeWindow()->getViewManager()->getType() == OCCViewer_Viewer::Type()) {
483       localSelection(myShape, TopAbs_FACE);
484     }
485   }
486   connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()),
487           this, SLOT(SelectionIntoArgument()));
488 }
489
490 //=================================================================================
491 // function : enableWidgets
492 // purpose  : Enable widgets of faces in accordance with value of main object
493 //=================================================================================
494 void BlocksGUI_TrsfDlg::enableWidgets()
495 {
496   int anId = getConstructorId();
497
498   bool toEnable = !myShape->_is_nil();
499
500   if (anId == 0) {
501     //mySelName[Face1]->setEnabled(toEnable);
502     //mySelName[Face2]->setEnabled(toEnable);
503     //mySelBtn[Face1]->setEnabled(toEnable);
504     //mySelBtn[Face2]->setEnabled(toEnable);
505
506     if (!toEnable)  {
507       mySelName[Face1]->setText("");
508       mySelName[Face2]->setText("");
509       myFaces[Face1] = -1;
510       myFaces[Face2] = -1;
511     }
512   }
513   else if (anId == 1) {
514     //mySelName[Face1U]->setEnabled(toEnable);
515     //mySelName[Face2U]->setEnabled(toEnable);
516     //mySelName[Face1V]->setEnabled(toEnable);
517     //mySelName[Face2V]->setEnabled(toEnable);
518     //mySelBtn[Face1U]->setEnabled(toEnable);
519     //mySelBtn[Face2U]->setEnabled(toEnable);
520     //mySelBtn[Face1V]->setEnabled(toEnable);
521     //mySelBtn[Face2V]->setEnabled(toEnable);
522
523     if (!toEnable) {
524       mySelName[Face1U]->setText("");
525       mySelName[Face2U]->setText("");
526       mySelName[Face1V]->setText("");
527       mySelName[Face2V]->setText("");
528       myFaces[Face1U] = -1;
529       myFaces[Face2U] = -1;
530       myFaces[Face1V] = -1;
531       myFaces[Face2V] = -1;
532     }
533   }
534 }
535
536 //=================================================================================
537 // function : createOperation
538 // purpose  :
539 //=================================================================================
540 GEOM::GEOM_IOperations_ptr BlocksGUI_TrsfDlg::createOperation()
541 {
542   return getGeomEngine()->GetIBlocksOperations(getStudyId());
543 }
544
545 //=================================================================================
546 // function : isValid
547 // purpose  : Verify validity of input data
548 //=================================================================================
549 bool BlocksGUI_TrsfDlg::isValid (QString&)
550 {
551   bool ok = false;
552   switch (getConstructorId()) {
553   case 0:
554     ok = !myShape->_is_nil() && myFaces[Face1] > 0;
555     break;
556   case 1:
557     ok = !myShape->_is_nil() && myFaces[Face1U] > 0 && myFaces[Face1V] > 0;
558     break;
559   default:
560     break;
561   }
562   return ok;
563 }
564
565 //=================================================================================
566 // function : execute
567 // purpose  :
568 //=================================================================================
569 bool BlocksGUI_TrsfDlg::execute (ObjectList& objects)
570 {
571   bool res = false;
572
573   GEOM::GEOM_Object_var anObj;
574
575   switch (getConstructorId()) {
576   case 0:
577     anObj = GEOM::GEOM_IBlocksOperations::_narrow(getOperation())->
578       MakeMultiTransformation1D(myShape,
579                                 myFaces[Face1], myFaces[Face2],
580                                 (int)mySpinBox[SpinBox1]->value());
581     res = true;
582     break;
583   case 1:
584     anObj = GEOM::GEOM_IBlocksOperations::_narrow(getOperation())->
585       MakeMultiTransformation2D (myShape,
586                                  myFaces[Face1U], myFaces[Face2U],
587                                  (int)mySpinBox[SpinBox2U]->value(),
588                                  myFaces[Face1V], myFaces[Face2V],
589                                  (int)mySpinBox[SpinBox2V]->value());
590     res = true;
591     break;
592   default:
593     break;
594   }
595
596   if (!anObj->_is_nil())
597     objects.push_back(anObj._retn());
598
599   return res;
600 }