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.salome-platform.org/ or email : webmaster.salome@opencascade.com
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()
107 SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance();
108 if ( aSpaceMouse && aSpaceMouse->isSpaceMouseOn() )
109 aSpaceMouse->close( x11Display() );
115 \return corresponding render window interactor
117 vtkGenericRenderWindowInteractor*
118 QVTK_RenderWindowInteractor
121 return myDevice.GetPointer();
125 \return corresponding render window
128 QVTK_RenderWindowInteractor
131 return myRenderWindow.GetPointer();
135 Just to simplify usage of its device (vtkGenericRenderWindowInteractor)
138 QVTK_RenderWindowInteractor
139 ::InvokeEvent(unsigned long theEvent, void* theCallData)
141 GetDevice()->InvokeEvent(theEvent,theCallData);
145 Need for initial contents display on Win32
148 QVTK_RenderWindowInteractor
152 update(); // needed for initial contents display on Win32
156 To implement final initialization, just before the widget is displayed
159 QVTK_RenderWindowInteractor
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();
171 To adjust widget and vtkRenderWindow size
174 QVTK_RenderWindowInteractor
175 ::resize(int w, int h)
177 GetDevice()->UpdateSize(w,h);
181 Custom paint event handler
184 QVTK_RenderWindowInteractor
185 ::paintEvent( QPaintEvent* theEvent )
187 GetDevice()->CreateTimer(VTKI_TIMER_FIRST);
192 Custom resize event handler
195 QVTK_RenderWindowInteractor
196 ::resizeEvent( QResizeEvent* theEvent )
198 int* aSize = getRenderWindow()->GetSize();
199 int aWidth = aSize[0];
200 int aHeight = aSize[1];
202 GetDevice()->UpdateSize(width(),height());
204 if(isVisible() && aWidth && aHeight){
205 if( aWidth != width() || aHeight != height() ) {
206 vtkRendererCollection * aRenderers = getRenderWindow()->GetRenderers();
207 aRenderers->InitTraversal();
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));
215 aCoeff = double(aWidth)/double(width());
216 aCamera->SetParallelScale(aScale*aCoeff);
227 Custom context menu event handler
230 QVTK_RenderWindowInteractor
231 ::contextMenuEvent( QContextMenuEvent* event )
235 Custom mouse move event handler
238 QVTK_RenderWindowInteractor
239 ::mouseMoveEvent( QMouseEvent* event )
241 GetDevice()->SetEventInformationFlipY(event->x(),
243 event->state() & ControlButton,
244 event->state() & ShiftButton);
245 GetDevice()->MouseMoveEvent();
250 Custom mouse press event handler
253 QVTK_RenderWindowInteractor
254 ::mousePressEvent( QMouseEvent* event )
256 GetDevice()->SetEventInformationFlipY(event->x(),
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();
270 Custom mouse release event handler
273 QVTK_RenderWindowInteractor
274 ::mouseReleaseEvent( QMouseEvent *event )
276 GetDevice()->SetEventInformationFlipY(event->x(),
278 event->state() & ControlButton,
279 event->state() & ShiftButton);
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();
291 Custom mouse double click event handler
294 QVTK_RenderWindowInteractor
295 ::mouseDoubleClickEvent( QMouseEvent* event )
300 Custom mouse wheel event handler
303 QVTK_RenderWindowInteractor
304 ::wheelEvent( QWheelEvent* event )
312 Custom key press event handler
315 QVTK_RenderWindowInteractor
316 ::keyPressEvent( QKeyEvent* event )
318 GetDevice()->SetKeyEventInformation(event->state() & ControlButton,
319 event->state() & ShiftButton,
321 GetDevice()->KeyPressEvent();
322 GetDevice()->CharEvent();
326 Custom key release event handler
329 QVTK_RenderWindowInteractor
330 ::keyReleaseEvent( QKeyEvent * event )
332 GetDevice()->SetKeyEventInformation(event->state() & ControlButton,
333 event->state() & ShiftButton,
335 GetDevice()->KeyReleaseEvent();
340 Custom enter event handler
343 QVTK_RenderWindowInteractor
344 ::enterEvent( QEvent* event )
346 if(FOCUS_UNDER_MOUSE){
350 GetDevice()->EnterEvent();
354 Custom leave event handler
357 QVTK_RenderWindowInteractor
358 ::leaveEvent( QEvent * )
360 GetDevice()->LeaveEvent();
364 Reimplemented from QWidget in order to set window - receiver
365 of space mouse events.
368 QVTK_RenderWindowInteractor
369 ::focusInEvent( QFocusEvent* event )
371 QWidget::focusInEvent( event );
374 // register set space mouse events receiver
375 SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance();
379 if ( !aSpaceMouse->isSpaceMouseOn() )
380 // initialize 3D space mouse driver
381 aSpaceMouse->initialize( x11Display(), winId() );
383 aSpaceMouse->setWindow( x11Display(), winId() );
389 Reimplemented from QWidget in order to set window - receiver
390 of space mouse events.
393 QVTK_RenderWindowInteractor
394 ::focusOutEvent ( QFocusEvent* event )
396 QWidget::focusOutEvent( event );
399 // unregister set space mouse events receiver
400 SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance();
401 if ( aSpaceMouse && aSpaceMouse->isSpaceMouseOn() )
402 aSpaceMouse->setWindow( x11Display(), 0 );
410 To handle native Win32 events (from such devices as SpaceMouse)
412 bool QVTK_RenderWindowInteractor::winEvent( MSG* msg )
414 // TODO: Implement event handling for SpaceMouse
415 return QWidget::winEvent( msg );
421 To handle native X11 events (from such devices as SpaceMouse)
424 QVTK_RenderWindowInteractor
425 ::x11Event( XEvent *xEvent )
427 // handle 3d space mouse events
428 if ( SVTK_SpaceMouse* aSpaceMouse = SVTK_SpaceMouse::getInstance() )
430 if ( aSpaceMouse->isSpaceMouseOn() && xEvent->type == ClientMessage )
432 SVTK_SpaceMouse::MoveEvent anEvent;
433 int type = aSpaceMouse->translateEvent( x11Display(), xEvent, &anEvent, 1.0, 1.0 );
436 case SVTK_SpaceMouse::SpaceMouseMove:
437 GetDevice()->InvokeEvent( SVTK::SpaceMouseMoveEvent, anEvent.data );
439 case SVTK_SpaceMouse::SpaceButtonPress:
440 GetDevice()->InvokeEvent( SVTK::SpaceMouseButtonEvent, &anEvent.button );
442 case SVTK_SpaceMouse::SpaceButtonRelease:
445 return true; // stop handling the event
449 return QWidget::x11Event( xEvent );
457 SVTK_RenderWindowInteractor
458 ::SVTK_RenderWindowInteractor(QWidget* theParent,
459 const char* theName):
460 QVTK_RenderWindowInteractor(theParent,theName),
461 myEventCallbackCommand(vtkCallbackCommand::New())
463 myEventCallbackCommand->Delete();
465 myEventCallbackCommand->SetClientData(this);
468 myEventCallbackCommand->SetCallback(SVTK_RenderWindowInteractor::ProcessEvents);
472 To initialize properly the class
475 SVTK_RenderWindowInteractor
476 ::Initialize(vtkGenericRenderWindowInteractor* theDevice,
477 SVTK_Renderer* theRenderer,
478 SVTK_Selector* theSelector)
480 QVTK_RenderWindowInteractor::Initialize(theDevice);
481 SetRenderer(theRenderer);
482 SetSelector(theSelector);
488 SVTK_RenderWindowInteractor
489 ::~SVTK_RenderWindowInteractor()
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();
502 GetDevice()->SetRenderWindow(NULL);
506 To get corresponding SVTK_Renderer instance
509 SVTK_RenderWindowInteractor
512 return myRenderer.GetPointer();
516 To get corresponding SVTK_Renderer device (just to simplify collobaration with SVTK_Renderer)
519 SVTK_RenderWindowInteractor
522 return GetRenderer()->GetDevice();
527 \param theRenderer - new renderer
530 SVTK_RenderWindowInteractor
531 ::SetRenderer(SVTK_Renderer* theRenderer)
533 if(theRenderer == myRenderer.GetPointer())
537 myRenderWindow->RemoveRenderer(getRenderer());
539 myRenderer = theRenderer;
542 myRenderWindow->AddRenderer(getRenderer());
547 Changes interactor style
548 \param theStyle - new interactor style
551 SVTK_RenderWindowInteractor
552 ::InitInteractorStyle(vtkInteractorStyle* theStyle)
554 GetDevice()->SetInteractorStyle(theStyle);
558 To change current interactor style by pushing the new one into the container
561 SVTK_RenderWindowInteractor
562 ::PushInteractorStyle(vtkInteractorStyle* theStyle)
564 myInteractorStyles.push(PInteractorStyle(theStyle));
565 InitInteractorStyle(theStyle);
569 To restore previous interactor style
572 SVTK_RenderWindowInteractor
573 ::PopInteractorStyle()
575 if(GetInteractorStyle())
576 myInteractorStyles.pop();
578 if(GetInteractorStyle())
579 InitInteractorStyle(GetInteractorStyle());
583 To get current interactor style
586 SVTK_RenderWindowInteractor
587 ::GetInteractorStyle()
589 return myInteractorStyles.empty() ? 0 : myInteractorStyles.top().GetPointer();
594 To get current selector
597 SVTK_RenderWindowInteractor
600 return mySelector.GetPointer();
606 \param theSelector - new selector
609 SVTK_RenderWindowInteractor
610 ::SetSelector(SVTK_Selector* theSelector)
612 if(mySelector.GetPointer())
613 mySelector->RemoveObserver(myEventCallbackCommand.GetPointer());
615 mySelector = theSelector;
617 if(mySelector.GetPointer())
618 mySelector->AddObserver(vtkCommand::EndPickEvent,
619 myEventCallbackCommand.GetPointer(),
624 Main process VTK event method
627 SVTK_RenderWindowInteractor
628 ::ProcessEvents(vtkObject* vtkNotUsed(theObject),
629 unsigned long theEvent,
631 void* vtkNotUsed(theCallData))
633 SVTK_RenderWindowInteractor* self = reinterpret_cast<SVTK_RenderWindowInteractor*>(theClientData);
636 case vtkCommand::EndPickEvent:
637 self->onEmitSelectionChanged();
643 To change selection mode (just to simplify collobaration with SVTK_Selector)
646 SVTK_RenderWindowInteractor
647 ::SetSelectionMode(Selection_Mode theMode)
649 mySelector->SetSelectionMode(theMode);
653 To get current selection mode (just to simplify collobaration with SVTK_Selector)
656 SVTK_RenderWindowInteractor
657 ::SelectionMode() const
659 return mySelector->SelectionMode();
664 Emits signal selectionChanged()
667 SVTK_RenderWindowInteractor
668 ::onEmitSelectionChanged()
670 return emit selectionChanged();
675 Custom mouse move event handler
678 SVTK_RenderWindowInteractor
679 ::mouseMoveEvent( QMouseEvent* event )
681 QVTK_RenderWindowInteractor::mouseMoveEvent(event);
683 if(GENERATE_SUIT_EVENTS)
684 emit MouseMove( event );
689 Custom mouse press event handler
692 SVTK_RenderWindowInteractor
693 ::mousePressEvent( QMouseEvent* event )
695 QVTK_RenderWindowInteractor::mousePressEvent(event);
697 if(GENERATE_SUIT_EVENTS)
698 emit MouseButtonPressed( event );
703 Custom mouse release event handler
706 SVTK_RenderWindowInteractor
707 ::mouseReleaseEvent( QMouseEvent *event )
709 QVTK_RenderWindowInteractor::mouseReleaseEvent(event);
711 if(GENERATE_SUIT_EVENTS)
712 emit MouseButtonReleased( event );
717 Custom mouse double click event handler
720 SVTK_RenderWindowInteractor
721 ::mouseDoubleClickEvent( QMouseEvent* event )
723 QVTK_RenderWindowInteractor::mouseDoubleClickEvent(event);
725 if(GENERATE_SUIT_EVENTS)
726 emit MouseDoubleClicked( event );
731 Custom mouse wheel event handler
734 SVTK_RenderWindowInteractor
735 ::wheelEvent( QWheelEvent* event )
737 QVTK_RenderWindowInteractor::wheelEvent(event);
739 if(event->delta() > 0)
740 GetDevice()->InvokeEvent(SVTK::ZoomInEvent,NULL);
742 GetDevice()->InvokeEvent(SVTK::ZoomOutEvent,NULL);
744 if(GENERATE_SUIT_EVENTS)
745 emit WheelMoved( event );
749 Custom key press event handler
752 SVTK_RenderWindowInteractor
753 ::keyPressEvent( QKeyEvent* event )
755 QVTK_RenderWindowInteractor::keyPressEvent(event);
757 if(GENERATE_SUIT_EVENTS)
758 emit KeyPressed( event );
762 Custom key release event handler
765 SVTK_RenderWindowInteractor
766 ::keyReleaseEvent( QKeyEvent * event )
768 QVTK_RenderWindowInteractor::keyReleaseEvent(event);
770 if(GENERATE_SUIT_EVENTS)
771 emit KeyReleased( event );
775 Custom context menu event handler
778 SVTK_RenderWindowInteractor
779 ::contextMenuEvent( QContextMenuEvent* event )
781 if( !( event->state() & KeyButtonMask ) )
782 emit contextMenuRequested( event );