1 // Copyright (C) 2007-2014 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 // Author : OPEN CASCADE
24 // File: GLViewer_Viewer.cxx
25 // Created: November, 2004
26 //#include <GLViewerAfx.h>
28 #include "GLViewer_Viewer.h"
29 #include "GLViewer_Selector.h"
30 #include "GLViewer_ViewPort.h"
31 #include "GLViewer_ViewFrame.h"
33 //#include "SUIT_Desktop.h"
34 #include "SUIT_ViewWindow.h"
35 #include "SUIT_ViewManager.h"
37 #include <QApplication>
39 #include <QColorDialog>
40 #include <QMouseEvent>
41 #include <QWheelEvent>
43 #include <QRubberBand>
45 /* used for sketching */
46 static QEvent* l_mbPressEvent = 0;
51 GLViewer_Viewer::GLViewer_Viewer( const QString& title )
56 mySelMode( NoSelection )
63 GLViewer_Viewer::~GLViewer_Viewer()
70 \param theViewManager - new view manager
72 void GLViewer_Viewer::setViewManager(SUIT_ViewManager* theViewManager)
74 SUIT_ViewModel::setViewManager(theViewManager);
77 connect(theViewManager, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)),
78 this, SLOT(onMouseEvent(SUIT_ViewWindow*, QMouseEvent*)));
80 connect(theViewManager, SIGNAL(mouseMove(SUIT_ViewWindow*, QMouseEvent*)),
81 this, SLOT(onMouseEvent(SUIT_ViewWindow*, QMouseEvent*)));
83 connect(theViewManager, SIGNAL(mouseRelease(SUIT_ViewWindow*, QMouseEvent*)),
84 this, SLOT(onMouseEvent(SUIT_ViewWindow*, QMouseEvent*)));
86 connect(theViewManager, SIGNAL(wheel(SUIT_ViewWindow*, QWheelEvent*)),
87 this, SLOT(onWheelEvent(SUIT_ViewWindow*, QWheelEvent*)));
92 Builds popup for GL viewer
94 void GLViewer_Viewer::contextMenuPopup( QMenu* thePopup )
96 if( thePopup->actions().count() > 0 )
97 thePopup->addSeparator();
99 thePopup->addAction( tr( "CHANGE_BGCOLOR" ), this, SLOT( onChangeBgColor() ) );
103 Sets the background color with color selection dialog. [ virtual protected slot ]
105 void GLViewer_Viewer::onChangeBgColor()
107 GLViewer_ViewPort* vp = getActiveView()->getViewPort();
108 QColor selColor = QColorDialog::getColor( vp->backgroundColor() );
110 if( selColor.isValid() )
111 vp->setBackgroundColor( selColor );
115 Returns the active view. [ public ]
117 GLViewer_ViewFrame* GLViewer_Viewer::getActiveView() const
119 SUIT_ViewManager* aMgr = getViewManager();
120 return (GLViewer_ViewFrame*)( aMgr != 0 ? aMgr->getActiveView() : 0 );
125 Sets the selection mode for this viewer. [ public ]
127 void GLViewer_Viewer::setSelectionMode( GLViewer_Viewer::SelectionMode mode )
129 if ( mySelMode != mode )
132 onSelectionModeChanged();
137 Returns selector of this viewer. [ public ]
139 GLViewer_Selector* GLViewer_Viewer::getSelector() const
143 GLViewer_Viewer* mthis = (GLViewer_Viewer*)this;
144 mthis->mySelector = mthis->createSelector();
147 connect( mySelector, SIGNAL( selSelectionDone( bool, SelectionChangeStatus ) ), SLOT( onSelectionDone( bool, SelectionChangeStatus ) ) );
148 connect( mySelector, SIGNAL( selSelectionCancel() ), SLOT( onSelectionCancel() ) );
155 Returns the selection mode of this viewer. [ public ]
157 GLViewer_Viewer::SelectionMode GLViewer_Viewer::getSelectionMode() const
163 Handles requests for sketching in the active view. [ virtual public ]
165 void GLViewer_Viewer::activateSketching( int type )
167 GLViewer_ViewPort* vp = 0;
168 if ( !getActiveView() || !( vp = getActiveView()->getViewPort() ) )
171 if ( !vp->isSketchingEnabled() )
174 /* Finish current sketching */
175 if ( type == NoSketching )
179 onSketchingFinished();
184 /* Activate new sketching */
187 activateSketching( NoSketching ); /* concurrency not suported */
188 mySketcher = createSketcher( type );
189 onSketchingStarted();
194 Handles requests for transformations in the active view. [ virtual public ]
196 void GLViewer_Viewer::activateTransform( int type )
198 GLViewer_ViewPort* vp = 0;
199 if ( !getActiveView() || !( vp = getActiveView()->getViewPort() ) )
202 if ( !vp->isTransformEnabled() )
205 /* Finish current transform */
206 if ( type == NoTransform )
210 onTransformationFinished();
211 delete myTransformer;
215 /* Activate new transform */
218 activateTransform( NoTransform ); /* concurrency not suported */
219 myTransformer = createTransformer( type );
220 onTransformationStarted();
221 myTransformer->exec();
226 Creates default transformer. [ virtual protected ]
228 GLViewer_ViewTransformer* GLViewer_Viewer::createTransformer( int type )
230 return new GLViewer_ViewTransformer( this, type );
234 Creates default sketcher. [ virtual protected ]
236 GLViewer_ViewSketcher* GLViewer_Viewer::createSketcher( int type )
238 return new GLViewer_ViewSketcher( this, type );
242 Returns null by default. [ virtual protected ]
244 GLViewer_Selector* GLViewer_Viewer::createSelector()
250 Unhilights detected entities, lock selection, sets event filter
251 on the whole application. [ virtual protected ]
253 void GLViewer_Viewer::onTransformationStarted()
257 getSelector()->lock( true ); /* disable selection */
259 /* Watch events: any mouse/key event outside the
260 viewport will be considered as the end of
264 qApp->installEventFilter( this );
268 Unlock selection, removes event filter. [ virtual protected ]
270 void GLViewer_Viewer::onTransformationFinished()
273 getSelector()->lock( false ); /* enable selection */
275 /* Stop watch events */
278 qApp->removeEventFilter( this );
282 Unhilights detected entities. [ virtual protected ]
284 void GLViewer_Viewer::onSketchingStarted()
290 Selection by rectangle. [ virtual protected ]
292 void GLViewer_Viewer::onSketchingFinished()
294 if ( !getSelector() )
299 if ( mySketcher->type() == Rect )
301 QRect* selRect = (QRect*)mySketcher->data();
304 bool append = bool( mySketcher->buttonState() & GLViewer_Selector::appendKey() );
305 getSelector()->select( *selRect, append );
311 Installed while 'fit area' and 'global panning' operations are active. [ virtual protected ]
313 bool GLViewer_Viewer::eventFilter( QObject* o, QEvent* e )
315 if( !getActiveView() )
318 if( getActiveView()->getViewPort() == o->parent() )
321 bool mouseClickedOutside = ( e->type() == QEvent::MouseButtonPress &&
322 o != getActiveView()->getViewPort() );
323 bool anyKeyPressed = ( e->type() == QEvent::KeyPress );
324 if ( mouseClickedOutside || anyKeyPressed )
325 { /* terminate all */
326 activateTransform( NoTransform );
327 activateSketching( NoSketching );
328 //cout << "mouseClickedOutside || anyKeyPressed" << endl;
330 return QObject::eventFilter( o, e );
334 Called when smth is selected in this viewer. [ virtual protected slot ]
336 void GLViewer_Viewer::onSelectionDone( bool bAdded, SelectionChangeStatus status )
338 emit selectionChanged( status );
342 Called when selection is cleared in this viewer. [ virtual protected slot ]
344 void GLViewer_Viewer::onSelectionCancel()
346 emit selectionChanged( SCS_Invalid );
350 Listens to key events of the active view. [ virtual protected slot ]
352 void GLViewer_Viewer::onKeyEvent( SUIT_ViewWindow*, QKeyEvent* )
357 Listens to mouse events of the active view. [ virtual protected slot ]
359 void GLViewer_Viewer::onMouseEvent( SUIT_ViewWindow*, QMouseEvent* e )
361 //cout << "GLViewer_Viewer::onMouseEvent" << endl;
364 case QEvent::MouseButtonPress:
365 handleMousePress( e );
367 case QEvent::MouseMove:
368 handleMouseMove( e );
370 case QEvent::MouseButtonRelease:
371 handleMouseRelease( e );
378 Listens to mouse events of the active view. [ virtual protected slot ]
380 void GLViewer_Viewer::onWheelEvent( SUIT_ViewWindow*, QWheelEvent* e )
382 //cout << "GLViewer_Viewer::onMouseEvent" << endl;
393 Enables / disables rectangle sketching. [ virtual protected ]
395 void GLViewer_Viewer::onSelectionModeChanged()
397 bool enable = ( mySelMode == Multiple );
398 QVector<SUIT_ViewWindow*> views = getViewManager()->getViews();
399 for ( int i = 0, n = views.count(); i < n; i++ )
401 GLViewer_ViewPort* vp = ((GLViewer_ViewFrame*)views[i])->getViewPort();
403 vp->setSketchingEnabled( enable );
408 Updates all views of this viewer. Use 'flags' to customize update process. [ virtual public ]
410 void GLViewer_Viewer::update( int flags )
412 QVector<SUIT_ViewWindow*> views = getViewManager()->getViews();
413 for ( int i = 0, n = views.count(); i < n; i++ )
414 ((GLViewer_ViewFrame*)views[i])->onUpdate( flags );
418 Unhilights the currect detected objects. [ virtual private ]
420 void GLViewer_Viewer::unhilightDetected()
423 getSelector()->undetectAll();
427 Mouse press handler. If 'accelKey()' is pressed, activates default
428 transformations( Zoom or Pan ) in the active viewport. [ private ]
430 void GLViewer_Viewer::handleMousePress( QMouseEvent* e )
432 /* test accel for transforms */
433 if ( e->modifiers() & GLViewer_ViewTransformer::accelKey() )
435 Qt::MouseButton bs = e->button();
436 if ( bs == GLViewer_ViewTransformer::zoomButton() )
437 activateTransform( Zoom );
438 else if ( bs == GLViewer_ViewTransformer::panButton() )
439 activateTransform( Pan );
443 //checking for other operations before selection in release event
444 startOperations( e );
447 /* we may need it for sketching... */
448 l_mbPressEvent = new QMouseEvent( *e );
450 //checking for other operations before selection in release event
451 // startOperations( e );
453 /*e->button() == LeftButton && getSelector() )
455 bool append = bool ( e->state() & GLViewer_Selector::appendKey() );
456 getSelector()->select( append );
461 Mouse move handler. If dragged with MB1, activates rectangle sketching in
462 the active viewport, otherwise highlights the selectable entities. [ private ]
464 void GLViewer_Viewer::handleMouseMove( QMouseEvent* e )
466 /* Highlight for selection */
467 bool dragged = ( e->buttons() & ( Qt::LeftButton | Qt::MidButton | Qt::RightButton ) );
471 getSelector()->detect( e->x(), e->y() );
473 /* Try to activate default sketching
475 else if ( e->button() == GLViewer_ViewSketcher::sketchButton() )
477 activateSketching( Rect );
480 /* Activated OK. We should not forget initial mousepress
481 event and this mousemove event to start sketching from
482 the point of initial click */
483 if ( l_mbPressEvent )
485 QApplication::sendEvent( getActiveView()->getViewPort(), l_mbPressEvent );
486 delete l_mbPressEvent;
489 QApplication::sendEvent( getActiveView()->getViewPort(), e );
493 //Try to activate other operations
494 updateOperations( e );
498 Mouse move handler. Activates popup of the active view. [ private ]
500 void GLViewer_Viewer::handleMouseRelease( QMouseEvent* e )
503 /* tmp - in handleMousePress*/
504 if( e->button() == Qt::LeftButton && !(getActiveView()->getViewPort()->currentBlock() & BS_Selection) )
508 bool append = bool ( e->modifiers() & GLViewer_Selector::appendKey() );
509 getSelector()->select( append );
513 //Try to done active operations
514 finishOperations( e );
516 if ( l_mbPressEvent )
518 delete l_mbPressEvent;
524 Wheel rolling handler
526 void GLViewer_Viewer::handleWheel( QWheelEvent* e )
528 startOperations( e );
531 int GLViewer_ViewTransformer::panBtn = Qt::MidButton;
532 int GLViewer_ViewTransformer::zoomBtn = Qt::LeftButton;
533 int GLViewer_ViewTransformer::fitRectBtn = Qt::LeftButton;
534 int GLViewer_ViewTransformer::panGlobalBtn = Qt::LeftButton;
535 int GLViewer_ViewTransformer::acccelKey = Qt::ControlModifier;
540 GLViewer_ViewTransformer::GLViewer_ViewTransformer( GLViewer_Viewer* v, int type )
544 myMajorBtn( Qt::NoButton ),
548 if ( myType == GLViewer_Viewer::Pan ||
549 myType == GLViewer_Viewer::Zoom ||
550 myType == GLViewer_Viewer::PanGlobal ||
551 myType == GLViewer_Viewer::FitRect )
553 /* 'long' transforms need this */
554 initTransform( true );
561 GLViewer_ViewTransformer::~GLViewer_ViewTransformer()
563 if ( myType == GLViewer_Viewer::Pan ||
564 myType == GLViewer_Viewer::Zoom ||
565 myType == GLViewer_Viewer::PanGlobal ||
566 myType == GLViewer_Viewer::FitRect )
568 /* 'long' transforms need this */
569 initTransform( false );
572 //QAD_Application::getDesktop()->clearInfo();
578 Inits long transformations ( Zoom, Pan etc ) [ protected ]
580 Saves viewport state( cursor etc ) and installs event filter to process
581 mouse events if 'init' is true. Restores viewport state if 'init' is false.
583 void GLViewer_ViewTransformer::initTransform( bool init )
585 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
588 mySavedCursor = avp->cursor();
589 mySavedMouseTrack = avp->hasMouseTracking();
590 avp->setMouseTracking( false );
591 avp->installEventFilter( this );
595 avp->removeEventFilter( this );
596 avp->setMouseTracking( mySavedMouseTrack );
597 avp->setCursor( mySavedCursor );
602 Runs transfomation. Redefine to add your own 'instant' transforms
603 ( for ex., 'FitAll' is an instant transform ). [ virtual public ]
605 void GLViewer_ViewTransformer::exec()
607 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
613 case GLViewer_Viewer::Zoom:
614 myMajorBtn = zoomButton();
615 avp->setCursor( *avp->getZoomCursor() );
617 case GLViewer_Viewer::Pan:
618 myMajorBtn = panButton();
619 avp->setCursor( *avp->getPanCursor() );
621 case GLViewer_Viewer::PanGlobal:
622 myMajorBtn = panGlobalButton();
623 avp->setCursor( *avp->getPanglCursor() );
624 avp->fitAll( true, false ); /* view is ready now */
626 case GLViewer_Viewer::FitRect:
627 myMajorBtn = fitRectButton();
628 avp->setCursor( *avp->getHandCursor() );
630 case GLViewer_Viewer::Reset:
631 avp->reset(); onTransform( Fin );
633 case GLViewer_Viewer::FitAll:
634 avp->fitAll(); onTransform( Fin );
636 case GLViewer_Viewer::FitSelect:
637 avp->fitSelect(); onTransform( Fin );
644 Catches mouse events for the viewport. [ virtual protected ]
646 bool GLViewer_ViewTransformer::eventFilter( QObject* o, QEvent* e )
650 case QEvent::MouseMove:
651 case QEvent::MouseButtonPress:
652 case QEvent::MouseButtonRelease:
654 TransformState state = EnTrain;
655 QMouseEvent* me = ( QMouseEvent* )e;
657 myButtonState = me->modifiers();
658 if ( e->type() == QEvent::MouseButtonPress )
659 myButtonState |= me->button(); /* add pressed button */
661 int mouseOnlyState = ( myButtonState & ( Qt::LeftButton | Qt::MidButton | Qt::RightButton ) );
662 if ( myStart.isNull() )
666 myMajorBtn = mouseOnlyState;
669 if ( e->type() == QEvent::MouseButtonRelease && mouseOnlyState == myMajorBtn )
674 onTransform( state );
679 return QObject::eventFilter( o, e );
683 Transforms the viewport. Used for 'non-instant' transforms
684 only( ex. Rotate, Pan etc ). [ virtual protected ]
686 void GLViewer_ViewTransformer::onTransform( TransformState state )
688 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
689 bool doTrsf = ( myButtonState & myMajorBtn );
692 case GLViewer_Viewer::Zoom:
693 if ( state != Fin && doTrsf )
695 avp->zoom( myStart.x(), myStart.y(), myCurr.x(), myCurr.y() );
699 case GLViewer_Viewer::Pan:
700 if ( state != Fin && doTrsf )
702 avp->pan( myCurr.x() - myStart.x(), myStart.y() - myCurr.y() );
706 case GLViewer_Viewer::PanGlobal:
709 avp->setCenter( myCurr.x(), myCurr.y() );
712 case GLViewer_Viewer::FitRect:
716 QRect rect( qMin( myStart.x(), myCurr.x() ), qMin( myStart.y(), myCurr.y() ),
717 qAbs( myStart.x() - myCurr.x() ), qAbs( myStart.y() - myCurr.y() ) );
718 if ( !rect.isEmpty() )
723 avp->fitRect( rect );
740 myViewer->activateTransform( GLViewer_Viewer::NoTransform );
744 Draws rectangle by starting and current points
746 void GLViewer_ViewTransformer::drawRect(const QRect& theRect)
749 myRectBand = new QRubberBand( QRubberBand::Rectangle, myViewer->getActiveView()->getViewPort() );
751 palette.setColor(myRectBand->foregroundRole(), Qt::white);
752 myRectBand->setPalette(palette);
756 myRectBand->setGeometry( theRect );
757 myRectBand->setVisible( theRect.isValid() );
761 \brief Delete rubber band on the end on the dragging operation.
763 void GLViewer_ViewTransformer::endDrawRect()
765 if ( myRectBand ) myRectBand->hide();
772 Returns the type of the transformer. [ public ]
774 int GLViewer_ViewTransformer::type() const
780 int GLViewer_ViewSketcher::sketchBtn = Qt::LeftButton;
785 GLViewer_ViewSketcher::GLViewer_ViewSketcher( GLViewer_Viewer* viewer, int type )
794 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
798 mySavedCursor = avp->cursor();
799 avp->setCursor( *GLViewer_ViewPort::getHandCursor() );
800 avp->installEventFilter( this );
802 if ( myType == GLViewer_Viewer::Rect )
803 myData = new QRect();
809 GLViewer_ViewSketcher::~GLViewer_ViewSketcher()
811 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
812 avp->removeEventFilter( this );
813 avp->setCursor( mySavedCursor );
815 if ( myType == GLViewer_Viewer::Rect )
816 delete ( QRect* ) myData;
822 Catches mouse events for the viewport. [ virtual protected ]
824 bool GLViewer_ViewSketcher::eventFilter( QObject* o, QEvent* e )
828 case QEvent::MouseMove:
829 case QEvent::MouseButtonPress:
830 case QEvent::MouseButtonRelease:
832 SketchState state = EnTrain;
833 QMouseEvent* me = (QMouseEvent*)e;
835 myButtonState = me->modifiers();
836 if ( e->type() == QEvent::MouseButtonPress )
837 myButtonState |= me->button(); /* add pressed button */
839 if ( myStart.isNull() )
845 int mouseOnlyState = ( myButtonState & ( Qt::LeftButton | Qt::MidButton | Qt::RightButton ) );
846 if ( e->type() == QEvent::MouseButtonRelease && mouseOnlyState == sketchButton() )
856 return QObject::eventFilter( o, e );
860 Draws in the viewport. [ virtual protected ]
862 void GLViewer_ViewSketcher::onSketch( SketchState state )
864 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
868 if( myType == GLViewer_Viewer::Rect )
870 QRect* sketchRect = ( QRect* )data();
871 if ( myButtonState & sketchButton() )
873 QRect rect( qMin( myStart.x(), myCurr.x() ), qMin( myStart.y(), myCurr.y() ),
874 qAbs( myStart.x() - myCurr.x() ), qAbs( myStart.y() - myCurr.y() ) );
875 if ( !rect.isEmpty() )
877 if ( !sketchRect->isEmpty() && myRectBand )
878 myRectBand->hide(); /* erase */
881 drawRect( *sketchRect );
888 QApplication::syncX(); /* force rectangle redrawing */
889 myViewer->activateSketching( GLViewer_Viewer::NoSketching );
894 Draws rectangle by starting and current points
896 void GLViewer_ViewSketcher::drawRect(const QRect& theRect)
899 myRectBand = new QRubberBand( QRubberBand::Rectangle, myViewer->getActiveView()->getViewPort() );
901 palette.setColor(myRectBand->foregroundRole(), Qt::white);
902 myRectBand->setPalette(palette);
906 myRectBand->setGeometry( theRect );
907 myRectBand->setVisible( theRect.isValid() );
911 \brief Delete rubber band on the end on the dragging operation.
913 void GLViewer_ViewSketcher::endDrawRect()
915 if ( myRectBand ) myRectBand->hide();