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 /***************************************************************************
26 ** Class: GLViewer_Viewer
27 ** Descr: Viewer for QAD-based application
29 ** Created: UI team, 05.09.00
30 ****************************************************************************/
32 //#include <GLViewerAfx.h>
33 #include "GLViewer_Viewer.h"
34 #include "GLViewer_Selector.h"
35 #include "GLViewer_ViewPort.h"
36 #include "GLViewer_ViewFrame.h"
38 #include "SUIT_Desktop.h"
39 #include "SUIT_ViewWindow.h"
41 #include <qapplication.h>
43 #include <qpopupmenu.h>
44 #include <qcolordialog.h>
46 /* used for sketching */
47 static QEvent* l_mbPressEvent = 0;
52 GLViewer_Viewer::GLViewer_Viewer( const QString& title )
57 mySelMode( NoSelection )
64 GLViewer_Viewer::~GLViewer_Viewer()
69 //================================================================
70 // Function : setViewManager
72 //================================================================
73 void GLViewer_Viewer::setViewManager(SUIT_ViewManager* theViewManager)
75 SUIT_ViewModel::setViewManager(theViewManager);
78 connect(theViewManager, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)),
79 this, SLOT(onMouseEvent(SUIT_ViewWindow*, QMouseEvent*)));
81 connect(theViewManager, SIGNAL(mouseMove(SUIT_ViewWindow*, QMouseEvent*)),
82 this, SLOT(onMouseEvent(SUIT_ViewWindow*, QMouseEvent*)));
84 connect(theViewManager, SIGNAL(mouseRelease(SUIT_ViewWindow*, QMouseEvent*)),
85 this, SLOT(onMouseEvent(SUIT_ViewWindow*, QMouseEvent*)));
87 connect(theViewManager, SIGNAL(wheel(SUIT_ViewWindow*, QWheelEvent*)),
88 this, SLOT(onWheelEvent(SUIT_ViewWindow*, QWheelEvent*)));
92 //================================================================
93 // Function : contextMenuPopup
95 //================================================================
96 void GLViewer_Viewer::contextMenuPopup( QPopupMenu* thePopup )
98 if( thePopup->count() > 0 )
99 thePopup->insertSeparator();
101 thePopup->insertItem( tr( "CHANGE_BGCOLOR" ), this, SLOT( onChangeBgColor() ) );
105 Sets the background color with color selection dialog. [ virtual protected slot ]
107 void GLViewer_Viewer::onChangeBgColor()
109 GLViewer_ViewPort* vp = getActiveView()->getViewPort();
110 QColor selColor = QColorDialog::getColor( vp->backgroundColor() );
112 if( selColor.isValid() )
113 vp->setBackgroundColor( selColor );
117 Returns the active view. [ public ]
119 GLViewer_ViewFrame* GLViewer_Viewer::getActiveView() const
121 SUIT_ViewManager* aMgr = getViewManager();
122 return (GLViewer_ViewFrame*)( aMgr != 0 ? aMgr->getActiveView() : 0 );
127 Sets the selection mode for this viewer. [ public ]
129 void GLViewer_Viewer::setSelectionMode( GLViewer_Viewer::SelectionMode mode )
131 if ( mySelMode != mode )
134 onSelectionModeChanged();
139 Returns selector of this viewer. [ public ]
141 GLViewer_Selector* GLViewer_Viewer::getSelector() const
145 GLViewer_Viewer* mthis = (GLViewer_Viewer*)this;
146 mthis->mySelector = mthis->createSelector();
149 connect( mySelector, SIGNAL( selSelectionDone( bool, SelectionChangeStatus ) ), SLOT( onSelectionDone( bool, SelectionChangeStatus ) ) );
150 connect( mySelector, SIGNAL( selSelectionCancel() ), SLOT( onSelectionCancel() ) );
157 Returns the selection mode of this viewer. [ public ]
159 GLViewer_Viewer::SelectionMode GLViewer_Viewer::getSelectionMode() const
165 Handles requests for sketching in the active view. [ virtual public ]
167 void GLViewer_Viewer::activateSketching( int type )
169 GLViewer_ViewPort* vp = 0;
170 if ( !getActiveView() || !( vp = getActiveView()->getViewPort() ) )
173 if ( !vp->isSketchingEnabled() )
176 /* Finish current sketching */
177 if ( type == NoSketching )
181 onSketchingFinished();
186 /* Activate new sketching */
189 activateSketching( NoSketching ); /* concurrency not suported */
190 mySketcher = createSketcher( type );
191 onSketchingStarted();
196 Handles requests for transformations in the active view. [ virtual public ]
198 void GLViewer_Viewer::activateTransform( int type )
200 GLViewer_ViewPort* vp = 0;
201 if ( !getActiveView() || !( vp = getActiveView()->getViewPort() ) )
204 if ( !vp->isTransformEnabled() )
207 /* Finish current transform */
208 if ( type == NoTransform )
212 onTransformationFinished();
213 delete myTransformer;
217 /* Activate new transform */
220 activateTransform( NoTransform ); /* concurrency not suported */
221 myTransformer = createTransformer( type );
222 onTransformationStarted();
223 myTransformer->exec();
228 Creates default transformer. [ virtual protected ]
230 GLViewer_ViewTransformer* GLViewer_Viewer::createTransformer( int type )
232 return new GLViewer_ViewTransformer( this, type );
236 Creates default sketcher. [ virtual protected ]
238 GLViewer_ViewSketcher* GLViewer_Viewer::createSketcher( int type )
240 return new GLViewer_ViewSketcher( this, type );
244 Returns null by default. [ virtual protected ]
246 GLViewer_Selector* GLViewer_Viewer::createSelector()
252 Unhilights detected entities, lock selection, sets event filter
253 on the whole application. [ virtual protected ]
255 void GLViewer_Viewer::onTransformationStarted()
259 getSelector()->lock( true ); /* disable selection */
261 /* Watch events: any mouse/key event outside the
262 viewport will be considered as the end of
266 qApp->installEventFilter( this );
270 Unlock selection, removes event filter. [ virtual protected ]
272 void GLViewer_Viewer::onTransformationFinished()
275 getSelector()->lock( false ); /* enable selection */
277 /* Stop watch events */
280 qApp->removeEventFilter( this );
284 Unhilights detected entities. [ virtual protected ]
286 void GLViewer_Viewer::onSketchingStarted()
292 Selection by rectangle. [ virtual protected ]
294 void GLViewer_Viewer::onSketchingFinished()
296 if ( !getSelector() )
301 if ( mySketcher->type() == Rect )
303 QRect* selRect = (QRect*)mySketcher->data();
306 bool append = bool( mySketcher->buttonState() & GLViewer_Selector::appendKey() );
307 getSelector()->select( *selRect, append );
313 Installed while 'fit area' and 'global panning' operations are active. [ virtual protected ]
315 bool GLViewer_Viewer::eventFilter( QObject* o, QEvent* e )
317 if( !getActiveView() )
320 if( getActiveView()->getViewPort() == o->parent() )
323 bool mouseClickedOutside = ( e->type() == QEvent::MouseButtonPress &&
324 o != getActiveView()->getViewPort() );
325 bool anyKeyPressed = ( e->type() == QEvent::KeyPress );
326 if ( mouseClickedOutside || anyKeyPressed )
327 { /* terminate all */
328 activateTransform( NoTransform );
329 activateSketching( NoSketching );
330 //cout << "mouseClickedOutside || anyKeyPressed" << endl;
332 return QObject::eventFilter( o, e );
336 Called when smth is selected in this viewer. [ virtual protected slot ]
338 void GLViewer_Viewer::onSelectionDone( bool bAdded, SelectionChangeStatus status )
340 emit selectionChanged( status );
344 Called when selection is cleared in this viewer. [ virtual protected slot ]
346 void GLViewer_Viewer::onSelectionCancel()
348 emit selectionChanged( SCS_Invalid );
352 Listens to key events of the active view. [ virtual protected slot ]
354 void GLViewer_Viewer::onKeyEvent( SUIT_ViewWindow*, QKeyEvent* )
359 Listens to mouse events of the active view. [ virtual protected slot ]
361 void GLViewer_Viewer::onMouseEvent( SUIT_ViewWindow*, QMouseEvent* e )
363 //cout << "GLViewer_Viewer::onMouseEvent" << endl;
366 case QEvent::MouseButtonPress:
367 handleMousePress( e );
369 case QEvent::MouseMove:
370 handleMouseMove( e );
372 case QEvent::MouseButtonRelease:
373 handleMouseRelease( e );
380 Listens to mouse events of the active view. [ virtual protected slot ]
382 void GLViewer_Viewer::onWheelEvent( SUIT_ViewWindow*, QWheelEvent* e )
384 //cout << "GLViewer_Viewer::onMouseEvent" << endl;
395 Enables / disables rectangle sketching. [ virtual protected ]
397 void GLViewer_Viewer::onSelectionModeChanged()
399 bool enable = ( mySelMode == Multiple );
400 QPtrVector<SUIT_ViewWindow> views = getViewManager()->getViews();
401 for ( int i = 0, n = views.count(); i < n; i++ )
403 GLViewer_ViewPort* vp = ((GLViewer_ViewFrame*)views[i])->getViewPort();
405 vp->setSketchingEnabled( enable );
410 Updates all views of this viewer. Use 'flags' to customize update process. [ virtual public ]
412 void GLViewer_Viewer::update( int flags )
414 QPtrVector<SUIT_ViewWindow> views = getViewManager()->getViews();
415 for ( int i = 0, n = views.count(); i < n; i++ )
416 ((GLViewer_ViewFrame*)views[i])->onUpdate( flags );
420 Unhilights the currect detected objects. [ virtual private ]
422 void GLViewer_Viewer::unhilightDetected()
425 getSelector()->undetectAll();
429 Mouse press handler. If 'accelKey()' is pressed, activates default
430 transformations( Zoom or Pan ) in the active viewport. [ private ]
432 void GLViewer_Viewer::handleMousePress( QMouseEvent* e )
434 /* test accel for transforms */
435 if ( e->state() & GLViewer_ViewTransformer::accelKey() )
437 ButtonState bs = e->button();
438 if ( bs == GLViewer_ViewTransformer::zoomButton() )
439 activateTransform( Zoom );
440 else if ( bs == GLViewer_ViewTransformer::panButton() )
441 activateTransform( Pan );
445 //checking for other operations before selection in release event
446 startOperations( e );
449 /* we may need it for sketching... */
450 l_mbPressEvent = new QMouseEvent( *e );
452 //checking for other operations before selection in release event
453 // startOperations( e );
455 /*e->button() == LeftButton && getSelector() )
457 bool append = bool ( e->state() & GLViewer_Selector::appendKey() );
458 getSelector()->select( append );
463 Mouse move handler. If dragged with MB1, activates rectangle sketching in
464 the active viewport, otherwise highlights the selectable entities. [ private ]
466 void GLViewer_Viewer::handleMouseMove( QMouseEvent* e )
468 /* Highlight for selection */
469 bool dragged = ( e->state() & ( LeftButton | MidButton | RightButton ) );
473 getSelector()->detect( e->x(), e->y() );
475 /* Try to activate default sketching
477 else if ( e->state() == GLViewer_ViewSketcher::sketchButton() )
479 activateSketching( Rect );
482 /* Activated OK. We should not forget initial mousepress
483 event and this mousemove event to start sketching from
484 the point of initial click */
485 if ( l_mbPressEvent )
487 QApplication::sendEvent( getActiveView()->getViewPort(), l_mbPressEvent );
488 delete l_mbPressEvent;
491 QApplication::sendEvent( getActiveView()->getViewPort(), e );
495 //Try to activate other operations
496 updateOperations( e );
500 Mouse move handler. Activates popup of the active view. [ private ]
502 void GLViewer_Viewer::handleMouseRelease( QMouseEvent* e )
505 /* tmp - in handleMousePress*/
506 if( e->button() == LeftButton && !(getActiveView()->getViewPort()->currentBlock() & BS_Selection) )
510 bool append = bool ( e->state() & GLViewer_Selector::appendKey() );
511 getSelector()->select( append );
515 //Try to done active operations
516 finishOperations( e );
518 if ( l_mbPressEvent )
520 delete l_mbPressEvent;
526 Wheel rolling handler
528 void GLViewer_Viewer::handleWheel( QWheelEvent* e )
530 startOperations( e );
533 /****************************************************************
534 ** Class: GLViewer_ViewTransformer
536 *****************************************************************/
537 int GLViewer_ViewTransformer::panBtn = Qt::MidButton;
538 int GLViewer_ViewTransformer::zoomBtn = Qt::LeftButton;
539 int GLViewer_ViewTransformer::fitRectBtn = Qt::LeftButton;
540 int GLViewer_ViewTransformer::panGlobalBtn = Qt::LeftButton;
541 int GLViewer_ViewTransformer::acccelKey = Qt::ControlButton;
546 GLViewer_ViewTransformer::GLViewer_ViewTransformer( GLViewer_Viewer* v, int type )
550 myMajorBtn( NoButton ),
553 if ( myType == GLViewer_Viewer::Pan ||
554 myType == GLViewer_Viewer::Zoom ||
555 myType == GLViewer_Viewer::PanGlobal ||
556 myType == GLViewer_Viewer::FitRect )
558 /* 'long' transforms need this */
559 initTransform( true );
566 GLViewer_ViewTransformer::~GLViewer_ViewTransformer()
568 if ( myType == GLViewer_Viewer::Pan ||
569 myType == GLViewer_Viewer::Zoom ||
570 myType == GLViewer_Viewer::PanGlobal ||
571 myType == GLViewer_Viewer::FitRect )
573 /* 'long' transforms need this */
574 initTransform( false );
577 //QAD_Application::getDesktop()->clearInfo();
581 Inits long transformations ( Zoom, Pan etc ) [ protected ]
583 Saves viewport state( cursor etc ) and installs event filter to process
584 mouse events if 'init' is true. Restores viewport state if 'init' is false.
586 void GLViewer_ViewTransformer::initTransform( bool init )
588 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
591 mySavedCursor = avp->cursor();
592 mySavedMouseTrack = avp->hasMouseTracking();
593 avp->setMouseTracking( false );
594 avp->installEventFilter( this );
598 avp->removeEventFilter( this );
599 avp->setMouseTracking( mySavedMouseTrack );
600 avp->setCursor( mySavedCursor );
605 Runs transfomation. Redefine to add your own 'instant' transforms
606 ( for ex., 'FitAll' is an instant transform ). [ virtual public ]
608 void GLViewer_ViewTransformer::exec()
610 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
616 case GLViewer_Viewer::Zoom:
617 myMajorBtn = zoomButton();
618 avp->setCursor( *avp->getZoomCursor() );
620 case GLViewer_Viewer::Pan:
621 myMajorBtn = panButton();
622 avp->setCursor( *avp->getPanCursor() );
624 case GLViewer_Viewer::PanGlobal:
625 myMajorBtn = panGlobalButton();
626 avp->setCursor( *avp->getPanglCursor() );
627 avp->fitAll( true, false ); /* view is ready now */
629 case GLViewer_Viewer::FitRect:
630 myMajorBtn = fitRectButton();
631 avp->setCursor( *avp->getHandCursor() );
633 case GLViewer_Viewer::Reset:
634 avp->reset(); onTransform( Fin );
636 case GLViewer_Viewer::FitAll:
637 avp->fitAll(); onTransform( Fin );
639 case GLViewer_Viewer::FitSelect:
640 avp->fitSelect(); onTransform( Fin );
647 Catches mouse events for the viewport. [ virtual protected ]
649 bool GLViewer_ViewTransformer::eventFilter( QObject* o, QEvent* e )
653 case QEvent::MouseMove:
654 case QEvent::MouseButtonPress:
655 case QEvent::MouseButtonRelease:
657 TransformState state = EnTrain;
658 QMouseEvent* me = ( QMouseEvent* )e;
660 myButtonState = me->state();
661 if ( e->type() == QEvent::MouseButtonPress )
662 myButtonState |= me->button(); /* add pressed button */
664 int mouseOnlyState = ( myButtonState & ( LeftButton | MidButton | RightButton ) );
665 if ( myStart.isNull() )
669 myMajorBtn = mouseOnlyState;
672 if ( e->type() == QEvent::MouseButtonRelease && mouseOnlyState == myMajorBtn )
677 onTransform( state );
682 return QObject::eventFilter( o, e );
686 Transforms the viewport. Used for 'non-instant' transforms
687 only( ex. Rotate, Pan etc ). [ virtual protected ]
689 void GLViewer_ViewTransformer::onTransform( TransformState state )
691 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
692 bool doTrsf = ( myButtonState & myMajorBtn );
695 case GLViewer_Viewer::Zoom:
696 if ( state != Fin && doTrsf )
698 avp->zoom( myStart.x(), myStart.y(), myCurr.x(), myCurr.y() );
702 case GLViewer_Viewer::Pan:
703 if ( state != Fin && doTrsf )
705 avp->pan( myCurr.x() - myStart.x(), myStart.y() - myCurr.y() );
709 case GLViewer_Viewer::PanGlobal:
712 avp->setCenter( myCurr.x(), myCurr.y() );
715 case GLViewer_Viewer::FitRect:
719 QRect rect( QMIN( myStart.x(), myCurr.x() ), QMIN( myStart.y(), myCurr.y() ),
720 QABS( myStart.x() - myCurr.x() ), QABS( myStart.y() - myCurr.y() ) );
721 if ( !rect.isEmpty() )
726 avp->fitRect( rect );
730 QPainter p( avp->getPaintDevice() ); // for QAD_GLWidget
731 p.setPen( Qt::white );
732 p.setRasterOp( Qt::XorROP );
733 if ( !myDrawRect.isEmpty() )
734 p.drawRect( myDrawRect ); /* erase */
749 myViewer->activateTransform( GLViewer_Viewer::NoTransform );
753 Returns the type of the transformer. [ public ]
755 int GLViewer_ViewTransformer::type() const
761 /****************************************************************
762 ** Class: GLViewer_ViewSketcher
764 *****************************************************************/
765 int GLViewer_ViewSketcher::sketchBtn = LeftButton;
770 GLViewer_ViewSketcher::GLViewer_ViewSketcher( GLViewer_Viewer* viewer, int type )
778 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
782 mySavedCursor = avp->cursor();
783 avp->setCursor( *GLViewer_ViewPort::getHandCursor() );
784 avp->installEventFilter( this );
786 if ( myType == GLViewer_Viewer::Rect )
787 myData = new QRect();
793 GLViewer_ViewSketcher::~GLViewer_ViewSketcher()
795 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
796 avp->removeEventFilter( this );
797 avp->setCursor( mySavedCursor );
799 if ( myType == GLViewer_Viewer::Rect )
800 delete ( QRect* ) myData;
804 Catches mouse events for the viewport. [ virtual protected ]
806 bool GLViewer_ViewSketcher::eventFilter( QObject* o, QEvent* e )
810 case QEvent::MouseMove:
811 case QEvent::MouseButtonPress:
812 case QEvent::MouseButtonRelease:
814 SketchState state = EnTrain;
815 QMouseEvent* me = (QMouseEvent*)e;
817 myButtonState = me->state();
818 if ( e->type() == QEvent::MouseButtonPress )
819 myButtonState |= me->button(); /* add pressed button */
821 if ( myStart.isNull() )
827 int mouseOnlyState = ( myButtonState & ( LeftButton | MidButton | RightButton ) );
828 if ( e->type() == QEvent::MouseButtonRelease && mouseOnlyState == sketchButton() )
838 return QObject::eventFilter( o, e );
842 Draws in the viewport. [ virtual protected ]
844 void GLViewer_ViewSketcher::onSketch( SketchState state )
846 GLViewer_ViewPort* avp = myViewer->getActiveView()->getViewPort();
850 if( myType == GLViewer_Viewer::Rect )
852 QRect* sketchRect = ( QRect* )data();
853 if ( myButtonState & sketchButton() )
855 QRect rect( QMIN( myStart.x(), myCurr.x() ), QMIN( myStart.y(), myCurr.y() ),
856 QABS( myStart.x() - myCurr.x() ), QABS( myStart.y() - myCurr.y() ) );
857 if ( !rect.isEmpty() )
860 p.setPen( Qt::white );
861 p.setRasterOp( Qt::XorROP );
862 if ( !sketchRect->isEmpty() )
863 p.drawRect( *sketchRect ); /* erase */
866 p.drawRect( *sketchRect );
873 QApplication::syncX(); /* force rectangle redrawing */
874 myViewer->activateSketching( GLViewer_Viewer::NoSketching );