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