Salome HOME
NRI : First integration.
[modules/visu.git] / src / VISUGUI / VisuGUI_NonIsometricDlg.cxx
1 using namespace std;
2 //  File      : SALOMEGUI_NonIsometricDlg.cxx
3 //  Created   : Thu Dec 18 12:01:00 2002
4 //  Author    : Vasily Rusyaev 
5 //  Project   : SALOME PRO
6 //  Module    : SALOMEGUI
7 //  Copyright : Open CASCADE 
8 //  $Header$ 
9
10 #include "VisuGUI_NonIsometricDlg.h"
11
12 #include <qgroupbox.h>
13 #include <qlabel.h>
14 #include <qpushbutton.h>
15 #include <qspinbox.h>
16 #include <qcombobox.h>
17 #include <qlayout.h>
18 #include <qlistbox.h>
19 //#include <qapplication.h>
20
21 #include "QAD_SpinBoxDbl.h"
22 #include "utilities.h"
23
24 #include "QAD_Application.h"
25 #include "QAD_Desktop.h"
26 #include "QAD_StudyFrame.h"
27 #include "QAD_RightFrame.h"
28 #include "VTKViewer_ViewFrame.h"
29 #include "VISU_Actor.h"
30
31 #include <vtkTransformPolyDataFilter.h>
32 #include <vtkDataSetMapper.h> 
33
34 /*!
35   Constructor
36 */
37 VisuGUI_NonIsometricDlg::VisuGUI_NonIsometricDlg( QWidget* parent, const char* name, bool modal, WFlags fl )
38     : QDialog( parent, name, modal, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu )
39 {
40
41   QAD_StudyFrame* sf = QAD_Application::getDesktop()->getActiveStudy()->getActiveStudyFrame();
42   VTKViewer_NonIsometricTransform *aTransform = NULL;
43   if ( sf->getTypeView() == VIEW_VTK ) 
44     {
45       VTKViewer_ViewFrame* vf =  (VTKViewer_ViewFrame*) ( sf->getRightFrame()->getViewFrame() );
46       aTransform = vf->getNonIsometricTransform();
47     }
48
49     if ( !name )
50         setName( "NonIsometricDlg" );
51     setCaption( tr( "Scaling" ) );
52     setSizeGripEnabled( TRUE );
53
54     // Create layout for this dialog
55     QGridLayout* layoutDlg = new QGridLayout( this );
56     layoutDlg->setSpacing(6);
57     layoutDlg->setMargin(11);
58
59     // Create croup box with grid layout
60     QGroupBox* GroupBox = new QGroupBox( this, "GroupBox" );
61
62     QGridLayout* glGroupBox = new QGridLayout( GroupBox );
63     glGroupBox->setMargin(11);
64     glGroupBox->setSpacing(6);
65
66     //Create font: 14pnts, bold, italic
67     //It will be used for all labels in this group box
68     QFont m_font14bi = font();
69     m_font14bi.setPointSize((int)(m_font14bi.pointSize()*1.4));
70 //    m_font14bi.setItalic( TRUE );
71     m_font14bi.setBold( TRUE );
72
73     // Create "Choose function" label
74     QLabel* TextLabel1 = new QLabel( tr( "Choose function:" ), GroupBox, "TextLabel1" );
75     glGroupBox->addWidget ( TextLabel1, 1, 0 );
76
77     // Create "Type the coefficient" label
78     QLabel* TextLabel2 = new QLabel( tr( "Coefficient:" ), GroupBox, "TextLabel2" );
79     glGroupBox->addWidget ( TextLabel2, 2, 0 );
80
81     // Create "Applying function" label
82     QLabel* TextLabel3 = new QLabel( tr( "Applying function:" ), GroupBox, "TextLabel3" );
83     glGroupBox->addWidget ( TextLabel3, 3, 0 );
84
85     glGroupBox->addColSpacing ( 1, 10 );
86
87     // Create "X" label
88     QLabel* TextLabelX = new QLabel( "X", GroupBox, "TextLabelX" );
89     TextLabelX->setAlignment( int( QLabel::AlignCenter ) );
90     //NRI    TextLabelX->setFont( m_font14bi );
91     glGroupBox->addWidget ( TextLabelX, 0, 2 );
92
93     // Create combobox for selecting scaling function on a X axis
94     m_cbXfunction = new QComboBox( FALSE, GroupBox, "m_cbXFunction");
95     m_cbXfunction->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed));
96     m_cbXfunction->setMinimumWidth( 80 );
97     glGroupBox->addWidget(m_cbXfunction, 1, 2 );
98
99     // Create double spinbox for changing coef. in the scaling function on a X axis
100     m_sbXcoeff = new QAD_SpinBoxDbl( GroupBox, "m_sbXcoeff" );
101     m_sbXcoeff->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed));
102     m_sbXcoeff->setMinimumWidth( 80 );
103     glGroupBox->addWidget(m_sbXcoeff, 2, 2 );
104
105     // Create informative label about the applying scaling function on a X axis
106     m_lXFunction = new QLabel( GroupBox, "m_lXFunction" );
107     //NRI    m_lXFunction->setFont( m_font14bi ); 
108     m_lXFunction->setAlignment( int( QLabel::AlignCenter ) );
109     glGroupBox->addWidget(m_lXFunction, 3, 2 );
110
111     FillComboBox( m_cbXfunction );
112
113     // Create "Y" label
114     QLabel* TextLabelY = new QLabel( "Y", GroupBox, "TextLabelY" );
115     TextLabelY->setAlignment( int( QLabel::AlignCenter ) );
116     //NRI    TextLabelY->setFont( m_font14bi ); 
117     glGroupBox->addWidget ( TextLabelY, 0, 3 );
118
119     // Create combobox for selecting scaling function on a Y axis
120     m_cbYfunction = new QComboBox( FALSE, GroupBox, "m_cbYFunction");
121     m_cbYfunction->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed));
122     m_cbYfunction->setMinimumWidth( 80 );
123     glGroupBox->addWidget(m_cbYfunction, 1, 3 );
124
125     // Create double spinbox for changing coef. in the scaling function on a Y axis
126     m_sbYcoeff = new QAD_SpinBoxDbl( GroupBox, "m_sbYcoeff" );
127     m_sbYcoeff->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed));
128     m_sbYcoeff->setMinimumWidth( 80 );
129     glGroupBox->addWidget(m_sbYcoeff, 2, 3 );
130
131     // Create informative label about the applying scaling function on a Y axis
132     m_lYFunction = new QLabel( GroupBox, "m_lYFunction" );
133     m_lYFunction->setAlignment( int( QLabel::AlignCenter ) );
134     //NRI    m_lYFunction->setFont( m_font14bi ); 
135     glGroupBox->addWidget(m_lYFunction, 3, 3 );
136
137     FillComboBox( m_cbYfunction );
138
139     // Create "Z" label
140     QLabel* TextLabelZ = new QLabel( "Z", GroupBox, "TextLabelZ" );
141     TextLabelZ->setAlignment( int( QLabel::AlignCenter ) );
142     //NRI    TextLabelZ->setFont( m_font14bi ); 
143     glGroupBox->addWidget ( TextLabelZ, 0, 4 );
144
145     // Create combobox for selecting scaling function on a Z axis
146     m_cbZfunction = new QComboBox( FALSE, GroupBox, "m_cbZFunction");
147     m_cbZfunction->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed));
148     m_cbZfunction->setMinimumWidth( 80 );
149     glGroupBox->addWidget(m_cbZfunction, 1, 4 );
150
151     // Create double spinbox for changing coef. in the scaling function on a Z axis
152     m_sbZcoeff = new QAD_SpinBoxDbl( GroupBox, "m_sbZcoeff" );
153     m_sbZcoeff->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed));
154     m_sbZcoeff->setMinimumWidth( 80 );
155     glGroupBox->addWidget(m_sbZcoeff, 2, 4 );
156
157     // Create informative label about the applying scaling function on a Z axis
158     m_lZFunction = new QLabel( GroupBox, "m_lZFunction" );
159     m_lZFunction->setAlignment( int( QLabel::AlignCenter ) );
160     //NRI    m_lZFunction->setFont( m_font14bi ); 
161     glGroupBox->addWidget(m_lZFunction, 3, 4 );
162
163     FillComboBox( m_cbZfunction );
164
165     if ( aTransform ) {
166       int item = aTransform->GetFunctionType(AxisFunction::XAxis);
167       m_cbXfunction->setCurrentItem(item);
168       if (item) { 
169         m_sbXcoeff ->setEnabled (TRUE);
170          FunctionChanged( m_cbXfunction);
171       }
172       item = aTransform->GetFunctionType(AxisFunction::YAxis);
173       m_cbYfunction->setCurrentItem(item);
174       if (item) {
175         m_sbYcoeff ->setEnabled (TRUE);
176         FunctionChanged( m_cbYfunction );
177       }
178       item = aTransform->GetFunctionType(AxisFunction::ZAxis);
179       m_cbZfunction->setCurrentItem(item);
180       if (item) {
181         m_sbZcoeff ->setEnabled (TRUE);
182         FunctionChanged( m_cbZfunction);
183       }
184       m_sbXcoeff -> setValue(aTransform->GetCoeff(AxisFunction::XAxis));
185       m_sbYcoeff -> setValue(aTransform->GetCoeff(AxisFunction::YAxis));
186       m_sbZcoeff -> setValue(aTransform->GetCoeff(AxisFunction::ZAxis));
187     }
188
189     // Create <Reset> button
190     QPushButton* m_bReset = new QPushButton( tr( "&Reset" ), GroupBox, "m_bReset" );
191     glGroupBox->addWidget( m_bReset, 4, 4 );
192
193     layoutDlg->addWidget(GroupBox,0,0);
194
195     // OK, CANCEL, Apply button
196     QGroupBox* aWgt = new QGroupBox( this );
197     QHBoxLayout* aHBoxLayout = new QHBoxLayout( aWgt );
198     aHBoxLayout->setMargin(11);
199     aHBoxLayout->setSpacing(6);
200
201     // Create <OK> button
202     QPushButton* m_bOk = new QPushButton( tr( "O&K" ), aWgt, "m_bOk" );
203     m_bOk->setDefault( TRUE );
204     m_bOk->setAutoDefault( TRUE );
205     aHBoxLayout->addWidget( m_bOk );
206     aHBoxLayout->addStretch();
207     
208     // Create <Apply> button
209     QPushButton* m_bApply = new QPushButton( tr( "&Apply" ), aWgt, "m_bApply" );
210     m_bApply->setAutoDefault( TRUE );
211     aHBoxLayout->addWidget( m_bApply );
212     aHBoxLayout->addStretch();
213
214     // Create <Cancel> button
215     QPushButton* m_bCancel = new QPushButton( tr( "&Cancel" ), aWgt, "m_bCancel" );
216     m_bCancel->setAutoDefault( TRUE );
217     aHBoxLayout->addWidget( m_bCancel );
218
219     layoutDlg->addWidget(aWgt,1,0);
220
221     // signals and slots connections
222     connect( m_bCancel, SIGNAL( clicked() ), this, SLOT( reject() ) );
223     connect( m_bOk, SIGNAL( clicked() ), this, SLOT( onClickOk( ) ) );
224     connect( m_bApply, SIGNAL( clicked() ), this, SLOT( onClickApply( ) ) );
225     connect( m_bReset, SIGNAL( clicked() ), this, SLOT( onClickReset( ) ) );
226 }
227
228 /*  
229  *  Destroys the object and frees any allocated resources
230  */
231 VisuGUI_NonIsometricDlg::~VisuGUI_NonIsometricDlg()
232 {
233     // no need to delete child widgets, Qt does it all for us
234 }
235
236 void VisuGUI_NonIsometricDlg::onClickOk()
237 {
238   //apply changes
239   onClickApply();
240   //Close dialog
241   accept();
242 }
243
244 void VisuGUI_NonIsometricDlg::onClickApply()
245 {
246   bool changed = false;
247   QAD_StudyFrame* sf = QAD_Application::getDesktop()->getActiveStudy()->getActiveStudyFrame();
248   if ( sf->getTypeView() == VIEW_VTK )
249     {
250       int Xfunction = m_cbXfunction->currentItem();
251       int Yfunction = m_cbYfunction->currentItem();
252       int Zfunction = m_cbZfunction->currentItem();
253
254       
255       VTKViewer_ViewFrame* vf =  (VTKViewer_ViewFrame*) ( sf->getRightFrame()->getViewFrame() );
256       VTKViewer_NonIsometricTransform *aTransform = vf->getNonIsometricTransform();
257       
258       vtkRenderer* Renderer = vf->getRenderer();
259       vtkActorCollection* theActors = Renderer->GetActors();
260       theActors->InitTraversal();
261       vtkActor *actor = theActors->GetNextActor();
262
263       aTransform->SetFunction( AxisFunction::XAxis,
264                                (VTKViewer_NonIsometricTransform::Function) Xfunction,
265                                m_sbXcoeff->value() ); 
266
267       aTransform->SetFunction( AxisFunction::YAxis,
268                                (VTKViewer_NonIsometricTransform::Function) Yfunction,
269                                m_sbYcoeff->value() ); 
270
271       aTransform->SetFunction( AxisFunction::ZAxis,
272                                (VTKViewer_NonIsometricTransform::Function) Zfunction,
273                                m_sbZcoeff->value() ); 
274
275       while( actor )
276         {
277           //SALOME_Actor* pSA = dynamic_cast<SALOME_Actor*> (actor);
278           SALOME_Actor* pSA = dynamic_cast<VISU_Actor*> (actor);
279           if (pSA)
280             {
281               //MESSAGE (actor->GetMapper()->GetClassName ())
282               vtkPolyDataMapper* mapper = NULL;
283               vtkMapper* initialMapper = pSA->GetInitialMapper();
284               if ( initialMapper == NULL )
285                 initialMapper =   actor->GetMapper();
286               if ( initialMapper->IsA("vtkDataSetMapper") )
287                 mapper = vtkDataSetMapper::SafeDownCast( initialMapper )->GetPolyDataMapper ();
288               else
289                 mapper = vtkPolyDataMapper::SafeDownCast( initialMapper );
290               //MESSAGE (mapper->GetClassName ())
291
292               if (mapper)
293                 {
294                   //create transformation
295
296                   //create Filter
297                   vtkTransformPolyDataFilter *aTransformFilter = vtkTransformPolyDataFilter::New();
298                   aTransformFilter->SetInput ( mapper->GetInput() );
299                   aTransformFilter->SetTransform (aTransform);
300
301                   //create new mapper
302                   vtkDataSetMapper *aMapper = vtkDataSetMapper::New();
303                   aMapper->SetInput (aTransformFilter->GetOutput());
304                   aMapper->ShallowCopy ( actor->GetMapper());
305
306                   //set new mapper
307                   actor->SetMapper (aMapper);
308                   
309                   aTransformFilter->Delete();
310                   aMapper->Delete();
311                   changed = true;
312                 }
313             }
314           actor = theActors->GetNextActor();
315         }
316       if (changed)
317         vf->Repaint();
318       //in order to improve perfomance
319       if ( !Xfunction && !Yfunction && !Zfunction )
320         vf->setNonIsometricTransform( NULL );
321     }
322 }
323
324 void VisuGUI_NonIsometricDlg::onClickReset()
325 {
326   //it's workaround for QComboBox - it doesn't send activated signal using setCurrentItem function
327   //therefore we connect on highlighted signal, use setCurrentItem() and disconnect highlighted signal
328
329   connect (m_cbXfunction, SIGNAL( highlighted ( const QString& ) ), this, SLOT( onFunctionChanged ( ) ) );
330
331   m_cbXfunction->setCurrentItem ( 0 );
332   m_cbXfunction->disconnect( SIGNAL( highlighted ( const QString& ) ) );
333
334   connect (m_cbYfunction, SIGNAL( highlighted ( const QString& ) ), this, SLOT( onFunctionChanged ( ) ) );
335   m_cbYfunction->setCurrentItem ( 0 );
336   m_cbYfunction->disconnect( SIGNAL( highlighted ( const QString& ) ) );
337
338   connect (m_cbZfunction, SIGNAL( highlighted ( const QString& ) ), this, SLOT( onFunctionChanged ( ) ) );
339   m_cbZfunction->setCurrentItem ( 0 );
340   m_cbZfunction->disconnect( SIGNAL( highlighted ( const QString& ) ) );
341 }
342
343 //Populates combobox and makes all needed connects
344 void VisuGUI_NonIsometricDlg::FillComboBox(QComboBox* cb)
345 {
346   cb->insertItem( tr ("None") ); 
347   cb->insertItem ( tr ("Linear") ); 
348 //  cb->insertItem ( tr ("Logarithmic") );
349
350   
351   connect (cb, SIGNAL( activated ( const QString& ) ), this, SLOT( onFunctionChanged ( ) ) );
352
353   //it's workaround for QComboBox - it doesn't send activated signal using setCurrentItem function
354   //therefore we connect on highlighted signal, use setCurrentItem() and disconnect highlighted signal
355   cb->setCurrentItem ( 1 );
356   connect (cb, SIGNAL( highlighted ( const QString& ) ), this, SLOT( onFunctionChanged ( ) ) );
357   cb->setCurrentItem ( 0 );
358   cb->disconnect( SIGNAL( highlighted ( const QString& ) ) );
359
360 }
361
362 void VisuGUI_NonIsometricDlg::onFunctionChanged()
363 {
364   //TODO
365   const QComboBox* cbFunction = (const QComboBox* ) sender();
366   FunctionChanged(cbFunction);
367 }
368
369 void VisuGUI_NonIsometricDlg::FunctionChanged(const QComboBox* cbFunction )
370 {
371   //TODO
372   const QString & function = cbFunction-> currentText();
373   QAD_SpinBoxDbl* sbCoeff;
374   QLabel* lFunction;
375   QString axis;
376   QString formula;
377   //this variable stores index in bounds array for vtkRenderer
378   // 0 - xmin, xmax
379   // 2 - ymin, ymax
380   // 4 - zmin, zmax
381   int boundIndex;
382
383   if (cbFunction == m_cbXfunction)
384     {
385       sbCoeff = m_sbXcoeff;
386       lFunction = m_lXFunction;
387       axis = "x";
388       boundIndex = 0;
389     }
390   else
391     if (cbFunction == m_cbYfunction)
392       {
393         sbCoeff = m_sbYcoeff;
394         lFunction = m_lYFunction;
395         axis = "y";
396         boundIndex = 2;
397       }
398   else  
399     if (cbFunction == m_cbZfunction)
400       {
401         sbCoeff = m_sbZcoeff;
402         lFunction = m_lZFunction;
403         axis = "z";
404         boundIndex = 4;
405       }
406   else
407     return ;
408
409   sbCoeff->setEnabled (TRUE);
410   formula = axis;
411
412   if ( function == tr ("None") )
413     {
414       sbCoeff->setMinValue( 1.0 );
415       sbCoeff->setMaxValue( 1.0 );
416       sbCoeff->setValue( 1.0 );
417       sbCoeff->setEnabled ( FALSE );
418       formula += QString(" = ");
419       formula += axis;
420       lFunction->setText( formula );
421     }
422   else
423     if ( function == tr ("Linear") )
424       {
425         sbCoeff->setMinValue( -1.7E308 );
426         sbCoeff->setMaxValue( 1.7E+308 );
427         //      sbCoeff->setValue( 1.0 );
428         formula += QString(" = k");
429         formula += axis;
430         lFunction->setText( formula );
431       }
432   else
433     if ( function == tr ("Logarithmic") )
434       {
435         // TODO
436         QAD_StudyFrame* sf = QAD_Application::getDesktop()->getActiveStudy()->getActiveStudyFrame();
437         if ( sf->getTypeView() == VIEW_VTK )
438           {
439             vtkRenderer* Renderer = ((VTKViewer_ViewFrame*)sf->getRightFrame()->getViewFrame())->getRenderer();
440             float bounds[6];
441             Renderer->ComputeVisiblePropBounds (bounds);
442             //we use following formula lg (x+a) and x+a >= 1
443             //therefore a >= 1-x
444             double minValue;
445             if ( bounds[boundIndex] > 0 && bounds[boundIndex+1] > 0 )
446               minValue = 1 - bounds[boundIndex+1];
447             else
448               minValue = 1 - bounds[boundIndex];
449             MESSAGE ( "Bounds " << bounds[0] << " " << bounds[1] << " " << bounds[2] << " " << bounds[3] << " " << bounds[4] << " " << bounds[5] << " " )
450             sbCoeff->setMinValue( minValue );
451             sbCoeff->setMaxValue( 1.7E+308 );
452             sbCoeff->setValue( minValue );
453             formula += QString(" = lg(");
454             formula += axis;
455             formula += QString("+a), a >= %1").arg( minValue );
456           }
457         else
458           {
459             sbCoeff->setEnabled (FALSE);
460             formula = "";
461           }
462         lFunction->setText( formula );
463       }
464 }