1 // Copyright (C) 2007-2008 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
22 // SALOME VTKViewer : build VTK viewer into Salome desktop
28 #include "SVTK_RenderWindowInteractor.h"
29 //#include "SVTK_GenericRenderWindowInteractor.h"
31 #include "SVTK_InteractorStyle.h"
32 #include "SVTK_Renderer.h"
33 #include "SVTK_Functor.h"
34 #include "SALOME_Actor.h"
37 // Put Qt includes before the X11 includes which #define the symbol None
38 // (see SVTK_SpaceMouse.h) to avoid the compilation error.
42 #include <QMouseEvent>
44 #include "SVTK_SpaceMouse.h"
45 #include "SVTK_Event.h"
47 #include "VTKViewer_Algorithm.h"
50 #include <vtkObjectFactory.h>
51 #include <vtkRendererCollection.h>
52 #include <vtkRenderWindow.h>
53 #include <vtkGenericRenderWindowInteractor.h>
54 #include <vtkCallbackCommand.h>
55 #include <vtkCommand.h>
56 #include <vtkPicker.h>
57 #include <vtkCamera.h>
61 static bool GENERATE_SUIT_EVENTS = false;
62 static bool FOCUS_UNDER_MOUSE = false;
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 Need for initial contents display on Win32
154 QVTK_RenderWindowInteractor
158 update(); // needed for initial contents display on Win32
162 To implement final initialization, just before the widget is displayed
165 QVTK_RenderWindowInteractor
168 // Final initialization just before the widget is displayed
169 GetDevice()->SetSize(width(),height());
170 if(!GetDevice()->GetInitialized() && GetDevice()->GetRenderWindow()){
171 GetDevice()->Initialize();
172 GetDevice()->ConfigureEvent();
177 To adjust widget and vtkRenderWindow size
180 QVTK_RenderWindowInteractor
181 ::resize(int w, int h)
183 GetDevice()->UpdateSize(w,h);
187 Custom paint event handler
190 QVTK_RenderWindowInteractor
191 ::paintEvent( QPaintEvent* theEvent )
193 GetDevice()->CreateTimer(VTKI_TIMER_FIRST);
198 Custom resize event handler
201 QVTK_RenderWindowInteractor
202 ::resizeEvent( QResizeEvent* theEvent )
204 int* aSize = getRenderWindow()->GetSize();
205 int aWidth = aSize[0];
206 int aHeight = aSize[1];
208 GetDevice()->UpdateSize(width(),height());
210 if(isVisible() && aWidth && aHeight){
211 if( aWidth != width() || aHeight != height() ) {
212 vtkRendererCollection * aRenderers = getRenderWindow()->GetRenderers();
213 aRenderers->InitTraversal();
215 if(vtkRenderer *aRenderer = aRenderers->GetNextItem()) {
216 vtkCamera *aCamera = aRenderer->GetActiveCamera();
217 double aScale = aCamera->GetParallelScale();
218 if((aWidth - width())*(aHeight - height()) > 0)
219 aCoeff = sqrt(double(aWidth)/double(width())*double(height())/double(aHeight));
221 aCoeff = double(aWidth)/double(width());
222 aCamera->SetParallelScale(aScale*aCoeff);
233 Custom context menu event handler
236 QVTK_RenderWindowInteractor
237 ::contextMenuEvent( QContextMenuEvent* event )
241 Custom mouse move event handler
244 QVTK_RenderWindowInteractor
245 ::mouseMoveEvent( QMouseEvent* event )
247 GetDevice()->SetEventInformationFlipY(event->x(),
249 event->modifiers() & Qt::ControlModifier,
250 event->modifiers() & Qt::ShiftModifier);
251 GetDevice()->MouseMoveEvent();
256 Custom mouse press event handler
259 QVTK_RenderWindowInteractor
260 ::mousePressEvent( QMouseEvent* event )
262 GetDevice()->SetEventInformationFlipY(event->x(),
264 event->modifiers() & Qt::ControlModifier,
265 event->modifiers() & Qt::ShiftModifier);
266 if( event->button() & Qt::LeftButton )
267 GetDevice()->LeftButtonPressEvent();
268 else if( event->button() & Qt::MidButton )
269 GetDevice()->MiddleButtonPressEvent();
270 else if( event->button() & Qt::RightButton )
271 GetDevice()->RightButtonPressEvent();
276 Custom mouse release event handler
279 QVTK_RenderWindowInteractor
280 ::mouseReleaseEvent( QMouseEvent *event )
282 GetDevice()->SetEventInformationFlipY(event->x(),
284 event->modifiers() & Qt::ControlModifier,
285 event->modifiers() & Qt::ShiftModifier);
287 if( event->button() & Qt::LeftButton )
288 GetDevice()->LeftButtonReleaseEvent();
289 else if( event->button() & Qt::MidButton )
290 GetDevice()->MiddleButtonReleaseEvent();
291 else if( event->button() & Qt::RightButton )
292 GetDevice()->RightButtonReleaseEvent();
297 Custom mouse double click event handler
300 QVTK_RenderWindowInteractor
301 ::mouseDoubleClickEvent( QMouseEvent* event )
306 Custom mouse wheel event handler
309 QVTK_RenderWindowInteractor
310 ::wheelEvent( QWheelEvent* event )
318 Custom key press event handler
321 QVTK_RenderWindowInteractor
322 ::keyPressEvent( QKeyEvent* event )
324 GetDevice()->SetKeyEventInformation(event->modifiers() & Qt::ControlModifier,
325 event->modifiers() & Qt::ShiftModifier,
327 GetDevice()->KeyPressEvent();
328 GetDevice()->CharEvent();
332 Custom key release event handler
335 QVTK_RenderWindowInteractor
336 ::keyReleaseEvent( QKeyEvent * event )
338 GetDevice()->SetKeyEventInformation(event->modifiers() & Qt::ControlModifier,
339 event->modifiers() & Qt::ShiftModifier,
341 GetDevice()->KeyReleaseEvent();
346 Custom enter event handler
349 QVTK_RenderWindowInteractor
350 ::enterEvent( QEvent* event )
352 if(FOCUS_UNDER_MOUSE){
356 GetDevice()->EnterEvent();
360 Custom leave event handler
363 QVTK_RenderWindowInteractor
364 ::leaveEvent( QEvent * )
366 GetDevice()->LeaveEvent();
370 Reimplemented from QWidget in order to set window - receiver
371 of space mouse events.
374 QVTK_RenderWindowInteractor
375 ::focusInEvent( QFocusEvent* event )
377 QWidget::focusInEvent( event );
380 // register set space mouse events receiver
381 SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance();
385 if ( !aSpaceMouse->isSpaceMouseOn() )
386 // initialize 3D space mouse driver
387 aSpaceMouse->initialize( QX11Info::display(), winId() );
389 aSpaceMouse->setWindow( QX11Info::display(), winId() );
395 Reimplemented from QWidget in order to set window - receiver
396 of space mouse events.
399 QVTK_RenderWindowInteractor
400 ::focusOutEvent ( QFocusEvent* event )
402 QWidget::focusOutEvent( event );
405 // unregister set space mouse events receiver
406 SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance();
407 if ( aSpaceMouse && aSpaceMouse->isSpaceMouseOn() )
408 aSpaceMouse->setWindow( QX11Info::display(), 0 );
416 To handle native Win32 events (from such devices as SpaceMouse)
418 bool QVTK_RenderWindowInteractor::winEvent( MSG* msg, long* result )
420 // TODO: Implement event handling for SpaceMouse
421 return QWidget::winEvent( msg, result);
427 To handle native X11 events (from such devices as SpaceMouse)
430 QVTK_RenderWindowInteractor
431 ::x11Event( XEvent *xEvent )
433 // handle 3d space mouse events
434 if ( SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance() )
436 if ( aSpaceMouse->isSpaceMouseOn() && xEvent->type == ClientMessage )
438 SVTK_SpaceMouse::MoveEvent anEvent;
439 int type = aSpaceMouse->translateEvent( QX11Info::display(), xEvent, &anEvent, 1.0, 1.0 );
442 case SVTK_SpaceMouse::SpaceMouseMove:
443 GetDevice()->InvokeEvent( SVTK::SpaceMouseMoveEvent, anEvent.data );
445 case SVTK_SpaceMouse::SpaceButtonPress:
446 GetDevice()->InvokeEvent( SVTK::SpaceMouseButtonEvent, &anEvent.button );
448 case SVTK_SpaceMouse::SpaceButtonRelease:
451 return true; // stop handling the event
455 return QWidget::x11Event( xEvent );
463 SVTK_RenderWindowInteractor
464 ::SVTK_RenderWindowInteractor(QWidget* theParent,
465 const char* theName):
466 QVTK_RenderWindowInteractor(theParent,theName),
467 myEventCallbackCommand(vtkCallbackCommand::New())
469 myEventCallbackCommand->Delete();
471 myEventCallbackCommand->SetClientData(this);
474 myEventCallbackCommand->SetCallback(SVTK_RenderWindowInteractor::ProcessEvents);
478 To initialize properly the class
481 SVTK_RenderWindowInteractor
482 ::Initialize(vtkGenericRenderWindowInteractor* theDevice,
483 SVTK_Renderer* theRenderer,
484 SVTK_Selector* theSelector)
486 QVTK_RenderWindowInteractor::Initialize(theDevice);
487 SetRenderer(theRenderer);
488 SetSelector(theSelector);
494 SVTK_RenderWindowInteractor
495 ::~SVTK_RenderWindowInteractor()
497 // Sequence of the destruction call are fixed and should be changed.
498 // vtkRenderWindow instance should be destroyed after all vtkRenderer's
499 GetDevice()->SetInteractorStyle(NULL);
500 while(!myInteractorStyles.empty()){
501 const PInteractorStyle& aStyle = myInteractorStyles.top();
502 aStyle->SetInteractor(NULL);
503 myInteractorStyles.pop();
508 GetDevice()->SetRenderWindow(NULL);
512 To get corresponding SVTK_Renderer instance
515 SVTK_RenderWindowInteractor
518 return myRenderer.GetPointer();
522 To get corresponding SVTK_Renderer device (just to simplify collobaration with SVTK_Renderer)
525 SVTK_RenderWindowInteractor
528 return GetRenderer()->GetDevice();
533 \param theRenderer - new renderer
536 SVTK_RenderWindowInteractor
537 ::SetRenderer(SVTK_Renderer* theRenderer)
539 if(theRenderer == myRenderer.GetPointer())
543 myRenderWindow->RemoveRenderer(getRenderer());
545 myRenderer = theRenderer;
548 myRenderWindow->AddRenderer(getRenderer());
553 Changes interactor style
554 \param theStyle - new interactor style
557 SVTK_RenderWindowInteractor
558 ::InitInteractorStyle(vtkInteractorStyle* theStyle)
560 GetDevice()->SetInteractorStyle(theStyle);
564 To change current interactor style by pushing the new one into the container
567 SVTK_RenderWindowInteractor
568 ::PushInteractorStyle(vtkInteractorStyle* theStyle)
570 myInteractorStyles.push(PInteractorStyle(theStyle));
571 InitInteractorStyle(theStyle);
575 To restore previous interactor style
578 SVTK_RenderWindowInteractor
579 ::PopInteractorStyle()
581 if(GetInteractorStyle())
582 myInteractorStyles.pop();
584 if(GetInteractorStyle())
585 InitInteractorStyle(GetInteractorStyle());
589 To get current interactor style
592 SVTK_RenderWindowInteractor
593 ::GetInteractorStyle()
595 return myInteractorStyles.empty() ? 0 : myInteractorStyles.top().GetPointer();
600 To get current selector
603 SVTK_RenderWindowInteractor
606 return mySelector.GetPointer();
612 \param theSelector - new selector
615 SVTK_RenderWindowInteractor
616 ::SetSelector(SVTK_Selector* theSelector)
618 if(mySelector.GetPointer())
619 mySelector->RemoveObserver(myEventCallbackCommand.GetPointer());
621 mySelector = theSelector;
623 if(mySelector.GetPointer())
624 mySelector->AddObserver(vtkCommand::EndPickEvent,
625 myEventCallbackCommand.GetPointer(),
630 Main process VTK event method
633 SVTK_RenderWindowInteractor
634 ::ProcessEvents(vtkObject* vtkNotUsed(theObject),
635 unsigned long theEvent,
637 void* vtkNotUsed(theCallData))
639 SVTK_RenderWindowInteractor* self = reinterpret_cast<SVTK_RenderWindowInteractor*>(theClientData);
642 case vtkCommand::EndPickEvent:
643 self->onEmitSelectionChanged();
649 To change selection mode (just to simplify collobaration with SVTK_Selector)
652 SVTK_RenderWindowInteractor
653 ::SetSelectionMode(Selection_Mode theMode)
655 mySelector->SetSelectionMode(theMode);
659 To get current selection mode (just to simplify collobaration with SVTK_Selector)
662 SVTK_RenderWindowInteractor
663 ::SelectionMode() const
665 return mySelector->SelectionMode();
670 Emits signal selectionChanged()
673 SVTK_RenderWindowInteractor
674 ::onEmitSelectionChanged()
676 return emit selectionChanged();
681 Custom mouse move event handler
684 SVTK_RenderWindowInteractor
685 ::mouseMoveEvent( QMouseEvent* event )
687 QVTK_RenderWindowInteractor::mouseMoveEvent(event);
689 if(GENERATE_SUIT_EVENTS)
690 emit MouseMove( event );
695 Custom mouse press event handler
698 SVTK_RenderWindowInteractor
699 ::mousePressEvent( QMouseEvent* event )
701 QVTK_RenderWindowInteractor::mousePressEvent(event);
703 if(GENERATE_SUIT_EVENTS)
704 emit MouseButtonPressed( event );
709 Custom mouse release event handler
712 SVTK_RenderWindowInteractor
713 ::mouseReleaseEvent( QMouseEvent *event )
715 bool aRightBtn = event->button() == Qt::RightButton;
716 bool isOperation = false;
717 if( aRightBtn && GetInteractorStyle()) {
718 SVTK_InteractorStyle* style = dynamic_cast<SVTK_InteractorStyle*>( GetInteractorStyle() );
720 isOperation = style->CurrentState() != VTK_INTERACTOR_STYLE_CAMERA_NONE;
723 QVTK_RenderWindowInteractor::mouseReleaseEvent(event);
725 if ( aRightBtn && !isOperation && !( event->modifiers() & Qt::ControlModifier ) &&
726 !( event->modifiers() & Qt::ShiftModifier ) ) {
727 QContextMenuEvent aEvent( QContextMenuEvent::Mouse,
728 event->pos(), event->globalPos() );
729 emit contextMenuRequested( &aEvent );
731 if(GENERATE_SUIT_EVENTS)
732 emit MouseButtonReleased( event );
737 Custom mouse double click event handler
740 SVTK_RenderWindowInteractor
741 ::mouseDoubleClickEvent( QMouseEvent* event )
743 QVTK_RenderWindowInteractor::mouseDoubleClickEvent(event);
745 if(GENERATE_SUIT_EVENTS)
746 emit MouseDoubleClicked( event );
751 Custom mouse wheel event handler
754 SVTK_RenderWindowInteractor
755 ::wheelEvent( QWheelEvent* event )
757 QVTK_RenderWindowInteractor::wheelEvent(event);
759 if(event->delta() > 0)
760 GetDevice()->InvokeEvent(SVTK::ZoomInEvent,NULL);
762 GetDevice()->InvokeEvent(SVTK::ZoomOutEvent,NULL);
764 if(GENERATE_SUIT_EVENTS)
765 emit WheelMoved( event );
769 Custom key press event handler
772 SVTK_RenderWindowInteractor
773 ::keyPressEvent( QKeyEvent* event )
775 QVTK_RenderWindowInteractor::keyPressEvent(event);
777 if(GENERATE_SUIT_EVENTS)
778 emit KeyPressed( event );
782 Custom key release event handler
785 SVTK_RenderWindowInteractor
786 ::keyReleaseEvent( QKeyEvent * event )
788 QVTK_RenderWindowInteractor::keyReleaseEvent(event);
790 if(GENERATE_SUIT_EVENTS)
791 emit KeyReleased( event );