1 // Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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, or (at your option) any later version.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // SALOME VTKViewer : build VTK viewer into Salome desktop
27 #include "SVTK_RenderWindowInteractor.h"
29 #include "SVTK_InteractorStyle.h"
30 #include "SVTK_Renderer.h"
31 #include "SVTK_Functor.h"
32 #include "SALOME_Actor.h"
35 // Put Qt includes before the X11 includes which #define the symbol None
36 // (see SVTK_SpaceMouse.h) to avoid the compilation error.
40 #include <QMouseEvent>
42 #include "SVTK_SpaceMouse.h"
43 #include "SVTK_Event.h"
45 #include "VTKViewer_Algorithm.h"
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>
57 static bool GENERATE_SUIT_EVENTS = true;
58 static bool FOCUS_UNDER_MOUSE = false;
60 // workaround about the bug in vtkImplicitPlaneWidget class
61 // that eats mouse button release event
62 // causing clipping plane preview in SMESH sticking up
63 #define Fix_Of_vtkImplicitPlaneWidget_bug
68 QVTK_RenderWindowInteractor
69 ::QVTK_RenderWindowInteractor(QWidget* theParent,
72 myRenderWindow(vtkRenderWindow::New())
74 setAttribute( Qt::WA_PaintOnScreen );
75 setAttribute( Qt::WA_NoSystemBackground );
77 setObjectName(theName);
79 setMouseTracking(true);
81 myRenderWindow->Delete();
82 myRenderWindow->DoubleBufferOn();
85 myRenderWindow->SetDisplayId((void*)QX11Info::display());
87 myRenderWindow->SetWindowId((void*)winId());
91 To initialize by vtkGenericRenderWindowInteractor instance
94 QVTK_RenderWindowInteractor
95 ::Initialize(vtkGenericRenderWindowInteractor* theDevice)
98 myDevice->SetRenderWindow( NULL );
100 myDevice = theDevice;
103 theDevice->SetRenderWindow( getRenderWindow() );
109 QVTK_RenderWindowInteractor
110 ::~QVTK_RenderWindowInteractor()
113 SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance();
114 if ( aSpaceMouse && aSpaceMouse->isSpaceMouseOn() )
115 aSpaceMouse->close( QX11Info::display() );
121 \return corresponding render window interactor
123 vtkGenericRenderWindowInteractor*
124 QVTK_RenderWindowInteractor
127 return myDevice.GetPointer();
131 \return corresponding render window
134 QVTK_RenderWindowInteractor
137 return myRenderWindow.GetPointer();
141 Just to simplify usage of its device (vtkGenericRenderWindowInteractor)
144 QVTK_RenderWindowInteractor
145 ::InvokeEvent(unsigned long theEvent, void* theCallData)
147 GetDevice()->InvokeEvent(theEvent,theCallData);
151 Get paint engine for the scene
153 QPaintEngine* QVTK_RenderWindowInteractor::paintEngine() const
159 Need for initial contents display on Win32
162 QVTK_RenderWindowInteractor
166 update(); // needed for initial contents display on Win32
170 To implement final initialization, just before the widget is displayed
173 QVTK_RenderWindowInteractor
176 // Final initialization just before the widget is displayed
177 GetDevice()->SetSize(width(),height());
178 if(!GetDevice()->GetInitialized() && GetDevice()->GetRenderWindow()){
179 GetDevice()->Initialize();
180 GetDevice()->ConfigureEvent();
185 To adjust widget and vtkRenderWindow size
188 QVTK_RenderWindowInteractor
189 ::resize(int w, int h)
191 GetDevice()->UpdateSize(w,h);
195 Custom paint event handler
198 QVTK_RenderWindowInteractor
199 ::paintEvent( QPaintEvent* theEvent )
201 GetDevice()->CreateTimer(VTKI_TIMER_FIRST);
206 Custom resize event handler
209 QVTK_RenderWindowInteractor
210 ::resizeEvent( QResizeEvent* theEvent )
212 int* aSize = getRenderWindow()->GetSize();
213 int aWidth = aSize[0];
214 int aHeight = aSize[1];
216 GetDevice()->UpdateSize(width(),height());
218 if(isVisible() && aWidth && aHeight){
219 if( aWidth != width() || aHeight != height() ) {
220 vtkRendererCollection * aRenderers = getRenderWindow()->GetRenderers();
221 aRenderers->InitTraversal();
223 if(vtkRenderer *aRenderer = aRenderers->GetNextItem()) {
224 vtkCamera *aCamera = aRenderer->GetActiveCamera();
225 double aScale = aCamera->GetParallelScale();
226 if((aWidth - width())*(aHeight - height()) > 0)
227 aCoeff = sqrt(double(aWidth)/double(width())*double(height())/double(aHeight));
229 aCoeff = double(aWidth)/double(width());
230 aCamera->SetParallelScale(aScale*aCoeff);
241 Custom context menu event handler
244 QVTK_RenderWindowInteractor
245 ::contextMenuEvent( QContextMenuEvent* event )
249 Custom mouse move event handler
252 QVTK_RenderWindowInteractor
253 ::mouseMoveEvent( QMouseEvent* event )
255 GetDevice()->SetEventInformationFlipY(event->x(),
257 event->modifiers() & Qt::ControlModifier,
258 event->modifiers() & Qt::ShiftModifier);
259 GetDevice()->MouseMoveEvent();
264 Custom mouse press event handler
267 QVTK_RenderWindowInteractor
268 ::mousePressEvent( QMouseEvent* event )
270 GetDevice()->SetEventInformationFlipY(event->x(),
272 event->modifiers() & Qt::ControlModifier,
273 event->modifiers() & Qt::ShiftModifier);
274 if( event->button() & Qt::LeftButton )
275 GetDevice()->LeftButtonPressEvent();
276 else if( event->button() & Qt::MidButton )
277 GetDevice()->MiddleButtonPressEvent();
278 else if( event->button() & Qt::RightButton )
279 GetDevice()->RightButtonPressEvent();
284 Custom mouse release event handler
287 QVTK_RenderWindowInteractor
288 ::mouseReleaseEvent( QMouseEvent *event )
290 GetDevice()->SetEventInformationFlipY(event->x(),
292 event->modifiers() & Qt::ControlModifier,
293 event->modifiers() & Qt::ShiftModifier);
295 if( event->button() & Qt::LeftButton )
296 GetDevice()->LeftButtonReleaseEvent();
297 else if( event->button() & Qt::MidButton )
298 GetDevice()->MiddleButtonReleaseEvent();
299 else if( event->button() & Qt::RightButton ) {
300 #if defined(Fix_Of_vtkImplicitPlaneWidget_bug)
301 GetDevice()->SetEventInformationFlipY( -99999, -99999,
302 event->modifiers() & Qt::ControlModifier,
303 event->modifiers() & Qt::ShiftModifier);
304 bool blocked = blockSignals( true );
305 GetDevice()->LeftButtonPressEvent();
306 GetDevice()->LeftButtonReleaseEvent();
307 blockSignals( blocked );
308 GetDevice()->SetEventInformationFlipY(event->x(),
310 event->modifiers() & Qt::ControlModifier,
311 event->modifiers() & Qt::ShiftModifier);
313 GetDevice()->RightButtonReleaseEvent();
319 Custom mouse double click event handler
322 QVTK_RenderWindowInteractor
323 ::mouseDoubleClickEvent( QMouseEvent* event )
328 Custom mouse wheel event handler
331 QVTK_RenderWindowInteractor
332 ::wheelEvent( QWheelEvent* event )
336 GetDevice()->SetEventInformationFlipY(event->x(),
338 event->modifiers() & Qt::ControlModifier,
339 event->modifiers() & Qt::ShiftModifier);
340 if ( event->delta()>0)
341 GetDevice()->MouseWheelForwardEvent();
343 GetDevice()->MouseWheelBackwardEvent();
348 Custom key press event handler
351 QVTK_RenderWindowInteractor
352 ::keyPressEvent( QKeyEvent* event )
354 GetDevice()->SetKeyEventInformation(event->modifiers() & Qt::ControlModifier,
355 event->modifiers() & Qt::ShiftModifier,
357 GetDevice()->KeyPressEvent();
358 GetDevice()->CharEvent();
362 Custom key release event handler
365 QVTK_RenderWindowInteractor
366 ::keyReleaseEvent( QKeyEvent * event )
368 GetDevice()->SetKeyEventInformation(event->modifiers() & Qt::ControlModifier,
369 event->modifiers() & Qt::ShiftModifier,
371 GetDevice()->KeyReleaseEvent();
376 Custom enter event handler
379 QVTK_RenderWindowInteractor
380 ::enterEvent( QEvent* event )
382 if(FOCUS_UNDER_MOUSE){
386 GetDevice()->EnterEvent();
390 Custom leave event handler
393 QVTK_RenderWindowInteractor
394 ::leaveEvent( QEvent * )
396 GetDevice()->LeaveEvent();
400 Reimplemented from QWidget in order to set window - receiver
401 of space mouse events.
404 QVTK_RenderWindowInteractor
405 ::focusInEvent( QFocusEvent* event )
407 QWidget::focusInEvent( event );
410 // register set space mouse events receiver
411 SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance();
415 if ( !aSpaceMouse->isSpaceMouseOn() )
416 // initialize 3D space mouse driver
417 aSpaceMouse->initialize( QX11Info::display(), winId() );
419 aSpaceMouse->setWindow( QX11Info::display(), winId() );
425 Reimplemented from QWidget in order to set window - receiver
426 of space mouse events.
429 QVTK_RenderWindowInteractor
430 ::focusOutEvent ( QFocusEvent* event )
432 QWidget::focusOutEvent( event );
435 // unregister set space mouse events receiver
436 SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance();
437 if ( aSpaceMouse && aSpaceMouse->isSpaceMouseOn() )
438 aSpaceMouse->setWindow( QX11Info::display(), 0 );
446 To handle native Win32 events (from such devices as SpaceMouse)
448 bool QVTK_RenderWindowInteractor::winEvent( MSG* msg, long* result )
450 // TODO: Implement event handling for SpaceMouse
451 return QWidget::winEvent( msg, result);
457 To handle native X11 events (from such devices as SpaceMouse)
460 QVTK_RenderWindowInteractor
461 ::x11Event( XEvent *xEvent )
463 // handle 3d space mouse events
464 if ( SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance() )
466 if ( aSpaceMouse->isSpaceMouseOn() && xEvent->type == ClientMessage )
468 SVTK_SpaceMouse::MoveEvent anEvent;
469 int type = aSpaceMouse->translateEvent( QX11Info::display(), xEvent, &anEvent, 1.0, 1.0 );
472 case SVTK_SpaceMouse::SpaceMouseMove:
473 GetDevice()->InvokeEvent( SVTK::SpaceMouseMoveEvent, anEvent.data );
475 case SVTK_SpaceMouse::SpaceButtonPress:
476 GetDevice()->InvokeEvent( SVTK::SpaceMouseButtonEvent, &anEvent.button );
478 case SVTK_SpaceMouse::SpaceButtonRelease:
481 return true; // stop handling the event
485 return QWidget::x11Event( xEvent );
493 SVTK_RenderWindowInteractor
494 ::SVTK_RenderWindowInteractor(QWidget* theParent,
495 const char* theName):
496 QVTK_RenderWindowInteractor(theParent,theName),
497 myEventCallbackCommand(vtkCallbackCommand::New())
499 myEventCallbackCommand->Delete();
501 myEventCallbackCommand->SetClientData(this);
504 myEventCallbackCommand->SetCallback(SVTK_RenderWindowInteractor::ProcessEvents);
508 To initialize properly the class
511 SVTK_RenderWindowInteractor
512 ::Initialize(vtkGenericRenderWindowInteractor* theDevice,
513 SVTK_Renderer* theRenderer,
514 SVTK_Selector* theSelector)
516 QVTK_RenderWindowInteractor::Initialize(theDevice);
517 SetRenderer(theRenderer);
518 SetSelector(theSelector);
524 SVTK_RenderWindowInteractor
525 ::~SVTK_RenderWindowInteractor()
527 // Sequence of the destruction call are fixed and should be changed.
528 // vtkRenderWindow instance should be destroyed after all vtkRenderer's
529 GetDevice()->SetInteractorStyle(NULL);
530 while(!myInteractorStyles.empty()){
531 const PInteractorStyle& aStyle = myInteractorStyles.top();
532 aStyle->SetInteractor(NULL);
533 myInteractorStyles.pop();
538 GetDevice()->SetRenderWindow(NULL);
542 To get corresponding SVTK_Renderer instance
545 SVTK_RenderWindowInteractor
548 return myRenderer.GetPointer();
552 To get corresponding SVTK_Renderer device (just to simplify collobaration with SVTK_Renderer)
555 SVTK_RenderWindowInteractor
558 return GetRenderer()->GetDevice();
563 \param theRenderer - new renderer
566 SVTK_RenderWindowInteractor
567 ::SetRenderer(SVTK_Renderer* theRenderer)
569 if(theRenderer == myRenderer.GetPointer())
573 myRenderWindow->RemoveRenderer(getRenderer());
575 myRenderer = theRenderer;
578 myRenderWindow->AddRenderer(getRenderer());
583 Changes interactor style
584 \param theStyle - new interactor style
587 SVTK_RenderWindowInteractor
588 ::InitInteractorStyle(vtkInteractorStyle* theStyle)
590 GetDevice()->SetInteractorStyle(theStyle);
594 To change current interactor style by pushing the new one into the container
597 SVTK_RenderWindowInteractor
598 ::PushInteractorStyle(vtkInteractorStyle* theStyle)
600 myInteractorStyles.push(PInteractorStyle(theStyle));
601 InitInteractorStyle(theStyle);
605 To restore previous interactor style
608 SVTK_RenderWindowInteractor
609 ::PopInteractorStyle()
611 if(GetInteractorStyle())
612 myInteractorStyles.pop();
614 if(GetInteractorStyle())
615 InitInteractorStyle(GetInteractorStyle());
619 To get current interactor style
622 SVTK_RenderWindowInteractor
623 ::GetInteractorStyle()
625 return myInteractorStyles.empty() ? 0 : myInteractorStyles.top().GetPointer();
630 To get current selector
633 SVTK_RenderWindowInteractor
636 return mySelector.GetPointer();
642 \param theSelector - new selector
645 SVTK_RenderWindowInteractor
646 ::SetSelector(SVTK_Selector* theSelector)
648 if(mySelector.GetPointer())
649 mySelector->RemoveObserver(myEventCallbackCommand.GetPointer());
651 mySelector = theSelector;
653 if(mySelector.GetPointer())
654 mySelector->AddObserver(vtkCommand::EndPickEvent,
655 myEventCallbackCommand.GetPointer(),
660 Main process VTK event method
663 SVTK_RenderWindowInteractor
664 ::ProcessEvents(vtkObject* vtkNotUsed(theObject),
665 unsigned long theEvent,
667 void* vtkNotUsed(theCallData))
669 SVTK_RenderWindowInteractor* self = reinterpret_cast<SVTK_RenderWindowInteractor*>(theClientData);
672 case vtkCommand::EndPickEvent:
673 self->onEmitSelectionChanged();
679 To change selection mode (just to simplify collobaration with SVTK_Selector)
682 SVTK_RenderWindowInteractor
683 ::SetSelectionMode(Selection_Mode theMode)
685 mySelector->SetSelectionMode(theMode);
689 To get current selection mode (just to simplify collobaration with SVTK_Selector)
692 SVTK_RenderWindowInteractor
693 ::SelectionMode() const
695 return mySelector->SelectionMode();
700 Emits signal selectionChanged()
703 SVTK_RenderWindowInteractor
704 ::onEmitSelectionChanged()
706 return emit selectionChanged();
711 Custom mouse move event handler
714 SVTK_RenderWindowInteractor
715 ::mouseMoveEvent( QMouseEvent* event )
717 QVTK_RenderWindowInteractor::mouseMoveEvent(event);
719 if(GENERATE_SUIT_EVENTS)
720 emit MouseMove( event );
725 Custom mouse press event handler
728 SVTK_RenderWindowInteractor
729 ::mousePressEvent( QMouseEvent* event )
731 QVTK_RenderWindowInteractor::mousePressEvent(event);
733 if(GENERATE_SUIT_EVENTS)
734 emit MouseButtonPressed( event );
739 Custom mouse release event handler
742 SVTK_RenderWindowInteractor
743 ::mouseReleaseEvent( QMouseEvent *event )
745 SVTK_InteractorStyle* style = 0;
746 bool aRightBtn = event->button() == Qt::RightButton;
747 bool isOperation = false;
748 bool isPolygonalSelection = false;
749 if( aRightBtn && GetInteractorStyle()) {
750 style = dynamic_cast<SVTK_InteractorStyle*>( GetInteractorStyle() );
752 isOperation = style->CurrentState() != VTK_INTERACTOR_STYLE_CAMERA_NONE;
755 QVTK_RenderWindowInteractor::mouseReleaseEvent(event);
758 isPolygonalSelection = style->GetPolygonState() == Finished;
759 style->SetPolygonState( Disable );
762 if ( aRightBtn && !isOperation && !isPolygonalSelection &&
763 !( event->modifiers() & Qt::ControlModifier ) &&
764 !( event->modifiers() & Qt::ShiftModifier ) ) {
765 QContextMenuEvent aEvent( QContextMenuEvent::Mouse,
766 event->pos(), event->globalPos() );
767 emit contextMenuRequested( &aEvent );
769 if(GENERATE_SUIT_EVENTS)
770 emit MouseButtonReleased( event );
775 Custom mouse double click event handler
778 SVTK_RenderWindowInteractor
779 ::mouseDoubleClickEvent( QMouseEvent* event )
781 if( GetInteractorStyle() && event->button() == Qt::LeftButton ) {
782 SVTK_InteractorStyle* style = dynamic_cast<SVTK_InteractorStyle*>( GetInteractorStyle() );
784 style->OnMouseButtonDoubleClick();
787 QVTK_RenderWindowInteractor::mouseDoubleClickEvent(event);
789 if(GENERATE_SUIT_EVENTS)
790 emit MouseDoubleClicked( event );
795 Custom mouse wheel event handler
798 SVTK_RenderWindowInteractor
799 ::wheelEvent( QWheelEvent* event )
801 QVTK_RenderWindowInteractor::wheelEvent(event);
803 if(event->delta() > 0)
804 GetDevice()->InvokeEvent(SVTK::ZoomInEvent,NULL);
806 GetDevice()->InvokeEvent(SVTK::ZoomOutEvent,NULL);
808 if(GENERATE_SUIT_EVENTS)
809 emit WheelMoved( event );
813 Custom key press event handler
816 SVTK_RenderWindowInteractor
817 ::keyPressEvent( QKeyEvent* event )
819 QVTK_RenderWindowInteractor::keyPressEvent(event);
821 if(GENERATE_SUIT_EVENTS)
822 emit KeyPressed( event );
826 Custom key release event handler
829 SVTK_RenderWindowInteractor
830 ::keyReleaseEvent( QKeyEvent * event )
832 QVTK_RenderWindowInteractor::keyReleaseEvent(event);
834 if(GENERATE_SUIT_EVENTS)
835 emit KeyReleased( event );