1 // Copyright (C) 2007-2013 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.
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;
64 QVTK_RenderWindowInteractor
65 ::QVTK_RenderWindowInteractor(QWidget* theParent,
68 myRenderWindow(vtkRenderWindow::New())
70 setAttribute( Qt::WA_PaintOnScreen );
71 setAttribute( Qt::WA_NoSystemBackground );
73 setObjectName(theName);
75 setMouseTracking(true);
77 myRenderWindow->Delete();
78 myRenderWindow->DoubleBufferOn();
81 myRenderWindow->SetDisplayId((void*)QX11Info::display());
83 myRenderWindow->SetWindowId((void*)winId());
87 To initialize by vtkGenericRenderWindowInteractor instance
90 QVTK_RenderWindowInteractor
91 ::Initialize(vtkGenericRenderWindowInteractor* theDevice)
94 myDevice->SetRenderWindow( NULL );
99 theDevice->SetRenderWindow( getRenderWindow() );
105 QVTK_RenderWindowInteractor
106 ::~QVTK_RenderWindowInteractor()
109 SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance();
110 if ( aSpaceMouse && aSpaceMouse->isSpaceMouseOn() )
111 aSpaceMouse->close( QX11Info::display() );
117 \return corresponding render window interactor
119 vtkGenericRenderWindowInteractor*
120 QVTK_RenderWindowInteractor
123 return myDevice.GetPointer();
127 \return corresponding render window
130 QVTK_RenderWindowInteractor
133 return myRenderWindow.GetPointer();
137 Just to simplify usage of its device (vtkGenericRenderWindowInteractor)
140 QVTK_RenderWindowInteractor
141 ::InvokeEvent(unsigned long theEvent, void* theCallData)
143 GetDevice()->InvokeEvent(theEvent,theCallData);
147 Get paint engine for the scene
149 QPaintEngine* QVTK_RenderWindowInteractor::paintEngine() const
155 Need for initial contents display on Win32
158 QVTK_RenderWindowInteractor
162 update(); // needed for initial contents display on Win32
166 To implement final initialization, just before the widget is displayed
169 QVTK_RenderWindowInteractor
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();
181 To adjust widget and vtkRenderWindow size
184 QVTK_RenderWindowInteractor
185 ::resize(int w, int h)
187 GetDevice()->UpdateSize(w,h);
191 Custom paint event handler
194 QVTK_RenderWindowInteractor
195 ::paintEvent( QPaintEvent* theEvent )
197 GetDevice()->CreateTimer(VTKI_TIMER_FIRST);
202 Custom resize event handler
205 QVTK_RenderWindowInteractor
206 ::resizeEvent( QResizeEvent* theEvent )
208 int* aSize = getRenderWindow()->GetSize();
209 int aWidth = aSize[0];
210 int aHeight = aSize[1];
212 GetDevice()->UpdateSize(width(),height());
214 if(isVisible() && aWidth && aHeight){
215 if( aWidth != width() || aHeight != height() ) {
216 vtkRendererCollection * aRenderers = getRenderWindow()->GetRenderers();
217 aRenderers->InitTraversal();
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));
225 aCoeff = double(aWidth)/double(width());
226 aCamera->SetParallelScale(aScale*aCoeff);
237 Custom context menu event handler
240 QVTK_RenderWindowInteractor
241 ::contextMenuEvent( QContextMenuEvent* event )
245 Custom mouse move event handler
248 QVTK_RenderWindowInteractor
249 ::mouseMoveEvent( QMouseEvent* event )
251 GetDevice()->SetEventInformationFlipY(event->x(),
253 event->modifiers() & Qt::ControlModifier,
254 event->modifiers() & Qt::ShiftModifier);
255 GetDevice()->MouseMoveEvent();
260 Custom mouse press event handler
263 QVTK_RenderWindowInteractor
264 ::mousePressEvent( QMouseEvent* event )
266 GetDevice()->SetEventInformationFlipY(event->x(),
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();
280 Custom mouse release event handler
283 QVTK_RenderWindowInteractor
284 ::mouseReleaseEvent( QMouseEvent *event )
286 GetDevice()->SetEventInformationFlipY(event->x(),
288 event->modifiers() & Qt::ControlModifier,
289 event->modifiers() & Qt::ShiftModifier);
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 #ifndef Fix_Of_vtkImplicitPlaneWidget_bug
297 GetDevice()->SetEventInformationFlipY( -99999, -99999,
298 event->modifiers() & Qt::ControlModifier,
299 event->modifiers() & Qt::ShiftModifier);
300 GetDevice()->LeftButtonPressEvent();
301 GetDevice()->LeftButtonReleaseEvent();
302 GetDevice()->SetEventInformationFlipY(event->x(),
304 event->modifiers() & Qt::ControlModifier,
305 event->modifiers() & Qt::ShiftModifier);
307 GetDevice()->RightButtonReleaseEvent();
313 Custom mouse double click event handler
316 QVTK_RenderWindowInteractor
317 ::mouseDoubleClickEvent( QMouseEvent* event )
322 Custom mouse wheel event handler
325 QVTK_RenderWindowInteractor
326 ::wheelEvent( QWheelEvent* event )
330 GetDevice()->SetEventInformationFlipY(event->x(),
332 event->modifiers() & Qt::ControlModifier,
333 event->modifiers() & Qt::ShiftModifier);
334 if ( event->delta()>0)
335 GetDevice()->MouseWheelForwardEvent();
337 GetDevice()->MouseWheelBackwardEvent();
342 Custom key press event handler
345 QVTK_RenderWindowInteractor
346 ::keyPressEvent( QKeyEvent* event )
348 GetDevice()->SetKeyEventInformation(event->modifiers() & Qt::ControlModifier,
349 event->modifiers() & Qt::ShiftModifier,
351 GetDevice()->KeyPressEvent();
352 GetDevice()->CharEvent();
356 Custom key release event handler
359 QVTK_RenderWindowInteractor
360 ::keyReleaseEvent( QKeyEvent * event )
362 GetDevice()->SetKeyEventInformation(event->modifiers() & Qt::ControlModifier,
363 event->modifiers() & Qt::ShiftModifier,
365 GetDevice()->KeyReleaseEvent();
370 Custom enter event handler
373 QVTK_RenderWindowInteractor
374 ::enterEvent( QEvent* event )
376 if(FOCUS_UNDER_MOUSE){
380 GetDevice()->EnterEvent();
384 Custom leave event handler
387 QVTK_RenderWindowInteractor
388 ::leaveEvent( QEvent * )
390 GetDevice()->LeaveEvent();
394 Reimplemented from QWidget in order to set window - receiver
395 of space mouse events.
398 QVTK_RenderWindowInteractor
399 ::focusInEvent( QFocusEvent* event )
401 QWidget::focusInEvent( event );
404 // register set space mouse events receiver
405 SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance();
409 if ( !aSpaceMouse->isSpaceMouseOn() )
410 // initialize 3D space mouse driver
411 aSpaceMouse->initialize( QX11Info::display(), winId() );
413 aSpaceMouse->setWindow( QX11Info::display(), winId() );
419 Reimplemented from QWidget in order to set window - receiver
420 of space mouse events.
423 QVTK_RenderWindowInteractor
424 ::focusOutEvent ( QFocusEvent* event )
426 QWidget::focusOutEvent( event );
429 // unregister set space mouse events receiver
430 SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance();
431 if ( aSpaceMouse && aSpaceMouse->isSpaceMouseOn() )
432 aSpaceMouse->setWindow( QX11Info::display(), 0 );
440 To handle native Win32 events (from such devices as SpaceMouse)
442 bool QVTK_RenderWindowInteractor::winEvent( MSG* msg, long* result )
444 // TODO: Implement event handling for SpaceMouse
445 return QWidget::winEvent( msg, result);
451 To handle native X11 events (from such devices as SpaceMouse)
454 QVTK_RenderWindowInteractor
455 ::x11Event( XEvent *xEvent )
457 // handle 3d space mouse events
458 if ( SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance() )
460 if ( aSpaceMouse->isSpaceMouseOn() && xEvent->type == ClientMessage )
462 SVTK_SpaceMouse::MoveEvent anEvent;
463 int type = aSpaceMouse->translateEvent( QX11Info::display(), xEvent, &anEvent, 1.0, 1.0 );
466 case SVTK_SpaceMouse::SpaceMouseMove:
467 GetDevice()->InvokeEvent( SVTK::SpaceMouseMoveEvent, anEvent.data );
469 case SVTK_SpaceMouse::SpaceButtonPress:
470 GetDevice()->InvokeEvent( SVTK::SpaceMouseButtonEvent, &anEvent.button );
472 case SVTK_SpaceMouse::SpaceButtonRelease:
475 return true; // stop handling the event
479 return QWidget::x11Event( xEvent );
487 SVTK_RenderWindowInteractor
488 ::SVTK_RenderWindowInteractor(QWidget* theParent,
489 const char* theName):
490 QVTK_RenderWindowInteractor(theParent,theName),
491 myEventCallbackCommand(vtkCallbackCommand::New())
493 myEventCallbackCommand->Delete();
495 myEventCallbackCommand->SetClientData(this);
498 myEventCallbackCommand->SetCallback(SVTK_RenderWindowInteractor::ProcessEvents);
502 To initialize properly the class
505 SVTK_RenderWindowInteractor
506 ::Initialize(vtkGenericRenderWindowInteractor* theDevice,
507 SVTK_Renderer* theRenderer,
508 SVTK_Selector* theSelector)
510 QVTK_RenderWindowInteractor::Initialize(theDevice);
511 SetRenderer(theRenderer);
512 SetSelector(theSelector);
518 SVTK_RenderWindowInteractor
519 ::~SVTK_RenderWindowInteractor()
521 // Sequence of the destruction call are fixed and should be changed.
522 // vtkRenderWindow instance should be destroyed after all vtkRenderer's
523 GetDevice()->SetInteractorStyle(NULL);
524 while(!myInteractorStyles.empty()){
525 const PInteractorStyle& aStyle = myInteractorStyles.top();
526 aStyle->SetInteractor(NULL);
527 myInteractorStyles.pop();
532 GetDevice()->SetRenderWindow(NULL);
536 To get corresponding SVTK_Renderer instance
539 SVTK_RenderWindowInteractor
542 return myRenderer.GetPointer();
546 To get corresponding SVTK_Renderer device (just to simplify collobaration with SVTK_Renderer)
549 SVTK_RenderWindowInteractor
552 return GetRenderer()->GetDevice();
557 \param theRenderer - new renderer
560 SVTK_RenderWindowInteractor
561 ::SetRenderer(SVTK_Renderer* theRenderer)
563 if(theRenderer == myRenderer.GetPointer())
567 myRenderWindow->RemoveRenderer(getRenderer());
569 myRenderer = theRenderer;
572 myRenderWindow->AddRenderer(getRenderer());
577 Changes interactor style
578 \param theStyle - new interactor style
581 SVTK_RenderWindowInteractor
582 ::InitInteractorStyle(vtkInteractorStyle* theStyle)
584 GetDevice()->SetInteractorStyle(theStyle);
588 To change current interactor style by pushing the new one into the container
591 SVTK_RenderWindowInteractor
592 ::PushInteractorStyle(vtkInteractorStyle* theStyle)
594 myInteractorStyles.push(PInteractorStyle(theStyle));
595 InitInteractorStyle(theStyle);
599 To restore previous interactor style
602 SVTK_RenderWindowInteractor
603 ::PopInteractorStyle()
605 if(GetInteractorStyle())
606 myInteractorStyles.pop();
608 if(GetInteractorStyle())
609 InitInteractorStyle(GetInteractorStyle());
613 To get current interactor style
616 SVTK_RenderWindowInteractor
617 ::GetInteractorStyle()
619 return myInteractorStyles.empty() ? 0 : myInteractorStyles.top().GetPointer();
624 To get current selector
627 SVTK_RenderWindowInteractor
630 return mySelector.GetPointer();
636 \param theSelector - new selector
639 SVTK_RenderWindowInteractor
640 ::SetSelector(SVTK_Selector* theSelector)
642 if(mySelector.GetPointer())
643 mySelector->RemoveObserver(myEventCallbackCommand.GetPointer());
645 mySelector = theSelector;
647 if(mySelector.GetPointer())
648 mySelector->AddObserver(vtkCommand::EndPickEvent,
649 myEventCallbackCommand.GetPointer(),
654 Main process VTK event method
657 SVTK_RenderWindowInteractor
658 ::ProcessEvents(vtkObject* vtkNotUsed(theObject),
659 unsigned long theEvent,
661 void* vtkNotUsed(theCallData))
663 SVTK_RenderWindowInteractor* self = reinterpret_cast<SVTK_RenderWindowInteractor*>(theClientData);
666 case vtkCommand::EndPickEvent:
667 self->onEmitSelectionChanged();
673 To change selection mode (just to simplify collobaration with SVTK_Selector)
676 SVTK_RenderWindowInteractor
677 ::SetSelectionMode(Selection_Mode theMode)
679 mySelector->SetSelectionMode(theMode);
683 To get current selection mode (just to simplify collobaration with SVTK_Selector)
686 SVTK_RenderWindowInteractor
687 ::SelectionMode() const
689 return mySelector->SelectionMode();
694 Emits signal selectionChanged()
697 SVTK_RenderWindowInteractor
698 ::onEmitSelectionChanged()
700 return emit selectionChanged();
705 Custom mouse move event handler
708 SVTK_RenderWindowInteractor
709 ::mouseMoveEvent( QMouseEvent* event )
711 QVTK_RenderWindowInteractor::mouseMoveEvent(event);
713 if(GENERATE_SUIT_EVENTS)
714 emit MouseMove( event );
719 Custom mouse press event handler
722 SVTK_RenderWindowInteractor
723 ::mousePressEvent( QMouseEvent* event )
725 QVTK_RenderWindowInteractor::mousePressEvent(event);
727 if(GENERATE_SUIT_EVENTS)
728 emit MouseButtonPressed( event );
733 Custom mouse release event handler
736 SVTK_RenderWindowInteractor
737 ::mouseReleaseEvent( QMouseEvent *event )
739 SVTK_InteractorStyle* style = 0;
740 bool aRightBtn = event->button() == Qt::RightButton;
741 bool isOperation = false;
742 bool isPolygonalSelection = false;
743 if( aRightBtn && GetInteractorStyle()) {
744 style = dynamic_cast<SVTK_InteractorStyle*>( GetInteractorStyle() );
746 isOperation = style->CurrentState() != VTK_INTERACTOR_STYLE_CAMERA_NONE;
749 QVTK_RenderWindowInteractor::mouseReleaseEvent(event);
752 isPolygonalSelection = style->GetPolygonState() == Finished;
753 style->SetPolygonState( Disable );
756 if ( aRightBtn && !isOperation && !isPolygonalSelection &&
757 !( event->modifiers() & Qt::ControlModifier ) &&
758 !( event->modifiers() & Qt::ShiftModifier ) ) {
759 QContextMenuEvent aEvent( QContextMenuEvent::Mouse,
760 event->pos(), event->globalPos() );
761 emit contextMenuRequested( &aEvent );
763 if(GENERATE_SUIT_EVENTS)
764 emit MouseButtonReleased( event );
769 Custom mouse double click event handler
772 SVTK_RenderWindowInteractor
773 ::mouseDoubleClickEvent( QMouseEvent* event )
775 if( GetInteractorStyle() && event->button() == Qt::LeftButton ) {
776 SVTK_InteractorStyle* style = dynamic_cast<SVTK_InteractorStyle*>( GetInteractorStyle() );
778 style->OnMouseButtonDoubleClick();
781 QVTK_RenderWindowInteractor::mouseDoubleClickEvent(event);
783 if(GENERATE_SUIT_EVENTS)
784 emit MouseDoubleClicked( event );
789 Custom mouse wheel event handler
792 SVTK_RenderWindowInteractor
793 ::wheelEvent( QWheelEvent* event )
795 QVTK_RenderWindowInteractor::wheelEvent(event);
797 if(event->delta() > 0)
798 GetDevice()->InvokeEvent(SVTK::ZoomInEvent,NULL);
800 GetDevice()->InvokeEvent(SVTK::ZoomOutEvent,NULL);
802 if(GENERATE_SUIT_EVENTS)
803 emit WheelMoved( event );
807 Custom key press event handler
810 SVTK_RenderWindowInteractor
811 ::keyPressEvent( QKeyEvent* event )
813 QVTK_RenderWindowInteractor::keyPressEvent(event);
815 if(GENERATE_SUIT_EVENTS)
816 emit KeyPressed( event );
820 Custom key release event handler
823 SVTK_RenderWindowInteractor
824 ::keyReleaseEvent( QKeyEvent * event )
826 QVTK_RenderWindowInteractor::keyReleaseEvent(event);
828 if(GENERATE_SUIT_EVENTS)
829 emit KeyReleased( event );