1 // File: GLViewer_Viewer.cxx
2 // Created: November, 2004
4 // Copyright (C) CEA 2004
6 /***************************************************************************
7 ** Class: GLViewer_Viewer
8 ** Descr: Viewer for QAD-based application
10 ** Created: UI team, 05.09.00
11 ****************************************************************************/
13 #include "GLViewer_Viewer.h"
15 #include "GLViewer_Selector.h"
16 #include "GLViewer_ViewPort.h"
17 #include "GLViewer_ViewFrame.h"
19 #include "SUIT_Desktop.h"
20 #include "SUIT_ViewWindow.h"
23 #include <qapplication.h>
25 /* used for sketching */
26 static QEvent* l_mbPressEvent = 0;
31 GLViewer_Viewer::GLViewer_Viewer( const QString& title )
36 mySelMode( NoSelection )
43 GLViewer_Viewer::~GLViewer_Viewer()
48 //================================================================
49 // Function : setViewManager
51 //================================================================
52 void GLViewer_Viewer::setViewManager(SUIT_ViewManager* theViewManager)
54 SUIT_ViewModel::setViewManager(theViewManager);
57 connect(theViewManager, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)),
58 this, SLOT(onMouseEvent(SUIT_ViewWindow*, QMouseEvent*)));
60 connect(theViewManager, SIGNAL(mouseMove(SUIT_ViewWindow*, QMouseEvent*)),
61 this, SLOT(onMouseEvent(SUIT_ViewWindow*, QMouseEvent*)));
63 connect(theViewManager, SIGNAL(mouseRelease(SUIT_ViewWindow*, QMouseEvent*)),
64 this, SLOT(onMouseEvent(SUIT_ViewWindow*, QMouseEvent*)));
66 connect(theViewManager, SIGNAL(wheel(SUIT_ViewWindow*, QWheelEvent*)),
67 this, SLOT(onWheelEvent(SUIT_ViewWindow*, QWheelEvent*)));
72 Returns the active view. [ public ]
74 GLViewer_ViewFrame* GLViewer_Viewer::getActiveView() const
76 SUIT_ViewManager* aMgr = getViewManager();
77 return (GLViewer_ViewFrame*)( aMgr != 0 ? aMgr->getActiveView() : 0 );
82 Sets the selection mode for this viewer. [ public ]
84 void GLViewer_Viewer::setSelectionMode( GLViewer_Viewer::SelectionMode mode )
86 if ( mySelMode != mode )
89 onSelectionModeChanged();
94 Returns selector of this viewer. [ public ]
96 GLViewer_Selector* GLViewer_Viewer::getSelector() const
100 GLViewer_Viewer* mthis = (GLViewer_Viewer*)this;
101 mthis->mySelector = mthis->createSelector();
104 connect( mySelector, SIGNAL( selSelectionDone( bool, SelectionChangeStatus ) ), SLOT( onSelectionDone( bool, SelectionChangeStatus ) ) );
105 connect( mySelector, SIGNAL( selSelectionCancel() ), SLOT( onSelectionCancel() ) );
112 Returns the selection mode of this viewer. [ public ]
114 GLViewer_Viewer::SelectionMode GLViewer_Viewer::getSelectionMode() const
120 Handles requests for sketching in the active view. [ virtual public ]
122 void GLViewer_Viewer::activateSketching( int type )
124 GLViewer_ViewPort* vp = 0;
125 if ( !getActiveView() || !( vp = getActiveView()->getViewPort() ) )
128 if ( !vp->isSketchingEnabled() )
131 /* Finish current sketching */
132 if ( type == NoSketching )
136 onSketchingFinished();
141 /* Activate new sketching */
144 activateSketching( NoSketching ); /* concurrency not suported */
145 mySketcher = createSketcher( type );
146 onSketchingStarted();
151 Handles requests for transformations in the active view. [ virtual public ]
153 void GLViewer_Viewer::activateTransform( int type )
155 GLViewer_ViewPort* vp = 0;
156 if ( !getActiveView() || !( vp = getActiveView()->getViewPort() ) )
159 if ( !vp->isTransformEnabled() )
162 /* Finish current transform */
163 if ( type == NoTransform )
167 onTransformationFinished();
168 delete myTransformer;
172 /* Activate new transform */
175 activateTransform( NoTransform ); /* concurrency not suported */
176 myTransformer = createTransformer( type );
177 onTransformationStarted();
178 myTransformer->exec();
183 Creates default transformer. [ virtual protected ]
185 GLViewer_ViewTransformer* GLViewer_Viewer::createTransformer( int type )
187 return new GLViewer_ViewTransformer( this, type );
191 Creates default sketcher. [ virtual protected ]
193 GLViewer_ViewSketcher* GLViewer_Viewer::createSketcher( int type )
195 return new GLViewer_ViewSketcher( this, type );
199 Returns null by default. [ virtual protected ]
201 GLViewer_Selector* GLViewer_Viewer::createSelector()
207 Unhilights detected entities, lock selection, sets event filter
208 on the whole application. [ virtual protected ]
210 void GLViewer_Viewer::onTransformationStarted()
214 getSelector()->lock( true ); /* disable selection */
216 /* Watch events: any mouse/key event outside the
217 viewport will be considered as the end of
221 //int type = myTransformer->type();
222 qApp->installEventFilter( this );
226 Unlock selection, removes event filter. [ virtual protected ]
228 void GLViewer_Viewer::onTransformationFinished()
231 getSelector()->lock( false ); /* enable selection */
233 /* Stop watch events */
236 //int type = myTransformer->type();
237 qApp->removeEventFilter( this );
241 Unhilights detected entities. [ virtual protected ]
243 void GLViewer_Viewer::onSketchingStarted()
249 Selection by rectangle. [ virtual protected ]
251 void GLViewer_Viewer::onSketchingFinished()
253 if ( !getSelector() )
258 if ( mySketcher->type() == Rect )
260 QRect* selRect = (QRect*)mySketcher->data();
263 bool append = bool( mySketcher->buttonState() & GLViewer_Selector::appendKey() );
264 getSelector()->select( *selRect, append );
270 Installed while 'fit area' and 'global panning' operations are active. [ virtual protected ]
272 bool GLViewer_Viewer::eventFilter( QObject* o, QEvent* e )
274 if( !getActiveView() )
277 if( getActiveView()->getViewPort() == o->parent() ) // for QAD_GLWidget
280 bool mouseClickedOutside = ( e->type() == QEvent::MouseButtonPress &&
281 o != getActiveView()->getViewPort() );
282 bool anyKeyPressed = ( e->type() == QEvent::KeyPress );
283 if ( mouseClickedOutside || anyKeyPressed )
284 { /* terminate all */
285 activateTransform( NoTransform );
286 activateSketching( NoSketching );
287 //cout << "mouseClickedOutside || anyKeyPressed" << endl;
289 return QObject::eventFilter( o, e );
293 Called when smth is selected in this viewer. [ virtual protected slot ]
295 void GLViewer_Viewer::onSelectionDone( bool bAdded, SelectionChangeStatus status )
297 emit selectionChanged( status );
301 Called when selection is cleared in this viewer. [ virtual protected slot ]
303 void GLViewer_Viewer::onSelectionCancel()
305 emit selectionChanged( SCS_Invalid );
309 Listens to key events of the active view. [ virtual protected slot ]
311 void GLViewer_Viewer::onKeyEvent( SUIT_ViewWindow*, QKeyEvent* )
316 Listens to mouse events of the active view. [ virtual protected slot ]
318 void GLViewer_Viewer::onMouseEvent( SUIT_ViewWindow*, QMouseEvent* e )
320 //cout << "GLViewer_Viewer::onMouseEvent" << endl;
323 case QEvent::MouseButtonPress:
324 handleMousePress( e );
326 case QEvent::MouseMove:
327 handleMouseMove( e );
329 case QEvent::MouseButtonRelease:
330 handleMouseRelease( e );
337 Listens to mouse events of the active view. [ virtual protected slot ]
339 void GLViewer_Viewer::onWheelEvent( SUIT_ViewWindow*, QWheelEvent* e )
341 //cout << "GLViewer_Viewer::onMouseEvent" << endl;
352 Enables / disables rectangle sketching. [ virtual protected ]
354 void GLViewer_Viewer::onSelectionModeChanged()
356 bool enable = ( mySelMode == Multiple );
357 QPtrVector<SUIT_ViewWindow> views = getViewManager()->getViews();
358 for ( int i = 0, n = views.count(); i < n; i++ )
360 GLViewer_ViewPort* vp = ((GLViewer_ViewFrame*)views[i])->getViewPort();
362 vp->setSketchingEnabled( enable );
367 Updates all views of this viewer. Use 'flags' to customize update process. [ virtual public ]
369 void GLViewer_Viewer::update( int flags )
371 QPtrVector<SUIT_ViewWindow> views = getViewManager()->getViews();
372 for ( int i = 0, n = views.count(); i < n; i++ )
373 ((GLViewer_ViewFrame*)views[i])->onUpdate( flags );
377 Unhilights the currect detected objects. [ virtual private ]
379 void GLViewer_Viewer::unhilightDetected()
382 getSelector()->detect( -1, -1 );
386 Mouse press handler. If 'accelKey()' is pressed, activates default
387 transformations( Zoom or Pan ) in the active viewport. [ private ]
389 void GLViewer_Viewer::handleMousePress( QMouseEvent* e )
391 /* test accel for transforms */
392 if ( e->state() & GLViewer_ViewTransformer::accelKey() )
394 ButtonState bs = e->button();
395 if ( bs == GLViewer_ViewTransformer::zoomButton() )
396 activateTransform( Zoom );
397 else if ( bs == GLViewer_ViewTransformer::panButton() )
398 activateTransform( Pan );
402 //checking for other operations before selection in release event
403 startOperations( e );
406 /* we may need it for sketching... */
407 l_mbPressEvent = new QMouseEvent( *e );
409 //checking for other operations before selection in release event
410 // startOperations( e );
412 /*e->button() == LeftButton && getSelector() )
414 bool append = bool ( e->state() & GLViewer_Selector::appendKey() );
415 getSelector()->select( append );
420 Mouse move handler. If dragged with MB1, activates rectangle sketching in
421 the active viewport, otherwise highlights the selectable entities. [ private ]
423 void GLViewer_Viewer::handleMouseMove( QMouseEvent* e )
425 /* Highlight for selection */
426 bool dragged = ( e->state() & ( LeftButton | MidButton | RightButton ) );
430 getSelector()->detect( e->x(), e->y() );
432 /* Try to activate default sketching
434 else if ( e->state() == GLViewer_ViewSketcher::sketchButton() )
436 activateSketching( Rect );
439 /* Activated OK. We should not forget initial mousepress
440 event and this mousemove event to start sketching from
441 the point of initial click */
442 if ( l_mbPressEvent )
444 QApplication::sendEvent( getActiveView()->getViewPort(), l_mbPressEvent );
445 delete l_mbPressEvent;
448 QApplication::sendEvent( getActiveView()->getViewPort(), e );
452 //Try to activate other operations
453 updateOperations( e );
457 Mouse move handler. Activates popup of the active view. [ private ]
459 void GLViewer_Viewer::handleMouseRelease( QMouseEvent* e )
462 /* tmp - in handleMousePress*/
463 if( e->button() == LeftButton && !(getActiveView()->getViewPort()->currentBlock() & BS_Selection) )
467 bool append = bool ( e->state() & GLViewer_Selector::appendKey() );
468 getSelector()->select( append );
472 //Try to done active operations
473 finishOperations( e );
475 if ( l_mbPressEvent )
477 delete l_mbPressEvent;
483 Wheel rolling handler
485 void GLViewer_Viewer::handleWheel( QWheelEvent* e )
487 startOperations( e );
490 /****************************************************************
491 ** Class: GLViewer_ViewTransformer
493 *****************************************************************/
494 int GLViewer_ViewTransformer::panBtn = Qt::MidButton;
495 int GLViewer_ViewTransformer::zoomBtn = Qt::LeftButton;
496 int GLViewer_ViewTransformer::fitRectBtn = Qt::LeftButton;
497 int GLViewer_ViewTransformer::panGlobalBtn = Qt::LeftButton;
498 int GLViewer_ViewTransformer::acccelKey = Qt::ControlButton;
503 GLViewer_ViewTransformer::GLViewer_ViewTransformer( GLViewer_Viewer* v, int type )
507 myMajorBtn( NoButton ),
510 if ( myType == GLViewer_Viewer::Pan ||
511 myType == GLViewer_Viewer::Zoom ||
512 myType == GLViewer_Viewer::PanGlobal ||
513 myType == GLViewer_Viewer::FitRect )
515 /* 'long' transforms need this */
516 initTransform( true );
523 GLViewer_ViewTransformer::~GLViewer_ViewTransformer()
525 if ( myType == GLViewer_Viewer::Pan ||
526 myType == GLViewer_Viewer::Zoom ||
527 myType == GLViewer_Viewer::PanGlobal ||
528 myType == GLViewer_Viewer::FitRect )
530 /* 'long' transforms need this */
531 initTransform( false );
534 //QAD_Application::getDesktop()->clearInfo();
538 Inits long transformations ( Zoom, Pan etc ) [ protected ]
540 Saves viewport state( cursor etc ) and installs event filter to process
541 mouse events if 'init' is true. Restores viewport state if 'init' is false.
543 void GLViewer_ViewTransformer::initTransform( bool init )
545 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
548 mySavedCursor = avp->cursor();
549 mySavedMouseTrack = avp->hasMouseTracking();
550 avp->setMouseTracking( false );
551 avp->installEventFilter( this );
555 avp->removeEventFilter( this );
556 avp->setMouseTracking( mySavedMouseTrack );
557 avp->setCursor( mySavedCursor );
562 Runs transfomation. Redefine to add your own 'instant' transforms
563 ( for ex., 'FitAll' is an instant transform ). [ virtual public ]
565 void GLViewer_ViewTransformer::exec()
567 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
571 //QAD_Desktop* d = QAD_Application::getDesktop();
574 case GLViewer_Viewer::Zoom:
575 myMajorBtn = zoomButton();
576 avp->setCursor( *avp->getZoomCursor() );
577 //d->putInfo( myViewer->tr( "PRP_VW_ZOOM" ) );
579 case GLViewer_Viewer::Pan:
580 myMajorBtn = panButton();
581 avp->setCursor( *avp->getPanCursor() );
582 //d->putInfo( myViewer->tr( "PRP_VW_PAN" ) );
584 case GLViewer_Viewer::PanGlobal:
585 myMajorBtn = panGlobalButton();
586 avp->setCursor( *avp->getPanglCursor() );
587 avp->fitAll( true, false ); /* view is ready now */
588 //d->putInfo( myViewer->tr( "PRP_VW_POINTCENTER" ) );
590 case GLViewer_Viewer::FitRect:
591 myMajorBtn = fitRectButton();
592 avp->setCursor( *avp->getHandCursor() );
593 //d->putInfo( myViewer->tr( "PRP_VW_SKETCHAREA" ) );
595 case GLViewer_Viewer::Reset:
596 avp->reset(); onTransform( Fin );
598 case GLViewer_Viewer::FitAll:
599 avp->fitAll(); onTransform( Fin );
601 case GLViewer_Viewer::FitSelect:
602 avp->fitSelect(); onTransform( Fin );
609 Catches mouse events for the viewport. [ virtual protected ]
611 bool GLViewer_ViewTransformer::eventFilter( QObject* o, QEvent* e )
615 case QEvent::MouseMove:
616 case QEvent::MouseButtonPress:
617 case QEvent::MouseButtonRelease:
619 TransformState state = EnTrain;
620 QMouseEvent* me = ( QMouseEvent* )e;
622 myButtonState = me->state();
623 if ( e->type() == QEvent::MouseButtonPress )
624 myButtonState |= me->button(); /* add pressed button */
626 int mouseOnlyState = ( myButtonState & ( LeftButton | MidButton | RightButton ) );
627 if ( myStart.isNull() )
631 myMajorBtn = mouseOnlyState;
634 if ( e->type() == QEvent::MouseButtonRelease && mouseOnlyState == myMajorBtn )
639 onTransform( state );
644 return QObject::eventFilter( o, e );
648 Transforms the viewport. Used for 'non-instant' transforms
649 only( ex. Rotate, Pan etc ). [ virtual protected ]
651 void GLViewer_ViewTransformer::onTransform( TransformState state )
653 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
654 bool doTrsf = ( myButtonState & myMajorBtn );
657 case GLViewer_Viewer::Zoom:
658 if ( state != Fin && doTrsf )
660 avp->zoom( myStart.x(), myStart.y(), myCurr.x(), myCurr.y() );
664 case GLViewer_Viewer::Pan:
665 if ( state != Fin && doTrsf )
667 avp->pan( myCurr.x() - myStart.x(), myStart.y() - myCurr.y() );
671 case GLViewer_Viewer::PanGlobal:
674 avp->setCenter( myCurr.x(), myCurr.y() );
677 case GLViewer_Viewer::FitRect:
681 QRect rect( QMIN( myStart.x(), myCurr.x() ), QMIN( myStart.y(), myCurr.y() ),
682 QABS( myStart.x() - myCurr.x() ), QABS( myStart.y() - myCurr.y() ) );
683 if ( !rect.isEmpty() )
688 avp->fitRect( rect );
692 QPainter p( avp->getPaintDevice() ); // for QAD_GLWidget
693 p.setPen( Qt::white );
694 p.setRasterOp( Qt::XorROP );
695 if ( !myDrawRect.isEmpty() )
696 p.drawRect( myDrawRect ); /* erase */
711 myViewer->activateTransform( GLViewer_Viewer::NoTransform );
715 Returns the type of the transformer. [ public ]
717 int GLViewer_ViewTransformer::type() const
723 /****************************************************************
724 ** Class: GLViewer_ViewSketcher
726 *****************************************************************/
727 int GLViewer_ViewSketcher::sketchBtn = LeftButton;
732 GLViewer_ViewSketcher::GLViewer_ViewSketcher( GLViewer_Viewer* viewer, int type )
740 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
744 mySavedCursor = avp->cursor();
745 avp->setCursor( *GLViewer_ViewPort::getHandCursor() );
746 avp->installEventFilter( this );
748 if ( myType == GLViewer_Viewer::Rect )
749 myData = new QRect();
755 GLViewer_ViewSketcher::~GLViewer_ViewSketcher()
757 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
758 avp->removeEventFilter( this );
759 avp->setCursor( mySavedCursor );
761 if ( myType == GLViewer_Viewer::Rect )
762 delete ( QRect* ) myData;
764 //QAD_Application::getDesktop()->clearInfo();
768 Catches mouse events for the viewport. [ virtual protected ]
770 bool GLViewer_ViewSketcher::eventFilter( QObject* o, QEvent* e )
774 case QEvent::MouseMove:
775 case QEvent::MouseButtonPress:
776 case QEvent::MouseButtonRelease:
778 SketchState state = EnTrain;
779 QMouseEvent* me = (QMouseEvent*)e;
781 myButtonState = me->state();
782 if ( e->type() == QEvent::MouseButtonPress )
783 myButtonState |= me->button(); /* add pressed button */
785 if ( myStart.isNull() )
791 int mouseOnlyState = ( myButtonState & ( LeftButton | MidButton | RightButton ) );
792 if ( e->type() == QEvent::MouseButtonRelease && mouseOnlyState == sketchButton() )
802 return QObject::eventFilter( o, e );
806 Draws in the viewport. [ virtual protected ]
808 void GLViewer_ViewSketcher::onSketch( SketchState state )
810 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
814 if( myType == GLViewer_Viewer::Rect )
816 QRect* sketchRect = ( QRect* )data();
817 if ( myButtonState & sketchButton() )
819 QRect rect( QMIN( myStart.x(), myCurr.x() ), QMIN( myStart.y(), myCurr.y() ),
820 QABS( myStart.x() - myCurr.x() ), QABS( myStart.y() - myCurr.y() ) );
821 if ( !rect.isEmpty() )
824 p.setPen( Qt::white );
825 p.setRasterOp( Qt::XorROP );
826 if ( !sketchRect->isEmpty() )
827 p.drawRect( *sketchRect ); /* erase */
830 p.drawRect( *sketchRect );
837 QApplication::syncX(); /* force rectangle redrawing */
838 myViewer->activateSketching( GLViewer_Viewer::NoSketching );