]> SALOME platform Git repositories - modules/geom.git/blob - src/TransformationGUI/TransformationGUI_ScaleDlg.cxx
Salome HOME
Implementation Notebook in the GEOM.
[modules/geom.git] / src / TransformationGUI / TransformationGUI_ScaleDlg.cxx
1 // GEOM GEOMGUI : GUI for Geometry component
2 //
3 // Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 // File   : TransformationGUI_ScaleDlg.cxx
23 // Author : Lucien PIGNOLONI, Open CASCADE S.A.S.
24
25 #include "TransformationGUI_ScaleDlg.h"
26
27 #include <DlgRef.h>
28 #include <GeometryGUI.h>
29 #include <GEOMBase.h>
30
31 #include <SalomeApp_DoubleSpinBox.h>
32 #include <SUIT_Session.h>
33 #include <SUIT_ResourceMgr.h>
34 #include <SalomeApp_Application.h>
35 #include <LightApp_SelectionMgr.h>
36
37 // OCCT Includes
38 #include <TopoDS_Shape.hxx>
39 #include <TopoDS.hxx>
40 #include <TopExp.hxx>
41 #include <TColStd_IndexedMapOfInteger.hxx>
42 #include <TopTools_IndexedMapOfShape.hxx>
43
44 #include <GEOMImpl_Types.hxx>
45
46 //=================================================================================
47 // class    : TransformationGUI_ScaleDlg()
48 // purpose  : Constructs a TransformationGUI_ScaleDlg which is a child of 'parent', with the
49 //            name 'name' and widget flags set to 'f'.
50 //            The dialog will by default be modeless, unless you set 'modal' to
51 //            TRUE to construct a modal dialog.
52 //=================================================================================
53 TransformationGUI_ScaleDlg::TransformationGUI_ScaleDlg (GeometryGUI* theGeometryGUI, QWidget* parent,
54                                                         bool modal, Qt::WindowFlags fl)
55   : GEOMBase_Skeleton(theGeometryGUI, parent, modal, fl),
56     myInitial(true)
57 {
58   SUIT_ResourceMgr* aResMgr = myGeomGUI->getApp()->resourceMgr();
59   QPixmap image1 (aResMgr->loadPixmap("GEOM", tr("ICON_DLG_SCALE")));
60   QPixmap image2 (aResMgr->loadPixmap("GEOM", tr("ICON_DLG_SCALE_ALONG_AXES")));
61   QPixmap image3 (aResMgr->loadPixmap("GEOM", tr("ICON_SELECT")));
62
63   setWindowTitle(tr("GEOM_SCALE_TITLE"));
64
65   // Constructors
66   mainFrame()->GroupConstructors->setTitle(tr("GEOM_SCALE"));
67   mainFrame()->RadioButton1->setIcon(image1);
68   mainFrame()->RadioButton2->setIcon(image2);
69   mainFrame()->RadioButton3->setAttribute(Qt::WA_DeleteOnClose);
70   mainFrame()->RadioButton3->close();
71
72   // Own widgets
73   GroupBox1 = new QGroupBox(tr("GEOM_ARGUMENTS"), this);
74   QGridLayout* OwnLayout = new QGridLayout(GroupBox1);
75   OwnLayout->setSpacing(6);
76   OwnLayout->setMargin(11);
77
78   TextLabel1 = new QLabel(tr("GEOM_OBJECTS"), GroupBox1);
79   PushButton1 = new QPushButton(GroupBox1);
80   PushButton1->setIcon(image3);
81   PushButton1->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
82   LineEdit1 = new QLineEdit(GroupBox1);
83   LineEdit1->setReadOnly(true);
84   LineEdit1->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
85
86   TextLabel2 = new QLabel(tr("GEOM_CENTRAL_POINT"), GroupBox1);
87   PushButton2 = new QPushButton(GroupBox1);
88   PushButton2->setIcon(image3);
89   PushButton2->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
90   LineEdit2 = new QLineEdit(GroupBox1);
91   LineEdit2->setReadOnly(true);
92   LineEdit2->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
93
94   TextLabel3 = new QLabel(tr("GEOM_SCALE_FACTOR"), GroupBox1);
95   SpinBox_FX = new SalomeApp_DoubleSpinBox(GroupBox1);
96
97   TextLabel4 = new QLabel(tr("GEOM_SCALE_FACTOR_Y"), GroupBox1);
98   SpinBox_FY = new SalomeApp_DoubleSpinBox(GroupBox1);
99
100   TextLabel5 = new QLabel(tr("GEOM_SCALE_FACTOR_Z"), GroupBox1);
101   SpinBox_FZ = new SalomeApp_DoubleSpinBox(GroupBox1);
102
103   CheckBoxCopy = new QCheckBox(tr("GEOM_CREATE_COPY"), GroupBox1);
104   CheckBoxCopy->setChecked(true);
105
106   // Layouting
107   OwnLayout->addWidget(TextLabel1,   0, 0);
108   OwnLayout->addWidget(PushButton1,  0, 1);
109   OwnLayout->addWidget(LineEdit1,    0, 2, 1, 2);
110   OwnLayout->addWidget(TextLabel2,   1, 0);
111   OwnLayout->addWidget(PushButton2,  1, 1);
112   OwnLayout->addWidget(LineEdit2,    1, 2, 1, 2);
113   OwnLayout->addWidget(TextLabel3,   2, 0);
114   OwnLayout->addWidget(SpinBox_FX,   2, 2);
115   OwnLayout->addWidget(TextLabel4,   3, 0);
116   OwnLayout->addWidget(SpinBox_FY,   3, 2);
117   OwnLayout->addWidget(TextLabel5,   4, 0);
118   OwnLayout->addWidget(SpinBox_FZ,   4, 2);
119   OwnLayout->addWidget(CheckBoxCopy, 5, 0, 1, 4);
120
121   QVBoxLayout* layout = new QVBoxLayout(centralWidget());
122   layout->setMargin(0); layout->setSpacing(6);
123   layout->addWidget(GroupBox1);
124
125   setHelpFileName("scale_operation_page.html");
126
127   // Modification of an existing object by offset is not allowed
128   CheckBoxCopy->hide();
129
130   // Activate Create a Copy mode
131   CreateCopyModeChanged(true);
132
133   // Allowed inheritance of children and visual properties by the scaling result
134   mainFrame()->GroupBoxPublish->show();
135
136   Init();
137 }
138
139 //=================================================================================
140 // function : ~TransformationGUI_ScaleDlg()
141 // purpose  : Destroys the object and frees any allocated resources
142 //=================================================================================
143 TransformationGUI_ScaleDlg::~TransformationGUI_ScaleDlg()
144 {
145 }
146
147 //=================================================================================
148 // function : Init()
149 // purpose  :
150 //=================================================================================
151 void TransformationGUI_ScaleDlg::Init()
152 {
153   // Min, max, step and decimals for spin boxes & initial values
154   double aFactor = 2.0;
155   double SpecificStep = 0.5;
156
157   initSpinBox(SpinBox_FX, COORD_MIN, COORD_MAX, SpecificStep, DBL_DIGITS_DISPLAY);
158   initSpinBox(SpinBox_FY, COORD_MIN, COORD_MAX, SpecificStep, DBL_DIGITS_DISPLAY);
159   initSpinBox(SpinBox_FZ, COORD_MIN, COORD_MAX, SpecificStep, DBL_DIGITS_DISPLAY);
160   SpinBox_FX->setValue(aFactor);
161   SpinBox_FY->setValue(aFactor);
162   SpinBox_FZ->setValue(aFactor);
163
164   // init variables
165   LineEdit1->setText("");
166   LineEdit2->setText("");
167
168   myPoint = GEOM::GEOM_Object::_nil();
169
170   // Signals and slots connections
171   connect(buttonOk(),        SIGNAL(clicked()), this, SLOT(ClickOnOk()));
172   connect(buttonApply(),     SIGNAL(clicked()), this, SLOT(ClickOnApply()));
173   connect(this, SIGNAL(constructorsClicked(int)), this, SLOT(ConstructorsClicked(int)));
174
175   connect(PushButton1, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
176   connect(PushButton2, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
177
178   connect(LineEdit1, SIGNAL(returnPressed()), this, SLOT(LineEditReturnPressed()));
179   connect(LineEdit2, SIGNAL(returnPressed()), this, SLOT(LineEditReturnPressed()));
180
181   connect(SpinBox_FX, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox()));
182   connect(SpinBox_FY, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox()));
183   connect(SpinBox_FZ, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox()));
184
185   connect(myGeomGUI, SIGNAL(SignalDefaultStepValueChanged(double)), this, SLOT(SetDoubleSpinBoxStep(double)));
186
187   connect(CheckBoxCopy, SIGNAL(toggled(bool)), this, SLOT(CreateCopyModeChanged(bool)));
188
189   initName(tr("GEOM_SCALE"));
190
191   ConstructorsClicked(0);
192 }
193
194 //=================================================================================
195 // function : ConstructorsClicked()
196 // purpose  : Radio button management
197 //=================================================================================
198 void TransformationGUI_ScaleDlg::ConstructorsClicked (int constructorId)
199 {
200   disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0);
201
202   switch (constructorId) {
203   case 0: // translation an object by dx, dy, dz
204     TextLabel3->setText(tr("GEOM_SCALE_FACTOR"));
205     TextLabel4->hide();
206     TextLabel5->hide();
207     SpinBox_FY->hide();
208     SpinBox_FZ->hide();
209
210     PushButton1->click();
211     break;
212   case 1: // translation an object by 2 points
213     TextLabel3->setText(tr("GEOM_SCALE_FACTOR_X"));
214     TextLabel4->show();
215     TextLabel5->show();
216     SpinBox_FY->show();
217     SpinBox_FZ->show();
218
219     PushButton1->click();
220     break;
221   default:
222     break;
223   }
224
225   qApp->processEvents();
226   updateGeometry();
227   resize(minimumSize());
228
229   if (myInitial) {
230     myInitial = false;
231     SelectionIntoArgument();
232   }
233   else {
234     displayPreview();
235   }
236 }
237
238 //=================================================================================
239 // function : ClickOnOk()
240 // purpose  :
241 //=================================================================================
242 void TransformationGUI_ScaleDlg::ClickOnOk()
243 {
244   if (ClickOnApply())
245     ClickOnCancel();
246 }
247
248 //=================================================================================
249 // function : ClickOnApply()
250 // purpose  :
251 //=================================================================================
252 bool TransformationGUI_ScaleDlg::ClickOnApply()
253 {
254   if (!onAccept(CheckBoxCopy->isChecked()))
255     return false;
256
257   initName(tr("GEOM_SCALE"));
258   // activate selection and connect selection manager
259   ConstructorsClicked(getConstructorId());
260   return true;
261 }
262
263 //=================================================================================
264 // function : SelectionIntoArgument()
265 // purpose  : Called when selection is changed or on dialog initialization or activation
266 //=================================================================================
267 void TransformationGUI_ScaleDlg::SelectionIntoArgument()
268 {
269   erasePreview();
270   myEditCurrentArgument->setText("");
271
272   if (myEditCurrentArgument == LineEdit1)
273     myObjects.length(0);
274   else if (myEditCurrentArgument == LineEdit2)
275     myPoint = GEOM::GEOM_Object::_nil();
276
277   LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr();
278   SALOME_ListIO aSelList;
279   aSelMgr->selectedObjects(aSelList);
280
281   QString aName;
282
283   if (myEditCurrentArgument == LineEdit1)
284   {
285     int aNbSel = GEOMBase::GetNameOfSelectedIObjects(aSelList, aName);
286     if (aNbSel < 1)
287       return;
288
289     GEOMBase::ConvertListOfIOInListOfGO(aSelList, myObjects);
290     if (!myObjects.length())
291       return;
292     else
293       myEditCurrentArgument->setText(aName);
294   }
295   else if (myEditCurrentArgument == LineEdit2)
296   {
297     GEOM::GEOM_Object_var aSelectedObject = GEOM::GEOM_Object::_nil();
298     if (aSelList.Extent() == 1)
299     {
300       Standard_Boolean testResult = Standard_False;
301       aSelectedObject = GEOMBase::ConvertIOinGEOMObject(aSelList.First(), testResult);
302       if (testResult)
303       {
304         aName = GEOMBase::GetName(aSelectedObject);
305
306         TopoDS_Shape aShape;
307         if (GEOMBase::GetShape(aSelectedObject, aShape, TopAbs_SHAPE) && !aShape.IsNull())
308         {
309           TColStd_IndexedMapOfInteger aMap;
310           aSelMgr->GetIndexes(aSelList.First(), aMap);
311           if (aMap.Extent() == 1)
312           {
313             int anIndex = aMap(1);
314             aName += QString(":vertex_%1").arg(anIndex);
315
316             //Find SubShape Object in Father
317             GEOM::GEOM_Object_var aFindedObject = findObjectInFather(aSelectedObject, aName);
318
319             if (aFindedObject == GEOM::GEOM_Object::_nil()) { // Object not found in study
320               GEOM::GEOM_IShapesOperations_var aShapesOp =
321                 getGeomEngine()->GetIShapesOperations(getStudyId());
322               aSelectedObject = aShapesOp->GetSubShape(aSelectedObject, anIndex);
323             }
324             else
325               aSelectedObject = aFindedObject; // get Object from study
326           }
327           else // Global Selection
328           {
329             if (aShape.ShapeType() != TopAbs_VERTEX) {
330               aSelectedObject = GEOM::GEOM_Object::_nil();
331               aName = "";
332             }
333           }
334         }
335       }
336     }
337
338     myPoint = aSelectedObject;
339     myEditCurrentArgument->setText(aName);
340
341     if (!myPoint->_is_nil() && !myObjects.length())
342       PushButton1->click();
343   }
344
345   // clear selection
346   disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0);
347   myGeomGUI->getApp()->selectionMgr()->clearSelected();
348   connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()),
349           this, SLOT(SelectionIntoArgument()));
350
351   displayPreview();
352 }
353
354 //=================================================================================
355 // function : SetEditCurrentArgument()
356 // purpose  :
357 //=================================================================================
358 void TransformationGUI_ScaleDlg::SetEditCurrentArgument()
359 {
360   QPushButton* send = (QPushButton*)sender();
361
362   disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0);
363   globalSelection();
364
365   if (send == PushButton1) {
366     myEditCurrentArgument = LineEdit1;
367
368     PushButton2->setDown(false);
369     LineEdit2->setEnabled(false);
370   }
371   else if (send == PushButton2) {
372     myEditCurrentArgument = LineEdit2;
373
374     localSelection(GEOM::GEOM_Object::_nil(), TopAbs_VERTEX);
375
376     PushButton1->setDown(false);
377     LineEdit1->setEnabled(false);
378   }
379   connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()),
380           this, SLOT(SelectionIntoArgument()));
381
382   // enable line edit
383   myEditCurrentArgument->setEnabled(true);
384   myEditCurrentArgument->setFocus();
385   // after setFocus(), because it will be setDown(false) when loses focus
386   send->setDown(true);
387
388   // seems we need it only to avoid preview disappearing, caused by selection mode change
389   displayPreview();
390 }
391
392 //=================================================================================
393 // function : LineEditReturnPressed()
394 // purpose  :
395 //=================================================================================
396 void TransformationGUI_ScaleDlg::LineEditReturnPressed()
397 {
398   QLineEdit* send = (QLineEdit*)sender();
399   if (send == LineEdit1 || send == LineEdit2)
400   {
401     myEditCurrentArgument = send;
402     GEOMBase_Skeleton::LineEditReturnPressed();
403   }
404 }
405
406 //=================================================================================
407 // function : ActivateThisDialog()
408 // purpose  :
409 //=================================================================================
410 void TransformationGUI_ScaleDlg::ActivateThisDialog()
411 {
412   GEOMBase_Skeleton::ActivateThisDialog();
413
414   // reinit, because some selected objects could be removed
415   Init();
416 }
417
418 //=================================================================================
419 // function : enterEvent()
420 // purpose  :
421 //=================================================================================
422 void TransformationGUI_ScaleDlg::enterEvent (QEvent*)
423 {
424   if (!mainFrame()->GroupConstructors->isEnabled())
425     ActivateThisDialog();
426 }
427
428 //=================================================================================
429 // function : ValueChangedInSpinBox()
430 // purpose  :
431 //=================================================================================
432 void TransformationGUI_ScaleDlg::ValueChangedInSpinBox()
433 {
434   displayPreview();
435 }
436
437 //=================================================================================
438 // function : SetDoubleSpinBoxStep()
439 // purpose  : Double spin box management
440 //=================================================================================
441 void TransformationGUI_ScaleDlg::SetDoubleSpinBoxStep(double step)
442 {
443   SpinBox_FX->setSingleStep(step);
444   SpinBox_FY->setSingleStep(step);
445   SpinBox_FZ->setSingleStep(step);
446 }
447
448 //=================================================================================
449 // function : createOperation
450 // purpose  :
451 //=================================================================================
452 GEOM::GEOM_IOperations_ptr TransformationGUI_ScaleDlg::createOperation()
453 {
454   return getGeomEngine()->GetITransformOperations(getStudyId());
455 }
456
457 //=================================================================================
458 // function : isValid
459 // purpose  :
460 //=================================================================================
461 bool TransformationGUI_ScaleDlg::isValid (QString& msg)
462 {
463   if (myObjects.length() > 0 && fabs(SpinBox_FX->value()) > 0.00001)
464   {
465     // && !myPoint->_is_nil()
466     if (getConstructorId() == 0) {
467       return SpinBox_FX->isValid( msg, !IsPreview() );
468     }
469     if (fabs(SpinBox_FY->value()) > 0.00001 &&
470         fabs(SpinBox_FZ->value()) > 0.00001 &&
471         SpinBox_FX->isValid( msg, !IsPreview()) &&
472         SpinBox_FY->isValid( msg, !IsPreview()) &&
473         SpinBox_FZ->isValid( msg, !IsPreview()))
474       return true;
475   }
476   return false;
477 }
478
479 //=================================================================================
480 // function : execute
481 // purpose  :
482 //=================================================================================
483 bool TransformationGUI_ScaleDlg::execute (ObjectList& objects)
484 {
485   bool toCreateCopy = IsPreview() || CheckBoxCopy->isChecked();
486
487   GEOM::GEOM_Object_var anObj;
488
489   switch (getConstructorId())
490   {
491   case 0:
492     {
493       if (toCreateCopy)
494       {
495         for (int i = 0; i < myObjects.length(); i++)
496         {
497           anObj = GEOM::GEOM_ITransformOperations::_narrow(getOperation())->
498             ScaleShapeCopy(myObjects[i], myPoint, SpinBox_FX->value());
499           if (!anObj->_is_nil()) {
500             if(!IsPreview()) 
501               anObj->SetParameters(SpinBox_FX->text().toLatin1().constData());
502             objects.push_back(anObj._retn());
503           }
504         }
505       }
506       else
507       {
508         for (int i = 0; i < myObjects.length(); i++)
509         {
510           anObj = GEOM::GEOM_ITransformOperations::_narrow(getOperation())->
511             ScaleShape(myObjects[i], myPoint, SpinBox_FX->value());
512           if (!anObj->_is_nil())
513             objects.push_back(anObj._retn());
514         }
515       }
516     }
517     break;
518   case 1:
519     {
520       if (toCreateCopy)
521       {
522         for (int i = 0; i < myObjects.length(); i++)
523         {
524           anObj = GEOM::GEOM_ITransformOperations::_narrow(getOperation())->
525             ScaleShapeAlongAxesCopy(myObjects[i], myPoint, SpinBox_FX->value(),
526                                      SpinBox_FY->value(), SpinBox_FZ->value());
527           if (!anObj->_is_nil())
528             if(!IsPreview()) {
529               QStringList aParameters;
530               aParameters<<SpinBox_FX->text();
531               aParameters<<SpinBox_FY->text();
532               aParameters<<SpinBox_FZ->text();
533               anObj->SetParameters(GeometryGUI::JoinObjectParameters(aParameters));
534             }
535             objects.push_back(anObj._retn());
536         }
537       }
538       else
539       {
540         for (int i = 0; i < myObjects.length(); i++)
541         {
542           anObj = GEOM::GEOM_ITransformOperations::_narrow(getOperation())->
543             ScaleShapeAlongAxes(myObjects[i], myPoint, SpinBox_FX->value(),
544                                  SpinBox_FY->value(), SpinBox_FZ->value());
545           if (!anObj->_is_nil())
546             objects.push_back(anObj._retn());
547         }
548       }
549     }
550     break;
551   default:
552     break;
553   }
554
555   return true;
556 }
557
558 //=================================================================================
559 // function : restoreSubShapes
560 // purpose  :
561 //=================================================================================
562 void TransformationGUI_ScaleDlg::restoreSubShapes (SALOMEDS::Study_ptr   theStudy,
563                                                    SALOMEDS::SObject_ptr theSObject)
564 {
565   if (mainFrame()->CheckBoxRestoreSS->isChecked()) {
566     // empty list of arguments means that all arguments should be restored
567     getGeomEngine()->RestoreSubShapesSO(theStudy, theSObject, GEOM::ListOfGO(),
568                                         /*theFindMethod=*/GEOM::FSM_Transformed,
569                                         /*theInheritFirstArg=*/true);
570   }
571 }
572
573 //=================================================================================
574 // function :  CreateCopyModeChanged()
575 // purpose  :
576 //=================================================================================
577 void TransformationGUI_ScaleDlg::CreateCopyModeChanged (bool isCreateCopy)
578 {
579   mainFrame()->GroupBoxName->setEnabled(isCreateCopy);
580 }
581
582 //=================================================================================
583 // function : addSubshapesToStudy
584 // purpose  : virtual method to add new SubObjects if local selection
585 //=================================================================================
586 void TransformationGUI_ScaleDlg::addSubshapesToStudy()
587 {
588   bool toCreateCopy = IsPreview() || CheckBoxCopy->isChecked();
589   if (toCreateCopy)
590   {
591     if (!myPoint->_is_nil())
592     {
593       QMap<QString, GEOM::GEOM_Object_var> objMap;
594       objMap[LineEdit2->text()] = myPoint;
595       addSubshapesToFather(objMap);
596     }
597   }
598 }