Salome HOME
0bfea67d9c0eb11e5e54ec3fd7b5e32215de31e2
[modules/gui.git] / src / SVTK / SVTK_ViewParameterDlg.cxx
1 // Copyright (C) 2007-2021  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 //  SALOME VTKViewer : build VTK viewer into Salome desktop
21 //  File   : 
22 //  Author : 
23
24 #include "SVTK_ViewParameterDlg.h"
25 #include "SVTK_ViewWindow.h"
26 #include "SVTK_RenderWindowInteractor.h"
27 #include "SVTK_Event.h"
28 #include "SVTK_InteractorStyle.h"
29
30 #include "VTKViewer_Utilities.h"
31
32 #include "QtxAction.h"
33
34 #include <QLineEdit>
35 #include <QGroupBox>
36 #include <QLabel>
37 #include <QPushButton>
38 #include <QGridLayout>
39 #include <QDoubleValidator>
40 #include <QCheckBox>
41 #include <QRadioButton>
42 #include <QButtonGroup>
43
44 #include <vtkCallbackCommand.h>
45 #include <vtkRenderer.h>
46 #include <vtkCamera.h>
47 #include <vtkGenericRenderWindowInteractor.h>
48
49 /*!
50   Constructor
51 */
52 SVTK_ViewParameterDlg::SVTK_ViewParameterDlg(QtxAction* theAction,
53                                              SVTK_ViewWindow* theParent,
54                                              const char* theName):
55   ViewerTools_DialogBase(theAction, theParent, theName),
56   myMainWindow(theParent),
57   myRWInteractor(theParent->GetInteractor()),
58   myPriority(0.0),
59   myEventCallbackCommand(vtkCallbackCommand::New())
60 {
61   setWindowTitle(tr("DLG_TITLE"));
62   setSizeGripEnabled(true);
63
64   // Top layout
65   QVBoxLayout* aTopLayout = new QVBoxLayout(this);
66   aTopLayout->setSpacing(6);
67   aTopLayout->setMargin(11);
68
69   // Projection mode
70   QGroupBox* aGroupBoxMode = new QGroupBox(tr("PROJECTION_MODE"), this);
71   QHBoxLayout* aLayout1 = new QHBoxLayout(aGroupBoxMode);
72
73   QRadioButton* aOrtho = new QRadioButton(tr("ORTHOGONAL_MODE"), aGroupBoxMode);
74   QRadioButton* aPersp = new QRadioButton(tr("PERSPECTIVE_MODE"), aGroupBoxMode);
75
76   aLayout1->addWidget(aOrtho);
77   aLayout1->addWidget(aPersp);
78
79   myProjectionMode = new QButtonGroup(aGroupBoxMode);
80   myProjectionMode->addButton(aOrtho, 0);
81   myProjectionMode->addButton(aPersp, 1);
82   connect(myProjectionMode, SIGNAL(buttonClicked(int)), SLOT(onProjectionModeChanged(int)));
83
84   // Focal point
85   QGroupBox* aGroupBoxFocal = new QGroupBox(tr("FOCAL_POINT"), this);
86   QVBoxLayout* aLayout2 = new QVBoxLayout(aGroupBoxFocal);
87
88   myToBBCenter = new QPushButton(aGroupBoxFocal);
89   myToBBCenter->setText(tr("LBL_TOBBCENTER"));
90   aLayout2->addWidget(myToBBCenter);
91   connect(myToBBCenter, SIGNAL(clicked()), this, SLOT(onToBBCenter()));
92
93   myToOrigin = new QPushButton(aGroupBoxFocal);
94   myToOrigin->setText(tr("LBL_TOORIGIN"));
95   aLayout2->addWidget(myToOrigin);
96   connect(myToOrigin, SIGNAL(clicked()), this, SLOT(onToOrigin()));
97
98   mySelectPoint = new QPushButton(aGroupBoxFocal);
99   mySelectPoint->setText(tr("LBL_SELECTPOINT"));
100   mySelectPoint->setCheckable(true);
101   aLayout2->addWidget(mySelectPoint);
102   connect(mySelectPoint, SIGNAL(clicked()), this, SLOT(onSelectPoint()));
103
104   // Focal point coordinates
105   myFocalCoords = new QFrame(aGroupBoxFocal);
106   myFocalCoords->setObjectName("FocalPointCoordinates");
107
108   QHBoxLayout* aCoordLayout = new QHBoxLayout(myFocalCoords);
109   aCoordLayout->setSpacing(6);
110   aCoordLayout->setMargin(0);
111   
112   QLabel* aLabelX = new QLabel(tr("LBL_X"), myFocalCoords);
113   aLabelX->setFixedWidth(25);
114   myFocalX = new QLineEdit(myFocalCoords);
115   myFocalX->setValidator(new QDoubleValidator(myFocalX));
116   myFocalX->setText(QString::number(0.0));
117   connect(myFocalX, SIGNAL(textChanged(const QString&)), SLOT(onFocalCoordChanged()));
118   
119   QLabel* aLabelY = new QLabel(tr("LBL_Y"), myFocalCoords);
120   aLabelY->setFixedWidth(25);
121   myFocalY = new QLineEdit(myFocalCoords);
122   myFocalY->setValidator(new QDoubleValidator(myFocalY));
123   myFocalY->setText(QString::number(0.0));
124   connect(myFocalY, SIGNAL(textChanged(const QString&)), SLOT(onFocalCoordChanged()));
125
126   QLabel* aLabelZ = new QLabel(tr("LBL_Z"), myFocalCoords);
127   aLabelZ->setFixedWidth(25);
128   myFocalZ = new QLineEdit(myFocalCoords);
129   myFocalZ->setValidator(new QDoubleValidator(myFocalZ));
130   myFocalZ->setText(QString::number(0.0));
131   connect(myFocalZ, SIGNAL(textChanged(const QString&)), SLOT(onFocalCoordChanged()));
132
133   aCoordLayout->addWidget(aLabelX);
134   aCoordLayout->addWidget(myFocalX);
135   aCoordLayout->addWidget(aLabelY);
136   aCoordLayout->addWidget(myFocalY);
137   aCoordLayout->addWidget(aLabelZ);
138   aCoordLayout->addWidget(myFocalZ);
139   aLayout2->addWidget(myFocalCoords);
140
141   // Camera position
142   QGroupBox* aGroupBoxCamera = new QGroupBox(tr("CAMERA_POSITION"), this);
143   QVBoxLayout* aLayout3 = new QVBoxLayout(aGroupBoxCamera);
144
145   QRadioButton* aWorld = new QRadioButton(tr("WORLD_COORDINATES"), aGroupBoxCamera);
146   QRadioButton* aRelative = new QRadioButton(tr("FOCAL_RELATIVE"), aGroupBoxCamera);
147
148   QHBoxLayout* aHLayout = new QHBoxLayout;
149   aHLayout->addWidget(aWorld);
150   aHLayout->addWidget(aRelative);
151   aLayout3->addLayout(aHLayout);
152
153   myCameraPositionMode = new QButtonGroup(aGroupBoxCamera);
154   myCameraPositionMode->addButton(aWorld, 0);
155   myCameraPositionMode->addButton(aRelative, 1);
156   connect(myCameraPositionMode, SIGNAL(buttonClicked(int)), SLOT(onPositionModeChanged(int)));
157
158   // Camera coordinates
159   myCameraCoords = new QFrame(aGroupBoxCamera);
160   myCameraCoords->setObjectName("CameraCoordinates");
161
162   aCoordLayout = new QHBoxLayout(myCameraCoords);
163   aCoordLayout->setSpacing(6);
164   aCoordLayout->setMargin(0);
165
166   aLabelX = new QLabel(tr("LBL_X"), myCameraCoords);
167   aLabelX->setFixedWidth(25);
168   myCameraX = new QLineEdit(myCameraCoords);
169   myCameraX->setValidator(new QDoubleValidator(myCameraX));
170   myCameraX->setText(QString::number(0.0));
171   connect(myCameraX, SIGNAL(textChanged(const QString&)), SLOT(onCameraCoordChanged()));
172
173   aLabelY = new QLabel(tr("LBL_Y"), myCameraCoords);
174   aLabelY->setFixedWidth(25);
175   myCameraY = new QLineEdit(myCameraCoords);
176   myCameraY->setValidator(new QDoubleValidator(myCameraY));
177   myCameraY->setText(QString::number(0.0));
178   connect(myCameraY, SIGNAL(textChanged(const QString&)), SLOT(onCameraCoordChanged()));
179
180   aLabelZ = new QLabel(tr("LBL_Z"), myCameraCoords);
181   aLabelZ->setFixedWidth(25);
182   myCameraZ = new QLineEdit(myCameraCoords);
183   myCameraZ->setValidator(new QDoubleValidator(myCameraZ));
184   myCameraZ->setText(QString::number(1.0));
185   connect(myCameraZ, SIGNAL(textChanged(const QString&)), SLOT(onCameraCoordChanged()));
186
187   aCoordLayout->addWidget(aLabelX);
188   aCoordLayout->addWidget(myCameraX);
189   aCoordLayout->addWidget(aLabelY);
190   aCoordLayout->addWidget(myCameraY);
191   aCoordLayout->addWidget(aLabelZ);
192   aCoordLayout->addWidget(myCameraZ);
193   aLayout3->addWidget(myCameraCoords);
194
195   // Projection direction
196   QFrame* line1 = new QFrame(aGroupBoxCamera);
197   line1->setFrameStyle(QFrame::HLine | QFrame::Sunken);
198   aLayout3->addWidget(line1);
199
200   QLabel* aLabel = new QLabel(tr("PROJECTION_DIRECTION"), aGroupBoxCamera);
201   aLayout3->addWidget(aLabel);
202
203   myProjDirection = new QFrame(aGroupBoxCamera);
204   myProjDirection->setObjectName("ProjectionDirection");
205
206   aCoordLayout = new QHBoxLayout(myProjDirection);
207   aCoordLayout->setSpacing(6);
208   aCoordLayout->setMargin(0);
209
210   aLabelX = new QLabel(tr("LBL_DX"), myProjDirection);
211   aLabelX->setFixedWidth(25);
212   myProjDirX = new QLineEdit(myProjDirection);
213   myProjDirX->setValidator(new QDoubleValidator(myProjDirX));
214   myProjDirX->setText(QString::number(0.0));
215   connect(myProjDirX, SIGNAL(textChanged(const QString&)), SLOT(onDirectionChanged()));
216
217   aLabelY = new QLabel(tr("LBL_DY"), myProjDirection);
218   aLabelY->setFixedWidth(25);
219   myProjDirY = new QLineEdit(myProjDirection);
220   myProjDirY->setValidator(new QDoubleValidator(myProjDirY));
221   myProjDirY->setText(QString::number(0.0));
222   connect(myProjDirY, SIGNAL(textChanged(const QString&)), SLOT(onDirectionChanged()));
223
224   aLabelZ = new QLabel(tr("LBL_DZ"), myProjDirection);
225   aLabelZ->setFixedWidth(25);
226   myProjDirZ = new QLineEdit(myProjDirection);
227   myProjDirZ->setValidator(new QDoubleValidator(myProjDirZ));
228   myProjDirZ->setText(QString::number(-1.0));
229   connect(myProjDirZ, SIGNAL(textChanged(const QString&)), SLOT(onDirectionChanged()));
230
231   aCoordLayout->addWidget(aLabelX);
232   aCoordLayout->addWidget(myProjDirX);
233   aCoordLayout->addWidget(aLabelY);
234   aCoordLayout->addWidget(myProjDirY);
235   aCoordLayout->addWidget(aLabelZ);
236   aCoordLayout->addWidget(myProjDirZ);
237   aLayout3->addWidget(myProjDirection);
238
239   // Distance to focal point
240   QHBoxLayout* aHorLayout = new QHBoxLayout;
241   aHorLayout->setSpacing(6);
242
243   aLabel = new QLabel(tr("FOCAL_DISTANCE"), aGroupBoxCamera);
244   myDistance = new QLineEdit(aGroupBoxCamera);
245   QDoubleValidator* aVal = new QDoubleValidator(myDistance);
246   aVal->setBottom(0.0002); // VTK minimal distance
247   myDistance->setValidator(aVal);
248   myDistance->setText(QString::number(1.0));
249   connect(myDistance, SIGNAL(textChanged(const QString&)), SLOT(onDistanceChanged()));
250   
251   aHorLayout->addWidget(aLabel);
252   aHorLayout->addWidget(myDistance);
253   aLayout3->addLayout(aHorLayout);
254
255   // View Up direction
256   QFrame* line2 = new QFrame(aGroupBoxCamera);
257   line2->setFrameStyle(QFrame::HLine | QFrame::Sunken);
258   aLayout3->addWidget(line2);
259
260   aLabel = new QLabel(tr("VIEW_UP_DIRECTION"), aGroupBoxCamera);
261   aLayout3->addWidget(aLabel);
262
263   myViewDirection = new QFrame(aGroupBoxCamera);
264   myViewDirection->setObjectName("ViewUpDirection");
265   aLayout3->addWidget(myViewDirection);
266
267   aCoordLayout = new QHBoxLayout(myViewDirection);
268   aCoordLayout->setSpacing(6);
269   aCoordLayout->setMargin(0);
270
271   aLabelX = new QLabel(tr("LBL_DX"), myViewDirection);
272   aLabelX->setFixedWidth(25);
273   myViewDirX = new QLineEdit(myViewDirection);
274   myViewDirX->setValidator(new QDoubleValidator(myViewDirX));
275   myViewDirX->setText(QString::number(0.0));
276   connect(myViewDirX, SIGNAL(textChanged(const QString&)), SLOT(onViewDirectionChanged()));
277
278   aLabelY = new QLabel(tr("LBL_DY"), myViewDirection);
279   aLabelY->setFixedWidth(25);
280   myViewDirY = new QLineEdit(myViewDirection);
281   myViewDirY->setValidator(new QDoubleValidator(myViewDirY));
282   myViewDirY->setText(QString::number(1.0));
283   connect(myViewDirY, SIGNAL(textChanged(const QString&)), SLOT(onViewDirectionChanged()));
284
285   aLabelZ = new QLabel(tr("LBL_DZ"), myViewDirection);
286   aLabelZ->setFixedWidth(25);
287   myViewDirZ = new QLineEdit(myViewDirection);
288   myViewDirZ->setValidator(new QDoubleValidator(myViewDirZ));
289   myViewDirZ->setText(QString::number(0.0));
290   connect(myViewDirZ, SIGNAL(textChanged(const QString&)), SLOT(onViewDirectionChanged()));
291
292   aCoordLayout->addWidget(aLabelX);
293   aCoordLayout->addWidget(myViewDirX);
294   aCoordLayout->addWidget(aLabelY);
295   aCoordLayout->addWidget(myViewDirY);
296   aCoordLayout->addWidget(aLabelZ);
297   aCoordLayout->addWidget(myViewDirZ);
298
299   // Zooming
300   QGroupBox* aGroupBoxZoom = new QGroupBox(tr("ZOOMING"), this);
301   QVBoxLayout* aLayout4 = new QVBoxLayout(aGroupBoxZoom);
302
303   // Parallel scale
304   myScaleBox = new QFrame(aGroupBoxZoom);
305   myScaleBox->setObjectName("ScaleValue");
306
307   aHorLayout = new QHBoxLayout(myScaleBox);
308   aHorLayout->setSpacing(6);
309   aHorLayout->setMargin(0);
310
311   aLabel = new QLabel(tr("LBL_SCALE"), myScaleBox);
312   myScale = new QLineEdit(myScaleBox);
313   QDoubleValidator* aVal2 = new QDoubleValidator(myScale);
314   aVal2->setBottom(0.000001); // VTK minimal scale
315   myScale->setValidator(aVal2);
316   myScale->setText(QString::number(1.0));
317   connect(myScale, SIGNAL(textChanged(const QString&)), SLOT(onZoomChanged()));
318
319   aHorLayout->addWidget(aLabel);
320   aHorLayout->addWidget(myScale);
321   aLayout4->addWidget(myScaleBox);
322
323   // View Angle
324   myViewAngleBox = new QFrame(aGroupBoxZoom);
325   myViewAngleBox->setObjectName("ViewAngle");
326
327   aHorLayout = new QHBoxLayout(myViewAngleBox);
328   aHorLayout->setSpacing(6);
329   aHorLayout->setMargin(0);
330
331   aLabel = new QLabel(tr("LBL_VIEW_ANGLE"), myViewAngleBox);
332   myViewAngle = new QLineEdit(myViewAngleBox);
333   QDoubleValidator* aVal3 = new QDoubleValidator(myViewAngle);
334   aVal3->setBottom(0.000001); // VTK minimal scale
335   aVal3->setTop(179); // VTK minimal scale
336   myViewAngle->setValidator(aVal3);
337   myViewAngle->setText(QString::number(30.0));
338   connect(myViewAngle, SIGNAL(textChanged(const QString&)), SLOT(onZoomChanged()));
339
340   aHorLayout->addWidget(aLabel);
341   aHorLayout->addWidget(myViewAngle);
342   aLayout4->addWidget(myViewAngleBox);
343
344   // "Close" button
345   QGroupBox* aGroupBox = new QGroupBox(this);
346   QHBoxLayout* aHBoxLayout2 = new QHBoxLayout(aGroupBox);
347   aHBoxLayout2->setMargin(11);
348   aHBoxLayout2->setSpacing(6);
349
350   QPushButton* m_bClose = new QPushButton(tr("&Close"), aGroupBox );
351   m_bClose->setObjectName("m_bClose");
352   m_bClose->setAutoDefault(true);
353   m_bClose->setFixedSize(m_bClose->sizeHint());
354   connect(m_bClose, SIGNAL(clicked()), this, SLOT(onClickClose()));
355
356   // Layout buttons
357   aHBoxLayout2->addWidget(m_bClose);
358
359   // Layout top level widgets
360   aTopLayout->addWidget(aGroupBoxMode);
361   aTopLayout->addWidget(aGroupBoxFocal);
362   aTopLayout->addWidget(aGroupBoxCamera);
363   aTopLayout->addWidget(aGroupBoxZoom);
364   aTopLayout->addWidget(aGroupBox);
365   aTopLayout->addStretch();
366
367   // initial state
368   myProjectionMode->button(0)->setChecked(true);
369   myCameraPositionMode->button(0)->setChecked(true);
370
371   setEnabled(myCameraCoords, myCameraPositionMode->checkedId() == 0);
372
373   myScaleBox->setVisible(myProjectionMode->checkedId() == 0);
374   myViewAngleBox->setVisible(myProjectionMode->checkedId() == 1);
375
376   updateData();
377
378   this->resize(400, this->sizeHint().height());
379
380   myEventCallbackCommand->Delete();
381   myEventCallbackCommand->SetClientData(this);
382   myEventCallbackCommand->SetCallback(SVTK_ViewParameterDlg::ProcessEvents);
383   myIsObserverAdded = false;
384   myBusy = false;
385 }
386
387 /*
388  *  Destroys the object and frees any allocated resources
389  */
390 SVTK_ViewParameterDlg::~SVTK_ViewParameterDlg()
391 {
392   // no need to delete child widgets, Qt does it all for us
393 }
394
395 void SVTK_ViewParameterDlg::addObserver()
396 {
397   if ( !myIsObserverAdded ) {
398     vtkInteractorStyle* aIStyle = myRWInteractor->GetInteractorStyle();
399     aIStyle->AddObserver(SVTK::FocalPointChanged, myEventCallbackCommand.GetPointer(), myPriority);
400
401     vtkRenderer *aRenderer = myRWInteractor->getRenderer();
402     aRenderer->AddObserver(vtkCommand::EndEvent, myEventCallbackCommand.GetPointer(), myPriority);
403
404     myIsObserverAdded = true;
405   }
406 }
407
408 /*!
409   Processes events
410 */
411 void SVTK_ViewParameterDlg::ProcessEvents(vtkObject* vtkNotUsed(theObject), 
412                                           unsigned long theEvent,
413                                           void* theClientData, 
414                                           void* theCallData)
415 {
416   SVTK_ViewParameterDlg* self = reinterpret_cast<SVTK_ViewParameterDlg*>(theClientData);
417   double* aCoord;
418   switch ( theEvent ) {
419   case SVTK::FocalPointChanged:
420     if ( theCallData )
421     {
422       aCoord = (double*)theCallData;
423       self->myBusy = true;
424       self->myFocalX->setText( QString::number(aCoord[0]) );
425       self->myFocalY->setText( QString::number(aCoord[1]) );
426       self->myFocalZ->setText( QString::number(aCoord[2]) );
427       self->myBusy = false;
428       self->onFocalCoordChanged();
429     }
430     break;
431   case vtkCommand::EndEvent:
432     if ( self->myRWInteractor->getRenderer()->GetActiveCamera()->GetMTime() > self->myCameraMTime )
433       self->updateData();
434     break;
435   }
436 }
437
438 void SVTK_ViewParameterDlg::updateData()
439 {
440   myBusy = true;
441   vtkCamera* aCamera = myRWInteractor->getRenderer()->GetActiveCamera();
442
443   int aParallel = aCamera->GetParallelProjection();
444   myProjectionMode->button(aParallel?0:1)->setChecked(true);
445   onProjectionModeChanged( myProjectionMode->checkedId() );
446
447   double focal[3], pos[3], vup[3], proj[3], dist, scale, angle;
448
449   aCamera->GetFocalPoint(focal);
450   myFocalX->setText(QString::number(focal[0]));
451   myFocalY->setText(QString::number(focal[1]));
452   myFocalZ->setText(QString::number(focal[2]));
453
454   aCamera->GetPosition(pos);
455   myCameraX->setText(QString::number(pos[0]));
456   myCameraY->setText(QString::number(pos[1]));
457   myCameraZ->setText(QString::number(pos[2]));
458
459   aCamera->GetDirectionOfProjection(proj);
460   myProjDirX->setText(QString::number(proj[0]));
461   myProjDirY->setText(QString::number(proj[1]));
462   myProjDirZ->setText(QString::number(proj[2]));
463
464   aCamera->GetViewUp(vup);
465   myViewDirX->setText(QString::number(vup[0]));
466   myViewDirY->setText(QString::number(vup[1]));
467   myViewDirZ->setText(QString::number(vup[2]));
468
469   dist = aCamera->GetDistance();
470   myDistance->setText(QString::number(dist));
471
472   scale = aCamera->GetParallelScale();
473   myScale->setText(QString::number(scale));
474
475   angle = aCamera->GetViewAngle();
476   myViewAngle->setText(QString::number(angle));
477
478   myCameraMTime.Modified();
479   myBusy = false;
480 }
481
482 void SVTK_ViewParameterDlg::setEnabled(QFrame* theWidget, const bool theState)
483 {
484   QObjectList aChildren(theWidget->children());
485   QObject* anObj;
486   for(int i = 0; i < aChildren.size(); i++)
487   {
488     anObj = aChildren.at(i);
489     if (anObj !=0 && anObj->inherits("QLineEdit"))
490       ((QLineEdit*)anObj)->setReadOnly(!theState);
491     if (anObj !=0 && anObj->inherits("QPushButton"))
492       ((QLineEdit*)anObj)->setEnabled(theState);
493   }
494   
495 }
496
497 void SVTK_ViewParameterDlg::onProjectionModeChanged(int /*mode*/)
498 {
499   int aBtn = myProjectionMode->checkedId();
500
501   vtkCamera* aCamera = myRWInteractor->getRenderer()->GetActiveCamera();
502   aCamera->SetParallelProjection(aBtn == 0);
503   if (!myBusy)
504     myMainWindow->activateProjectionMode(!aBtn);
505
506   // update view
507   myRWInteractor->GetDevice()->CreateTimer(VTKI_TIMER_FIRST);
508
509   if ( aBtn == 0 ) {
510     myViewAngleBox->setVisible(false);
511     myScaleBox->setVisible(true);
512   }
513   else {
514     myScaleBox->setVisible(false);
515     myViewAngleBox->setVisible(true);
516   }
517 }
518
519 void SVTK_ViewParameterDlg::onPositionModeChanged(int /*mode*/)
520 {
521   setEnabled(myCameraCoords, myCameraPositionMode->checkedId() == 0);
522 }
523
524 void SVTK_ViewParameterDlg::onToBBCenter()
525 {
526   if ( mySelectPoint->isChecked() )
527     mySelectPoint->toggle();
528
529   myMainWindow->activateSetFocalPointGravity();
530 }
531
532 void SVTK_ViewParameterDlg::onToOrigin()
533 {
534   if ( mySelectPoint->isChecked() )
535     mySelectPoint->toggle();
536
537   myBusy = true;
538   myFocalX->setText(QString::number(0.0));
539   myFocalY->setText(QString::number(0.0));
540   myFocalZ->setText(QString::number(0.0));
541   myBusy = false;
542
543   onFocalCoordChanged();
544 }
545
546 void SVTK_ViewParameterDlg::onSelectPoint()
547 {
548   if ( mySelectPoint->isChecked() )
549     myMainWindow->activateStartFocalPointSelection();
550   else
551     mySelectPoint->toggle();
552 }
553
554 void SVTK_ViewParameterDlg::onFocalCoordChanged()
555 {
556   if ( myBusy ) return;
557
558   if ( mySelectPoint->isChecked() )
559     mySelectPoint->toggle();
560
561   vtkCamera* aCamera = myRWInteractor->getRenderer()->GetActiveCamera();
562   aCamera->SetFocalPoint(myFocalX->text().toDouble(),
563                          myFocalY->text().toDouble(),
564                          myFocalZ->text().toDouble());
565
566   aCamera->OrthogonalizeViewUp();
567   myRWInteractor->getRenderer()->ResetCameraClippingRange();
568
569   // update view
570   myRWInteractor->GetDevice()->CreateTimer(VTKI_TIMER_FIRST);
571
572   myMainWindow->activateSetFocalPointSelected();
573
574   //updateProjection();
575 }
576
577 void SVTK_ViewParameterDlg::onCameraCoordChanged()
578 {
579   if ( myBusy ) return;
580
581   vtkCamera* aCamera = myRWInteractor->getRenderer()->GetActiveCamera();
582   aCamera->SetPosition(myCameraX->text().toDouble(),
583                        myCameraY->text().toDouble(),
584                        myCameraZ->text().toDouble());
585
586   aCamera->OrthogonalizeViewUp();
587   myRWInteractor->getRenderer()->ResetCameraClippingRange();
588
589   // update view
590   myRWInteractor->GetDevice()->CreateTimer(VTKI_TIMER_FIRST);
591
592   //updateProjection();
593 }
594
595 void SVTK_ViewParameterDlg::onDirectionChanged()
596 {
597   if ( myBusy ) return;
598
599   updateCoordinates();
600 }
601
602 void SVTK_ViewParameterDlg::onDistanceChanged()
603 {
604   if ( myBusy ) return;
605
606   updateCoordinates();
607 }
608
609 void SVTK_ViewParameterDlg::onViewDirectionChanged()
610 {
611   if ( myBusy ) return;
612
613   vtkCamera* aCamera = myRWInteractor->getRenderer()->GetActiveCamera();
614   aCamera->SetViewUp(myViewDirX->text().toDouble(),
615                      myViewDirY->text().toDouble(),
616                      myViewDirZ->text().toDouble());
617
618   // update view
619   myRWInteractor->GetDevice()->CreateTimer(VTKI_TIMER_FIRST);
620 }
621
622 void SVTK_ViewParameterDlg::onZoomChanged()
623 {
624   if ( myBusy ) return;
625
626   vtkCamera* aCamera = myRWInteractor->getRenderer()->GetActiveCamera();
627
628   switch( myProjectionMode->checkedId() ) {
629   case 0:
630     aCamera->SetParallelScale(myScale->text().toDouble());
631     break;
632   case 1:
633     aCamera->SetViewAngle(myViewAngle->text().toDouble());
634     break;
635   }
636
637   // update view
638   myRWInteractor->GetDevice()->CreateTimer(VTKI_TIMER_FIRST);
639 }
640
641 void SVTK_ViewParameterDlg::onClickClose()
642 {
643   reject();
644 }
645
646 void SVTK_ViewParameterDlg::updateProjection()
647 {
648   double pnt[3], pos[3], dir[3], dist;
649
650   pnt[0] = myFocalX->text().toDouble();
651   pnt[1] = myFocalY->text().toDouble();
652   pnt[2] = myFocalZ->text().toDouble();
653
654   pos[0] = myCameraX->text().toDouble();
655   pos[1] = myCameraY->text().toDouble();
656   pos[2] = myCameraZ->text().toDouble();
657
658   dir[0] = pnt[0] - pos[0];
659   dir[1] = pnt[1] - pos[1];
660   dir[2] = pnt[2] - pos[2];
661
662   dist = sqrt( dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2] );
663
664   if ( dist > 0.0002 ) {
665     dir[0] = dir[0] / dist;
666     dir[1] = dir[1] / dist;
667     dir[2] = dir[2] / dist;
668   }
669
670   myBusy = true;
671   myProjDirX->setText(QString::number(dir[0]));
672   myProjDirY->setText(QString::number(dir[1]));
673   myProjDirZ->setText(QString::number(dir[2]));
674
675   myDistance->setText(QString::number(dist));
676   myBusy = false;
677 }
678
679 void SVTK_ViewParameterDlg::updateCoordinates()
680 {
681   double pnt[3], pos[3], dir[3], dist;
682
683   pnt[0] = myFocalX->text().toDouble();
684   pnt[1] = myFocalY->text().toDouble();
685   pnt[2] = myFocalZ->text().toDouble();
686
687   pos[0] = myCameraX->text().toDouble();
688   pos[1] = myCameraY->text().toDouble();
689   pos[2] = myCameraZ->text().toDouble();
690
691   dir[0] = myProjDirX->text().toDouble();
692   dir[1] = myProjDirY->text().toDouble();
693   dir[2] = myProjDirZ->text().toDouble();
694
695   dist = myDistance->text().toDouble();
696
697   if (myCameraPositionMode->checkedId() == 1) {
698     // recompute camera position
699     dir[0] = -dir[0]; dir[1] = -dir[1]; dir[2] = -dir[2];
700     if (computePoint(pnt, dir, dist, pos)) {
701       myBusy = true;
702       myCameraX->setText(QString::number(pos[0]));
703       myCameraY->setText(QString::number(pos[1]));
704       myCameraZ->setText(QString::number(pos[2]));
705       myBusy = false;
706       onCameraCoordChanged();
707     }
708   }
709   else {
710     // recompute focal point
711     if (computePoint(pos, dir, dist, pnt)) {
712       if (mySelectPoint->isChecked())
713         mySelectPoint->toggle();
714       myBusy = true;
715       myFocalX->setText(QString::number(pnt[0]));
716       myFocalY->setText(QString::number(pnt[1]));
717       myFocalZ->setText(QString::number(pnt[2]));
718       myBusy = false;
719       onFocalCoordChanged();
720     }
721   }
722 }
723
724 bool SVTK_ViewParameterDlg::computePoint(const double start[3], 
725                                          const double dir[3], 
726                                          const double dist, 
727                                          double result[3])
728 {
729   double d = sqrt(dir[0]*dir[0]+dir[1]*dir[1]+dir[2]*dir[2]);
730   if ( d < 0.0002 ) return false;
731
732   for (int i = 0; i < 3; i++)
733     result[i] = start[i] + dir[i] * dist / d;
734
735   return true;
736 }