1 // Copyright (C) 2005 OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
19 // Author : OPEN CASCADE
22 // File: GLViewer_Viewer.cxx
23 // Created: November, 2004
25 //#include <GLViewerAfx.h>
26 #include "GLViewer_Viewer.h"
27 #include "GLViewer_Selector.h"
28 #include "GLViewer_ViewPort.h"
29 #include "GLViewer_ViewFrame.h"
31 #include "SUIT_Desktop.h"
32 #include "SUIT_ViewWindow.h"
34 #include <qapplication.h>
36 #include <qpopupmenu.h>
37 #include <qcolordialog.h>
39 /* used for sketching */
40 static QEvent* l_mbPressEvent = 0;
45 GLViewer_Viewer::GLViewer_Viewer( const QString& title )
50 mySelMode( NoSelection )
57 GLViewer_Viewer::~GLViewer_Viewer()
64 \param theViewManager - new view manager
66 void GLViewer_Viewer::setViewManager(SUIT_ViewManager* theViewManager)
68 SUIT_ViewModel::setViewManager(theViewManager);
71 connect(theViewManager, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)),
72 this, SLOT(onMouseEvent(SUIT_ViewWindow*, QMouseEvent*)));
74 connect(theViewManager, SIGNAL(mouseMove(SUIT_ViewWindow*, QMouseEvent*)),
75 this, SLOT(onMouseEvent(SUIT_ViewWindow*, QMouseEvent*)));
77 connect(theViewManager, SIGNAL(mouseRelease(SUIT_ViewWindow*, QMouseEvent*)),
78 this, SLOT(onMouseEvent(SUIT_ViewWindow*, QMouseEvent*)));
80 connect(theViewManager, SIGNAL(wheel(SUIT_ViewWindow*, QWheelEvent*)),
81 this, SLOT(onWheelEvent(SUIT_ViewWindow*, QWheelEvent*)));
86 Builds popup for GL viewer
88 void GLViewer_Viewer::contextMenuPopup( QPopupMenu* thePopup )
90 if( thePopup->count() > 0 )
91 thePopup->insertSeparator();
93 thePopup->insertItem( tr( "CHANGE_BGCOLOR" ), this, SLOT( onChangeBgColor() ) );
97 Sets the background color with color selection dialog. [ virtual protected slot ]
99 void GLViewer_Viewer::onChangeBgColor()
101 GLViewer_ViewPort* vp = getActiveView()->getViewPort();
102 QColor selColor = QColorDialog::getColor( vp->backgroundColor() );
104 if( selColor.isValid() )
105 vp->setBackgroundColor( selColor );
109 Returns the active view. [ public ]
111 GLViewer_ViewFrame* GLViewer_Viewer::getActiveView() const
113 SUIT_ViewManager* aMgr = getViewManager();
114 return (GLViewer_ViewFrame*)( aMgr != 0 ? aMgr->getActiveView() : 0 );
119 Sets the selection mode for this viewer. [ public ]
121 void GLViewer_Viewer::setSelectionMode( GLViewer_Viewer::SelectionMode mode )
123 if ( mySelMode != mode )
126 onSelectionModeChanged();
131 Returns selector of this viewer. [ public ]
133 GLViewer_Selector* GLViewer_Viewer::getSelector() const
137 GLViewer_Viewer* mthis = (GLViewer_Viewer*)this;
138 mthis->mySelector = mthis->createSelector();
141 connect( mySelector, SIGNAL( selSelectionDone( bool, SelectionChangeStatus ) ), SLOT( onSelectionDone( bool, SelectionChangeStatus ) ) );
142 connect( mySelector, SIGNAL( selSelectionCancel() ), SLOT( onSelectionCancel() ) );
149 Returns the selection mode of this viewer. [ public ]
151 GLViewer_Viewer::SelectionMode GLViewer_Viewer::getSelectionMode() const
157 Handles requests for sketching in the active view. [ virtual public ]
159 void GLViewer_Viewer::activateSketching( int type )
161 GLViewer_ViewPort* vp = 0;
162 if ( !getActiveView() || !( vp = getActiveView()->getViewPort() ) )
165 if ( !vp->isSketchingEnabled() )
168 /* Finish current sketching */
169 if ( type == NoSketching )
173 onSketchingFinished();
178 /* Activate new sketching */
181 activateSketching( NoSketching ); /* concurrency not suported */
182 mySketcher = createSketcher( type );
183 onSketchingStarted();
188 Handles requests for transformations in the active view. [ virtual public ]
190 void GLViewer_Viewer::activateTransform( int type )
192 GLViewer_ViewPort* vp = 0;
193 if ( !getActiveView() || !( vp = getActiveView()->getViewPort() ) )
196 if ( !vp->isTransformEnabled() )
199 /* Finish current transform */
200 if ( type == NoTransform )
204 onTransformationFinished();
205 delete myTransformer;
209 /* Activate new transform */
212 activateTransform( NoTransform ); /* concurrency not suported */
213 myTransformer = createTransformer( type );
214 onTransformationStarted();
215 myTransformer->exec();
220 Creates default transformer. [ virtual protected ]
222 GLViewer_ViewTransformer* GLViewer_Viewer::createTransformer( int type )
224 return new GLViewer_ViewTransformer( this, type );
228 Creates default sketcher. [ virtual protected ]
230 GLViewer_ViewSketcher* GLViewer_Viewer::createSketcher( int type )
232 return new GLViewer_ViewSketcher( this, type );
236 Returns null by default. [ virtual protected ]
238 GLViewer_Selector* GLViewer_Viewer::createSelector()
244 Unhilights detected entities, lock selection, sets event filter
245 on the whole application. [ virtual protected ]
247 void GLViewer_Viewer::onTransformationStarted()
251 getSelector()->lock( true ); /* disable selection */
253 /* Watch events: any mouse/key event outside the
254 viewport will be considered as the end of
258 qApp->installEventFilter( this );
262 Unlock selection, removes event filter. [ virtual protected ]
264 void GLViewer_Viewer::onTransformationFinished()
267 getSelector()->lock( false ); /* enable selection */
269 /* Stop watch events */
272 qApp->removeEventFilter( this );
276 Unhilights detected entities. [ virtual protected ]
278 void GLViewer_Viewer::onSketchingStarted()
284 Selection by rectangle. [ virtual protected ]
286 void GLViewer_Viewer::onSketchingFinished()
288 if ( !getSelector() )
293 if ( mySketcher->type() == Rect )
295 QRect* selRect = (QRect*)mySketcher->data();
298 bool append = bool( mySketcher->buttonState() & GLViewer_Selector::appendKey() );
299 getSelector()->select( *selRect, append );
305 Installed while 'fit area' and 'global panning' operations are active. [ virtual protected ]
307 bool GLViewer_Viewer::eventFilter( QObject* o, QEvent* e )
309 if( !getActiveView() )
312 if( getActiveView()->getViewPort() == o->parent() )
315 bool mouseClickedOutside = ( e->type() == QEvent::MouseButtonPress &&
316 o != getActiveView()->getViewPort() );
317 bool anyKeyPressed = ( e->type() == QEvent::KeyPress );
318 if ( mouseClickedOutside || anyKeyPressed )
319 { /* terminate all */
320 activateTransform( NoTransform );
321 activateSketching( NoSketching );
322 //cout << "mouseClickedOutside || anyKeyPressed" << endl;
324 return QObject::eventFilter( o, e );
328 Called when smth is selected in this viewer. [ virtual protected slot ]
330 void GLViewer_Viewer::onSelectionDone( bool bAdded, SelectionChangeStatus status )
332 emit selectionChanged( status );
336 Called when selection is cleared in this viewer. [ virtual protected slot ]
338 void GLViewer_Viewer::onSelectionCancel()
340 emit selectionChanged( SCS_Invalid );
344 Listens to key events of the active view. [ virtual protected slot ]
346 void GLViewer_Viewer::onKeyEvent( SUIT_ViewWindow*, QKeyEvent* )
351 Listens to mouse events of the active view. [ virtual protected slot ]
353 void GLViewer_Viewer::onMouseEvent( SUIT_ViewWindow*, QMouseEvent* e )
355 //cout << "GLViewer_Viewer::onMouseEvent" << endl;
358 case QEvent::MouseButtonPress:
359 handleMousePress( e );
361 case QEvent::MouseMove:
362 handleMouseMove( e );
364 case QEvent::MouseButtonRelease:
365 handleMouseRelease( e );
372 Listens to mouse events of the active view. [ virtual protected slot ]
374 void GLViewer_Viewer::onWheelEvent( SUIT_ViewWindow*, QWheelEvent* e )
376 //cout << "GLViewer_Viewer::onMouseEvent" << endl;
387 Enables / disables rectangle sketching. [ virtual protected ]
389 void GLViewer_Viewer::onSelectionModeChanged()
391 bool enable = ( mySelMode == Multiple );
392 QPtrVector<SUIT_ViewWindow> views = getViewManager()->getViews();
393 for ( int i = 0, n = views.count(); i < n; i++ )
395 GLViewer_ViewPort* vp = ((GLViewer_ViewFrame*)views[i])->getViewPort();
397 vp->setSketchingEnabled( enable );
402 Updates all views of this viewer. Use 'flags' to customize update process. [ virtual public ]
404 void GLViewer_Viewer::update( int flags )
406 QPtrVector<SUIT_ViewWindow> views = getViewManager()->getViews();
407 for ( int i = 0, n = views.count(); i < n; i++ )
408 ((GLViewer_ViewFrame*)views[i])->onUpdate( flags );
412 Unhilights the currect detected objects. [ virtual private ]
414 void GLViewer_Viewer::unhilightDetected()
417 getSelector()->undetectAll();
421 Mouse press handler. If 'accelKey()' is pressed, activates default
422 transformations( Zoom or Pan ) in the active viewport. [ private ]
424 void GLViewer_Viewer::handleMousePress( QMouseEvent* e )
426 /* test accel for transforms */
427 if ( e->state() & GLViewer_ViewTransformer::accelKey() )
429 ButtonState bs = e->button();
430 if ( bs == GLViewer_ViewTransformer::zoomButton() )
431 activateTransform( Zoom );
432 else if ( bs == GLViewer_ViewTransformer::panButton() )
433 activateTransform( Pan );
437 //checking for other operations before selection in release event
438 startOperations( e );
441 /* we may need it for sketching... */
442 l_mbPressEvent = new QMouseEvent( *e );
444 //checking for other operations before selection in release event
445 // startOperations( e );
447 /*e->button() == LeftButton && getSelector() )
449 bool append = bool ( e->state() & GLViewer_Selector::appendKey() );
450 getSelector()->select( append );
455 Mouse move handler. If dragged with MB1, activates rectangle sketching in
456 the active viewport, otherwise highlights the selectable entities. [ private ]
458 void GLViewer_Viewer::handleMouseMove( QMouseEvent* e )
460 /* Highlight for selection */
461 bool dragged = ( e->state() & ( LeftButton | MidButton | RightButton ) );
465 getSelector()->detect( e->x(), e->y() );
467 /* Try to activate default sketching
469 else if ( e->state() == GLViewer_ViewSketcher::sketchButton() )
471 activateSketching( Rect );
474 /* Activated OK. We should not forget initial mousepress
475 event and this mousemove event to start sketching from
476 the point of initial click */
477 if ( l_mbPressEvent )
479 QApplication::sendEvent( getActiveView()->getViewPort(), l_mbPressEvent );
480 delete l_mbPressEvent;
483 QApplication::sendEvent( getActiveView()->getViewPort(), e );
487 //Try to activate other operations
488 updateOperations( e );
492 Mouse move handler. Activates popup of the active view. [ private ]
494 void GLViewer_Viewer::handleMouseRelease( QMouseEvent* e )
497 /* tmp - in handleMousePress*/
498 if( e->button() == LeftButton && !(getActiveView()->getViewPort()->currentBlock() & BS_Selection) )
502 bool append = bool ( e->state() & GLViewer_Selector::appendKey() );
503 getSelector()->select( append );
507 //Try to done active operations
508 finishOperations( e );
510 if ( l_mbPressEvent )
512 delete l_mbPressEvent;
518 Wheel rolling handler
520 void GLViewer_Viewer::handleWheel( QWheelEvent* e )
522 startOperations( e );
525 int GLViewer_ViewTransformer::panBtn = Qt::MidButton;
526 int GLViewer_ViewTransformer::zoomBtn = Qt::LeftButton;
527 int GLViewer_ViewTransformer::fitRectBtn = Qt::LeftButton;
528 int GLViewer_ViewTransformer::panGlobalBtn = Qt::LeftButton;
529 int GLViewer_ViewTransformer::acccelKey = Qt::ControlButton;
534 GLViewer_ViewTransformer::GLViewer_ViewTransformer( GLViewer_Viewer* v, int type )
538 myMajorBtn( NoButton ),
541 if ( myType == GLViewer_Viewer::Pan ||
542 myType == GLViewer_Viewer::Zoom ||
543 myType == GLViewer_Viewer::PanGlobal ||
544 myType == GLViewer_Viewer::FitRect )
546 /* 'long' transforms need this */
547 initTransform( true );
554 GLViewer_ViewTransformer::~GLViewer_ViewTransformer()
556 if ( myType == GLViewer_Viewer::Pan ||
557 myType == GLViewer_Viewer::Zoom ||
558 myType == GLViewer_Viewer::PanGlobal ||
559 myType == GLViewer_Viewer::FitRect )
561 /* 'long' transforms need this */
562 initTransform( false );
565 //QAD_Application::getDesktop()->clearInfo();
569 Inits long transformations ( Zoom, Pan etc ) [ protected ]
571 Saves viewport state( cursor etc ) and installs event filter to process
572 mouse events if 'init' is true. Restores viewport state if 'init' is false.
574 void GLViewer_ViewTransformer::initTransform( bool init )
576 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
579 mySavedCursor = avp->cursor();
580 mySavedMouseTrack = avp->hasMouseTracking();
581 avp->setMouseTracking( false );
582 avp->installEventFilter( this );
586 avp->removeEventFilter( this );
587 avp->setMouseTracking( mySavedMouseTrack );
588 avp->setCursor( mySavedCursor );
593 Runs transfomation. Redefine to add your own 'instant' transforms
594 ( for ex., 'FitAll' is an instant transform ). [ virtual public ]
596 void GLViewer_ViewTransformer::exec()
598 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
604 case GLViewer_Viewer::Zoom:
605 myMajorBtn = zoomButton();
606 avp->setCursor( *avp->getZoomCursor() );
608 case GLViewer_Viewer::Pan:
609 myMajorBtn = panButton();
610 avp->setCursor( *avp->getPanCursor() );
612 case GLViewer_Viewer::PanGlobal:
613 myMajorBtn = panGlobalButton();
614 avp->setCursor( *avp->getPanglCursor() );
615 avp->fitAll( true, false ); /* view is ready now */
617 case GLViewer_Viewer::FitRect:
618 myMajorBtn = fitRectButton();
619 avp->setCursor( *avp->getHandCursor() );
621 case GLViewer_Viewer::Reset:
622 avp->reset(); onTransform( Fin );
624 case GLViewer_Viewer::FitAll:
625 avp->fitAll(); onTransform( Fin );
627 case GLViewer_Viewer::FitSelect:
628 avp->fitSelect(); onTransform( Fin );
635 Catches mouse events for the viewport. [ virtual protected ]
637 bool GLViewer_ViewTransformer::eventFilter( QObject* o, QEvent* e )
641 case QEvent::MouseMove:
642 case QEvent::MouseButtonPress:
643 case QEvent::MouseButtonRelease:
645 TransformState state = EnTrain;
646 QMouseEvent* me = ( QMouseEvent* )e;
648 myButtonState = me->state();
649 if ( e->type() == QEvent::MouseButtonPress )
650 myButtonState |= me->button(); /* add pressed button */
652 int mouseOnlyState = ( myButtonState & ( LeftButton | MidButton | RightButton ) );
653 if ( myStart.isNull() )
657 myMajorBtn = mouseOnlyState;
660 if ( e->type() == QEvent::MouseButtonRelease && mouseOnlyState == myMajorBtn )
665 onTransform( state );
670 return QObject::eventFilter( o, e );
674 Transforms the viewport. Used for 'non-instant' transforms
675 only( ex. Rotate, Pan etc ). [ virtual protected ]
677 void GLViewer_ViewTransformer::onTransform( TransformState state )
679 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
680 bool doTrsf = ( myButtonState & myMajorBtn );
683 case GLViewer_Viewer::Zoom:
684 if ( state != Fin && doTrsf )
686 avp->zoom( myStart.x(), myStart.y(), myCurr.x(), myCurr.y() );
690 case GLViewer_Viewer::Pan:
691 if ( state != Fin && doTrsf )
693 avp->pan( myCurr.x() - myStart.x(), myStart.y() - myCurr.y() );
697 case GLViewer_Viewer::PanGlobal:
700 avp->setCenter( myCurr.x(), myCurr.y() );
703 case GLViewer_Viewer::FitRect:
707 QRect rect( QMIN( myStart.x(), myCurr.x() ), QMIN( myStart.y(), myCurr.y() ),
708 QABS( myStart.x() - myCurr.x() ), QABS( myStart.y() - myCurr.y() ) );
709 if ( !rect.isEmpty() )
714 avp->fitRect( rect );
718 QPainter p( avp->getPaintDevice() ); // for QAD_GLWidget
719 p.setPen( Qt::white );
720 p.setRasterOp( Qt::XorROP );
721 if ( !myDrawRect.isEmpty() )
722 p.drawRect( myDrawRect ); /* erase */
737 myViewer->activateTransform( GLViewer_Viewer::NoTransform );
741 Returns the type of the transformer. [ public ]
743 int GLViewer_ViewTransformer::type() const
749 int GLViewer_ViewSketcher::sketchBtn = LeftButton;
754 GLViewer_ViewSketcher::GLViewer_ViewSketcher( GLViewer_Viewer* viewer, int type )
762 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
766 mySavedCursor = avp->cursor();
767 avp->setCursor( *GLViewer_ViewPort::getHandCursor() );
768 avp->installEventFilter( this );
770 if ( myType == GLViewer_Viewer::Rect )
771 myData = new QRect();
777 GLViewer_ViewSketcher::~GLViewer_ViewSketcher()
779 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
780 avp->removeEventFilter( this );
781 avp->setCursor( mySavedCursor );
783 if ( myType == GLViewer_Viewer::Rect )
784 delete ( QRect* ) myData;
788 Catches mouse events for the viewport. [ virtual protected ]
790 bool GLViewer_ViewSketcher::eventFilter( QObject* o, QEvent* e )
794 case QEvent::MouseMove:
795 case QEvent::MouseButtonPress:
796 case QEvent::MouseButtonRelease:
798 SketchState state = EnTrain;
799 QMouseEvent* me = (QMouseEvent*)e;
801 myButtonState = me->state();
802 if ( e->type() == QEvent::MouseButtonPress )
803 myButtonState |= me->button(); /* add pressed button */
805 if ( myStart.isNull() )
811 int mouseOnlyState = ( myButtonState & ( LeftButton | MidButton | RightButton ) );
812 if ( e->type() == QEvent::MouseButtonRelease && mouseOnlyState == sketchButton() )
822 return QObject::eventFilter( o, e );
826 Draws in the viewport. [ virtual protected ]
828 void GLViewer_ViewSketcher::onSketch( SketchState state )
830 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
834 if( myType == GLViewer_Viewer::Rect )
836 QRect* sketchRect = ( QRect* )data();
837 if ( myButtonState & sketchButton() )
839 QRect rect( QMIN( myStart.x(), myCurr.x() ), QMIN( myStart.y(), myCurr.y() ),
840 QABS( myStart.x() - myCurr.x() ), QABS( myStart.y() - myCurr.y() ) );
841 if ( !rect.isEmpty() )
844 p.setPen( Qt::white );
845 p.setRasterOp( Qt::XorROP );
846 if ( !sketchRect->isEmpty() )
847 p.drawRect( *sketchRect ); /* erase */
850 p.drawRect( *sketchRect );
857 QApplication::syncX(); /* force rectangle redrawing */
858 myViewer->activateSketching( GLViewer_Viewer::NoSketching );