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 // Author : OPEN CASCADE
23 // File: GLViewer_Viewer.cxx
24 // Created: November, 2004
25 //#include <GLViewerAfx.h>
27 #include "GLViewer_Viewer.h"
28 #include "GLViewer_Selector.h"
29 #include "GLViewer_ViewPort.h"
30 #include "GLViewer_ViewFrame.h"
32 //#include "SUIT_Desktop.h"
33 #include "SUIT_ViewWindow.h"
34 #include "SUIT_ViewManager.h"
36 #include <QApplication>
38 #include <QColorDialog>
39 #include <QMouseEvent>
40 #include <QWheelEvent>
42 #include <QRubberBand>
44 /* used for sketching */
45 static QEvent* l_mbPressEvent = 0;
50 GLViewer_Viewer::GLViewer_Viewer( const QString& title )
55 mySelMode( NoSelection )
62 GLViewer_Viewer::~GLViewer_Viewer()
69 \param theViewManager - new view manager
71 void GLViewer_Viewer::setViewManager(SUIT_ViewManager* theViewManager)
73 SUIT_ViewModel::setViewManager(theViewManager);
76 connect(theViewManager, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)),
77 this, SLOT(onMouseEvent(SUIT_ViewWindow*, QMouseEvent*)));
79 connect(theViewManager, SIGNAL(mouseMove(SUIT_ViewWindow*, QMouseEvent*)),
80 this, SLOT(onMouseEvent(SUIT_ViewWindow*, QMouseEvent*)));
82 connect(theViewManager, SIGNAL(mouseRelease(SUIT_ViewWindow*, QMouseEvent*)),
83 this, SLOT(onMouseEvent(SUIT_ViewWindow*, QMouseEvent*)));
85 connect(theViewManager, SIGNAL(wheel(SUIT_ViewWindow*, QWheelEvent*)),
86 this, SLOT(onWheelEvent(SUIT_ViewWindow*, QWheelEvent*)));
91 Builds popup for GL viewer
93 void GLViewer_Viewer::contextMenuPopup( QMenu* thePopup )
95 if( thePopup->actions().count() > 0 )
96 thePopup->addSeparator();
98 thePopup->addAction( tr( "CHANGE_BGCOLOR" ), this, SLOT( onChangeBgColor() ) );
102 Sets the background color with color selection dialog. [ virtual protected slot ]
104 void GLViewer_Viewer::onChangeBgColor()
106 GLViewer_ViewPort* vp = getActiveView()->getViewPort();
107 QColor selColor = QColorDialog::getColor( vp->backgroundColor() );
109 if( selColor.isValid() )
110 vp->setBackgroundColor( selColor );
114 Returns the active view. [ public ]
116 GLViewer_ViewFrame* GLViewer_Viewer::getActiveView() const
118 SUIT_ViewManager* aMgr = getViewManager();
119 return (GLViewer_ViewFrame*)( aMgr != 0 ? aMgr->getActiveView() : 0 );
124 Sets the selection mode for this viewer. [ public ]
126 void GLViewer_Viewer::setSelectionMode( GLViewer_Viewer::SelectionMode mode )
128 if ( mySelMode != mode )
131 onSelectionModeChanged();
136 Returns selector of this viewer. [ public ]
138 GLViewer_Selector* GLViewer_Viewer::getSelector() const
142 GLViewer_Viewer* mthis = (GLViewer_Viewer*)this;
143 mthis->mySelector = mthis->createSelector();
146 connect( mySelector, SIGNAL( selSelectionDone( bool, SelectionChangeStatus ) ), SLOT( onSelectionDone( bool, SelectionChangeStatus ) ) );
147 connect( mySelector, SIGNAL( selSelectionCancel() ), SLOT( onSelectionCancel() ) );
154 Returns the selection mode of this viewer. [ public ]
156 GLViewer_Viewer::SelectionMode GLViewer_Viewer::getSelectionMode() const
162 Handles requests for sketching in the active view. [ virtual public ]
164 void GLViewer_Viewer::activateSketching( int type )
166 GLViewer_ViewPort* vp = 0;
167 if ( !getActiveView() || !( vp = getActiveView()->getViewPort() ) )
170 if ( !vp->isSketchingEnabled() )
173 /* Finish current sketching */
174 if ( type == NoSketching )
178 onSketchingFinished();
183 /* Activate new sketching */
186 activateSketching( NoSketching ); /* concurrency not suported */
187 mySketcher = createSketcher( type );
188 onSketchingStarted();
193 Handles requests for transformations in the active view. [ virtual public ]
195 void GLViewer_Viewer::activateTransform( int type )
197 GLViewer_ViewPort* vp = 0;
198 if ( !getActiveView() || !( vp = getActiveView()->getViewPort() ) )
201 if ( !vp->isTransformEnabled() )
204 /* Finish current transform */
205 if ( type == NoTransform )
209 onTransformationFinished();
210 delete myTransformer;
214 /* Activate new transform */
217 activateTransform( NoTransform ); /* concurrency not suported */
218 myTransformer = createTransformer( type );
219 onTransformationStarted();
220 myTransformer->exec();
225 Creates default transformer. [ virtual protected ]
227 GLViewer_ViewTransformer* GLViewer_Viewer::createTransformer( int type )
229 return new GLViewer_ViewTransformer( this, type );
233 Creates default sketcher. [ virtual protected ]
235 GLViewer_ViewSketcher* GLViewer_Viewer::createSketcher( int type )
237 return new GLViewer_ViewSketcher( this, type );
241 Returns null by default. [ virtual protected ]
243 GLViewer_Selector* GLViewer_Viewer::createSelector()
249 Unhilights detected entities, lock selection, sets event filter
250 on the whole application. [ virtual protected ]
252 void GLViewer_Viewer::onTransformationStarted()
256 getSelector()->lock( true ); /* disable selection */
258 /* Watch events: any mouse/key event outside the
259 viewport will be considered as the end of
263 qApp->installEventFilter( this );
267 Unlock selection, removes event filter. [ virtual protected ]
269 void GLViewer_Viewer::onTransformationFinished()
272 getSelector()->lock( false ); /* enable selection */
274 /* Stop watch events */
277 qApp->removeEventFilter( this );
281 Unhilights detected entities. [ virtual protected ]
283 void GLViewer_Viewer::onSketchingStarted()
289 Selection by rectangle. [ virtual protected ]
291 void GLViewer_Viewer::onSketchingFinished()
293 if ( !getSelector() )
298 if ( mySketcher->type() == Rect )
300 QRect* selRect = (QRect*)mySketcher->data();
303 bool append = bool( mySketcher->buttonState() & GLViewer_Selector::appendKey() );
304 getSelector()->select( *selRect, append );
310 Installed while 'fit area' and 'global panning' operations are active. [ virtual protected ]
312 bool GLViewer_Viewer::eventFilter( QObject* o, QEvent* e )
314 if( !getActiveView() )
317 if( getActiveView()->getViewPort() == o->parent() )
320 bool mouseClickedOutside = ( e->type() == QEvent::MouseButtonPress &&
321 o != getActiveView()->getViewPort() );
322 bool anyKeyPressed = ( e->type() == QEvent::KeyPress );
323 if ( mouseClickedOutside || anyKeyPressed )
324 { /* terminate all */
325 activateTransform( NoTransform );
326 activateSketching( NoSketching );
327 //cout << "mouseClickedOutside || anyKeyPressed" << endl;
329 return QObject::eventFilter( o, e );
333 Called when smth is selected in this viewer. [ virtual protected slot ]
335 void GLViewer_Viewer::onSelectionDone( bool bAdded, SelectionChangeStatus status )
337 emit selectionChanged( status );
341 Called when selection is cleared in this viewer. [ virtual protected slot ]
343 void GLViewer_Viewer::onSelectionCancel()
345 emit selectionChanged( SCS_Invalid );
349 Listens to key events of the active view. [ virtual protected slot ]
351 void GLViewer_Viewer::onKeyEvent( SUIT_ViewWindow*, QKeyEvent* )
356 Listens to mouse events of the active view. [ virtual protected slot ]
358 void GLViewer_Viewer::onMouseEvent( SUIT_ViewWindow*, QMouseEvent* e )
360 //cout << "GLViewer_Viewer::onMouseEvent" << endl;
363 case QEvent::MouseButtonPress:
364 handleMousePress( e );
366 case QEvent::MouseMove:
367 handleMouseMove( e );
369 case QEvent::MouseButtonRelease:
370 handleMouseRelease( e );
377 Listens to mouse events of the active view. [ virtual protected slot ]
379 void GLViewer_Viewer::onWheelEvent( SUIT_ViewWindow*, QWheelEvent* e )
381 //cout << "GLViewer_Viewer::onMouseEvent" << endl;
392 Enables / disables rectangle sketching. [ virtual protected ]
394 void GLViewer_Viewer::onSelectionModeChanged()
396 bool enable = ( mySelMode == Multiple );
397 QVector<SUIT_ViewWindow*> views = getViewManager()->getViews();
398 for ( int i = 0, n = views.count(); i < n; i++ )
400 GLViewer_ViewPort* vp = ((GLViewer_ViewFrame*)views[i])->getViewPort();
402 vp->setSketchingEnabled( enable );
407 Updates all views of this viewer. Use 'flags' to customize update process. [ virtual public ]
409 void GLViewer_Viewer::update( int flags )
411 QVector<SUIT_ViewWindow*> views = getViewManager()->getViews();
412 for ( int i = 0, n = views.count(); i < n; i++ )
413 ((GLViewer_ViewFrame*)views[i])->onUpdate( flags );
417 Unhilights the currect detected objects. [ virtual private ]
419 void GLViewer_Viewer::unhilightDetected()
422 getSelector()->undetectAll();
426 Mouse press handler. If 'accelKey()' is pressed, activates default
427 transformations( Zoom or Pan ) in the active viewport. [ private ]
429 void GLViewer_Viewer::handleMousePress( QMouseEvent* e )
431 /* test accel for transforms */
432 if ( e->modifiers() & GLViewer_ViewTransformer::accelKey() )
434 Qt::MouseButton bs = e->button();
435 if ( bs == GLViewer_ViewTransformer::zoomButton() )
436 activateTransform( Zoom );
437 else if ( bs == GLViewer_ViewTransformer::panButton() )
438 activateTransform( Pan );
442 //checking for other operations before selection in release event
443 startOperations( e );
446 /* we may need it for sketching... */
447 l_mbPressEvent = new QMouseEvent( *e );
449 //checking for other operations before selection in release event
450 // startOperations( e );
452 /*e->button() == LeftButton && getSelector() )
454 bool append = bool ( e->state() & GLViewer_Selector::appendKey() );
455 getSelector()->select( append );
460 Mouse move handler. If dragged with MB1, activates rectangle sketching in
461 the active viewport, otherwise highlights the selectable entities. [ private ]
463 void GLViewer_Viewer::handleMouseMove( QMouseEvent* e )
465 /* Highlight for selection */
466 bool dragged = ( e->buttons() & ( Qt::LeftButton | Qt::MidButton | Qt::RightButton ) );
470 getSelector()->detect( e->x(), e->y() );
472 /* Try to activate default sketching
474 else if ( e->button() == GLViewer_ViewSketcher::sketchButton() )
476 activateSketching( Rect );
479 /* Activated OK. We should not forget initial mousepress
480 event and this mousemove event to start sketching from
481 the point of initial click */
482 if ( l_mbPressEvent )
484 QApplication::sendEvent( getActiveView()->getViewPort(), l_mbPressEvent );
485 delete l_mbPressEvent;
488 QApplication::sendEvent( getActiveView()->getViewPort(), e );
492 //Try to activate other operations
493 updateOperations( e );
497 Mouse move handler. Activates popup of the active view. [ private ]
499 void GLViewer_Viewer::handleMouseRelease( QMouseEvent* e )
502 /* tmp - in handleMousePress*/
503 if( e->button() == Qt::LeftButton && !(getActiveView()->getViewPort()->currentBlock() & BS_Selection) )
507 bool append = bool ( e->modifiers() & GLViewer_Selector::appendKey() );
508 getSelector()->select( append );
512 //Try to done active operations
513 finishOperations( e );
515 if ( l_mbPressEvent )
517 delete l_mbPressEvent;
523 Wheel rolling handler
525 void GLViewer_Viewer::handleWheel( QWheelEvent* e )
527 startOperations( e );
530 int GLViewer_ViewTransformer::panBtn = Qt::MidButton;
531 int GLViewer_ViewTransformer::zoomBtn = Qt::LeftButton;
532 int GLViewer_ViewTransformer::fitRectBtn = Qt::LeftButton;
533 int GLViewer_ViewTransformer::panGlobalBtn = Qt::LeftButton;
534 int GLViewer_ViewTransformer::acccelKey = Qt::ControlModifier;
539 GLViewer_ViewTransformer::GLViewer_ViewTransformer( GLViewer_Viewer* v, int type )
543 myMajorBtn( Qt::NoButton ),
547 if ( myType == GLViewer_Viewer::Pan ||
548 myType == GLViewer_Viewer::Zoom ||
549 myType == GLViewer_Viewer::PanGlobal ||
550 myType == GLViewer_Viewer::FitRect )
552 /* 'long' transforms need this */
553 initTransform( true );
560 GLViewer_ViewTransformer::~GLViewer_ViewTransformer()
562 if ( myType == GLViewer_Viewer::Pan ||
563 myType == GLViewer_Viewer::Zoom ||
564 myType == GLViewer_Viewer::PanGlobal ||
565 myType == GLViewer_Viewer::FitRect )
567 /* 'long' transforms need this */
568 initTransform( false );
571 //QAD_Application::getDesktop()->clearInfo();
577 Inits long transformations ( Zoom, Pan etc ) [ protected ]
579 Saves viewport state( cursor etc ) and installs event filter to process
580 mouse events if 'init' is true. Restores viewport state if 'init' is false.
582 void GLViewer_ViewTransformer::initTransform( bool init )
584 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
587 mySavedCursor = avp->cursor();
588 mySavedMouseTrack = avp->hasMouseTracking();
589 avp->setMouseTracking( false );
590 avp->installEventFilter( this );
594 avp->removeEventFilter( this );
595 avp->setMouseTracking( mySavedMouseTrack );
596 avp->setCursor( mySavedCursor );
601 Runs transfomation. Redefine to add your own 'instant' transforms
602 ( for ex., 'FitAll' is an instant transform ). [ virtual public ]
604 void GLViewer_ViewTransformer::exec()
606 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
612 case GLViewer_Viewer::Zoom:
613 myMajorBtn = zoomButton();
614 avp->setCursor( *avp->getZoomCursor() );
616 case GLViewer_Viewer::Pan:
617 myMajorBtn = panButton();
618 avp->setCursor( *avp->getPanCursor() );
620 case GLViewer_Viewer::PanGlobal:
621 myMajorBtn = panGlobalButton();
622 avp->setCursor( *avp->getPanglCursor() );
623 avp->fitAll( true, false ); /* view is ready now */
625 case GLViewer_Viewer::FitRect:
626 myMajorBtn = fitRectButton();
627 avp->setCursor( *avp->getHandCursor() );
629 case GLViewer_Viewer::Reset:
630 avp->reset(); onTransform( Fin );
632 case GLViewer_Viewer::FitAll:
633 avp->fitAll(); onTransform( Fin );
635 case GLViewer_Viewer::FitSelect:
636 avp->fitSelect(); onTransform( Fin );
643 Catches mouse events for the viewport. [ virtual protected ]
645 bool GLViewer_ViewTransformer::eventFilter( QObject* o, QEvent* e )
649 case QEvent::MouseMove:
650 case QEvent::MouseButtonPress:
651 case QEvent::MouseButtonRelease:
653 TransformState state = EnTrain;
654 QMouseEvent* me = ( QMouseEvent* )e;
656 myButtonState = me->modifiers();
657 if ( e->type() == QEvent::MouseButtonPress )
658 myButtonState |= me->button(); /* add pressed button */
660 int mouseOnlyState = ( myButtonState & ( Qt::LeftButton | Qt::MidButton | Qt::RightButton ) );
661 if ( myStart.isNull() )
665 myMajorBtn = mouseOnlyState;
668 if ( e->type() == QEvent::MouseButtonRelease && mouseOnlyState == myMajorBtn )
673 onTransform( state );
678 return QObject::eventFilter( o, e );
682 Transforms the viewport. Used for 'non-instant' transforms
683 only( ex. Rotate, Pan etc ). [ virtual protected ]
685 void GLViewer_ViewTransformer::onTransform( TransformState state )
687 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
688 bool doTrsf = ( myButtonState & myMajorBtn );
691 case GLViewer_Viewer::Zoom:
692 if ( state != Fin && doTrsf )
694 avp->zoom( myStart.x(), myStart.y(), myCurr.x(), myCurr.y() );
698 case GLViewer_Viewer::Pan:
699 if ( state != Fin && doTrsf )
701 avp->pan( myCurr.x() - myStart.x(), myStart.y() - myCurr.y() );
705 case GLViewer_Viewer::PanGlobal:
708 avp->setCenter( myCurr.x(), myCurr.y() );
711 case GLViewer_Viewer::FitRect:
715 QRect rect( qMin( myStart.x(), myCurr.x() ), qMin( myStart.y(), myCurr.y() ),
716 qAbs( myStart.x() - myCurr.x() ), qAbs( myStart.y() - myCurr.y() ) );
717 if ( !rect.isEmpty() )
722 avp->fitRect( rect );
739 myViewer->activateTransform( GLViewer_Viewer::NoTransform );
743 Draws rectangle by starting and current points
745 void GLViewer_ViewTransformer::drawRect(const QRect& theRect)
748 myRectBand = new QRubberBand( QRubberBand::Rectangle, myViewer->getActiveView()->getViewPort() );
750 palette.setColor(myRectBand->foregroundRole(), Qt::white);
751 myRectBand->setPalette(palette);
755 myRectBand->setGeometry( theRect );
756 myRectBand->setVisible( theRect.isValid() );
760 \brief Delete rubber band on the end on the dragging operation.
762 void GLViewer_ViewTransformer::endDrawRect()
764 if ( myRectBand ) myRectBand->hide();
771 Returns the type of the transformer. [ public ]
773 int GLViewer_ViewTransformer::type() const
779 int GLViewer_ViewSketcher::sketchBtn = Qt::LeftButton;
784 GLViewer_ViewSketcher::GLViewer_ViewSketcher( GLViewer_Viewer* viewer, int type )
793 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
797 mySavedCursor = avp->cursor();
798 avp->setCursor( *GLViewer_ViewPort::getHandCursor() );
799 avp->installEventFilter( this );
801 if ( myType == GLViewer_Viewer::Rect )
802 myData = new QRect();
808 GLViewer_ViewSketcher::~GLViewer_ViewSketcher()
810 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
811 avp->removeEventFilter( this );
812 avp->setCursor( mySavedCursor );
814 if ( myType == GLViewer_Viewer::Rect )
815 delete ( QRect* ) myData;
821 Catches mouse events for the viewport. [ virtual protected ]
823 bool GLViewer_ViewSketcher::eventFilter( QObject* o, QEvent* e )
827 case QEvent::MouseMove:
828 case QEvent::MouseButtonPress:
829 case QEvent::MouseButtonRelease:
831 SketchState state = EnTrain;
832 QMouseEvent* me = (QMouseEvent*)e;
834 myButtonState = me->modifiers();
835 if ( e->type() == QEvent::MouseButtonPress )
836 myButtonState |= me->button(); /* add pressed button */
838 if ( myStart.isNull() )
844 int mouseOnlyState = ( myButtonState & ( Qt::LeftButton | Qt::MidButton | Qt::RightButton ) );
845 if ( e->type() == QEvent::MouseButtonRelease && mouseOnlyState == sketchButton() )
855 return QObject::eventFilter( o, e );
859 Draws in the viewport. [ virtual protected ]
861 void GLViewer_ViewSketcher::onSketch( SketchState state )
863 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
867 if( myType == GLViewer_Viewer::Rect )
869 QRect* sketchRect = ( QRect* )data();
870 if ( myButtonState & sketchButton() )
872 QRect rect( qMin( myStart.x(), myCurr.x() ), qMin( myStart.y(), myCurr.y() ),
873 qAbs( myStart.x() - myCurr.x() ), qAbs( myStart.y() - myCurr.y() ) );
874 if ( !rect.isEmpty() )
876 if ( !sketchRect->isEmpty() && myRectBand )
877 myRectBand->hide(); /* erase */
880 drawRect( *sketchRect );
887 QApplication::syncX(); /* force rectangle redrawing */
888 myViewer->activateSketching( GLViewer_Viewer::NoSketching );
893 Draws rectangle by starting and current points
895 void GLViewer_ViewSketcher::drawRect(const QRect& theRect)
898 myRectBand = new QRubberBand( QRubberBand::Rectangle, myViewer->getActiveView()->getViewPort() );
900 palette.setColor(myRectBand->foregroundRole(), Qt::white);
901 myRectBand->setPalette(palette);
905 myRectBand->setGeometry( theRect );
906 myRectBand->setVisible( theRect.isValid() );
910 \brief Delete rubber band on the end on the dragging operation.
912 void GLViewer_ViewSketcher::endDrawRect()
914 if ( myRectBand ) myRectBand->hide();