Salome HOME
Merge from V6_main_20120808 08Aug12
[modules/gui.git] / src / SVTK / SVTK_RenderWindowInteractor.cxx
1 // Copyright (C) 2007-2012  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
23 //  SALOME VTKViewer : build VTK viewer into Salome desktop
24 //  File   : 
25 //  Author : 
26
27 #include "SVTK_RenderWindowInteractor.h"
28
29 #include "SVTK_InteractorStyle.h"
30 #include "SVTK_Renderer.h"
31 #include "SVTK_Functor.h"
32 #include "SALOME_Actor.h"
33
34 // QT Includes
35 // Put Qt includes before the X11 includes which #define the symbol None
36 // (see SVTK_SpaceMouse.h) to avoid the compilation error.
37 #ifndef WIN32
38 # include <QX11Info>
39 #endif
40 #include <QMouseEvent>
41
42 #include "SVTK_SpaceMouse.h" 
43 #include "SVTK_Event.h" 
44
45 #include "VTKViewer_Algorithm.h"
46
47 // VTK Includes
48 #include <vtkObjectFactory.h>
49 #include <vtkRendererCollection.h>
50 #include <vtkRenderWindow.h>
51 #include <vtkGenericRenderWindowInteractor.h>
52 #include <vtkCallbackCommand.h>
53 #include <vtkCommand.h>
54 #include <vtkPicker.h>
55 #include <vtkCamera.h>
56
57 static bool GENERATE_SUIT_EVENTS = true;
58 static bool FOCUS_UNDER_MOUSE = false;
59
60
61 /*!
62   Constructor
63 */
64 QVTK_RenderWindowInteractor
65 ::QVTK_RenderWindowInteractor(QWidget* theParent, 
66                               const char* theName):
67   QWidget(theParent),
68   myRenderWindow(vtkRenderWindow::New())
69 {
70   setAttribute( Qt::WA_PaintOnScreen );
71   setAttribute( Qt::WA_NoSystemBackground );
72
73   setObjectName(theName);
74
75   setMouseTracking(true);
76
77   myRenderWindow->Delete();
78   myRenderWindow->DoubleBufferOn();
79
80 #ifndef WIN32
81   myRenderWindow->SetDisplayId((void*)QX11Info::display());
82 #endif
83   myRenderWindow->SetWindowId((void*)winId());
84 }
85
86 /*!
87   To initialize by vtkGenericRenderWindowInteractor instance
88 */
89 void 
90 QVTK_RenderWindowInteractor
91 ::Initialize(vtkGenericRenderWindowInteractor* theDevice)
92 {
93   if ( GetDevice() )
94     myDevice->SetRenderWindow( NULL );
95
96   myDevice = theDevice;
97
98   if ( theDevice )
99     theDevice->SetRenderWindow( getRenderWindow() );
100 }
101
102 /*!
103   Destructor
104 */
105 QVTK_RenderWindowInteractor
106 ::~QVTK_RenderWindowInteractor() 
107 {
108 #ifndef WIN32
109   SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance();
110   if ( aSpaceMouse && aSpaceMouse->isSpaceMouseOn() )
111     aSpaceMouse->close( QX11Info::display() );
112 #endif
113 }
114
115
116 /*!
117   \return corresponding render window interactor
118 */
119 vtkGenericRenderWindowInteractor* 
120 QVTK_RenderWindowInteractor
121 ::GetDevice()
122 {
123   return myDevice.GetPointer();
124 }
125
126 /*!
127   \return corresponding render window
128 */
129 vtkRenderWindow*
130 QVTK_RenderWindowInteractor
131 ::getRenderWindow()
132 {
133   return myRenderWindow.GetPointer();
134 }
135
136 /*!
137   Just to simplify usage of its device (vtkGenericRenderWindowInteractor)
138 */
139 void
140 QVTK_RenderWindowInteractor
141 ::InvokeEvent(unsigned long theEvent, void* theCallData)
142 {
143   GetDevice()->InvokeEvent(theEvent,theCallData);
144 }
145
146 /*!
147   Get paint engine for the scene
148 */
149 QPaintEngine* QVTK_RenderWindowInteractor::paintEngine() const
150 {
151   return 0;
152 }
153
154 /*!
155   Need for initial contents display on Win32
156 */
157 void
158 QVTK_RenderWindowInteractor
159 ::show()
160 {
161   QWidget::show();
162   update(); // needed for initial contents display on Win32
163 }
164
165 /*!
166   To implement final initialization, just before the widget is displayed
167 */
168 void
169 QVTK_RenderWindowInteractor
170 ::polish()
171 {
172   // Final initialization just before the widget is displayed
173   GetDevice()->SetSize(width(),height());
174   if(!GetDevice()->GetInitialized() && GetDevice()->GetRenderWindow()){
175     GetDevice()->Initialize();
176     GetDevice()->ConfigureEvent();
177   }
178 }
179
180 /*!
181   To adjust widget and vtkRenderWindow size
182 */
183 void
184 QVTK_RenderWindowInteractor
185 ::resize(int w, int h) 
186 {
187   GetDevice()->UpdateSize(w,h);
188 }
189
190 /*!
191   Custom paint event handler
192 */
193 void
194 QVTK_RenderWindowInteractor
195 ::paintEvent( QPaintEvent* theEvent ) 
196 {
197   GetDevice()->CreateTimer(VTKI_TIMER_FIRST);
198 }
199
200
201 /*!
202   Custom resize event handler
203 */
204 void
205 QVTK_RenderWindowInteractor
206 ::resizeEvent( QResizeEvent* theEvent )
207 {
208   int* aSize = getRenderWindow()->GetSize();
209   int aWidth = aSize[0];
210   int aHeight = aSize[1];
211
212   GetDevice()->UpdateSize(width(),height());
213
214   if(isVisible() && aWidth && aHeight){
215     if( aWidth != width() || aHeight != height() ) {
216       vtkRendererCollection * aRenderers = getRenderWindow()->GetRenderers();
217       aRenderers->InitTraversal();
218       double aCoeff = 1.0;
219       if(vtkRenderer *aRenderer = aRenderers->GetNextItem()) {
220         vtkCamera *aCamera = aRenderer->GetActiveCamera();
221         double aScale = aCamera->GetParallelScale();
222         if((aWidth - width())*(aHeight - height()) > 0)
223           aCoeff = sqrt(double(aWidth)/double(width())*double(height())/double(aHeight));
224         else
225           aCoeff = double(aWidth)/double(width());
226         aCamera->SetParallelScale(aScale*aCoeff);
227       }
228     }
229   }
230
231   update(); 
232 }
233
234
235
236 /*!
237   Custom context menu event handler
238 */
239 void
240 QVTK_RenderWindowInteractor
241 ::contextMenuEvent( QContextMenuEvent* event )
242 {}
243
244 /*!
245   Custom mouse move event handler
246 */
247 void
248 QVTK_RenderWindowInteractor
249 ::mouseMoveEvent( QMouseEvent* event ) 
250 {
251   GetDevice()->SetEventInformationFlipY(event->x(), 
252                                         event->y(),
253                                         event->modifiers() & Qt::ControlModifier,
254                                         event->modifiers() & Qt::ShiftModifier);
255   GetDevice()->MouseMoveEvent();
256 }
257
258
259 /*!
260   Custom mouse press event handler
261 */
262 void
263 QVTK_RenderWindowInteractor
264 ::mousePressEvent( QMouseEvent* event ) 
265 {
266   GetDevice()->SetEventInformationFlipY(event->x(), 
267                                         event->y(),
268                                         event->modifiers() & Qt::ControlModifier,
269                                         event->modifiers() & Qt::ShiftModifier);
270   if( event->button() & Qt::LeftButton )
271     GetDevice()->LeftButtonPressEvent();
272   else if( event->button() & Qt::MidButton )
273     GetDevice()->MiddleButtonPressEvent();
274   else if( event->button() & Qt::RightButton )
275     GetDevice()->RightButtonPressEvent();
276 }
277
278
279 /*!
280   Custom mouse release event handler
281 */
282 void
283 QVTK_RenderWindowInteractor
284 ::mouseReleaseEvent( QMouseEvent *event )
285 {
286   GetDevice()->SetEventInformationFlipY(event->x(), 
287                                         event->y(),
288                                         event->modifiers() & Qt::ControlModifier,
289                                         event->modifiers() & Qt::ShiftModifier);
290
291   if( event->button() & Qt::LeftButton )
292     GetDevice()->LeftButtonReleaseEvent();
293   else if( event->button() & Qt::MidButton )
294     GetDevice()->MiddleButtonReleaseEvent();
295   else if( event->button() & Qt::RightButton )
296     GetDevice()->RightButtonReleaseEvent();
297 }
298
299
300 /*!
301   Custom mouse double click event handler
302 */
303 void
304 QVTK_RenderWindowInteractor
305 ::mouseDoubleClickEvent( QMouseEvent* event )
306 {}
307
308
309 /*!
310   Custom mouse wheel event handler
311 */
312 void
313 QVTK_RenderWindowInteractor
314 ::wheelEvent( QWheelEvent* event )
315 {
316   activateWindow();
317   setFocus();
318   GetDevice()->SetEventInformationFlipY(event->x(), 
319                                         event->y(),
320                                         event->modifiers() & Qt::ControlModifier,
321                                         event->modifiers() & Qt::ShiftModifier);
322   if ( event->delta()>0)
323     GetDevice()->MouseWheelForwardEvent();
324   else
325     GetDevice()->MouseWheelBackwardEvent();
326 }
327
328
329 /*!
330   Custom key press event handler
331 */
332 void
333 QVTK_RenderWindowInteractor
334 ::keyPressEvent( QKeyEvent* event ) 
335 {
336   GetDevice()->SetKeyEventInformation(event->modifiers() & Qt::ControlModifier,
337                                       event->modifiers() & Qt::ShiftModifier,
338                                       event->key());
339   GetDevice()->KeyPressEvent();
340   GetDevice()->CharEvent();
341 }
342
343 /*!
344   Custom key release event handler
345 */
346 void
347 QVTK_RenderWindowInteractor
348 ::keyReleaseEvent( QKeyEvent * event ) 
349 {
350   GetDevice()->SetKeyEventInformation(event->modifiers() & Qt::ControlModifier,
351                                       event->modifiers() & Qt::ShiftModifier,
352                                       event->key());
353   GetDevice()->KeyReleaseEvent();
354 }
355
356
357 /*!
358   Custom enter event handler
359 */
360 void  
361 QVTK_RenderWindowInteractor
362 ::enterEvent( QEvent* event )
363 {
364   if(FOCUS_UNDER_MOUSE){
365     activateWindow();
366     setFocus();
367   }
368   GetDevice()->EnterEvent();
369 }
370
371 /*!
372   Custom leave event handler
373 */
374 void  
375 QVTK_RenderWindowInteractor
376 ::leaveEvent( QEvent * )
377 {
378   GetDevice()->LeaveEvent();
379 }
380
381 /*!
382   Reimplemented from QWidget in order to set window - receiver
383   of space mouse events. 
384 */
385 void  
386 QVTK_RenderWindowInteractor
387 ::focusInEvent( QFocusEvent* event )
388 {
389   QWidget::focusInEvent( event );
390
391 #ifndef WIN32
392   // register set space mouse events receiver
393   SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance();
394
395   if ( aSpaceMouse )
396   {
397     if ( !aSpaceMouse->isSpaceMouseOn() )
398       // initialize 3D space mouse driver 
399       aSpaceMouse->initialize( QX11Info::display(), winId() );
400     else
401       aSpaceMouse->setWindow( QX11Info::display(), winId() );
402   }
403 #endif
404 }
405
406 /*!
407   Reimplemented from QWidget in order to set window - receiver
408   of space mouse events. 
409 */
410 void  
411 QVTK_RenderWindowInteractor
412 ::focusOutEvent ( QFocusEvent* event )
413 {
414   QWidget::focusOutEvent( event );
415
416 #ifndef WIN32
417   // unregister set space mouse events receiver
418   SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance();
419   if ( aSpaceMouse && aSpaceMouse->isSpaceMouseOn() )
420     aSpaceMouse->setWindow( QX11Info::display(), 0 );
421 #endif
422 }
423
424
425 #ifdef WIN32
426
427 /*!
428   To handle native Win32 events (from such devices as SpaceMouse)
429 */
430 bool QVTK_RenderWindowInteractor::winEvent( MSG* msg, long* result )
431 {
432   // TODO: Implement event handling for SpaceMouse
433   return QWidget::winEvent( msg, result);
434 }
435
436 #else
437
438 /*!
439   To handle native X11 events (from such devices as SpaceMouse)
440 */
441 bool 
442 QVTK_RenderWindowInteractor
443 ::x11Event( XEvent *xEvent )
444 {
445   // handle 3d space mouse events
446   if ( SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance() )
447   {
448     if ( aSpaceMouse->isSpaceMouseOn() && xEvent->type == ClientMessage )
449     {
450       SVTK_SpaceMouse::MoveEvent anEvent;
451       int type = aSpaceMouse->translateEvent( QX11Info::display(), xEvent, &anEvent, 1.0, 1.0 );
452       switch ( type )
453       {
454       case SVTK_SpaceMouse::SpaceMouseMove:
455               GetDevice()->InvokeEvent( SVTK::SpaceMouseMoveEvent, anEvent.data );
456               break;
457       case SVTK_SpaceMouse::SpaceButtonPress:
458               GetDevice()->InvokeEvent( SVTK::SpaceMouseButtonEvent, &anEvent.button );
459               break;
460       case SVTK_SpaceMouse::SpaceButtonRelease:
461               break;
462       }
463       return true; // stop handling the event
464     }
465   }
466
467   return QWidget::x11Event( xEvent );
468 }
469
470 #endif
471
472 /*!
473   Constructor
474 */
475 SVTK_RenderWindowInteractor
476 ::SVTK_RenderWindowInteractor(QWidget* theParent, 
477                                const char* theName):
478   QVTK_RenderWindowInteractor(theParent,theName),
479   myEventCallbackCommand(vtkCallbackCommand::New())
480 {
481   myEventCallbackCommand->Delete();
482
483   myEventCallbackCommand->SetClientData(this); 
484   myPriority = 0.0;
485
486   myEventCallbackCommand->SetCallback(SVTK_RenderWindowInteractor::ProcessEvents);
487 }
488
489 /*!
490   To initialize properly the class
491 */
492 void
493 SVTK_RenderWindowInteractor
494 ::Initialize(vtkGenericRenderWindowInteractor* theDevice,
495              SVTK_Renderer* theRenderer,
496              SVTK_Selector* theSelector)
497 {
498   QVTK_RenderWindowInteractor::Initialize(theDevice);
499   SetRenderer(theRenderer);
500   SetSelector(theSelector);
501 }
502
503 /*!
504   Destructor
505 */
506 SVTK_RenderWindowInteractor
507 ::~SVTK_RenderWindowInteractor() 
508 {
509   // Sequence of the destruction call are fixed and should be changed.
510   // vtkRenderWindow instance should be destroyed after all vtkRenderer's
511   GetDevice()->SetInteractorStyle(NULL); 
512   while(!myInteractorStyles.empty()){
513     const PInteractorStyle& aStyle = myInteractorStyles.top();
514     aStyle->SetInteractor(NULL);
515     myInteractorStyles.pop();
516   }
517
518   SetRenderer(NULL);
519
520   GetDevice()->SetRenderWindow(NULL);
521 }
522
523 /*!
524   To get corresponding SVTK_Renderer instance
525 */
526 SVTK_Renderer* 
527 SVTK_RenderWindowInteractor
528 ::GetRenderer()
529 {
530   return myRenderer.GetPointer();
531 }
532
533 /*!
534   To get corresponding SVTK_Renderer device (just to simplify collobaration with SVTK_Renderer)
535 */
536 vtkRenderer* 
537 SVTK_RenderWindowInteractor
538 ::getRenderer()
539 {
540   return GetRenderer()->GetDevice();
541 }
542
543 /*!
544   Changes renderer
545   \param theRenderer - new renderer
546 */
547 void
548 SVTK_RenderWindowInteractor
549 ::SetRenderer(SVTK_Renderer* theRenderer)
550 {
551   if(theRenderer == myRenderer.GetPointer())
552     return;
553
554   if(GetRenderer())
555     myRenderWindow->RemoveRenderer(getRenderer());
556
557   myRenderer = theRenderer;
558
559   if(GetRenderer())
560     myRenderWindow->AddRenderer(getRenderer());
561 }
562
563
564 /*!
565   Changes interactor style
566   \param theStyle - new interactor style
567 */
568 void
569 SVTK_RenderWindowInteractor
570 ::InitInteractorStyle(vtkInteractorStyle* theStyle)
571 {
572   GetDevice()->SetInteractorStyle(theStyle); 
573 }
574
575 /*!
576   To change current interactor style by pushing the new one into the container
577 */
578 void
579 SVTK_RenderWindowInteractor
580 ::PushInteractorStyle(vtkInteractorStyle* theStyle)
581 {
582   myInteractorStyles.push(PInteractorStyle(theStyle));
583   InitInteractorStyle(theStyle);
584 }
585
586 /*!
587   To restore previous interactor style
588 */
589 void
590 SVTK_RenderWindowInteractor
591 ::PopInteractorStyle()
592 {
593   if(GetInteractorStyle())
594     myInteractorStyles.pop();
595   
596   if(GetInteractorStyle()) 
597     InitInteractorStyle(GetInteractorStyle());
598 }
599
600 /*!
601   To get current interactor style
602 */
603 vtkInteractorStyle* 
604 SVTK_RenderWindowInteractor
605 ::GetInteractorStyle()
606 {
607   return myInteractorStyles.empty() ? 0 : myInteractorStyles.top().GetPointer();
608 }
609
610
611 /*!
612   To get current selector
613 */
614 SVTK_Selector* 
615 SVTK_RenderWindowInteractor
616 ::GetSelector() 
617
618   return mySelector.GetPointer(); 
619 }
620
621
622 /*!
623   Changes selector
624   \param theSelector - new selector
625 */
626 void
627 SVTK_RenderWindowInteractor
628 ::SetSelector(SVTK_Selector* theSelector)
629
630   if(mySelector.GetPointer())
631     mySelector->RemoveObserver(myEventCallbackCommand.GetPointer());
632
633   mySelector = theSelector; 
634
635   if(mySelector.GetPointer())
636     mySelector->AddObserver(vtkCommand::EndPickEvent, 
637                             myEventCallbackCommand.GetPointer(), 
638                             myPriority);
639 }
640
641 /*!
642   Main process VTK event method
643 */
644 void 
645 SVTK_RenderWindowInteractor
646 ::ProcessEvents(vtkObject* vtkNotUsed(theObject), 
647                 unsigned long theEvent,
648                 void* theClientData, 
649                 void* vtkNotUsed(theCallData))
650 {
651   SVTK_RenderWindowInteractor* self = reinterpret_cast<SVTK_RenderWindowInteractor*>(theClientData);
652
653   switch(theEvent){
654   case vtkCommand::EndPickEvent:
655     self->onEmitSelectionChanged();
656     break;
657   }
658 }
659
660 /*!
661   To change selection mode (just to simplify collobaration with SVTK_Selector)
662 */
663 void
664 SVTK_RenderWindowInteractor
665 ::SetSelectionMode(Selection_Mode theMode)
666 {
667   mySelector->SetSelectionMode(theMode);
668 }
669
670 /*!
671   To get current selection mode (just to simplify collobaration with SVTK_Selector)
672 */
673 Selection_Mode
674 SVTK_RenderWindowInteractor
675 ::SelectionMode() const
676 {
677   return mySelector->SelectionMode();
678 }
679
680
681 /*!
682   Emits signal selectionChanged()
683 */
684 void
685 SVTK_RenderWindowInteractor
686 ::onEmitSelectionChanged()
687 {
688   return emit selectionChanged();
689 }
690
691
692 /*!
693   Custom mouse move event handler
694 */
695 void
696 SVTK_RenderWindowInteractor
697 ::mouseMoveEvent( QMouseEvent* event ) 
698 {
699   QVTK_RenderWindowInteractor::mouseMoveEvent(event);
700
701   if(GENERATE_SUIT_EVENTS)
702     emit MouseMove( event );
703 }
704
705
706 /*!
707   Custom mouse press event handler
708 */
709 void
710 SVTK_RenderWindowInteractor
711 ::mousePressEvent( QMouseEvent* event ) 
712 {
713   QVTK_RenderWindowInteractor::mousePressEvent(event);
714
715   if(GENERATE_SUIT_EVENTS)
716     emit MouseButtonPressed( event );
717 }
718
719
720 /*!
721   Custom mouse release event handler
722 */
723 void
724 SVTK_RenderWindowInteractor
725 ::mouseReleaseEvent( QMouseEvent *event )
726 {
727   bool aRightBtn = event->button() == Qt::RightButton;
728   bool isOperation = false;
729   if( aRightBtn && GetInteractorStyle()) {
730     SVTK_InteractorStyle* style = dynamic_cast<SVTK_InteractorStyle*>( GetInteractorStyle() );
731     if ( style )
732       isOperation = style->CurrentState() != VTK_INTERACTOR_STYLE_CAMERA_NONE;
733   }
734
735   QVTK_RenderWindowInteractor::mouseReleaseEvent(event);
736
737   if ( aRightBtn && !isOperation && !( event->modifiers() & Qt::ControlModifier ) &&
738        !( event->modifiers() & Qt::ShiftModifier ) ) {
739     QContextMenuEvent aEvent( QContextMenuEvent::Mouse,
740                               event->pos(), event->globalPos() );
741     emit contextMenuRequested( &aEvent );
742   }
743   if(GENERATE_SUIT_EVENTS)
744     emit MouseButtonReleased( event );
745 }
746
747
748 /*!
749   Custom mouse double click event handler
750 */
751 void
752 SVTK_RenderWindowInteractor
753 ::mouseDoubleClickEvent( QMouseEvent* event )
754 {
755   QVTK_RenderWindowInteractor::mouseDoubleClickEvent(event);
756
757   if(GENERATE_SUIT_EVENTS)
758     emit MouseDoubleClicked( event );
759 }
760
761
762 /*!
763   Custom mouse wheel event handler
764 */
765 void
766 SVTK_RenderWindowInteractor
767 ::wheelEvent( QWheelEvent* event )
768 {
769   QVTK_RenderWindowInteractor::wheelEvent(event);
770
771   if(event->delta() > 0)
772     GetDevice()->InvokeEvent(SVTK::ZoomInEvent,NULL);
773   else
774     GetDevice()->InvokeEvent(SVTK::ZoomOutEvent,NULL);
775
776   if(GENERATE_SUIT_EVENTS)
777     emit WheelMoved( event );
778 }
779
780 /*!
781   Custom key press event handler
782 */
783 void
784 SVTK_RenderWindowInteractor
785 ::keyPressEvent( QKeyEvent* event ) 
786 {
787   QVTK_RenderWindowInteractor::keyPressEvent(event);
788
789   if(GENERATE_SUIT_EVENTS)
790     emit KeyPressed( event );
791 }
792
793 /*!
794   Custom key release event handler
795 */
796 void
797 SVTK_RenderWindowInteractor
798 ::keyReleaseEvent( QKeyEvent * event ) 
799 {
800   QVTK_RenderWindowInteractor::keyReleaseEvent(event);
801
802   if(GENERATE_SUIT_EVENTS)
803     emit KeyReleased( event );
804 }
805