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 <GLViewerAfx.h>
14 #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"
22 #include <qapplication.h>
24 #include <qpopupmenu.h>
25 #include <qcolordialog.h>
27 /* used for sketching */
28 static QEvent* l_mbPressEvent = 0;
33 GLViewer_Viewer::GLViewer_Viewer( const QString& title )
38 mySelMode( NoSelection )
45 GLViewer_Viewer::~GLViewer_Viewer()
50 //================================================================
51 // Function : setViewManager
53 //================================================================
54 void GLViewer_Viewer::setViewManager(SUIT_ViewManager* theViewManager)
56 SUIT_ViewModel::setViewManager(theViewManager);
59 connect(theViewManager, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)),
60 this, SLOT(onMouseEvent(SUIT_ViewWindow*, QMouseEvent*)));
62 connect(theViewManager, SIGNAL(mouseMove(SUIT_ViewWindow*, QMouseEvent*)),
63 this, SLOT(onMouseEvent(SUIT_ViewWindow*, QMouseEvent*)));
65 connect(theViewManager, SIGNAL(mouseRelease(SUIT_ViewWindow*, QMouseEvent*)),
66 this, SLOT(onMouseEvent(SUIT_ViewWindow*, QMouseEvent*)));
68 connect(theViewManager, SIGNAL(wheel(SUIT_ViewWindow*, QWheelEvent*)),
69 this, SLOT(onWheelEvent(SUIT_ViewWindow*, QWheelEvent*)));
73 //================================================================
74 // Function : contextMenuPopup
76 //================================================================
77 void GLViewer_Viewer::contextMenuPopup( QPopupMenu* thePopup )
79 if( thePopup->count() > 0 )
80 thePopup->insertSeparator();
82 thePopup->insertItem( tr( "CHANGE_BGCOLOR" ), this, SLOT( onChangeBgColor() ) );
86 Sets the background color with color selection dialog. [ virtual protected slot ]
88 void GLViewer_Viewer::onChangeBgColor()
90 GLViewer_ViewPort* vp = getActiveView()->getViewPort();
91 QColor selColor = QColorDialog::getColor( vp->backgroundColor() );
93 if( selColor.isValid() )
94 vp->setBackgroundColor( selColor );
98 Returns the active view. [ public ]
100 GLViewer_ViewFrame* GLViewer_Viewer::getActiveView() const
102 SUIT_ViewManager* aMgr = getViewManager();
103 return (GLViewer_ViewFrame*)( aMgr != 0 ? aMgr->getActiveView() : 0 );
108 Sets the selection mode for this viewer. [ public ]
110 void GLViewer_Viewer::setSelectionMode( GLViewer_Viewer::SelectionMode mode )
112 if ( mySelMode != mode )
115 onSelectionModeChanged();
120 Returns selector of this viewer. [ public ]
122 GLViewer_Selector* GLViewer_Viewer::getSelector() const
126 GLViewer_Viewer* mthis = (GLViewer_Viewer*)this;
127 mthis->mySelector = mthis->createSelector();
130 connect( mySelector, SIGNAL( selSelectionDone( bool, SelectionChangeStatus ) ), SLOT( onSelectionDone( bool, SelectionChangeStatus ) ) );
131 connect( mySelector, SIGNAL( selSelectionCancel() ), SLOT( onSelectionCancel() ) );
138 Returns the selection mode of this viewer. [ public ]
140 GLViewer_Viewer::SelectionMode GLViewer_Viewer::getSelectionMode() const
146 Handles requests for sketching in the active view. [ virtual public ]
148 void GLViewer_Viewer::activateSketching( int type )
150 GLViewer_ViewPort* vp = 0;
151 if ( !getActiveView() || !( vp = getActiveView()->getViewPort() ) )
154 if ( !vp->isSketchingEnabled() )
157 /* Finish current sketching */
158 if ( type == NoSketching )
162 onSketchingFinished();
167 /* Activate new sketching */
170 activateSketching( NoSketching ); /* concurrency not suported */
171 mySketcher = createSketcher( type );
172 onSketchingStarted();
177 Handles requests for transformations in the active view. [ virtual public ]
179 void GLViewer_Viewer::activateTransform( int type )
181 GLViewer_ViewPort* vp = 0;
182 if ( !getActiveView() || !( vp = getActiveView()->getViewPort() ) )
185 if ( !vp->isTransformEnabled() )
188 /* Finish current transform */
189 if ( type == NoTransform )
193 onTransformationFinished();
194 delete myTransformer;
198 /* Activate new transform */
201 activateTransform( NoTransform ); /* concurrency not suported */
202 myTransformer = createTransformer( type );
203 onTransformationStarted();
204 myTransformer->exec();
209 Creates default transformer. [ virtual protected ]
211 GLViewer_ViewTransformer* GLViewer_Viewer::createTransformer( int type )
213 return new GLViewer_ViewTransformer( this, type );
217 Creates default sketcher. [ virtual protected ]
219 GLViewer_ViewSketcher* GLViewer_Viewer::createSketcher( int type )
221 return new GLViewer_ViewSketcher( this, type );
225 Returns null by default. [ virtual protected ]
227 GLViewer_Selector* GLViewer_Viewer::createSelector()
233 Unhilights detected entities, lock selection, sets event filter
234 on the whole application. [ virtual protected ]
236 void GLViewer_Viewer::onTransformationStarted()
240 getSelector()->lock( true ); /* disable selection */
242 /* Watch events: any mouse/key event outside the
243 viewport will be considered as the end of
247 qApp->installEventFilter( this );
251 Unlock selection, removes event filter. [ virtual protected ]
253 void GLViewer_Viewer::onTransformationFinished()
256 getSelector()->lock( false ); /* enable selection */
258 /* Stop watch events */
261 qApp->removeEventFilter( this );
265 Unhilights detected entities. [ virtual protected ]
267 void GLViewer_Viewer::onSketchingStarted()
273 Selection by rectangle. [ virtual protected ]
275 void GLViewer_Viewer::onSketchingFinished()
277 if ( !getSelector() )
282 if ( mySketcher->type() == Rect )
284 QRect* selRect = (QRect*)mySketcher->data();
287 bool append = bool( mySketcher->buttonState() & GLViewer_Selector::appendKey() );
288 getSelector()->select( *selRect, append );
294 Installed while 'fit area' and 'global panning' operations are active. [ virtual protected ]
296 bool GLViewer_Viewer::eventFilter( QObject* o, QEvent* e )
298 if( !getActiveView() )
301 if( getActiveView()->getViewPort() == o->parent() )
304 bool mouseClickedOutside = ( e->type() == QEvent::MouseButtonPress &&
305 o != getActiveView()->getViewPort() );
306 bool anyKeyPressed = ( e->type() == QEvent::KeyPress );
307 if ( mouseClickedOutside || anyKeyPressed )
308 { /* terminate all */
309 activateTransform( NoTransform );
310 activateSketching( NoSketching );
311 //cout << "mouseClickedOutside || anyKeyPressed" << endl;
313 return QObject::eventFilter( o, e );
317 Called when smth is selected in this viewer. [ virtual protected slot ]
319 void GLViewer_Viewer::onSelectionDone( bool bAdded, SelectionChangeStatus status )
321 emit selectionChanged( status );
325 Called when selection is cleared in this viewer. [ virtual protected slot ]
327 void GLViewer_Viewer::onSelectionCancel()
329 emit selectionChanged( SCS_Invalid );
333 Listens to key events of the active view. [ virtual protected slot ]
335 void GLViewer_Viewer::onKeyEvent( SUIT_ViewWindow*, QKeyEvent* )
340 Listens to mouse events of the active view. [ virtual protected slot ]
342 void GLViewer_Viewer::onMouseEvent( SUIT_ViewWindow*, QMouseEvent* e )
344 //cout << "GLViewer_Viewer::onMouseEvent" << endl;
347 case QEvent::MouseButtonPress:
348 handleMousePress( e );
350 case QEvent::MouseMove:
351 handleMouseMove( e );
353 case QEvent::MouseButtonRelease:
354 handleMouseRelease( e );
361 Listens to mouse events of the active view. [ virtual protected slot ]
363 void GLViewer_Viewer::onWheelEvent( SUIT_ViewWindow*, QWheelEvent* e )
365 //cout << "GLViewer_Viewer::onMouseEvent" << endl;
376 Enables / disables rectangle sketching. [ virtual protected ]
378 void GLViewer_Viewer::onSelectionModeChanged()
380 bool enable = ( mySelMode == Multiple );
381 QPtrVector<SUIT_ViewWindow> views = getViewManager()->getViews();
382 for ( int i = 0, n = views.count(); i < n; i++ )
384 GLViewer_ViewPort* vp = ((GLViewer_ViewFrame*)views[i])->getViewPort();
386 vp->setSketchingEnabled( enable );
391 Updates all views of this viewer. Use 'flags' to customize update process. [ virtual public ]
393 void GLViewer_Viewer::update( int flags )
395 QPtrVector<SUIT_ViewWindow> views = getViewManager()->getViews();
396 for ( int i = 0, n = views.count(); i < n; i++ )
397 ((GLViewer_ViewFrame*)views[i])->onUpdate( flags );
401 Unhilights the currect detected objects. [ virtual private ]
403 void GLViewer_Viewer::unhilightDetected()
406 getSelector()->undetectAll();
410 Mouse press handler. If 'accelKey()' is pressed, activates default
411 transformations( Zoom or Pan ) in the active viewport. [ private ]
413 void GLViewer_Viewer::handleMousePress( QMouseEvent* e )
415 /* test accel for transforms */
416 if ( e->state() & GLViewer_ViewTransformer::accelKey() )
418 ButtonState bs = e->button();
419 if ( bs == GLViewer_ViewTransformer::zoomButton() )
420 activateTransform( Zoom );
421 else if ( bs == GLViewer_ViewTransformer::panButton() )
422 activateTransform( Pan );
426 //checking for other operations before selection in release event
427 startOperations( e );
430 /* we may need it for sketching... */
431 l_mbPressEvent = new QMouseEvent( *e );
433 //checking for other operations before selection in release event
434 // startOperations( e );
436 /*e->button() == LeftButton && getSelector() )
438 bool append = bool ( e->state() & GLViewer_Selector::appendKey() );
439 getSelector()->select( append );
444 Mouse move handler. If dragged with MB1, activates rectangle sketching in
445 the active viewport, otherwise highlights the selectable entities. [ private ]
447 void GLViewer_Viewer::handleMouseMove( QMouseEvent* e )
449 /* Highlight for selection */
450 bool dragged = ( e->state() & ( LeftButton | MidButton | RightButton ) );
454 getSelector()->detect( e->x(), e->y() );
456 /* Try to activate default sketching
458 else if ( e->state() == GLViewer_ViewSketcher::sketchButton() )
460 activateSketching( Rect );
463 /* Activated OK. We should not forget initial mousepress
464 event and this mousemove event to start sketching from
465 the point of initial click */
466 if ( l_mbPressEvent )
468 QApplication::sendEvent( getActiveView()->getViewPort(), l_mbPressEvent );
469 delete l_mbPressEvent;
472 QApplication::sendEvent( getActiveView()->getViewPort(), e );
476 //Try to activate other operations
477 updateOperations( e );
481 Mouse move handler. Activates popup of the active view. [ private ]
483 void GLViewer_Viewer::handleMouseRelease( QMouseEvent* e )
486 /* tmp - in handleMousePress*/
487 if( e->button() == LeftButton && !(getActiveView()->getViewPort()->currentBlock() & BS_Selection) )
491 bool append = bool ( e->state() & GLViewer_Selector::appendKey() );
492 getSelector()->select( append );
496 //Try to done active operations
497 finishOperations( e );
499 if ( l_mbPressEvent )
501 delete l_mbPressEvent;
507 Wheel rolling handler
509 void GLViewer_Viewer::handleWheel( QWheelEvent* e )
511 startOperations( e );
514 /****************************************************************
515 ** Class: GLViewer_ViewTransformer
517 *****************************************************************/
518 int GLViewer_ViewTransformer::panBtn = Qt::MidButton;
519 int GLViewer_ViewTransformer::zoomBtn = Qt::LeftButton;
520 int GLViewer_ViewTransformer::fitRectBtn = Qt::LeftButton;
521 int GLViewer_ViewTransformer::panGlobalBtn = Qt::LeftButton;
522 int GLViewer_ViewTransformer::acccelKey = Qt::ControlButton;
527 GLViewer_ViewTransformer::GLViewer_ViewTransformer( GLViewer_Viewer* v, int type )
531 myMajorBtn( NoButton ),
534 if ( myType == GLViewer_Viewer::Pan ||
535 myType == GLViewer_Viewer::Zoom ||
536 myType == GLViewer_Viewer::PanGlobal ||
537 myType == GLViewer_Viewer::FitRect )
539 /* 'long' transforms need this */
540 initTransform( true );
547 GLViewer_ViewTransformer::~GLViewer_ViewTransformer()
549 if ( myType == GLViewer_Viewer::Pan ||
550 myType == GLViewer_Viewer::Zoom ||
551 myType == GLViewer_Viewer::PanGlobal ||
552 myType == GLViewer_Viewer::FitRect )
554 /* 'long' transforms need this */
555 initTransform( false );
558 //QAD_Application::getDesktop()->clearInfo();
562 Inits long transformations ( Zoom, Pan etc ) [ protected ]
564 Saves viewport state( cursor etc ) and installs event filter to process
565 mouse events if 'init' is true. Restores viewport state if 'init' is false.
567 void GLViewer_ViewTransformer::initTransform( bool init )
569 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
572 mySavedCursor = avp->cursor();
573 mySavedMouseTrack = avp->hasMouseTracking();
574 avp->setMouseTracking( false );
575 avp->installEventFilter( this );
579 avp->removeEventFilter( this );
580 avp->setMouseTracking( mySavedMouseTrack );
581 avp->setCursor( mySavedCursor );
586 Runs transfomation. Redefine to add your own 'instant' transforms
587 ( for ex., 'FitAll' is an instant transform ). [ virtual public ]
589 void GLViewer_ViewTransformer::exec()
591 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
597 case GLViewer_Viewer::Zoom:
598 myMajorBtn = zoomButton();
599 avp->setCursor( *avp->getZoomCursor() );
601 case GLViewer_Viewer::Pan:
602 myMajorBtn = panButton();
603 avp->setCursor( *avp->getPanCursor() );
605 case GLViewer_Viewer::PanGlobal:
606 myMajorBtn = panGlobalButton();
607 avp->setCursor( *avp->getPanglCursor() );
608 avp->fitAll( true, false ); /* view is ready now */
610 case GLViewer_Viewer::FitRect:
611 myMajorBtn = fitRectButton();
612 avp->setCursor( *avp->getHandCursor() );
614 case GLViewer_Viewer::Reset:
615 avp->reset(); onTransform( Fin );
617 case GLViewer_Viewer::FitAll:
618 avp->fitAll(); onTransform( Fin );
620 case GLViewer_Viewer::FitSelect:
621 avp->fitSelect(); onTransform( Fin );
628 Catches mouse events for the viewport. [ virtual protected ]
630 bool GLViewer_ViewTransformer::eventFilter( QObject* o, QEvent* e )
634 case QEvent::MouseMove:
635 case QEvent::MouseButtonPress:
636 case QEvent::MouseButtonRelease:
638 TransformState state = EnTrain;
639 QMouseEvent* me = ( QMouseEvent* )e;
641 myButtonState = me->state();
642 if ( e->type() == QEvent::MouseButtonPress )
643 myButtonState |= me->button(); /* add pressed button */
645 int mouseOnlyState = ( myButtonState & ( LeftButton | MidButton | RightButton ) );
646 if ( myStart.isNull() )
650 myMajorBtn = mouseOnlyState;
653 if ( e->type() == QEvent::MouseButtonRelease && mouseOnlyState == myMajorBtn )
658 onTransform( state );
663 return QObject::eventFilter( o, e );
667 Transforms the viewport. Used for 'non-instant' transforms
668 only( ex. Rotate, Pan etc ). [ virtual protected ]
670 void GLViewer_ViewTransformer::onTransform( TransformState state )
672 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
673 bool doTrsf = ( myButtonState & myMajorBtn );
676 case GLViewer_Viewer::Zoom:
677 if ( state != Fin && doTrsf )
679 avp->zoom( myStart.x(), myStart.y(), myCurr.x(), myCurr.y() );
683 case GLViewer_Viewer::Pan:
684 if ( state != Fin && doTrsf )
686 avp->pan( myCurr.x() - myStart.x(), myStart.y() - myCurr.y() );
690 case GLViewer_Viewer::PanGlobal:
693 avp->setCenter( myCurr.x(), myCurr.y() );
696 case GLViewer_Viewer::FitRect:
700 QRect rect( QMIN( myStart.x(), myCurr.x() ), QMIN( myStart.y(), myCurr.y() ),
701 QABS( myStart.x() - myCurr.x() ), QABS( myStart.y() - myCurr.y() ) );
702 if ( !rect.isEmpty() )
707 avp->fitRect( rect );
711 QPainter p( avp->getPaintDevice() ); // for QAD_GLWidget
712 p.setPen( Qt::white );
713 p.setRasterOp( Qt::XorROP );
714 if ( !myDrawRect.isEmpty() )
715 p.drawRect( myDrawRect ); /* erase */
730 myViewer->activateTransform( GLViewer_Viewer::NoTransform );
734 Returns the type of the transformer. [ public ]
736 int GLViewer_ViewTransformer::type() const
742 /****************************************************************
743 ** Class: GLViewer_ViewSketcher
745 *****************************************************************/
746 int GLViewer_ViewSketcher::sketchBtn = LeftButton;
751 GLViewer_ViewSketcher::GLViewer_ViewSketcher( GLViewer_Viewer* viewer, int type )
759 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
763 mySavedCursor = avp->cursor();
764 avp->setCursor( *GLViewer_ViewPort::getHandCursor() );
765 avp->installEventFilter( this );
767 if ( myType == GLViewer_Viewer::Rect )
768 myData = new QRect();
774 GLViewer_ViewSketcher::~GLViewer_ViewSketcher()
776 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
777 avp->removeEventFilter( this );
778 avp->setCursor( mySavedCursor );
780 if ( myType == GLViewer_Viewer::Rect )
781 delete ( QRect* ) myData;
785 Catches mouse events for the viewport. [ virtual protected ]
787 bool GLViewer_ViewSketcher::eventFilter( QObject* o, QEvent* e )
791 case QEvent::MouseMove:
792 case QEvent::MouseButtonPress:
793 case QEvent::MouseButtonRelease:
795 SketchState state = EnTrain;
796 QMouseEvent* me = (QMouseEvent*)e;
798 myButtonState = me->state();
799 if ( e->type() == QEvent::MouseButtonPress )
800 myButtonState |= me->button(); /* add pressed button */
802 if ( myStart.isNull() )
808 int mouseOnlyState = ( myButtonState & ( LeftButton | MidButton | RightButton ) );
809 if ( e->type() == QEvent::MouseButtonRelease && mouseOnlyState == sketchButton() )
819 return QObject::eventFilter( o, e );
823 Draws in the viewport. [ virtual protected ]
825 void GLViewer_ViewSketcher::onSketch( SketchState state )
827 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
831 if( myType == GLViewer_Viewer::Rect )
833 QRect* sketchRect = ( QRect* )data();
834 if ( myButtonState & sketchButton() )
836 QRect rect( QMIN( myStart.x(), myCurr.x() ), QMIN( myStart.y(), myCurr.y() ),
837 QABS( myStart.x() - myCurr.x() ), QABS( myStart.y() - myCurr.y() ) );
838 if ( !rect.isEmpty() )
841 p.setPen( Qt::white );
842 p.setRasterOp( Qt::XorROP );
843 if ( !sketchRect->isEmpty() )
844 p.drawRect( *sketchRect ); /* erase */
847 p.drawRect( *sketchRect );
854 QApplication::syncX(); /* force rectangle redrawing */
855 myViewer->activateSketching( GLViewer_Viewer::NoSketching );