Salome HOME
Fix pb with labels of rotation spin boxes (bad update after switch from IJK pane...
[modules/visu.git] / src / VISUGUI / VisuGUI_Plot3DDlg.cxx
1 //  VISU VISUGUI : GUI of VISU component
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
21 //
22 //
23 //
24 //  File   : VisuGUI_Plot3DDlg.cxx
25 //  Author : Laurent CORNABE & Hubert ROLLAND
26 //  Module : VISU
27 //  $Header$
28
29 #include "VisuGUI_Plot3DDlg.h"
30
31 #include "VisuGUI.h"
32 #include "VisuGUI_Tools.h"
33
34 #include "VISU_ViewManager_i.hh"
35 #include "VISU_Plot3DPL.hxx"
36
37 #include "SALOME_Actor.h"
38 #include "SVTK_ViewWindow.h"
39
40 #include <qlayout.h>
41 #include <qvalidator.h>
42 #include <qtabwidget.h>
43
44 #include <vtkUnstructuredGrid.h>
45 #include <vtkDataSetMapper.h>
46 #include <vtkRenderer.h>
47 #include <vtkPlaneSource.h>
48 #include <vtkPolyData.h>
49 #include <vtkMath.h>
50
51 using namespace std;
52
53 #define SURFACE_PRS_ID 0
54 #define CONTOUR_PRS_ID 1
55
56 //=======================================================================
57 //function : renderViewFrame
58 //purpose  :
59 //=======================================================================
60 static void renderViewFrame (SVTK_ViewWindow* vw)
61 {
62   if (vw) {
63 //if (vw->getRenderer()->GetActors()->GetNumberOfItems() > 0) {
64       vw->getRenderer()->ResetCameraClippingRange();
65       vw->Repaint();
66 //}
67   }
68 }
69
70 //=======================================================================
71 //class    : TPlane
72 //purpose  : actor of plane preview
73 //=======================================================================
74 class TPlane : public SALOME_Actor
75 {
76   float                mySize;
77   vtkDataSetMapper*    myMapper;
78   vtkPlaneSource*      myPlaneSource;
79
80  public:
81   // constructor
82   TPlane(float planeSize): mySize(planeSize)
83   {
84     Init();
85   }
86   // set plane parameters
87   void Set(float origin[3], float normal[3])
88   {
89     float point2[3], point1[3];
90     vtkMath::Perpendiculars(normal, point1, point2, 0.);
91     for (int i = 0; i < 3; ++i) {
92       point1[ i ] = point1[ i ] * mySize + origin[ i ];
93       point2[ i ] = point2[ i ] * mySize + origin[ i ];
94     }
95     myPlaneSource->SetOrigin(origin);
96     myPlaneSource->SetPoint1(point1);
97     myPlaneSource->SetPoint2(point2);
98     myPlaneSource->SetCenter(origin);
99   }
100   vtkTypeMacro(TPlane,SALOME_Actor);
101
102  protected:
103   void Init() {
104     myPlaneSource = vtkPlaneSource::New();
105     myMapper = vtkDataSetMapper::New();
106     myMapper->SetInput(myPlaneSource->GetOutput());
107     // actor methods
108     VisibilityOff();
109     PickableOff();
110     SetInfinitive(true);
111     SetOpacity(0.85);
112     SetMapper(myMapper);
113   }
114   ~TPlane() {
115     myMapper->RemoveAllInputs();
116     myMapper->Delete();
117     myPlaneSource->UnRegisterAllOutputs();
118     myPlaneSource->Delete();
119   };
120   // Not implemented.
121   TPlane(const TPlane&);
122   void operator=(const TPlane&);
123 };
124
125 //=======================================================================
126 //function : VisuGUI_Plot3DPane
127 //purpose  :
128 //=======================================================================
129 VisuGUI_Plot3DPane::VisuGUI_Plot3DPane (QWidget* parent)
130      : QVBox(parent), myInitFromPrs(false), myPreviewActor(NULL),
131        myViewWindow(VISU::GetViewWindow()), myPrs(NULL), myPipeCopy(NULL)
132 {
133   layout()->setAlignment(Qt::AlignTop);
134   setSpacing(6);
135
136   // Orientation
137
138   GBOrientation = new QButtonGroup (tr("Orientation"), this, "GBOrientation");
139   GBOrientation->setTitle(tr("ORIENTATION"));
140   GBOrientation->setColumnLayout(0, Qt::Vertical);
141   GBOrientation->layout()->setSpacing(0);
142   GBOrientation->layout()->setMargin(0);
143   QGridLayout* BGOrientationLayout = new QGridLayout (GBOrientation->layout());
144   BGOrientationLayout->setAlignment(Qt::AlignTop);
145   BGOrientationLayout->setSpacing(6);
146   BGOrientationLayout->setMargin(11);
147
148   QRadioButton *RBxy, *RByz, *RBzx;
149   RBxy = new QRadioButton (tr("// X-Y"), GBOrientation, "RBxy");
150   RByz = new QRadioButton (tr("// Y-Z"), GBOrientation, "RByz");
151   RBzx = new QRadioButton (tr("// Z-X"), GBOrientation, "RBzx");
152   BGOrientationLayout->addWidget(RBxy, 0, 0);
153   BGOrientationLayout->addWidget(RByz, 0, 1);
154   BGOrientationLayout->addWidget(RBzx, 0, 2);
155
156   // Rotation
157
158   QGroupBox* GBrot = new QGroupBox (tr("ROTATIONS"), this, "GBrot");
159   GBrot->setColumnLayout(0, Qt::Vertical);
160   GBrot->layout()->setSpacing(0);
161   GBrot->layout()->setMargin(0);
162   QGridLayout* GBrotLayout = new QGridLayout (GBrot->layout());
163   GBrotLayout->setAlignment(Qt::AlignTop);
164   GBrotLayout->setSpacing(6);
165   GBrotLayout->setMargin(11);
166   // label 1
167   LabelRot1 = new QLabel (tr("ROTATION_X"), GBrot, "LabelRot1");
168   GBrotLayout->addWidget(LabelRot1, 0, 0);
169   // spin 1
170   Rot1 = new QtxDblSpinBox (-180, 180, 5, GBrot);
171   Rot1->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
172   GBrotLayout->addWidget(Rot1, 0, 1);
173   // label 2
174   LabelRot2 = new QLabel (tr("ROTATION_Y"), GBrot, "LabelRot2");
175   GBrotLayout->addWidget(LabelRot2, 1, 0);
176   // spin 2
177   Rot2 = new QtxDblSpinBox (-180, 180, 5, GBrot);
178   Rot2->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
179   GBrotLayout->addWidget(Rot2, 1, 1);
180
181   // Position
182
183   QGroupBox* GBpos = new QGroupBox (tr("POSITION"), this, "GBpos");
184   GBpos->setColumnLayout(0, Qt::Horizontal);
185   GBpos->layout()->setSpacing(0);
186   GBpos->layout()->setMargin(0);
187   QGridLayout* GBposLayout = new QGridLayout (GBpos->layout());
188   GBposLayout->setAlignment(Qt::AlignTop);
189   GBposLayout->setSpacing(6);
190   GBposLayout->setMargin(11);
191   // value label
192   QLabel * valueLabel = new QLabel (tr("POSITION_VALUE"), GBpos, "LabelRot1");
193   GBposLayout->addWidget(valueLabel, 0, 0);
194   // value spin
195   PositionSpn = new QtxDblSpinBox (0, 1, 0.1, GBpos);
196   GBposLayout->addWidget(PositionSpn, 0, 1);
197   // Relative CheckBox
198   RelativeChkB = new QCheckBox (tr("RELATIVE"), GBpos, "RelativeChkB");
199   RelativeChkB->setChecked(true);
200   GBposLayout->addWidget(RelativeChkB, 0, 2);
201
202   // Scale, Presentation type, Nb Contours, Preview
203
204   QFrame* bottomFrame = new QFrame (this);
205   QGridLayout* bottomLayout = new QGridLayout (bottomFrame);
206   bottomLayout->setAlignment(Qt::AlignTop);
207   bottomLayout->setSpacing(11);
208   bottomLayout->setMargin(0);
209   // scale
210   QLabel* scaleLabel = new QLabel (tr("SCALE"), bottomFrame);
211   ScaleSpn = new QtxDblSpinBox (-1.e6, 1.e6, 0.1, bottomFrame);
212   // Presentation type
213   GBPrsType = new QHButtonGroup (tr("PRESENTATION_TYPE"), bottomFrame);
214   new QRadioButton (tr("SURFACE"), GBPrsType);
215   new QRadioButton (tr("CONTOUR"), GBPrsType);
216   // nb Contours
217   QLabel* nbContLabel = new QLabel (tr("NUMBER_CONTOURS"), bottomFrame);
218   NbContoursSpn = new QSpinBox (1, 999, 1, bottomFrame, "NbContoursSpn");
219   // Preview
220   PreviewChkB = new QCheckBox (tr("PREVIEW"), bottomFrame);
221   PreviewChkB->setChecked(false);
222
223   bottomLayout->addWidget(scaleLabel,    0, 0);
224   bottomLayout->addWidget(ScaleSpn,      0, 1);
225   bottomLayout->addMultiCellWidget(GBPrsType, 1, 1, 0, 1);
226   bottomLayout->addWidget(nbContLabel,   2, 0);
227   bottomLayout->addWidget(NbContoursSpn, 2, 1);
228   bottomLayout->addWidget(PreviewChkB,   3, 0);
229
230   // signals and slots connections
231   connect(GBOrientation, SIGNAL(clicked(int)),         this, SLOT(orientationChanged(int)));
232   connect(Rot1,          SIGNAL(valueChanged(double)), this, SLOT(updatePreview()));
233   connect(Rot2,          SIGNAL(valueChanged(double)), this, SLOT(updatePreview()));
234   connect(PositionSpn,   SIGNAL(valueChanged(double)), this, SLOT(onPositionSpn()));
235   connect(RelativeChkB,  SIGNAL(toggled(bool)),        this, SLOT(onRelativePos(bool)));
236   connect(GBPrsType,     SIGNAL(clicked(int)),         this, SLOT(onPrsType(int)));
237   connect(PreviewChkB,   SIGNAL(toggled(bool)),        this, SLOT(updatePreview()));
238 }
239
240 //=======================================================================
241 //function : destructor
242 //purpose  :
243 //=======================================================================
244 VisuGUI_Plot3DPane::~VisuGUI_Plot3DPane()
245 {
246 }
247
248 //=======================================================================
249 //function : storePrsParams
250 //purpose  : create a copy of Prs parameters and then store current
251 //           control values into the Prs
252 //=======================================================================
253 void VisuGUI_Plot3DPane::storePrsParams()
254 {
255   if (!myPipeCopy)
256     myPipeCopy = VISU_Plot3DPL::New();
257   if (myPrs) {
258     myPipeCopy->ShallowCopy(myPrs->GetPL());
259     storeToPrsObject(myPrs);
260   }
261 }
262
263 //=======================================================================
264 //function : restorePrsParams
265 //purpose  : restore Prs parameters from the copy
266 //=======================================================================
267 void VisuGUI_Plot3DPane::restorePrsParams()
268 {
269   if (!myPipeCopy)
270     myPipeCopy = VISU_Plot3DPL::New();
271   if (myPrs)
272     myPrs->GetPL()->ShallowCopy(myPipeCopy);
273 }
274
275 //=======================================================================
276 //function : onPositionSpn
277 //purpose  : update absolute position range
278 //=======================================================================
279 void VisuGUI_Plot3DPane::onPositionSpn()
280 {
281   if (myPrs && !RelativeChkB->isChecked()) {
282     float minPos, maxPos;
283     storePrsParams();
284     myPrs->GetPlot3DPL()->GetMinMaxPosition(minPos, maxPos);
285     restorePrsParams();
286     if (minPos > PositionSpn->value())
287       minPos = PositionSpn->value();
288     if (maxPos < PositionSpn->value())
289       maxPos = PositionSpn->value();
290     PositionSpn->setRange(minPos, maxPos);
291   }
292   updatePreview();
293 }
294
295 //=======================================================================
296 //function : orientationChanged
297 //purpose  : update rotation labels and preview
298 //=======================================================================
299 void VisuGUI_Plot3DPane::orientationChanged(int Id)
300 {
301   if (Id == 0) { // RBxy->isChecked()
302     LabelRot1->setText(tr("ROTATION_X"));
303     LabelRot2->setText(tr("ROTATION_Y"));
304   } else if (Id == 1) { // RByz->isChecked()
305     LabelRot1->setText(tr("ROTATION_Y"));
306     LabelRot2->setText(tr("ROTATION_Z"));
307   } else {
308     LabelRot1->setText(tr("ROTATION_Z"));
309     LabelRot2->setText(tr("ROTATION_X"));
310   }
311   updatePreview();
312 }
313
314 //=======================================================================
315 //function : onRelativePos
316 //purpose  : update position value and range
317 //=======================================================================
318 void VisuGUI_Plot3DPane::onRelativePos(bool isRelativePos)
319 {
320   float minPos = 0., maxPos = 1., pos = PositionSpn->value();
321   if (myPrs) {
322     storePrsParams();
323     myPrs->GetPlot3DPL()->GetMinMaxPosition(minPos, maxPos);
324     restorePrsParams();
325     if (-1e-7 < (maxPos - minPos) && (maxPos - minPos) < 1e-7) {
326       pos = 0;
327     } else {
328       if (isRelativePos) // absolute -> relative
329         pos = (pos - minPos) / (maxPos - minPos);
330       else  // relative -> absolute
331         pos = minPos * (1. - pos) + maxPos * pos;
332     }
333   }
334   if (isRelativePos) {
335     minPos = 0.;
336     maxPos = 1.;
337   }
338   PositionSpn->setMinValue(minPos);
339   PositionSpn->setMaxValue(maxPos);
340   PositionSpn->setLineStep((maxPos - minPos) / 10.);
341   PositionSpn->setValue(pos);
342 }
343
344 //=======================================================================
345 //function : onPrsType
346 //purpose  :
347 //=======================================================================
348 void VisuGUI_Plot3DPane::onPrsType(int id)
349 {
350   NbContoursSpn->setEnabled(id == CONTOUR_PRS_ID);
351 }
352
353 //=======================================================================
354 //function : updatePreview
355 //purpose  :
356 //=======================================================================
357 void VisuGUI_Plot3DPane::updatePreview()
358 {
359   if (myInitFromPrs || !myPrs || !myViewWindow)
360     return;
361   bool fitall = false;
362   if (PreviewChkB->isChecked()) // place preview plane
363   {
364     // get plane preview actor
365     TPlane* planePreview = (TPlane*) myPreviewActor;
366     if (!planePreview) {
367       myPreviewActor = planePreview = new TPlane(myPrs->GetInput()->GetLength());
368       myViewWindow->AddActor(planePreview);
369       fitall = !VISU::GetActor(myPrs, myViewWindow);
370     }
371     // set plane parameters corresponding to control values
372     storePrsParams();
373     float normal[3], origin[3];
374     myPrs->GetPlot3DPL()->GetBasePlane(origin, normal, true);
375     planePreview->Set(origin, normal);
376     restorePrsParams();
377   }
378   if (myPreviewActor)
379     myPreviewActor->SetVisibility(PreviewChkB->isChecked());
380
381   renderViewFrame(myViewWindow);
382
383   if (fitall) {
384     myPreviewActor->SetInfinitive(false);
385     myViewWindow->onFitAll();
386     myPreviewActor->SetInfinitive(true);
387   }
388 }
389
390 //=======================================================================
391 //function : initFromPrsObject
392 //purpose  :
393 //=======================================================================
394 void VisuGUI_Plot3DPane::initFromPrsObject(VISU::Plot3D_i* thePrs)
395 {
396   myInitFromPrs = true;
397   myPrs = thePrs;
398
399   // orientation
400   int id;
401   switch (thePrs->GetOrientationType()) {
402   case VISU::Plot3D::XY: id = 0; break;
403   case VISU::Plot3D::YZ: id = 1; break;
404   default: id = 2;
405   }
406   GBOrientation->setButton(id);
407   orientationChanged(id);
408
409   // rotation
410   Rot1->setValue(thePrs->GetRotateX() * 180./PI);
411   Rot2->setValue(thePrs->GetRotateY() * 180./PI);
412
413   // position
414   RelativeChkB->setChecked(thePrs->IsPositionRelative());
415   onRelativePos(thePrs->IsPositionRelative()); // update range
416   PositionSpn->setValue(thePrs->GetPlanePosition());
417
418   // scale
419   ScaleSpn->setValue(thePrs->GetScaleFactor());
420
421   // prs type
422   id = thePrs->GetIsContourPrs() ? CONTOUR_PRS_ID : SURFACE_PRS_ID;
423   GBPrsType->setButton(id);
424   onPrsType(id);
425
426   // nb contours
427   NbContoursSpn->setValue(thePrs->GetNbOfContours());
428
429   // disable cutting plane controls if the mesh is planar
430
431   if (thePrs->GetPL()->IsPlanarInput())
432   {
433     GBOrientation->setEnabled(false);
434     Rot1         ->setEnabled(false);
435     Rot2         ->setEnabled(false);
436     PositionSpn  ->setEnabled(false);
437     RelativeChkB ->setEnabled(false);
438     PreviewChkB  ->setEnabled(false);
439   }
440
441   myInitFromPrs = false;
442   updatePreview();
443 }
444
445 //=======================================================================
446 //function : storeToPrsObject
447 //purpose  :
448 //=======================================================================
449 int VisuGUI_Plot3DPane::storeToPrsObject(VISU::Plot3D_i* thePrs)
450 {
451   if (myInitFromPrs)
452     return 0;
453   // orientation
454   int id = GBOrientation->id (GBOrientation->selected());
455   VISU::Plot3D::Orientation ori;
456   switch (id) {
457   case 0 : ori = VISU::Plot3D::XY; break;
458   case 1 : ori = VISU::Plot3D::YZ; break;
459   default: ori = VISU::Plot3D::ZX;
460   }
461   // rotation
462   thePrs->SetOrientation(ori, Rot1->value()*PI/180., Rot2->value()*PI/180.);
463
464   // position
465   thePrs->SetPlanePosition(PositionSpn->value(), RelativeChkB->isChecked());
466
467   // scale
468   thePrs->SetScaleFactor(ScaleSpn->value());
469
470   // prs type
471   id = GBPrsType->id (GBPrsType->selected());
472   thePrs->SetContourPrs(id == CONTOUR_PRS_ID);
473
474   // nb contours
475   thePrs->SetNbOfContours(NbContoursSpn->value());
476
477   return 1;
478 }
479
480 //=======================================================================
481 //function : check
482 //purpose  :
483 //=======================================================================
484 bool VisuGUI_Plot3DPane::check()
485 {
486   if (myPreviewActor && myViewWindow) // erase preview
487   {
488     myPreviewActor->SetVisibility(false);
489     myViewWindow->RemoveActor(myPreviewActor);
490     myPreviewActor->Delete();
491     myPreviewActor = 0;
492   }
493
494   return true;
495 }
496
497 //=======================================================================
498 //function : Constructor
499 //purpose  :
500 //=======================================================================
501 VisuGUI_Plot3DDlg::VisuGUI_Plot3DDlg(QWidget* parent)
502   : QDialog(parent, "VisuGUI_Plot3DDlg", false, WStyle_Customize |
503             WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu)
504 {
505   setCaption(tr("TITLE"));
506   setSizeGripEnabled(TRUE);
507
508   QVBoxLayout* TopLayout = new QVBoxLayout(this);
509   TopLayout->setSpacing(6);
510   TopLayout->setMargin(11);
511
512   QTabWidget* aTabBox = new QTabWidget (this);
513   myIsoPane = new VisuGUI_Plot3DPane (this);
514   myIsoPane->setMargin(5);
515   aTabBox->addTab(myIsoPane, tr("PLOT3D_TAB_TITLE"));
516   myScalarPane = new VisuGUI_ScalarBarPane (this, false);
517   myScalarPane->setMargin(5);
518   aTabBox->addTab(myScalarPane, tr("SCALAR_BAR_TAB_TITLE"));
519
520   TopLayout->addWidget(aTabBox);
521
522   QGroupBox* GroupButtons = new QGroupBox (this, "GroupButtons");
523   GroupButtons->setGeometry(QRect(10, 10, 281, 48));
524   GroupButtons->setColumnLayout(0, Qt::Vertical);
525   GroupButtons->layout()->setSpacing(0);
526   GroupButtons->layout()->setMargin(0);
527   QGridLayout* GroupButtonsLayout = new QGridLayout (GroupButtons->layout());
528   GroupButtonsLayout->setAlignment(Qt::AlignTop);
529   GroupButtonsLayout->setSpacing(6);
530   GroupButtonsLayout->setMargin(11);
531
532   QPushButton* buttonOk = new QPushButton (tr("&OK"), GroupButtons, "buttonOk");
533   buttonOk->setAutoDefault(TRUE);
534   buttonOk->setDefault(TRUE);
535   GroupButtonsLayout->addWidget(buttonOk, 0, 0);
536   GroupButtonsLayout->addItem(new QSpacerItem (5, 5, QSizePolicy::Expanding, QSizePolicy::Minimum), 0, 1);
537   QPushButton* buttonCancel = new QPushButton (tr("&Cancel") , GroupButtons, "buttonCancel");
538   buttonCancel->setAutoDefault(TRUE);
539   GroupButtonsLayout->addWidget(buttonCancel, 0, 2);
540
541   TopLayout->addWidget(GroupButtons);
542
543   // signals and slots connections
544   connect(buttonOk,     SIGNAL(clicked()), this, SLOT(accept()));
545   connect(buttonCancel, SIGNAL(clicked()), this, SLOT(reject()));
546 }
547
548 //=======================================================================
549 //function : accept
550 //purpose  :
551 //=======================================================================
552 void VisuGUI_Plot3DDlg::accept()
553 {
554 /*if (!VISU::CheckActiveStudyLock()) {
555     return;
556   }
557   if (myIsoPane->check() && myScalarPane->check()) {
558     if (!isModal()) {
559       VISU::Plot3D_i* prs = myIsoPane->GetPrs();
560       bool isCreation = !VISU::GetActor(prs, myViewWindow);
561       if (storeToPrsObject(prs)) {
562         if (isCreation) { // creation
563           if (myViewWindow) {
564             try {
565               VISU::CreateActor(prs);
566             }
567             catch (...) {
568               reject();
569               return;
570             }
571             myViewWindow->onFitAll();
572           }
573         } else { // edition
574           VISU::RecreateActor(prs);
575           renderViewFrame(myViewWindow);
576         }
577       } else {
578         if (isCreation) {
579           prs->RemoveFromStudy();
580           //study->updateObjBrowser();
581         }
582       }
583 }*/
584     QDialog::accept();
585 //}
586 }
587
588 //=======================================================================
589 //function : reject
590 //purpose  :
591 //=======================================================================
592 void VisuGUI_Plot3DDlg::reject()
593 {
594   myIsoPane->check(); // hide preview
595
596 /*if (!isModal() && myIsoPane->GetPrs() &&
597       !VISU::GetActor(myIsoPane->GetPrs(), myViewWindow)) {
598     _PTR(Study) aStudy = VISU::GetCStudy(VISU::GetAppStudy(myModule));
599     if (!aStudy->GetProperties()->IsLocked()) {
600       myIsoPane->GetPrs()->RemoveFromStudy();
601       myIsoPane->GetStudyFrame()->getStudy()->updateObjBrowser();
602     }
603 }*/
604   QDialog::reject();
605 }