1 // SALOME VTKViewer : build VTK viewer into Salome desktop
3 // Copyright (C) 2003 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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
29 #include "SVTK_RenderWindowInteractor.h"
30 #include "SVTK_GenericRenderWindowInteractor.h"
32 #include "SVTK_InteractorStyle.h"
33 #include "SVTK_Renderer.h"
34 #include "SVTK_Functor.h"
35 #include "SALOME_Actor.h"
37 #include "SVTK_SpaceMouse.h"
38 #include "SVTK_Event.h"
40 #include "VTKViewer_Algorithm.h"
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>
54 #include <qapplication.h>
55 #include <qcolordialog.h>
56 #include <qpaintdevice.h>
60 static bool GENERATE_SUIT_EVENTS = false;
61 static bool FOCUS_UNDER_MOUSE = false;
67 QVTK_RenderWindowInteractor
68 ::QVTK_RenderWindowInteractor(QWidget* theParent,
70 QWidget(theParent,theName,Qt::WNoAutoErase),
71 myRenderWindow(vtkRenderWindow::New())
73 setMouseTracking(true);
75 myRenderWindow->Delete();
76 myRenderWindow->DoubleBufferOn();
79 myRenderWindow->SetDisplayId((void*)x11Display());
81 myRenderWindow->SetWindowId((void*)winId());
85 To initialize by vtkGenericRenderWindowInteractor instance
88 QVTK_RenderWindowInteractor
89 ::Initialize(vtkGenericRenderWindowInteractor* theDevice)
92 myDevice->SetRenderWindow(NULL);
97 theDevice->SetRenderWindow(getRenderWindow());
103 QVTK_RenderWindowInteractor
104 ::~QVTK_RenderWindowInteractor()
106 if(SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance())
107 if(aSpaceMouse->isSpaceMouseOn())
108 aSpaceMouse->close(x11Display());
113 \return corresponding render window interactor
115 vtkGenericRenderWindowInteractor*
116 QVTK_RenderWindowInteractor
119 return myDevice.GetPointer();
123 \return corresponding render window
126 QVTK_RenderWindowInteractor
129 return myRenderWindow.GetPointer();
133 Just to simplify usage of its device (vtkGenericRenderWindowInteractor)
136 QVTK_RenderWindowInteractor
137 ::InvokeEvent(unsigned long theEvent, void* theCallData)
139 GetDevice()->InvokeEvent(theEvent,theCallData);
143 Need for initial contents display on Win32
146 QVTK_RenderWindowInteractor
150 update(); // needed for initial contents display on Win32
154 To implement final initialization, just before the widget is displayed
157 QVTK_RenderWindowInteractor
160 // Final initialization just before the widget is displayed
161 GetDevice()->SetSize(width(),height());
162 if(!GetDevice()->GetInitialized()){
163 GetDevice()->Initialize();
164 GetDevice()->ConfigureEvent();
169 To adjust widget and vtkRenderWindow size
172 QVTK_RenderWindowInteractor
173 ::resize(int w, int h)
175 GetDevice()->UpdateSize(w,h);
179 Custom paint event handler
182 QVTK_RenderWindowInteractor
183 ::paintEvent( QPaintEvent* theEvent )
185 GetDevice()->CreateTimer(VTKI_TIMER_FIRST);
190 Custom resize event handler
193 QVTK_RenderWindowInteractor
194 ::resizeEvent( QResizeEvent* theEvent )
196 int* aSize = getRenderWindow()->GetSize();
197 int aWidth = aSize[0];
198 int aHeight = aSize[1];
200 GetDevice()->UpdateSize(width(),height());
202 if(isVisible() && aWidth && aHeight){
203 if( aWidth != width() || aHeight != height() ) {
204 vtkRendererCollection * aRenderers = getRenderWindow()->GetRenderers();
205 aRenderers->InitTraversal();
207 if(vtkRenderer *aRenderer = aRenderers->GetNextItem()) {
208 vtkCamera *aCamera = aRenderer->GetActiveCamera();
209 double aScale = aCamera->GetParallelScale();
210 if((aWidth - width())*(aHeight - height()) > 0)
211 aCoeff = sqrt(double(aWidth)/double(width())*double(height())/double(aHeight));
213 aCoeff = double(aWidth)/double(width());
214 aCamera->SetParallelScale(aScale*aCoeff);
225 Custom context menu event handler
228 QVTK_RenderWindowInteractor
229 ::contextMenuEvent( QContextMenuEvent* event )
233 Custom mouse move event handler
236 QVTK_RenderWindowInteractor
237 ::mouseMoveEvent( QMouseEvent* event )
239 GetDevice()->SetEventInformationFlipY(event->x(),
241 event->state() & ControlButton,
242 event->state() & ShiftButton);
243 GetDevice()->MouseMoveEvent();
248 Custom mouse press event handler
251 QVTK_RenderWindowInteractor
252 ::mousePressEvent( QMouseEvent* event )
254 GetDevice()->SetEventInformationFlipY(event->x(),
256 event->state() & ControlButton,
257 event->state() & ShiftButton);
258 if( event->button() & LeftButton )
259 GetDevice()->LeftButtonPressEvent();
260 else if( event->button() & MidButton )
261 GetDevice()->MiddleButtonPressEvent();
262 else if( event->button() & RightButton )
263 GetDevice()->RightButtonPressEvent();
268 Custom mouse release event handler
271 QVTK_RenderWindowInteractor
272 ::mouseReleaseEvent( QMouseEvent *event )
274 GetDevice()->SetEventInformationFlipY(event->x(),
276 event->state() & ControlButton,
277 event->state() & ShiftButton);
279 if( event->button() & LeftButton )
280 GetDevice()->LeftButtonReleaseEvent();
281 else if( event->button() & MidButton )
282 GetDevice()->MiddleButtonReleaseEvent();
283 else if( event->button() & RightButton )
284 GetDevice()->RightButtonReleaseEvent();
289 Custom mouse double click event handler
292 QVTK_RenderWindowInteractor
293 ::mouseDoubleClickEvent( QMouseEvent* event )
298 Custom mouse wheel event handler
301 QVTK_RenderWindowInteractor
302 ::wheelEvent( QWheelEvent* event )
310 Custom key press event handler
313 QVTK_RenderWindowInteractor
314 ::keyPressEvent( QKeyEvent* event )
316 GetDevice()->SetKeyEventInformation(event->state() & ControlButton,
317 event->state() & ShiftButton,
319 GetDevice()->KeyPressEvent();
320 GetDevice()->CharEvent();
324 Custom key release event handler
327 QVTK_RenderWindowInteractor
328 ::keyReleaseEvent( QKeyEvent * event )
330 GetDevice()->SetKeyEventInformation(event->state() & ControlButton,
331 event->state() & ShiftButton,
333 GetDevice()->KeyReleaseEvent();
338 Custom enter event handler
341 QVTK_RenderWindowInteractor
342 ::enterEvent( QEvent* event )
344 if(FOCUS_UNDER_MOUSE){
348 GetDevice()->EnterEvent();
352 Custom leave event handler
355 QVTK_RenderWindowInteractor
356 ::leaveEvent( QEvent * )
358 GetDevice()->LeaveEvent();
362 Reimplemented from QWidget in order to set window - receiver
363 of space mouse events.
366 QVTK_RenderWindowInteractor
367 ::focusInEvent( QFocusEvent* event )
369 QWidget::focusInEvent( event );
371 // register set space mouse events receiver
372 if(SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance()){
373 if(!aSpaceMouse->isSpaceMouseOn()) {// initialize 3D space mouse driver
374 aSpaceMouse->initialize(x11Display(),winId());
376 aSpaceMouse->setWindow(x11Display(),winId());
382 Reimplemented from QWidget in order to set window - receiver
383 of space mouse events.
386 QVTK_RenderWindowInteractor
387 ::focusOutEvent ( QFocusEvent* event )
389 QWidget::focusOutEvent( event );
391 // unregister set space mouse events receiver
392 if(SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance()){
393 if(aSpaceMouse->isSpaceMouseOn())
394 aSpaceMouse->setWindow(x11Display(),0);
400 To handle native X11 events (from such devices as SpaceMouse)
403 QVTK_RenderWindowInteractor
404 ::x11Event( XEvent *xEvent )
406 // handle 3d space mouse events
407 if(SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance()){
408 if(aSpaceMouse->isSpaceMouseOn() && xEvent->type == ClientMessage){
409 SVTK_SpaceMouse::MoveEvent anEvent;
410 int type = aSpaceMouse->translateEvent( x11Display(), xEvent, &anEvent, 1.0, 1.0 );
412 case SVTK_SpaceMouse::SpaceMouseMove :
413 GetDevice()->InvokeEvent(SVTK::SpaceMouseMoveEvent, anEvent.data );
415 case SVTK_SpaceMouse::SpaceButtonPress :
416 GetDevice()->InvokeEvent( SVTK::SpaceMouseButtonEvent, &anEvent.button );
418 case SVTK_SpaceMouse::SpaceButtonRelease :
421 return true; // stop handling the event
425 return QWidget::x11Event( xEvent );
431 SVTK_RenderWindowInteractor
432 ::SVTK_RenderWindowInteractor(QWidget* theParent,
433 const char* theName):
434 QVTK_RenderWindowInteractor(theParent,theName),
435 myEventCallbackCommand(vtkCallbackCommand::New())
437 myEventCallbackCommand->Delete();
439 myEventCallbackCommand->SetClientData(this);
442 myEventCallbackCommand->SetCallback(SVTK_RenderWindowInteractor::ProcessEvents);
446 To initialize properly the class
449 SVTK_RenderWindowInteractor
450 ::Initialize(vtkGenericRenderWindowInteractor* theDevice,
451 SVTK_Renderer* theRenderer,
452 SVTK_Selector* theSelector)
454 QVTK_RenderWindowInteractor::Initialize(theDevice);
455 SetRenderer(theRenderer);
456 SetSelector(theSelector);
462 SVTK_RenderWindowInteractor
463 ::~SVTK_RenderWindowInteractor()
465 // Sequence of the destruction call are fixed and should be changed.
466 // vtkRenderWindow instance should be destroyed after all vtkRenderer's
467 GetDevice()->SetInteractorStyle(NULL);
468 while(!myInteractorStyles.empty()){
469 const PInteractorStyle& aStyle = myInteractorStyles.top();
470 aStyle->SetInteractor(NULL);
471 myInteractorStyles.pop();
476 GetDevice()->SetRenderWindow(NULL);
480 To get corresponding SVTK_Renderer instance
483 SVTK_RenderWindowInteractor
486 return myRenderer.GetPointer();
490 To get corresponding SVTK_Renderer device (just to simplify collobaration with SVTK_Renderer)
493 SVTK_RenderWindowInteractor
496 return GetRenderer()->GetDevice();
501 \param theRenderer - new renderer
504 SVTK_RenderWindowInteractor
505 ::SetRenderer(SVTK_Renderer* theRenderer)
507 if(theRenderer == myRenderer.GetPointer())
511 myRenderWindow->RemoveRenderer(getRenderer());
513 myRenderer = theRenderer;
516 myRenderWindow->AddRenderer(getRenderer());
521 Changes interactor style
522 \param theStyle - new interactor style
525 SVTK_RenderWindowInteractor
526 ::InitInteractorStyle(vtkInteractorStyle* theStyle)
528 GetDevice()->SetInteractorStyle(theStyle);
532 To change current interactor style by pushing the new one into the container
535 SVTK_RenderWindowInteractor
536 ::PushInteractorStyle(vtkInteractorStyle* theStyle)
538 myInteractorStyles.push(PInteractorStyle(theStyle));
539 InitInteractorStyle(theStyle);
543 To restore previous interactor style
546 SVTK_RenderWindowInteractor
547 ::PopInteractorStyle()
549 if(GetInteractorStyle())
550 myInteractorStyles.pop();
552 if(GetInteractorStyle())
553 InitInteractorStyle(GetInteractorStyle());
557 To get current interactor style
560 SVTK_RenderWindowInteractor
561 ::GetInteractorStyle()
563 return myInteractorStyles.empty() ? 0 : myInteractorStyles.top().GetPointer();
568 To get current selector
571 SVTK_RenderWindowInteractor
574 return mySelector.GetPointer();
580 \param theSelector - new selector
583 SVTK_RenderWindowInteractor
584 ::SetSelector(SVTK_Selector* theSelector)
586 if(mySelector.GetPointer())
587 mySelector->RemoveObserver(myEventCallbackCommand.GetPointer());
589 mySelector = theSelector;
591 if(mySelector.GetPointer())
592 mySelector->AddObserver(vtkCommand::EndPickEvent,
593 myEventCallbackCommand.GetPointer(),
598 Main process VTK event method
601 SVTK_RenderWindowInteractor
602 ::ProcessEvents(vtkObject* vtkNotUsed(theObject),
603 unsigned long theEvent,
605 void* vtkNotUsed(theCallData))
607 SVTK_RenderWindowInteractor* self = reinterpret_cast<SVTK_RenderWindowInteractor*>(theClientData);
610 case vtkCommand::EndPickEvent:
611 self->onEmitSelectionChanged();
617 To change selection mode (just to simplify collobaration with SVTK_Selector)
620 SVTK_RenderWindowInteractor
621 ::SetSelectionMode(Selection_Mode theMode)
623 mySelector->SetSelectionMode(theMode);
627 To get current selection mode (just to simplify collobaration with SVTK_Selector)
630 SVTK_RenderWindowInteractor
631 ::SelectionMode() const
633 return mySelector->SelectionMode();
638 Emits signal selectionChanged()
641 SVTK_RenderWindowInteractor
642 ::onEmitSelectionChanged()
644 return emit selectionChanged();
649 Custom mouse move event handler
652 SVTK_RenderWindowInteractor
653 ::mouseMoveEvent( QMouseEvent* event )
655 QVTK_RenderWindowInteractor::mouseMoveEvent(event);
657 if(GENERATE_SUIT_EVENTS)
658 emit MouseMove( event );
663 Custom mouse press event handler
666 SVTK_RenderWindowInteractor
667 ::mousePressEvent( QMouseEvent* event )
669 QVTK_RenderWindowInteractor::mousePressEvent(event);
671 if(GENERATE_SUIT_EVENTS)
672 emit MouseButtonPressed( event );
677 Custom mouse release event handler
680 SVTK_RenderWindowInteractor
681 ::mouseReleaseEvent( QMouseEvent *event )
683 QVTK_RenderWindowInteractor::mouseReleaseEvent(event);
685 if(GENERATE_SUIT_EVENTS)
686 emit MouseButtonReleased( event );
691 Custom mouse double click event handler
694 SVTK_RenderWindowInteractor
695 ::mouseDoubleClickEvent( QMouseEvent* event )
697 QVTK_RenderWindowInteractor::mouseDoubleClickEvent(event);
699 if(GENERATE_SUIT_EVENTS)
700 emit MouseDoubleClicked( event );
705 Custom mouse wheel event handler
708 SVTK_RenderWindowInteractor
709 ::wheelEvent( QWheelEvent* event )
711 QVTK_RenderWindowInteractor::wheelEvent(event);
713 if(event->delta() > 0)
714 GetDevice()->InvokeEvent(SVTK::ZoomInEvent,NULL);
716 GetDevice()->InvokeEvent(SVTK::ZoomOutEvent,NULL);
718 if(GENERATE_SUIT_EVENTS)
719 emit WheelMoved( event );
723 Custom key press event handler
726 SVTK_RenderWindowInteractor
727 ::keyPressEvent( QKeyEvent* event )
729 QVTK_RenderWindowInteractor::keyPressEvent(event);
731 if(GENERATE_SUIT_EVENTS)
732 emit KeyPressed( event );
736 Custom key release event handler
739 SVTK_RenderWindowInteractor
740 ::keyReleaseEvent( QKeyEvent * event )
742 QVTK_RenderWindowInteractor::keyReleaseEvent(event);
744 if(GENERATE_SUIT_EVENTS)
745 emit KeyReleased( event );
749 Custom context menu event handler
752 SVTK_RenderWindowInteractor
753 ::contextMenuEvent( QContextMenuEvent* event )
755 if( !( event->state() & KeyButtonMask ) )
756 emit contextMenuRequested( event );