Salome HOME
f49b3ebd1921ecf54ed5c7a2c27687275c6404a6
[modules/gui.git] / src / SVTK / SVTK_ViewModel.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  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 #include <QMenu>
23 #include <QColorDialog>
24 #include <QToolBar>
25
26 #include <vtkCamera.h>
27 #include <vtkRenderer.h>
28 #include <vtkActorCollection.h>
29
30 //#include "SUIT_Session.h"
31 #include "SVTK_Selection.h"
32 #include "SVTK_ViewModel.h"
33 #include "SVTK_ViewWindow.h"
34 #include "SVTK_View.h"
35 //#include "SVTK_MainWindow.h"
36 #include "SVTK_Prs.h"
37
38 #include "VTKViewer_ViewModel.h"
39
40 #include "SUIT_ViewModel.h"
41 #include "SUIT_ViewManager.h"
42
43 #include "SALOME_Actor.h"
44
45 #include <QtxActionToolMgr.h>
46
47 // in order NOT TO link with SalomeApp, here the code returns SALOMEDS_Study.
48 // SalomeApp_Study::studyDS() does it as well, but -- here it is retrieved from 
49 // SALOMEDS::StudyManager - no linkage with SalomeApp. 
50
51 // Temporarily commented to avoid awful dependecy on SALOMEDS
52 // TODO: better mechanism of storing display/erse status in a study
53 // should be provided...
54 //static _PTR(Study) getStudyDS() 
55 //{
56 //  SALOMEDSClient_Study* aStudy = NULL;
57 //  _PTR(StudyManager) aMgr( new SALOMEDS_StudyManager() );
58   // get id of SUIT_Study, if it's a SalomeApp_Study, it will return
59   //    id of its underlying SALOMEDS::Study
60 //  SUIT_Application* app = SUIT_Session::session()->activeApplication();
61 //  if ( !app )  return _PTR(Study)(aStudy); 
62 //  SUIT_Study* stud = app->activeStudy();
63 //  if ( !stud ) return _PTR(Study)(aStudy);  
64 //  const int id = stud->id(); // virtual method, must return SALOMEDS_Study id
65   // get SALOMEDS_Study with this id from StudyMgr
66 //  return aMgr->GetStudyByID( id );
67 //}
68
69 /*!
70   Constructor
71 */
72 SVTK_Viewer::SVTK_Viewer()
73 {
74   myTrihedronSize = 105;
75   myTrihedronRelative = true;
76   myIncrementSpeed = 10;
77   myIncrementMode = 0;
78   myProjMode = 0;
79   myStyle = 0;
80   mySpaceBtn[0] = 1;
81   mySpaceBtn[1] = 2;
82   mySpaceBtn[2] = 9;
83 }
84
85 /*!
86   Destructor
87 */
88 SVTK_Viewer::~SVTK_Viewer() 
89 {
90 }
91
92 /*!
93   \return background color
94 */
95 QColor SVTK_Viewer::backgroundColor() const
96 {
97   return myBgColor;
98 }
99
100 /*!
101   Changes background color
102   \param theColor - new background color
103 */
104 void SVTK_Viewer::setBackgroundColor( const QColor& theColor )
105 {
106   if ( !theColor.isValid() )
107     return;
108
109   QVector<SUIT_ViewWindow*> aViews = myViewManager->getViews();
110   for(int i = 0, iEnd = aViews.size(); i < iEnd; i++){
111     if(SUIT_ViewWindow* aViewWindow = aViews.at(i)){
112       if(TViewWindow* aView = dynamic_cast<TViewWindow*>(aViewWindow)){
113         aView->setBackgroundColor(theColor);
114       }
115     }
116   }
117
118   myBgColor = theColor;
119 }
120
121 /*!Create new instance of view window on desktop \a theDesktop.
122  *\retval SUIT_ViewWindow* - created view window pointer.
123  */
124 SUIT_ViewWindow* SVTK_Viewer::createView( SUIT_Desktop* theDesktop )
125 {
126   TViewWindow* aViewWindow = new TViewWindow(theDesktop);
127   aViewWindow->Initialize(this);
128
129   aViewWindow->setBackgroundColor( backgroundColor() );
130   aViewWindow->SetTrihedronSize( trihedronSize(), trihedronRelative() );
131   aViewWindow->SetProjectionMode( projectionMode() );
132   aViewWindow->SetInteractionStyle( interactionStyle() );
133   aViewWindow->SetIncrementalSpeed( incrementalSpeed(), incrementalSpeedMode() );
134   aViewWindow->SetSpacemouseButtons( spacemouseBtn(1), spacemouseBtn(2), spacemouseBtn(3) );
135
136   connect(aViewWindow, SIGNAL( actorAdded(VTKViewer_Actor*) ), 
137           this,  SLOT(onActorAdded(VTKViewer_Actor*)));
138   connect(aViewWindow, SIGNAL( actorRemoved(VTKViewer_Actor*) ), 
139           this,  SLOT(onActorRemoved(VTKViewer_Actor*)));
140
141   return aViewWindow;
142 }
143
144 /*!
145   \return trihedron size
146 */
147 vtkFloatingPointType SVTK_Viewer::trihedronSize() const
148 {
149   return myTrihedronSize;
150 }
151
152 /*!
153   \return true if thihedron changes size in accordance with bounding box
154 */
155 bool SVTK_Viewer::trihedronRelative() const
156 {
157   return myTrihedronRelative;
158 }
159
160 /*!
161   Sets trihedron size and relativeness( whether thihedron changes size in accordance with bounding box)
162   \param theSize - new size
163   \param theRelative - new relativeness
164 */
165 void SVTK_Viewer::setTrihedronSize( const vtkFloatingPointType theSize, const bool theRelative )
166 {
167   myTrihedronSize = theSize;
168   myTrihedronRelative = theRelative;
169
170   if (SUIT_ViewManager* aViewManager = getViewManager()) {
171     QVector<SUIT_ViewWindow*> aViews = aViewManager->getViews();
172     for ( uint i = 0; i < aViews.count(); i++ )
173     {
174       if ( TViewWindow* aView = dynamic_cast<TViewWindow*>(aViews.at( i )) )
175               aView->SetTrihedronSize( theSize, theRelative );
176     }
177   }
178 }
179
180
181 /*!
182   \return projection mode
183 */
184 int SVTK_Viewer::projectionMode() const
185 {
186   return myProjMode;
187 }
188
189
190 /*!
191   Sets projection mode: 0 - orthogonal, 1 - perspective projection
192   \param theMode - new projection mode
193 */
194 void SVTK_Viewer::setProjectionMode( const int theMode )
195 {
196   if ( myProjMode != theMode ) {
197     myProjMode = theMode;
198
199     if (SUIT_ViewManager* aViewManager = getViewManager()) {
200       QVector<SUIT_ViewWindow*> aViews = aViewManager->getViews();
201       for ( uint i = 0; i < aViews.count(); i++ )
202       {
203         if ( TViewWindow* aView = dynamic_cast<TViewWindow*>(aViews.at( i )) )
204           aView->SetProjectionMode( theMode );
205       }
206     }
207   }
208 }
209
210 /*!
211   \return interaction style
212 */
213 int SVTK_Viewer::interactionStyle() const
214 {
215   return myStyle;
216 }
217
218 /*!
219   Sets interaction style: 0 - standard, 1 - keyboard free interaction
220   \param theStyle - new interaction style
221 */
222 void SVTK_Viewer::setInteractionStyle( const int theStyle )
223 {
224   myStyle = theStyle;
225   
226   if (SUIT_ViewManager* aViewManager = getViewManager()) {
227     QVector<SUIT_ViewWindow*> aViews = aViewManager->getViews();
228     for ( uint i = 0; i < aViews.count(); i++ )
229     {
230       if ( TViewWindow* aView = dynamic_cast<TViewWindow*>(aViews.at( i )) )
231         aView->SetInteractionStyle( theStyle );
232     }
233   }
234 }
235
236 /*!
237   \return incremental speed value
238 */
239 int SVTK_Viewer::incrementalSpeed() const
240 {
241   return myIncrementSpeed;
242 }
243
244 /*!
245   \return modification mode of the incremental speed 
246 */
247 int SVTK_Viewer::incrementalSpeedMode() const
248 {
249   return myIncrementMode;
250 }
251
252 /*!
253   Set the incremental speed value and modification mode
254   \param theValue - new value
255   \param theMode - new mode: 0 - arithmetic, 1 - geometrical progression
256 */
257 void SVTK_Viewer::setIncrementalSpeed( const int theValue, const int theMode )
258 {
259   myIncrementSpeed = theValue;
260   myIncrementMode = theMode;
261
262   if (SUIT_ViewManager* aViewManager = getViewManager()) {
263     QVector<SUIT_ViewWindow*> aViews = aViewManager->getViews();
264     for ( uint i = 0; i < aViews.count(); i++ )
265     {
266       if ( TViewWindow* aView = dynamic_cast<TViewWindow*>(aViews.at( i )) )
267         aView->SetIncrementalSpeed( theValue, theMode );
268     }
269   }
270 }
271
272 /*!
273   \return spacemouse button assigned to the specified function
274   \param theIndex - function by number (from 1 to 3)
275 */
276 int SVTK_Viewer::spacemouseBtn( const int theIndex ) const
277 {
278   if ( theIndex < 1 || theIndex > 3 ) 
279     return -1;
280   return mySpaceBtn[theIndex-1];
281 }
282
283 /*!
284   Set the spacemouse buttons
285   \param theBtn1, theBtn2, theBtn3 - new buttons
286 */
287 void SVTK_Viewer::setSpacemouseButtons( const int theBtn1, const int theBtn2, const int theBtn3 )
288 {
289   mySpaceBtn[0] = theBtn1;
290   mySpaceBtn[1] = theBtn2;
291   mySpaceBtn[2] = theBtn3;
292
293   if (SUIT_ViewManager* aViewManager = getViewManager()) {
294     QVector<SUIT_ViewWindow*> aViews = aViewManager->getViews();
295     for ( uint i = 0; i < aViews.count(); i++ )
296     {
297       if ( TViewWindow* aView = dynamic_cast<TViewWindow*>(aViews.at( i )) )
298         aView->SetSpacemouseButtons( theBtn1, theBtn2, theBtn3 );
299     }
300   }
301 }
302
303 /*!
304   Sets new view manager
305   \param theViewManager - new view manager
306 */
307 void SVTK_Viewer::setViewManager(SUIT_ViewManager* theViewManager)
308 {
309   SUIT_ViewModel::setViewManager(theViewManager);
310
311   if ( !theViewManager )
312     return;
313
314   connect(theViewManager, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)), 
315           this, SLOT(onMousePress(SUIT_ViewWindow*, QMouseEvent*)));
316   
317   connect(theViewManager, SIGNAL(mouseMove(SUIT_ViewWindow*, QMouseEvent*)), 
318           this, SLOT(onMouseMove(SUIT_ViewWindow*, QMouseEvent*)));
319   
320   connect(theViewManager, SIGNAL(mouseRelease(SUIT_ViewWindow*, QMouseEvent*)), 
321           this, SLOT(onMouseRelease(SUIT_ViewWindow*, QMouseEvent*)));
322 }
323
324 /*!
325   Builds popup for vtk viewer
326 */
327 void SVTK_Viewer::contextMenuPopup( QMenu* thePopup )
328 {
329   thePopup->addAction( VTKViewer_Viewer::tr( "MEN_DUMP_VIEW" ), this, SLOT( onDumpView() ) );
330   thePopup->addAction( VTKViewer_Viewer::tr( "MEN_CHANGE_BACKGROUD" ), this, SLOT( onChangeBgColor() ) );
331
332   thePopup->addSeparator();
333
334   if(TViewWindow* aView = dynamic_cast<TViewWindow*>(myViewManager->getActiveView())){
335     //Support of several toolbars in the popup menu
336     QList<QToolBar*> lst = qFindChildren<QToolBar*>( aView );
337     QList<QToolBar*>::const_iterator it = lst.begin(), last = lst.end();
338     for( ; it!=last; it++ )
339       thePopup->addAction( (*it)->toggleViewAction() );
340     aView->RefreshDumpImage();
341   }
342 }
343
344 /*!
345   SLOT: called on mouse button press, empty implementation
346 */
347 void SVTK_Viewer::onMousePress(SUIT_ViewWindow* vw, QMouseEvent* event)
348 {}
349
350 /*!
351   SLOT: called on mouse move, empty implementation
352 */
353 void SVTK_Viewer::onMouseMove(SUIT_ViewWindow* vw, QMouseEvent* event)
354 {}
355
356 /*!
357   SLOT: called on mouse button release, empty implementation
358 */
359 void SVTK_Viewer::onMouseRelease(SUIT_ViewWindow* vw, QMouseEvent* event)
360 {}
361
362 /*!
363   Enables/disables selection
364   \param isEnabled - new state
365 */
366 void SVTK_Viewer::enableSelection(bool isEnabled)
367 {
368   mySelectionEnabled = isEnabled;
369   //!! To be done for view windows
370 }
371
372 /*!
373   Enables/disables selection of many object
374   \param isEnabled - new state
375 */
376 void SVTK_Viewer::enableMultiselection(bool isEnable)
377 {
378   myMultiSelectionEnabled = isEnable;
379   //!! To be done for view windows
380 }
381
382 /*!
383   SLOT: called on dump view operation is activated, stores scene to raster file
384 */
385 void SVTK_Viewer::onDumpView()
386 {
387   if(SUIT_ViewWindow* aView = myViewManager->getActiveView())
388     aView->onDumpView();
389 }
390
391 /*!
392   SLOT: called if background color is to be changed changed, passes new color to view port
393 */
394 void SVTK_Viewer::onChangeBgColor()
395 {
396   if(SUIT_ViewWindow* aView = myViewManager->getActiveView()){
397     QColor aColor = QColorDialog::getColor( backgroundColor(), aView);
398     setBackgroundColor(aColor);
399   }
400 }
401
402 /*!
403   Display presentation
404   \param prs - presentation
405 */
406 void SVTK_Viewer::Display( const SALOME_VTKPrs* prs )
407 {
408   // try do downcast object
409   if(const SVTK_Prs* aPrs = dynamic_cast<const SVTK_Prs*>( prs )){
410     if(aPrs->IsNull())
411       return;
412     if(vtkActorCollection* anActorCollection = aPrs->GetObjects()){
413       // get SALOMEDS Study
414       // Temporarily commented to avoid awful dependecy on SALOMEDS
415       // TODO: better mechanism of storing display/erse status in a study
416       // should be provided...
417       // _PTR(Study) aStudy(getStudyDS());
418       anActorCollection->InitTraversal();
419       while(vtkActor* anActor = anActorCollection->GetNextActor()){
420         if(SALOME_Actor* anAct = SALOME_Actor::SafeDownCast(anActor)){
421           // Set visibility flag
422           // Temporarily commented to avoid awful dependecy on SALOMEDS
423           // TODO: better mechanism of storing display/erse status in a study
424           // should be provided...
425           //Handle(SALOME_InteractiveObject) anObj = anAct->getIO();
426           //if(!anObj.IsNull() && anObj->hasEntry() && aStudy){
427           //  ToolsGUI::SetVisibility(aStudy,anObj->getEntry(),true,this);
428           //}
429           // just display the object
430           QVector<SUIT_ViewWindow*> aViews = myViewManager->getViews();
431           for(int i = 0, iEnd = aViews.size(); i < iEnd; i++){
432             if(SVTK_ViewWindow* aViewWindow = dynamic_cast<SVTK_ViewWindow*>(aViews.at(i))){
433               if(SVTK_View* aView = aViewWindow->getView()){
434                 aView->Display(anAct,false);
435                 if(anAct->IsSetCamera()){
436                   vtkRenderer* aRenderer = aView->getRenderer();
437                   anAct->SetCamera( aRenderer->GetActiveCamera() );
438                 }
439               }
440             }
441           }
442         }
443       }
444     }
445   }
446 }
447
448 /*!
449   Erase presentation
450   \param prs - presentation
451   \param forced - removes object from view
452 */
453 void SVTK_Viewer::Erase( const SALOME_VTKPrs* prs, const bool forced )
454 {
455   // try do downcast object
456   if(const SVTK_Prs* aPrs = dynamic_cast<const SVTK_Prs*>( prs )){
457     if(aPrs->IsNull())
458       return;
459     if(vtkActorCollection* anActorCollection = aPrs->GetObjects()){
460       // get SALOMEDS Study
461       // Temporarily commented to avoid awful dependecy on SALOMEDS
462       // TODO: better mechanism of storing display/erse status in a study
463       // should be provided...
464       //_PTR(Study) aStudy(getStudyDS());
465       anActorCollection->InitTraversal();
466       while(vtkActor* anActor = anActorCollection->GetNextActor())
467         if(SALOME_Actor* anAct = SALOME_Actor::SafeDownCast(anActor)){
468           // Set visibility flag
469           // Temporarily commented to avoid awful dependecy on SALOMEDS
470           // TODO: better mechanism of storing display/erse status in a study
471           // should be provided...
472           //Handle(SALOME_InteractiveObject) anObj = anAct->getIO();
473           //if(!anObj.IsNull() && anObj->hasEntry() && aStudy){
474           //  ToolsGUI::SetVisibility(aStudy,anObj->getEntry(),false,this);
475           //}
476           // just display the object
477           QVector<SUIT_ViewWindow*> aViews = myViewManager->getViews();
478           for(int i = 0, iEnd = aViews.size(); i < iEnd; i++){
479             if(SVTK_ViewWindow* aViewWindow = dynamic_cast<SVTK_ViewWindow*>(aViews.at(i)))
480               if(SVTK_View* aView = aViewWindow->getView())
481                 if ( forced )
482                   aView->Remove(anAct,false);
483                 else
484                   aView->Erase(anAct,forced);
485           }
486         }
487     }
488   }
489 }
490
491 /*!
492   Erase all presentations
493   \param forced - removes all objects from view
494 */
495 void SVTK_Viewer::EraseAll( const bool forced )
496 {
497   // Temporarily commented to avoid awful dependecy on SALOMEDS
498   // TODO: better mechanism of storing display/erse status in a study
499   // should be provided...
500   //_PTR(Study) aStudy(getStudyDS());
501   QVector<SUIT_ViewWindow*> aViews = myViewManager->getViews();
502   for(int i = 0, iEnd = aViews.size(); i < iEnd; i++){
503     if(SVTK_ViewWindow* aViewWindow = dynamic_cast<SVTK_ViewWindow*>(aViews.at(i)))
504       if(SVTK_View* aView = aViewWindow->getView()){
505         vtkRenderer* aRenderer =  aView->getRenderer();
506         vtkActorCollection* anActorCollection = aRenderer->GetActors();
507         anActorCollection->InitTraversal();
508         while(vtkActor* anActor = anActorCollection->GetNextActor()){
509           if(SALOME_Actor* anAct = SALOME_Actor::SafeDownCast(anActor)){
510             // Set visibility flag
511             // Temporarily commented to avoid awful dependecy on SALOMEDS
512             // TODO: better mechanism of storing display/erse status in a study
513             // should be provided...
514             //Handle(SALOME_InteractiveObject) anObj = anAct->getIO();
515             //if(!anObj.IsNull() && anObj->hasEntry() && aStudy)
516             //  ToolsGUI::SetVisibility(aStudy,anObj->getEntry(),false,this);
517             if(forced)
518               aRenderer->RemoveActor(anAct);
519             else{
520               // just erase actor
521               anAct->SetVisibility( false );
522               // erase dependent actors
523               vtkActorCollection* aCollection = vtkActorCollection::New();
524               anAct->GetChildActors( aCollection );
525               aCollection->InitTraversal();
526               while(vtkActor* aSubAct = aCollection->GetNextActor())
527                 aSubAct->SetVisibility( false );
528               aCollection->Delete();
529             }
530           }
531         }
532       }
533   }
534   Repaint();
535 }
536
537 /*!
538   Create presentation corresponding to the entry
539   \param entry - entry
540 */
541 SALOME_Prs* SVTK_Viewer::CreatePrs( const char* entry )
542 {
543   SVTK_Prs* prs = new SVTK_Prs();
544   if ( entry ) {
545     if(SVTK_ViewWindow* aViewWindow = dynamic_cast<SVTK_ViewWindow*>(getViewManager()->getActiveView()))
546       if(SVTK_View* aView = aViewWindow->getView()){
547         vtkRenderer* aRenderer =  aView->getRenderer();
548         vtkActorCollection* theActors = aRenderer->GetActors();
549         theActors->InitTraversal();
550         vtkActor* ac;
551         while( ( ac = theActors->GetNextActor() ) ) {
552           SALOME_Actor* anActor = SALOME_Actor::SafeDownCast( ac );
553           if ( anActor && anActor->hasIO() && !strcmp( anActor->getIO()->getEntry(), entry ) ) {
554             prs->AddObject( ac );
555           }
556         }
557       }
558   }
559   return prs;
560 }
561
562 /*!
563   Auxiliary method called before displaying of objects
564 */
565 void SVTK_Viewer::BeforeDisplay( SALOME_Displayer* d )
566 {
567   d->BeforeDisplay( this, SALOME_VTKViewType() );
568 }
569
570 /*!
571   Auxiliary method called after displaying of objects
572 */
573 void SVTK_Viewer::AfterDisplay( SALOME_Displayer* d )
574 {
575   d->AfterDisplay( this, SALOME_VTKViewType() );
576 }
577
578 /*!
579   \return true if object is displayed in viewer
580   \param obj - object to be checked
581 */
582 bool SVTK_Viewer::isVisible( const Handle(SALOME_InteractiveObject)& io )
583 {
584   QVector<SUIT_ViewWindow*> aViews = myViewManager->getViews();
585   for(int i = 0, iEnd = aViews.size(); i < iEnd; i++)
586     if(SUIT_ViewWindow* aViewWindow = aViews.at(i))
587       if(TViewWindow* aViewWnd = dynamic_cast<TViewWindow*>(aViewWindow))
588         if(SVTK_View* aView = aViewWnd->getView())
589           if(!aView->isVisible( io ))
590             return false;
591
592   return true;
593 }
594
595 /*!
596   Updates current viewer
597 */
598 void SVTK_Viewer::Repaint()
599 {
600 //  if (theUpdateTrihedron) onAdjustTrihedron();
601   QVector<SUIT_ViewWindow*> aViews = myViewManager->getViews();
602   for(int i = 0, iEnd = aViews.size(); i < iEnd; i++)
603     if(TViewWindow* aViewWindow = dynamic_cast<TViewWindow*>(aViews.at(i)))
604       if(SVTK_View* aView = aViewWindow->getView())
605         aView->Repaint();
606 }
607  
608
609 void SVTK_Viewer::onActorAdded(VTKViewer_Actor* theActor)
610 {
611   emit actorAdded((SVTK_ViewWindow*)sender(), theActor);
612 }
613
614 void SVTK_Viewer::onActorRemoved(VTKViewer_Actor* theActor)
615 {
616   emit actorRemoved((SVTK_ViewWindow*)sender(), theActor);
617 }