]> SALOME platform Git repositories - modules/gui.git/commitdiff
Salome HOME
22070: interaction with clipping
authorapl <apl@opencascade.com>
Fri, 31 Jan 2014 08:00:14 +0000 (08:00 +0000)
committerapl <apl@opencascade.com>
Fri, 31 Jan 2014 08:00:14 +0000 (08:00 +0000)
src/OCCViewer/CMakeLists.txt
src/OCCViewer/OCCViewer_ClipPlaneInteractor.cxx [new file with mode: 0644]
src/OCCViewer/OCCViewer_ClipPlaneInteractor.h [new file with mode: 0644]
src/OCCViewer/OCCViewer_ClippingDlg.cxx
src/OCCViewer/OCCViewer_ClippingDlg.h
src/OCCViewer/OCCViewer_ViewportInputFilter.cxx [new file with mode: 0644]
src/OCCViewer/OCCViewer_ViewportInputFilter.h [new file with mode: 0644]

index 2c0c604979c010ccb9fecc1f9560cedd8cd9291b..dd8677eca58e51f66002c709d8a992e1f1a8304c 100755 (executable)
@@ -43,7 +43,7 @@ ADD_DEFINITIONS(${QT_DEFINITIONS} ${CAS_DEFINITIONS} ${OGL_DEFINITIONS})
 
 # libraries to link to
 SET(_link_LIBRARIES
-  ${OPENGL_LIBRARIES} ${QT_LIBRARIES} ${CAS_KERNEL} ${CAS_VIEWER}
+  ${OPENGL_LIBRARIES} ${QT_LIBRARIES} ${CAS_KERNEL} ${CAS_VIEWER} ${CAS_TKGeomAlgo}
   CASCatch qtx suit OpenGLUtils ViewerTools ViewerData
 )
 
@@ -66,6 +66,8 @@ SET(_moc_HEADERS
   OCCViewer_ViewPort3d.h
   OCCViewer_ViewSketcher.h
   OCCViewer_ViewWindow.h
+  OCCViewer_ViewportInputFilter.h
+  OCCViewer_ClipPlaneInteractor.h
 )
 
 # header files / no moc processing
@@ -157,6 +159,8 @@ SET(_other_SOURCES
   OCCViewer_ViewPort3d.cxx
   OCCViewer_ViewSketcher.cxx
   OCCViewer_ViewWindow.cxx
+  OCCViewer_ViewportInputFilter.cxx
+  OCCViewer_ClipPlaneInteractor.cxx
 )
 
 # sources / to compile
diff --git a/src/OCCViewer/OCCViewer_ClipPlaneInteractor.cxx b/src/OCCViewer/OCCViewer_ClipPlaneInteractor.cxx
new file mode 100644 (file)
index 0000000..7d06521
--- /dev/null
@@ -0,0 +1,691 @@
+// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "OCCViewer_ClipPlaneInteractor.h"
+#include "OCCViewer_ViewPort3d.h"
+#include "OCCViewer_ViewModel.h"
+
+#include <AIS_InteractiveContext.hxx>
+#include <SelectMgr_EntityOwner.hxx>
+#include <V3d_View.hxx>
+#include <Geom_Line.hxx>
+#include <Geom_Plane.hxx>
+#include <GeomAPI_IntCS.hxx>
+#include <gce_MakeDir.hxx>
+
+#include <QMouseEvent>
+#include <QKeyEvent>
+
+/*!
+  \brief Constructor.
+  \param theVM [in] the view manager.
+  \param theParent [in] the parent object.
+*/
+OCCViewer_ClipPlaneInteractor::OCCViewer_ClipPlaneInteractor( OCCViewer_ViewManager* theVM,
+                                                              QObject* theParent )
+: OCCViewer_ViewportInputFilter( theVM, theParent ),
+  myPerformingOp( DragOperation_Undef ),
+  myRotationCenter( gp::Origin() ),
+  myIsDraggable( false ),
+  myIsClickable( false )
+{
+}
+
+/*!
+  \brief Get sequence of planes to interact with.
+  \return the sequence of accepted planes.
+*/
+const OCCViewer_ClipPlaneInteractor::SeqOfPlanes& OCCViewer_ClipPlaneInteractor::planes() const
+{
+  return myPlanes;
+}
+
+/*!
+  \brief Sets sequence of planes allowed for interaction.
+  \param thePlanes [in] the sequence of accepted planes.
+*/
+void OCCViewer_ClipPlaneInteractor::setPlanes( const SeqOfPlanes& thePlanes )
+{
+  myPlanes = thePlanes;
+}
+
+/*!
+  \brief Sets center of rotation for the scene.
+  \param theCenter [in] the center of rotation.
+*/
+void OCCViewer_ClipPlaneInteractor::setRotationCenter( const gp_Pnt& theCenter )
+{
+  myRotationCenter = theCenter;
+}
+
+/*!
+  \brief Sets minimum and maximum bounding of the scene.
+         The sliding movements are limited to minimum
+         and maximum bounds.
+  \param theMinMax [in] the minimum and maximum bounds.
+*/
+void OCCViewer_ClipPlaneInteractor::setMinMax( const Bnd_Box& theMinMax )
+{
+  myMinMax = theMinMax;
+}
+
+/*!
+  \brief Enables or disables event processing within the viewer.
+*/
+void OCCViewer_ClipPlaneInteractor::setEnabled( const bool theIsEnabled )
+{
+  if ( !theIsEnabled )
+  {
+  }
+
+  myMouseDragPln    = gp_Pln();
+  myPerformingOp    = DragOperation_Undef;
+  myPickPos         = QPoint();
+  myDragPos         = QPoint();
+  myInteractedPlane = NULL;
+  myIsDraggable     = false;
+  myIsClickable     = false;
+
+  OCCViewer_ViewportInputFilter::setEnabled( theIsEnabled );
+}
+
+/*!
+  \brief Checks whether the interactive operation is in progress.
+  \return TRUE if the interaction is performed on IO object meaning
+          that no other operations in viewer should be processed.
+*/
+bool OCCViewer_ClipPlaneInteractor::isPerforming() const
+{
+  return !myInteractedPlane.IsNull();
+}
+
+/*!
+  \brief Checks whether the interactive plane can be clicked.
+  \return TRUE if the click interaction is supported for the plane.
+*/
+bool OCCViewer_ClipPlaneInteractor::isClickable( const Handle(AIS_Plane)& thePlane )
+{
+  bool isFound = Standard_False;
+  for ( int aPlaneIt = 0; aPlaneIt < myPlanes.size(); ++aPlaneIt )
+  {
+    if ( myPlanes[aPlaneIt] == thePlane )
+    {
+      isFound = true;
+      break;
+    }
+  }
+
+  if ( !isFound )
+  {
+    return false;
+  }
+
+  Handle(AIS_InteractiveContext) anAISContext = myViewer->getAISContext();
+
+  if ( anAISContext->IsSelected( thePlane ) )
+  {
+    return false;
+  }
+
+  return true;
+}
+
+/*!
+  \brief Checks whether the interactive plane can be dragged.
+  \return TRUE if the dragging interaction is supported for the plane.
+*/
+bool OCCViewer_ClipPlaneInteractor::isDraggable( const Handle(AIS_Plane)& thePlane )
+{
+  bool isFound = Standard_False;
+  for ( int aPlaneIt = 0; aPlaneIt < myPlanes.size(); ++aPlaneIt )
+  {
+    if ( myPlanes[aPlaneIt] == thePlane )
+    {
+      isFound = true;
+      break;
+    }
+  }
+
+  if ( !isFound )
+  {
+    return false;
+  }
+
+  Handle(AIS_InteractiveContext) anAISContext = myViewer->getAISContext();
+
+  if ( !anAISContext->IsSelected( thePlane ) )
+  {
+    return false;
+  }
+
+  return true;
+}
+
+/*!
+  \brief Checks whether it is possible to start interaction with plane.
+  \param thePickPos [in] the position of mouse picking.
+  \param theDragPos [in] the position of initial mouse dragging.
+  \param theDragOp [in] the drag operation to start.
+  \param thePlane [in] the detected plane.
+  \param theView [in] the view.
+*/
+bool OCCViewer_ClipPlaneInteractor::startDragging( const QPoint& thePickPos,
+                                                   const QPoint& theDragPos,
+                                                   const DragOperation theDragOp,
+                                                   const Handle(AIS_Plane)& thePlane,
+                                                   const Handle(V3d_View)& theView )
+{
+  // get point of view plane intersection with the plane
+  Standard_Real P[3], D[3];
+  theView->ConvertWithProj( thePickPos.x(), thePickPos.y(), P[0], P[1], P[2], D[0], D[1], D[2] );
+  gp_Lin aPickProj = gp_Lin( gp_Pnt( P[0], P[1], P[2] ), gp_Dir( D[0], D[1], D[2] ) );
+  gp_Pln aPlanePln = thePlane->Component()->Pln();
+
+  Handle(Geom_Line)  aPickLine   = new Geom_Line( aPickProj );
+  Handle(Geom_Plane) aCrossPlane = new Geom_Plane( aPlanePln );
+
+  GeomAPI_IntCS aFindPick( aPickLine, aCrossPlane );
+  if ( !aFindPick.IsDone() || aFindPick.NbPoints() == 0 )
+  {
+    return false;
+  }
+
+  // check plane geometry
+  Standard_Real aSizeX = 0.0;
+  Standard_Real aSizeY = 0.0;
+  thePlane->Size(aSizeX, aSizeY);
+  if ( aSizeX < Precision::Confusion() || aSizeY < Precision::Confusion() )
+  {
+    return false;
+  }
+
+  gp_Pnt aPickPoint = aFindPick.Point( 1 );
+
+  const gp_Dir& aPlaneN      = aPlanePln.Axis().Direction();
+  const gp_Dir& aPlaneX      = aPlanePln.XAxis().Direction();
+  const gp_Dir& aPlaneY      = aPlanePln.YAxis().Direction();
+  const gp_Pnt& aPlaneCenter = aPlanePln.Location();
+
+  switch ( theDragOp )
+  {
+    // sliding operation is started
+    case DragOperation_Slide :
+    {
+      if ( aPlaneN.IsParallel( aPickProj.Direction(), M_PI / 180.0 ) )
+      {
+        return false;
+      }
+
+      gp_Dir aMousePlnDir = ( aPickProj.Direction() ^ aPlaneN ) ^ aPlaneN;
+
+      myMouseDragPln     = gp_Pln( aPickPoint, aMousePlnDir );
+      myPlaneReferenceCS = gp_Ax3( aPlaneCenter, aPlaneN, aPlaneX );
+
+      return true;
+    }
+
+    // rotation operation is requested
+    case DragOperation_Rotate :
+    {
+      theView->ConvertWithProj( theDragPos.x(), theDragPos.y(), P[0], P[1], P[2], D[0], D[1], D[2] );
+      gp_Lin aDragProj = gp_Lin( gp_Pnt( P[0], P[1], P[2] ), gp_Dir( D[0], D[1], D[2] ) );
+
+      if ( aPickPoint.Distance( aDragProj.Location() ) < Precision::Confusion() )
+      {
+        return false;
+      }
+
+      // to determine whether we rotate around first or second axis, we
+      // construct a virtual "arm" as vector of from center of rotation
+      // to the picked point. Then we calculate dragging directions for both axes
+      // depending on the difference of picking and dragging mouse coordinates.
+      // The direction which is physically more easy to turn the "arm" is choosen
+      // and the corresponding plane for dragging is selected.
+
+      gp_Vec anArm = gp_Vec( myRotationCenter, aPickPoint );
+      Standard_Real anArmLength = anArm.Magnitude();
+      if ( anArmLength < Precision::Confusion() )
+      {
+        return false;
+      }
+
+      Handle(Geom_Line) aDragLine = new Geom_Line( aDragProj );
+      Standard_Real aMomentArm1 = 0.0;
+      Standard_Real aMomentArm2 = 0.0;
+      Standard_Real anArmLength1 = Abs( anArm * gp_Vec( aPlaneN ^ aPlaneX ) );
+      Standard_Real anArmLength2 = Abs( anArm * gp_Vec( aPlaneN ^ aPlaneY ) );
+
+      // check virtual "arm" dragging moment for first axis of rotation
+      if ( !aPlaneX.IsNormal( aDragProj.Direction(), M_PI / 180.0 ) && ( anArmLength1 / anArmLength > 0.3 ) )
+      {
+        Handle(Geom_Plane) aDragPln = new Geom_Plane( aPickPoint, aPlaneX );
+
+        gp_Pnt aDragPnt = aPickPoint;
+        gp_Vec aDragDir = gp_Vec( 0.0, 0.0, 0.0 );
+        GeomAPI_IntCS aFindCross( aDragLine, aDragPln );
+        if ( aFindCross.IsDone() && aFindCross.NbPoints() != 0 )
+        {
+          aDragPnt = aFindCross.Point( 1 );
+        }
+
+        if ( aDragPnt.Distance( aPickPoint ) > Precision::Confusion() )
+        {
+          aDragDir = gp_Vec( aPickPoint, aDragPnt );
+        }
+
+        aMomentArm1 = anArmLength1 * ( 1.0 - Abs( aDragDir.Normalized() * anArm.Normalized() ) );
+      }
+
+      // check virtual "arm" dragging moment for second axis of rotation
+      if ( !aPlaneY.IsNormal( aDragProj.Direction(), M_PI / 180.0 )&& ( anArmLength2 / anArmLength > 0.3 ) )
+      {
+        Handle(Geom_Plane) aDragPln = new Geom_Plane( aPickPoint, aPlaneY );
+
+        gp_Pnt aDragPnt = aPickPoint;
+        gp_Vec aDragDir = gp_Vec( 0.0, 0.0, 0.0 );
+        GeomAPI_IntCS aFindCross( aDragLine, aDragPln );
+        if ( aFindCross.IsDone() && aFindCross.NbPoints() != 0 )
+        {
+          aDragPnt = aFindCross.Point( 1 );
+        }
+
+        if ( aDragPnt.Distance( aPickPoint ) > Precision::Confusion() )
+        {
+          aDragDir = gp_Vec( aPickPoint, aDragPnt );
+        }
+
+        aMomentArm2 = anArmLength2 * ( 1.0 - Abs( aDragDir.Normalized() * anArm.Normalized() ) );
+      }
+
+      // choose the best plane for dragging
+      if ( aMomentArm1 >= aMomentArm2 )
+      {
+        gp_Vec aMousePlnN = gp_Vec( aPlaneX );
+
+        myMouseDragPln = gp_Pln( aPickPoint, aMousePlnN );
+
+        Standard_Real aDistance2Center = myMouseDragPln.Distance( aPlaneCenter );
+        gp_Pnt aCenterOnMousePln = aMousePlnN * gp_Vec( aPickPoint, aPlaneCenter ) < 0.0
+          ? aPlaneCenter.Translated( aMousePlnN *  aDistance2Center )
+          : aPlaneCenter.Translated( aMousePlnN * -aDistance2Center );
+
+        myRotationAxis = gp_Ax1( myRotationCenter, aMousePlnN );
+      }
+      else
+      {
+        gp_Vec aMousePlnN = gp_Vec( aPlaneY );
+
+        myMouseDragPln = gp_Pln( aPickPoint, aMousePlnN );
+
+        Standard_Real aDistance2Center = myMouseDragPln.Distance( aPlaneCenter );
+        gp_Pnt aCenterOnMousePln = aMousePlnN * gp_Vec( aPickPoint, aPlaneCenter ) < 0.0
+          ? aPlaneCenter.Translated( aMousePlnN *  aDistance2Center )
+          : aPlaneCenter.Translated( aMousePlnN * -aDistance2Center );
+
+        myRotationAxis = gp_Ax1( myRotationCenter, aMousePlnN );
+      }
+
+      myPlaneReferenceCS = gp_Ax3( aPlaneCenter, aPlaneN, aPlaneX );
+
+      return true;
+    }
+  }
+
+  return false;
+}
+
+/*!
+  \brief Performs dragging operation on the passed interactive plane.
+  \param theDragPos [in] the position of mouse dragging.
+  \param theDragOp [in] the drag operation to start.
+  \param thePlane [in] the operated plane.
+  \param theView [in] the view.
+*/
+void OCCViewer_ClipPlaneInteractor::performDragging( const QPoint& theDragPos,
+                                                     const DragOperation theDragOp,
+                                                     const Handle(AIS_Plane)& thePlane,
+                                                     const Handle(V3d_View)& theView )
+{
+  Standard_Real P[3], D[3];
+  theView->ConvertWithProj( theDragPos.x(), theDragPos.y(), P[0], P[1], P[2], D[0], D[1], D[2] );
+  gp_Lin aProjection = gp_Lin( gp_Pnt( P[0], P[1], P[2] ), gp_Dir( D[0], D[1], D[2] ) );
+
+  // get point on the plane
+  Handle(Geom_Line)  aCrossLine  = new Geom_Line( aProjection );
+  Handle(Geom_Plane) aCrossPlane = new Geom_Plane( myMouseDragPln );
+
+  GeomAPI_IntCS aFindCross( aCrossLine, aCrossPlane );
+  if ( !aFindCross.IsDone() || aFindCross.NbPoints() == 0 )
+  {
+    return;
+  }
+
+  gp_Pnt aDragPoint   = aFindCross.Point( 1 );
+  gp_Pnt aPlaneCenter = myPlaneReferenceCS.Location();
+  gp_Vec aPlaneN      = myPlaneReferenceCS.Direction();
+  gp_Vec aPlaneX      = myPlaneReferenceCS.XDirection();
+  gp_Pln aPlanePln    = gp_Pln( aPlaneCenter, aPlaneN );
+
+  switch ( theDragOp )
+  {
+    // sliding the plane along its normal
+    case DragOperation_Slide:
+    {
+      Standard_Real aTranslation = 
+        gp_Vec( aPlaneCenter, aDragPoint ) * gp_Vec( aPlaneN ) > 0.0
+          ?  aPlanePln.Distance( aDragPoint )
+          : -aPlanePln.Distance( aDragPoint );
+
+      gp_Pnt aNewCenter = aPlaneCenter.Translated( aPlaneN * aTranslation );
+
+      myPlaneReferenceCS = gp_Ax3( aNewCenter, aPlaneN, aPlaneX );
+
+      adjustBounds( myPlaneReferenceCS, myMinMax );
+
+      thePlane->SetComponent( new Geom_Plane( myPlaneReferenceCS ) );
+      thePlane->SetCenter( myPlaneReferenceCS.Location() );
+      thePlane->SetToUpdate();
+      thePlane->UpdateSelection();
+
+      myViewer->getAISContext()->Update( thePlane );
+    }
+    break;
+
+    case DragOperation_Rotate:
+    {
+      // project the dragging point on rotated plane
+      gp_Dir aRotAxis = myRotationAxis.Direction();
+      gp_Pln aDragAtCenterPln = gp_Pln( myRotationCenter, aRotAxis );
+      gp_Pnt aDragAtCenterPnt = gp_Vec( myRotationCenter, aDragPoint ) * gp_Vec( aRotAxis ) < 0.0
+        ? aDragPoint.Translated( gp_Vec( aRotAxis ) *  aDragAtCenterPln.Distance( aDragPoint ) )
+        : aDragPoint.Translated( gp_Vec( aRotAxis ) * -aDragAtCenterPln.Distance( aDragPoint ) );
+
+      gp_Pnt aDragOnPlanePnt = gp_Vec( aPlaneCenter, aDragAtCenterPnt ) * gp_Vec( aPlaneN ) < 0.0
+        ? aDragAtCenterPnt.Translated( gp_Vec( aPlaneN ) *  aPlanePln.Distance( aDragAtCenterPnt ) )
+        : aDragAtCenterPnt.Translated( gp_Vec( aPlaneN ) * -aPlanePln.Distance( aDragAtCenterPnt ) );
+
+      gp_Vec aDragPointVector( myRotationCenter, aDragAtCenterPnt );
+      gp_Vec aProjPointVector( myRotationCenter, aDragOnPlanePnt );
+
+      // check for rotation tolerance
+      if ( aDragPointVector.Magnitude() < 0.01 || aProjPointVector.Magnitude() < 0.01 )
+      {
+        return;
+      }
+
+      Standard_Real aTurnAngle = aProjPointVector.AngleWithRef( aDragPointVector, myRotationAxis.Direction() );
+
+      gp_Trsf aRotationTrsf;
+      aRotationTrsf.SetRotation( myRotationAxis, aTurnAngle );
+      myPlaneReferenceCS.Transform( aRotationTrsf );
+
+      adjustBounds( myPlaneReferenceCS, myMinMax );
+
+      gp_Ax3 aPlaneCS( myPlaneReferenceCS.Location(), myPlaneReferenceCS.Direction() );
+
+      thePlane->SetComponent( new Geom_Plane( aPlaneCS ) );
+      thePlane->SetCenter( myPlaneReferenceCS.Location() );
+      thePlane->SetToUpdate();
+      thePlane->UpdateSelection();
+
+      myViewer->getAISContext()->Update( thePlane );
+    }
+    break;
+  }
+}
+
+/*!
+  \brief Adjusts min-max bounds of the plane.
+  \param thePlane [in/out] the plane.
+  \param theMinMax [in] the min max bounds
+*/
+void OCCViewer_ClipPlaneInteractor::adjustBounds( gp_Ax3& thePlane, const Bnd_Box& theMinMax )
+{
+  gp_Trsf aRelativeTransform;
+  aRelativeTransform.SetTransformation( gp_Ax3(), thePlane );
+  Bnd_Box aRelativeBounds = theMinMax.Transformed( aRelativeTransform );
+
+  Standard_Real aXmin, aXmax, aYmin, aYmax, aZmin, aZmax;
+  aRelativeBounds.Get( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
+
+  if ( aZmax < 0.0 ) // out in positive direction
+  {
+    thePlane.Translate( gp_Vec( thePlane.Direction() ) * aZmax );
+  }
+  else if ( aZmin > 0.0 ) // out in negative direction
+  {
+    thePlane.Translate( gp_Vec( thePlane.Direction() ) * aZmin );
+  }
+}
+
+/*!
+  \brief Handle mouse press events. Starts interaction with detected plane.
+  \param theEvent [in] the user event.
+  \param theViewPort [in] the viewport.
+*/
+bool OCCViewer_ClipPlaneInteractor::mousePress( QMouseEvent* theEvent,
+                                                OCCViewer_ViewPort3d* theViewPort )
+{
+  if ( theEvent->button() != Qt::LeftButton )
+  {
+    return false;
+  }
+
+  Handle(V3d_View) aView3D = theViewPort->getView();
+
+  Handle(AIS_InteractiveContext) anAISContext = myViewer->getAISContext();
+
+  // check detection of plane
+  anAISContext->MoveTo( theEvent->x(), theEvent->y(), aView3D );
+
+  if ( !anAISContext->HasDetected() )
+  {
+    return false;
+  }
+
+  // check that there is only one detected entity
+  anAISContext->InitDetected();
+
+  Handle(AIS_Plane) aPlane;
+  Handle(SelectMgr_EntityOwner) aDetectedOwner = anAISContext->DetectedOwner();
+  if ( !aDetectedOwner.IsNull() )
+  {
+    aPlane = Handle(AIS_Plane)::DownCast( aDetectedOwner->Selectable() );
+  }
+
+  if ( aPlane.IsNull() )
+  {
+    aPlane = Handle(AIS_Plane)::DownCast( anAISContext->DetectedInteractive() );
+  }
+
+  myIsClickable = isClickable( aPlane );
+
+  // process mouse click on the object
+  if ( myIsClickable );
+  {
+    myViewer->getAISContext()->SetSelected( aPlane );
+    emit planeClicked( aPlane );
+  }
+
+  myIsDraggable = isDraggable( aPlane );
+
+  if ( !myIsClickable && !myIsDraggable )
+  {
+    return false;
+  }
+
+  myPickPos = theEvent->pos();
+  myInteractedPlane = aPlane;
+
+  return true;
+}
+
+/*!
+  \brief Handle mouse move events. Performs dragging if interaction is in progress.
+  \param theEvent [in] the user event.
+  \param theViewPort [in] the viewport.
+*/
+bool OCCViewer_ClipPlaneInteractor::mouseMove( QMouseEvent* theEvent,
+                                               OCCViewer_ViewPort3d* theViewPort )
+{
+  if ( !isPerforming() )
+  {
+    return false;
+  }
+
+  // no dragging operation can be performed...
+  if ( !myIsDraggable )
+  {
+    return true;
+  }
+
+  Handle(V3d_View) aView3D = theViewPort->getView();
+
+  myDragPos = theEvent->pos();
+
+  // checking whether it is possible to start dragging operation
+  if ( myPerformingOp == DragOperation_Undef )
+  {
+    int aDx = myDragPos.x() - myPickPos.x();
+    int aDy = myDragPos.y() - myPickPos.y();
+    if ( ( aDx * aDx + aDy * aDy ) < 16 )
+    {
+      return true;
+    }
+
+    DragOperation aDragOp =
+      theEvent->modifiers().testFlag(Qt::ControlModifier)
+        ? DragOperation_Rotate
+        : DragOperation_Slide;
+
+    myIsDraggable = startDragging( myPickPos, myDragPos, aDragOp, myInteractedPlane, aView3D );
+
+    if ( !myIsDraggable )
+    {
+      return true;
+    }
+
+    myPerformingOp = aDragOp;
+  }
+
+  // performing dragging operation
+  performDragging( myDragPos, myPerformingOp, myInteractedPlane, aView3D );
+
+  emit planeDragged( myInteractedPlane );
+
+  return true;
+}
+
+/*!
+  \brief Handle mouse release events. Stops interaction.
+  \param theEvent [in] the user event.
+  \param theViewPort [in] the viewport.
+*/
+bool OCCViewer_ClipPlaneInteractor::mouseRelease( QMouseEvent* theEvent,
+                                                  OCCViewer_ViewPort3d* theViewPort )
+{
+  if ( !isPerforming() )
+  {
+    return false;
+  }
+
+  myMouseDragPln    = gp_Pln();
+  myPerformingOp    = DragOperation_Undef;
+  myPickPos         = QPoint();
+  myDragPos         = QPoint();
+  myInteractedPlane = NULL;
+  myIsDraggable     = false;
+  myIsClickable     = false;
+  return true;
+}
+
+/*!
+  \brief Handle mouse double clicking events events. Stops the event propagation if
+         interaction with plane is in progress.
+  \param theEvent [in] the user event.
+  \param theViewPort [in] the viewport.
+*/
+bool OCCViewer_ClipPlaneInteractor::mouseDoubleClick( QMouseEvent* theEvent,
+                                                      OCCViewer_ViewPort3d* theViewPort )
+{
+  return isPerforming();
+}
+
+/*!
+  \brief Handle key pressing events. Stops the event propagation if
+         interaction with plane is in progress.
+  \param theEvent [in] the user event.
+  \param theViewPort [in] the viewport.
+*/
+bool OCCViewer_ClipPlaneInteractor::keyPress( QKeyEvent* theEvent,
+                                              OCCViewer_ViewPort3d* theViewPort )
+{
+  // react to pressing & releasing ctrl key modifier
+  if ( !isPerforming() )
+  {
+    return false;
+  }
+
+  DragOperation aDragOp =
+    theEvent->modifiers().testFlag(Qt::ControlModifier)
+      ? DragOperation_Rotate
+      : DragOperation_Slide;
+
+  if ( aDragOp != myPerformingOp )
+  {
+    myPerformingOp = DragOperation_Undef;
+    myIsDraggable  = isDraggable( myInteractedPlane );
+    myPickPos      = theViewPort->mapFromGlobal( QCursor::pos() );
+  }
+
+  return true;
+}
+
+/*!
+  \brief Handle key releasing events. Stops the event propagation if
+         interaction with plane is in progress.
+  \param theEvent [in] the user event.
+  \param theViewPort [in] the viewport.
+*/
+bool OCCViewer_ClipPlaneInteractor::keyRelease( QKeyEvent* theEvent,
+                                                OCCViewer_ViewPort3d* theViewPort )
+{
+  // react to pressing & releasing ctrl key modifier
+  if ( !isPerforming() )
+  {
+    return false;
+  }
+
+  DragOperation aDragOp =
+    theEvent->modifiers().testFlag(Qt::ControlModifier)
+      ? DragOperation_Rotate
+      : DragOperation_Slide;
+
+  if ( aDragOp != myPerformingOp )
+  {
+    myPerformingOp = DragOperation_Undef;
+    myIsDraggable  = isDraggable( myInteractedPlane );
+    myPickPos      = theViewPort->mapFromGlobal( QCursor::pos() );
+  }
+
+  return true;
+}
diff --git a/src/OCCViewer/OCCViewer_ClipPlaneInteractor.h b/src/OCCViewer/OCCViewer_ClipPlaneInteractor.h
new file mode 100644 (file)
index 0000000..d6d3c03
--- /dev/null
@@ -0,0 +1,123 @@
+// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef OCCVIEWER_CLIPPLANEINTERACTOR_H
+#define OCCVIEWER_CLIPPLANEINTERACTOR_H
+
+#include "OCCViewer_ViewportInputFilter.h"
+
+#include <AIS_Plane.hxx>
+#include <Bnd_Box.hxx>
+#include <gp_Pln.hxx>
+#include <gp_Ax3.hxx>
+
+#include <QPoint>
+
+#include <vector>
+
+class Handle(V3d_View);
+
+/*!
+  \class OCCViewer_ClipPlaneInteractor.
+  \brief The class provides mouse dragging operations with AIS_Plane:
+         1) Sliding plane by dragging it with point
+         2) Rotating plane around one or both of the rotation axes by
+            dragging its point with "ctrl" key pressed.
+*/
+class OCCViewer_ClipPlaneInteractor : public OCCViewer_ViewportInputFilter
+{
+  Q_OBJECT
+
+public:
+  typedef std::vector<Handle(AIS_Plane)> SeqOfPlanes;
+
+  // Performing interactive operation.
+  // - Slide: The picked point on plane is dragged along the normal of the plane.
+  // - Rotate: The picked point on plane is dragged around one of the specified rotation
+  //     axes ("x", "y" axes of the plane coordinate system, or two orthogonal arbitrary
+  //     specified ones). When starting the rotation a corresponding axis is
+  //     choosen depending on the direction of dragging. The axis is selected in
+  //     the following way: a virtual "arm" is constructed from center of
+  //     rotation to picking point. The dragging directions are constructed for
+  //     both of the rotation axes, then the direction which is "easiest to
+  //     turn" is selected (e.g. the "arm" projection is largest for that axis,
+  //     the direction of dragging is closer to orthogonal one for the axis).
+  enum DragOperation
+  {
+    DragOperation_Undef,
+    DragOperation_Slide,
+    DragOperation_Rotate
+  };
+
+public:
+  OCCViewer_ClipPlaneInteractor( OCCViewer_ViewManager*, QObject* theParent );
+
+  const                    SeqOfPlanes& planes() const;
+  void                     setPlanes( const SeqOfPlanes& );
+  void                     setRotationCenter( const gp_Pnt& );
+  void                     setMinMax( const Bnd_Box& );
+  virtual void             setEnabled( const bool );
+
+signals:
+  void                     planeClicked( const Handle_AIS_Plane& thePlane );
+  void                     planeDragged( const Handle_AIS_Plane& thePlane );
+
+protected:
+  bool                     isClickable( const Handle(AIS_Plane)& thePlane );
+  bool                     isDraggable( const Handle(AIS_Plane)& thePlane );
+  bool                     isPerforming() const;
+  bool                     startDragging( const QPoint& thePickPos,
+                                          const QPoint& theDragPos,
+                                          const DragOperation theOperation,
+                                          const Handle(AIS_Plane)& thePlane,
+                                          const Handle(V3d_View)& theView );
+  void                     performDragging( const QPoint& theDragPos,
+                                            const DragOperation theOperation,
+                                            const Handle(AIS_Plane)& thePlane,
+                                            const Handle(V3d_View)& theView );
+  void                     adjustBounds( gp_Ax3&, const Bnd_Box& );
+
+protected:
+  virtual bool             mouseMove( QMouseEvent*, OCCViewer_ViewPort3d* );
+  virtual bool             mousePress( QMouseEvent*, OCCViewer_ViewPort3d* );
+  virtual bool             mouseRelease( QMouseEvent*, OCCViewer_ViewPort3d* );
+  virtual bool             mouseDoubleClick( QMouseEvent*, OCCViewer_ViewPort3d* );
+  virtual bool             keyPress( QKeyEvent*, OCCViewer_ViewPort3d* );
+  virtual bool             keyRelease( QKeyEvent*, OCCViewer_ViewPort3d* );
+
+protected:
+
+  gp_Ax3            myPlaneReferenceCS;
+  gp_Ax1            myRotationAxis;
+  gp_Pln            myMouseDragPln;
+  QPoint            myDragPos;
+  QPoint            myPickPos;
+  DragOperation     myPerformingOp;
+  gp_Pnt            myRotationCenter;
+  Bnd_Box           myMinMax;
+  Handle(AIS_Plane) myInteractedPlane;
+  SeqOfPlanes       myPlanes;
+  bool              myIsDraggable;
+  bool              myIsClickable;
+};
+
+#endif
index 880406d30554080ca2e369712de7679f556d9877..06b51dba5d7522e11d3a6d300321f0bd443ae9b5 100644 (file)
@@ -32,6 +32,8 @@
 #include "OCCViewer_ViewWindow.h"
 #include "OCCViewer_ViewPort3d.h"
 #include "OCCViewer_ViewModel.h"
+#include "OCCViewer_ViewManager.h"
+#include "OCCViewer_ClipPlaneInteractor.h"
 
 #include <V3d_View.hxx>
 #include <Visual3d_View.hxx>
@@ -198,7 +200,7 @@ void Cross(const double first[3], const double second[3], double result[3])
 /*!
   Compute relative clipping plane in absolute coordinates
  */
-void RelativePlaneToAbsolute (OCCViewer_ClipPlane& thePlane, Handle(AIS_InteractiveContext) ic, double theDefaultSize )
+void relativePlaneToAbsolute (OCCViewer_ClipPlane& thePlane, Handle(AIS_InteractiveContext) ic, double theDefaultSize )
 {
   double aNormal[3];
   double aDir[2][3] = { { 0, 0, 0 }, { 0, 0, 0 } };
@@ -240,7 +242,6 @@ void RelativePlaneToAbsolute (OCCViewer_ClipPlane& thePlane, Handle(AIS_Interact
         aNormal[i] /= den;
       }
     }
-    Cross( aNormal, aDir[1], aDir[0] );
   }
 
   double anOrigin[3];
@@ -263,6 +264,129 @@ void RelativePlaneToAbsolute (OCCViewer_ClipPlane& thePlane, Handle(AIS_Interact
   thePlane.Dz = aNormal[2];
 }
 
+/*!
+  \brief Converts absolute plane definition to relative system.
+  \param thePlane [in/out] the plane to convert.
+  \param theIC [in] the interactive context.
+  \param theDefaultSize [in] the default trihedron size.
+ */
+void absolutePlaneToRelative( OCCViewer_ClipPlane& thePlane, Handle(AIS_InteractiveContext) theIC, double theDefaultSize )
+{
+  gp_Pnt aPlaneP( thePlane.X, thePlane.Y, thePlane.Z );
+  gp_Dir aPlaneN( thePlane.Dx, thePlane.Dy, thePlane.Dz );
+
+  double aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
+
+  getMinMaxFromContext( theIC, theDefaultSize, aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
+
+  Bnd_Box aMinMax;
+  aMinMax.Update( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
+
+  gp_Trsf aRelativeTransform;
+  aRelativeTransform.SetTransformation( gp_Ax3(), gp_Ax3( aPlaneP, aPlaneN ) );
+  Bnd_Box aRelativeBounds = aMinMax.Transformed( aRelativeTransform );
+
+  aRelativeBounds.Get( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
+
+  double aLength   = aZmax - aZmin;
+  double aDistance = aZmax;
+
+  double aRelativeDistance = aLength > 0.01 ? aDistance / aLength : 0.0;
+  aRelativeDistance = qMin( aRelativeDistance, aLength );
+  aRelativeDistance = qMax( aRelativeDistance, 0.0 );
+  thePlane.RelativeMode.Distance = aRelativeDistance;
+
+  const gp_Dir& aDX = gp::DX();
+  const gp_Dir& aDY = gp::DY();
+  const gp_Dir& aDZ = gp::DZ();
+  double anAng1 = 0.0;
+  double anAng2 = 0.0;
+  switch ( thePlane.RelativeMode.Orientation )
+  {
+    case 0:
+    {
+      if ( aDY.IsEqual( aPlaneN, Precision::Angular() ) )
+      {
+        anAng1 = 0.0;
+        anAng2 = 0.0;
+        break;
+      }
+
+      gp_Dir aDir1 = aPlaneN ^ aDX;
+      gp_Dir aDir2 = aDY ^ aPlaneN;
+      gp_Ax3 aRightHand( gp::Origin(), aPlaneN, aDY ^ aPlaneN );
+
+      if ( aDir1 * aRightHand.YDirection() < 0.0 )
+      {
+        aDir1.Reverse();
+      }
+      if ( aDir2 * aRightHand.XDirection() < 0.0 )
+      {
+        aDir2.Reverse();
+      }
+
+      anAng1 = aDY.AngleWithRef( aDir1,  aDX );
+      anAng2 = aDX.AngleWithRef( aDir2, -aDY );
+      break;
+    }
+    case 1:
+    {
+      if ( aDZ.IsEqual( aPlaneN, Precision::Angular() ) )
+      {
+        anAng1 = 0.0;
+        anAng2 = 0.0;
+        break;
+      }
+
+      gp_Dir aDir1 = aPlaneN ^ aDY;
+      gp_Dir aDir2 = aDZ ^ aPlaneN;
+      gp_Ax3 aRightHand( gp::Origin(), aPlaneN, aDZ ^ aPlaneN );
+
+      if ( aDir1 * aRightHand.YDirection() < 0.0 )
+      {
+        aDir1.Reverse();
+      }
+      if ( aDir2 * aRightHand.XDirection() < 0.0 )
+      {
+        aDir2.Reverse();
+      }
+
+      anAng1 = aDZ.AngleWithRef( aDir1,  aDY );
+      anAng2 = aDY.AngleWithRef( aDir2, -aDZ );
+      break;
+    }
+    case 2:
+    {
+      if ( aDX.IsEqual( aPlaneN, Precision::Angular() ) )
+      {
+        anAng1 = 0.0;
+        anAng2 = 0.0;
+        break;
+      }
+
+      gp_Dir aDir1 = aPlaneN ^ aDZ;
+      gp_Dir aDir2 = aDX ^ aPlaneN;
+      gp_Ax3 aRightHand( gp::Origin(), aPlaneN, aDX ^ aPlaneN );
+
+      if ( aDir1 * aRightHand.YDirection() < 0.0 )
+      {
+        aDir1.Reverse();
+      }
+      if ( aDir2 * aRightHand.XDirection() < 0.0 )
+      {
+        aDir2.Reverse();
+      }
+
+      anAng1 = aDX.AngleWithRef( aDir1,  aDZ );
+      anAng2 = aDZ.AngleWithRef( aDir2, -aDX );
+      break;
+    }
+  }
+
+  thePlane.RelativeMode.Rotation1 = anAng1 * ( 180.0 / M_PI );
+  thePlane.RelativeMode.Rotation2 = anAng2 * ( 180.0 / M_PI );
+}
+
 /*!
   Compute clipping plane size base point and normal
  */
@@ -492,6 +616,7 @@ OCCViewer_ClippingDlg::OCCViewer_ClippingDlg(OCCViewer_ViewWindow* parent , OCCV
 
   SliderDistance = new QSlider( Qt::Horizontal, GroupParameters );
   SliderDistance->setObjectName( "SliderDistance" );
+  SliderDistance->setFocusPolicy( Qt::NoFocus );
   SliderDistance->setMinimumSize( 300, 0 );
   SliderDistance->setMinimum( 0 );
   SliderDistance->setMaximum( 100 );
@@ -513,6 +638,7 @@ OCCViewer_ClippingDlg::OCCViewer_ClippingDlg(OCCViewer_ViewWindow* parent , OCCV
 
   SliderRotation1 = new QSlider( Qt::Horizontal, GroupParameters );
   SliderRotation1->setObjectName( "SliderRotation1" );
+  SliderRotation1->setFocusPolicy( Qt::NoFocus );
   SliderRotation1->setMinimumSize( 300, 0 );
   SliderRotation1->setMinimum( -180 );
   SliderRotation1->setMaximum( 180 );
@@ -535,6 +661,7 @@ OCCViewer_ClippingDlg::OCCViewer_ClippingDlg(OCCViewer_ViewWindow* parent , OCCV
 
   SliderRotation2 = new QSlider( Qt::Horizontal, GroupParameters );
   SliderRotation2->setObjectName( "SliderRotation2" );
+  SliderRotation2->setFocusPolicy( Qt::NoFocus );
   SliderRotation2->setMinimumSize( 300, 0 );
   SliderRotation2->setMinimum( -180 );
   SliderRotation2->setMaximum( 180 );
@@ -638,10 +765,16 @@ OCCViewer_ClippingDlg::OCCViewer_ClippingDlg(OCCViewer_ViewWindow* parent , OCCV
   myBusy = false;
   myIsSelectPlane = false;
   myIsPlaneCreation = false;
+  myIsUpdatingControls = false;
   myModel = model;
 
   myModel->getViewer3d()->InitActiveViews();
 
+  OCCViewer_ViewManager* aViewMgr = (OCCViewer_ViewManager*) myModel->getViewManager();
+  myInteractor = new OCCViewer_ClipPlaneInteractor( aViewMgr, this );
+  connect( myInteractor, SIGNAL( planeClicked( const Handle_AIS_Plane& ), ), SLOT( onPlaneClicked( const Handle_AIS_Plane& ) ) );
+  connect( myInteractor, SIGNAL( planeDragged( const Handle_AIS_Plane& ), ), SLOT( onPlaneDragged( const Handle_AIS_Plane& ) ) );
+
   myLocalPlanes = myModel->getClipPlanes();
   synchronize();
 }
@@ -772,25 +905,39 @@ void OCCViewer_ClippingDlg::displayPreview()
   int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
 
   for ( int i=0; i < clipPlanesCount(); i++ ) {
-  OCCViewer_ClipPlane& aClipPlane = getClipPlane(i);
+    OCCViewer_ClipPlane& aClipPlane = getClipPlane(i);
     if ( aClipPlane.IsOn ) {
       Handle(AIS_Plane) myPreviewPlane;
       double aSize;
       gp_Pnt aBasePnt;
       gp_Dir aNormal;
       clipPlaneParams(aClipPlane, ic, aSize, aBasePnt, aNormal, myModel->trihedronSize());
-      myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ) );
+      myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ), aBasePnt );
+      myPreviewPlane->SetTypeOfSensitivity( Select3D_TOS_INTERIOR );
       myPreviewPlane->SetSize( aSize, aSize );
-      ic->Display( myPreviewPlane, 1, -1, false );
       ic->SetWidth( myPreviewPlane, 10, false );
       ic->SetMaterial( myPreviewPlane, Graphic3d_NOM_PLASTIC, false );
       ic->SetTransparency( myPreviewPlane, 0.5, false );
       Quantity_Color c = (aCurPlaneIndex == i) ? Quantity_Color( 255. / 255., 70. / 255., 0. / 255., Quantity_TOC_RGB ) : Quantity_Color( 85 / 255., 85 / 255., 255 / 255., Quantity_TOC_RGB );
       ic->SetColor( myPreviewPlane, c , false );
+      ic->Display( myPreviewPlane, 1, 0, false );
       myPreviewPlaneVector.push_back( myPreviewPlane );
     }
   }
   myModel->update();
+
+  double aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
+  getMinMaxFromContext( ic, myModel->trihedronSize(), aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
+  gp_Pnt aRotationCenter( (aXmax + aXmin) * 0.5,
+                          (aYmax + aYmin) * 0.5,
+                          (aZmax + aZmin) * 0.5 );
+  Bnd_Box aMinMax;
+  aMinMax.Update( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
+
+  myInteractor->setPlanes( myPreviewPlaneVector );
+  myInteractor->setRotationCenter( aRotationCenter );
+  myInteractor->setMinMax( aMinMax );
+  myInteractor->setEnabled( true );
 }
 
 void OCCViewer_ClippingDlg::updatePreview() {
@@ -820,20 +967,23 @@ void OCCViewer_ClippingDlg::updatePreview() {
     }
     myPreviewPlane = myPreviewPlaneVector[aCurPlaneIndex];
     if(myPreviewPlane.IsNull()) {
-      //Plane was not created 
-      myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ) );
+      //Plane was not created
+      myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ), aBasePnt );
+      myPreviewPlane->SetTypeOfSensitivity( Select3D_TOS_INTERIOR );
       myPreviewPlane->SetSize( aSize, aSize );
-      ic->Display( myPreviewPlane, 1, -1, false );
+      ic->Display( myPreviewPlane, 1, 0, false );
       ic->SetWidth( myPreviewPlane, 10, false );
       ic->SetMaterial( myPreviewPlane, Graphic3d_NOM_PLASTIC, false );
       ic->SetTransparency( myPreviewPlane, 0.5, false );
       myPreviewPlaneVector[aCurPlaneIndex] = myPreviewPlane;
     } else {      
-      myPreviewPlane->SetComponent(new Geom_Plane( aBasePnt, aNormal ));
+      myPreviewPlane->SetComponent( new Geom_Plane( aBasePnt, aNormal ) );
+      myPreviewPlane->SetCenter( aBasePnt );
       myPreviewPlane->SetSize( aSize, aSize ); 
     }
 
     ic->SetColor( myPreviewPlane, Quantity_Color( 255. / 255., 70. / 255., 0. / 255., Quantity_TOC_RGB ), false );
+    ic->Update( myPreviewPlane, Standard_False );
   } else {
     if(myPreviewPlaneVector.size() > aCurPlaneIndex ) {
       myPreviewPlane = myPreviewPlaneVector[aCurPlaneIndex];
@@ -847,9 +997,21 @@ void OCCViewer_ClippingDlg::updatePreview() {
   for(int i = 0; i < myPreviewPlaneVector.size(); i++) {
     if( i == aCurPlaneIndex ) continue;
     if(!myPreviewPlaneVector[i].IsNull())
-      ic->SetColor( myPreviewPlaneVector[i], Quantity_Color( 85 / 255., 85 / 255., 255 / 255., Quantity_TOC_RGB ), false );  
+      ic->SetColor( myPreviewPlaneVector[i], Quantity_Color( 85 / 255., 85 / 255., 255 / 255., Quantity_TOC_RGB ), false );
   }
   myModel->update();
+
+  double aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
+  getMinMaxFromContext( ic, myModel->trihedronSize(), aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
+  gp_Pnt aRotationCenter( (aXmax + aXmin) * 0.5,
+                          (aYmax + aYmin) * 0.5,
+                          (aZmax + aZmin) * 0.5 );
+  Bnd_Box aMinMax;
+  aMinMax.Update( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
+
+  myInteractor->setPlanes( myPreviewPlaneVector );
+  myInteractor->setRotationCenter( aRotationCenter );
+  myInteractor->setMinMax( aMinMax );
 }
 
 /*!
@@ -872,6 +1034,7 @@ void OCCViewer_ClippingDlg::erasePreview()
   }
   myPreviewPlaneVector.clear();
   myModel->update();
+  myInteractor->setEnabled( false );
 }
 
 /*!
@@ -900,12 +1063,67 @@ void OCCViewer_ClippingDlg::updateClipping()
   }
 }
 
+/*!
+  Updates state of user controls.
+*/
+void OCCViewer_ClippingDlg::updateControls()
+{
+  if ( clipPlanesCount() == 0 )
+  {
+    initParam();
+    return;
+  }
+
+  int aPlaneIdx = ComboBoxPlanes->currentIndex();
+
+  OCCViewer_ClipPlane& aPlane = getClipPlane( aPlaneIdx );
+
+  if ( aPlane.PlaneMode == Absolute )
+  {
+    ModeStackedLayout->setCurrentIndex( 0 );
+    myCurrentClipPlaneMode = Absolute;
+    int anOrientation = aPlane.Orientation;
+    // Set plane parameters in the dialog
+    SpinBox_X->setValue( aPlane.X );
+    SpinBox_Y->setValue( aPlane.Y );
+    SpinBox_Z->setValue( aPlane.Z );
+    SpinBox_Dx->setValue( aPlane.Dx );
+    SpinBox_Dy->setValue( aPlane.Dy );
+    SpinBox_Dz->setValue( aPlane.Dz );
+    CBAbsoluteOrientation->setCurrentIndex( anOrientation );
+    onOrientationAbsoluteChanged( anOrientation );
+  }
+  else if( aPlane.PlaneMode == Relative )
+  {
+    ModeStackedLayout->setCurrentIndex( 1 );
+    myCurrentClipPlaneMode = Relative;
+    int anOrientation = aPlane.RelativeMode.Orientation;
+
+    // Set plane parameters in the dialog
+    QString aFmtDistance  = QString::number( aPlane.RelativeMode.Distance, '.', 2 );
+    QString aFmtRotation1 = QString::number( floor( aPlane.RelativeMode.Rotation1 ) );
+    QString aFmtRotation2 = QString::number( floor( aPlane.RelativeMode.Rotation2 ) );
+    aFmtRotation1 = QString( "%1\xB0" ).arg( aFmtRotation1 );
+    aFmtRotation2 = QString( "%1\xB0" ).arg( aFmtRotation2 );
+
+    SliderDistance->setValue( aPlane.RelativeMode.Distance * 100 );
+    TLValueDistance->setText( aFmtDistance );
+    SliderRotation1->setValue( floor( aPlane.RelativeMode.Rotation1 ) );
+    TLValueRotation1->setText( aFmtRotation1 );
+    SliderRotation2->setValue( floor( aPlane.RelativeMode.Rotation2 ) );
+    TLValueRotation2->setText( aFmtRotation2 );
+    CBRelativeOrientation->setCurrentIndex( anOrientation );
+    onOrientationRelativeChanged( anOrientation );
+  }
+
+  isActivePlane->setChecked( aPlane.IsOn );
+}
+
 /*!
   SLOT on new button click: create a new clipping plane
 */
 void OCCViewer_ClippingDlg::ClickOnNew()
 {
-
   OCCViewer_ClipPlane aPlane;
   aPlane.PlaneMode = (ClipPlaneMode )myCurrentClipPlaneMode;
   myLocalPlanes.push_back(aPlane);
@@ -1030,9 +1248,18 @@ void OCCViewer_ClippingDlg::onModeRelative()
 */
 void OCCViewer_ClippingDlg::onValueChanged()
 {
+  if ( myIsUpdatingControls )
+  {
+    return;
+  }
+
   SetCurrentPlaneParam();
+
   if ( myIsSelectPlane )
+  {
     return;
+  }
+
   updateClipping();
 }
 
@@ -1042,41 +1269,14 @@ void OCCViewer_ClippingDlg::onValueChanged()
 void OCCViewer_ClippingDlg::onSelectPlane ( int theIndex )
 {
   if ( clipPlanesCount() == 0 )
+  {
     return;
+  }
 
-  OCCViewer_ClipPlane& aClipPlane = getClipPlane (theIndex);
+  OCCViewer_ClipPlane& aClipPlane = getClipPlane( theIndex );
 
   myIsSelectPlane = true;
-  if ( aClipPlane.PlaneMode == Absolute ) {
-    ModeStackedLayout->setCurrentIndex( 0 );
-    myCurrentClipPlaneMode = Absolute;
-    int anOrientation = aClipPlane.Orientation;
-    // Set plane parameters in the dialog
-    SpinBox_X->setValue( aClipPlane.X );
-    SpinBox_Y->setValue( aClipPlane.Y );
-    SpinBox_Z->setValue( aClipPlane.Z );
-    SpinBox_Dx->setValue( aClipPlane.Dx );
-    SpinBox_Dy->setValue( aClipPlane.Dy );
-    SpinBox_Dz->setValue( aClipPlane.Dz );
-    CBAbsoluteOrientation->setCurrentIndex( anOrientation );
-    onOrientationAbsoluteChanged( anOrientation );
-  }
-  else if( aClipPlane.PlaneMode == Relative ) {
-    ModeStackedLayout->setCurrentIndex( 1 );
-    myCurrentClipPlaneMode = Relative;
-    int anOrientation = aClipPlane.RelativeMode.Orientation;
-    // Set plane parameters in the dialog
-    SliderDistance->setValue( aClipPlane.RelativeMode.Distance*100 );
-    TLValueDistance->setText( QString::number(aClipPlane.RelativeMode.Distance ) );
-    SliderRotation1->setValue( aClipPlane.RelativeMode.Rotation1 );
-    TLValueRotation1->setText( QString( "%1\xB0" ).arg( aClipPlane.RelativeMode.Rotation1 ) );
-    SliderRotation2->setValue( aClipPlane.RelativeMode.Rotation2 );
-    TLValueRotation2->setText( QString( "%1\xB0" ).arg( aClipPlane.RelativeMode.Rotation2 ) );
-    CBRelativeOrientation->setCurrentIndex( anOrientation );
-    onOrientationRelativeChanged( anOrientation );
-  }
-  
-  isActivePlane->setChecked( aClipPlane.IsOn );
+  updateControls();
   ComboBoxPlanes->setCurrentIndex( theIndex );
   myIsSelectPlane = false;
 }
@@ -1091,23 +1291,26 @@ void OCCViewer_ClippingDlg::SetCurrentPlaneParam()
 
   int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
 
OCCViewer_ClipPlane& aPlane = getClipPlane (aCurPlaneIndex);
 OCCViewer_ClipPlane& aPlane = getClipPlane( aCurPlaneIndex );
 
-  if ( aPlane.PlaneMode == Absolute ) {
+  if ( aPlane.PlaneMode == Absolute )
+  {
     aPlane.Orientation = CBAbsoluteOrientation->currentIndex();
-    aPlane.X = SpinBox_X->value();
-    aPlane.Y = SpinBox_Y->value();
-    aPlane.Z = SpinBox_Z->value();
+    aPlane.X  = SpinBox_X->value();
+    aPlane.Y  = SpinBox_Y->value();
+    aPlane.Z  = SpinBox_Z->value();
     aPlane.Dx = SpinBox_Dx->value();
     aPlane.Dy = SpinBox_Dy->value();
     aPlane.Dz = SpinBox_Dz->value();
+    absolutePlaneToRelative( aPlane, myModel->getAISContext(),myModel->trihedronSize() );
   }
-  else if( aPlane.PlaneMode == Relative ) {
+  else if( aPlane.PlaneMode == Relative )
+  {
     aPlane.RelativeMode.Orientation = CBRelativeOrientation->currentIndex();
     aPlane.RelativeMode.Distance = TLValueDistance->text().toDouble();
     aPlane.RelativeMode.Rotation1 = TLValueRotation1->text().remove("\xB0").toInt();
     aPlane.RelativeMode.Rotation2 = TLValueRotation2->text().remove("\xB0").toInt();
-    RelativePlaneToAbsolute (aPlane, myModel->getAISContext(),myModel->trihedronSize() );
+    relativePlaneToAbsolute( aPlane, myModel->getAISContext(),myModel->trihedronSize() );
   }
   aPlane.IsOn  = isActivePlane->isChecked();
 }
@@ -1143,7 +1346,7 @@ void OCCViewer_ClippingDlg::onInvert()
 
   if ( clipPlanesCount() != 0 ) {
     int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
-    OCCViewer_ClipPlane& aPlane = getClipPlane (aCurPlaneIndex);
+    OCCViewer_ClipPlane& aPlane = getClipPlane( aCurPlaneIndex );
     aPlane.IsInvert = !aPlane.IsInvert;
   }
   updateClipping();
@@ -1199,7 +1402,7 @@ void OCCViewer_ClippingDlg::onOrientationAbsoluteChanged( int mode )
       }
     
     int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
-    OCCViewer_ClipPlane& aPlane = getClipPlane (aCurPlaneIndex);
+    OCCViewer_ClipPlane& aPlane = getClipPlane( aCurPlaneIndex );
     if ( aPlane.IsInvert == true ) {
       aDx = -aDx; aDy = -aDy; aDz = -aDz;
     }
@@ -1210,8 +1413,12 @@ void OCCViewer_ClippingDlg::onOrientationAbsoluteChanged( int mode )
     SpinBox_Dz->setValue( aDz );
     myBusy = false;
   }
-  SetCurrentPlaneParam();
-  updateClipping();
+
+  if ( !myIsUpdatingControls )
+  {
+    SetCurrentPlaneParam();
+    updateClipping();
+  }
 }
 
 /*!
@@ -1235,9 +1442,15 @@ void OCCViewer_ClippingDlg::onOrientationRelativeChanged (int theItem)
     TextLabelRotation2->setText( tr( "ROTATION_AROUND_X_Z2Y" ) );
   }
 
-  if( (QComboBox*)sender() == CBRelativeOrientation )
-    SetCurrentPlaneParam();
-  updateClipping();
+  if ( !myIsUpdatingControls )
+  {
+    if( (QComboBox*)sender() == CBRelativeOrientation )
+    {
+      SetCurrentPlaneParam();
+    }
+
+    updateClipping();
+  }
 }
 
 /*!
@@ -1280,6 +1493,65 @@ void OCCViewer_ClippingDlg::onApply()
   myIsSelectPlane = false;
 }
 
+/*!
+  SLOT: Called when clip plane is clicked in viewer.
+*/
+void OCCViewer_ClippingDlg::onPlaneClicked( const Handle(AIS_Plane)& thePlane )
+{
+  for ( int aPlaneIt = 0; aPlaneIt < myPreviewPlaneVector.size(); aPlaneIt++ )
+  {
+    Handle(AIS_Plane)& aPlane = myPreviewPlaneVector.at( aPlaneIt );
+    if ( aPlane != thePlane )
+    {
+      continue;
+    }
+
+    ComboBoxPlanes->setCurrentIndex( aPlaneIt );
+
+    break;
+  }
+}
+
+/*!
+  SLOT: Called when clip plane is changed by dragging in viewer.
+*/
+void OCCViewer_ClippingDlg::onPlaneDragged( const Handle(AIS_Plane)& thePlane )
+{
+  for ( int aPlaneIt = 0; aPlaneIt < myPreviewPlaneVector.size(); aPlaneIt++ )
+  {
+    Handle(AIS_Plane)& aPlane = myPreviewPlaneVector.at( aPlaneIt );
+    if ( aPlane != thePlane )
+    {
+      continue;
+    }
+
+    OCCViewer_ClipPlane& aClipPlane = getClipPlane( aPlaneIt );
+
+    gp_Pln aPln = thePlane->Component()->Pln();
+    const gp_Pnt& aPlaneP = aPln.Location();
+    const gp_Dir& aPlaneN = aPln.Axis().Direction();
+
+    aClipPlane.X  = aPlaneP.X();
+    aClipPlane.Y  = aPlaneP.Y();
+    aClipPlane.Z  = aPlaneP.Z();
+    aClipPlane.Dx = aPlaneN.X();
+    aClipPlane.Dy = aPlaneN.Y();
+    aClipPlane.Dz = aPlaneN.Z();
+    absolutePlaneToRelative( aClipPlane, myModel->getAISContext(), myModel->trihedronSize() );
+
+    myIsUpdatingControls = true;
+    updateControls();
+    myIsUpdatingControls = false;
+
+    if ( AutoApplyCheckBox->isChecked() )
+    {
+      onApply();
+    }
+
+    break;
+  }
+}
+
 /*!
   SLOT: Called when value of slider distance change
 */
@@ -1308,10 +1580,12 @@ void OCCViewer_ClippingDlg::SliderRotation2HasMoved( int value )
   onValueChanged();
 }
 
-OCCViewer_ClipPlane& OCCViewer_ClippingDlg::getClipPlane (int theIndex) {
-  return myLocalPlanes[theIndex];
+OCCViewer_ClipPlane& OCCViewer_ClippingDlg::getClipPlane( int theIdx )
+{
+  return myLocalPlanes[theIdx];
 }
 
-int OCCViewer_ClippingDlg::clipPlanesCount() {
+int OCCViewer_ClippingDlg::clipPlanesCount()
+{
   return myLocalPlanes.size();
 }
index 934cefb6bc73d34a163d0e9e231f73263c6b38aa..e8f1795a66ac8450720c89e70003e4b7d2deea67 100644 (file)
@@ -43,6 +43,7 @@ class QMenu;
 
 class OCCViewer_Viewer;
 class OCCViewer_ViewWindow;
+class OCCViewer_ClipPlaneInteractor;
 
 /*!
   \class OCCViewer_ClippingDlg
@@ -70,8 +71,9 @@ private :
   void updatePreview();
   bool isValid();
   void updateClipping();
+  void updateControls();
 
-  OCCViewer_ClipPlane& getClipPlane (int theIndex);
+  OCCViewer_ClipPlane& getClipPlane( int );
   int clipPlanesCount();
 
   QComboBox* ComboBoxPlanes;
@@ -129,11 +131,14 @@ private :
   std::vector<Handle(AIS_Plane)> myPreviewPlaneVector;
 
   bool myIsSelectPlane;
+  bool myIsUpdatingControls;
   bool myBusy;
   bool myIsPlaneCreation;
 
   ClipPlanesList myLocalPlanes;
-    
+
+  OCCViewer_ClipPlaneInteractor* myInteractor;
+
 public slots:
   void onApply();
 
@@ -156,7 +161,7 @@ private slots:
   void onReset();
   void onInvert();
   void onOrientationAbsoluteChanged( int );
-  void onOrientationRelativeChanged (int);
+  void onOrientationRelativeChanged( int );
 
   void onPreview( bool on );
   void onAutoApply(bool);
@@ -164,6 +169,9 @@ private slots:
   void SliderDistanceHasMoved(int);
   void SliderRotation1HasMoved(int);
   void SliderRotation2HasMoved(int);
+
+  void onPlaneClicked( const Handle_AIS_Plane& thePlane );
+  void onPlaneDragged( const Handle_AIS_Plane& thePlane );
 };
 
 #endif // OCCVIEWER_CLIPPINGDLG_H
diff --git a/src/OCCViewer/OCCViewer_ViewportInputFilter.cxx b/src/OCCViewer/OCCViewer_ViewportInputFilter.cxx
new file mode 100644 (file)
index 0000000..c8c0f9c
--- /dev/null
@@ -0,0 +1,157 @@
+// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "OCCViewer_ViewportInputFilter.h"
+#include "OCCViewer_ViewManager.h"
+#include "OCCViewer_ViewModel.h"
+#include "OCCViewer_ViewWindow.h"
+#include "OCCViewer_ViewPort3d.h"
+
+#include <QMouseEvent>
+#include <QKeyEvent>
+
+/*!
+  \brief Constructor.
+  \param theVM [in] the view manager to embed the filter into.
+  \param theParent [in] the parent object.
+*/
+OCCViewer_ViewportInputFilter::OCCViewer_ViewportInputFilter( OCCViewer_ViewManager* theVM,
+                                                              QObject* theParent )
+: QObject( theParent ),
+  myVM( theVM )
+{
+}
+
+/*!
+  \brief Destructor.
+*/
+OCCViewer_ViewportInputFilter::~OCCViewer_ViewportInputFilter()
+{
+  setEnabled( false );
+}
+
+/*!
+  \brief Enables or disables event processing within the viewer.
+*/
+void OCCViewer_ViewportInputFilter::setEnabled(const bool theIsEnabled)
+{
+  if ( theIsEnabled == myIsEnabled )
+  {
+    return;
+  }
+
+  if ( theIsEnabled )
+  {
+    // install event filtering on viewer windows
+    myViewer = (OCCViewer_Viewer*) myVM->getViewModel();
+    if ( !myVM || !myViewer )
+    {
+      return;
+    }
+
+    connect( myVM, SIGNAL( viewCreated( SUIT_ViewWindow* ) ), SLOT( onViewCreated( SUIT_ViewWindow* ) ) );
+    connect( myVM, SIGNAL( deleteView ( SUIT_ViewWindow* ) ), SLOT( onViewRemoved( SUIT_ViewWindow* ) ) );
+
+    QVector<SUIT_ViewWindow*>           aViews  = myVM->getViews();
+    QVector<SUIT_ViewWindow*>::iterator aViewIt = aViews.begin();
+    for ( ; aViewIt != aViews.end(); ++aViewIt )
+    {
+      connectView( *aViewIt );
+    }
+  }
+  else
+  {
+    // remove event filtering from viewer windows
+    QVector<SUIT_ViewWindow*>           aViews  = myVM->getViews();
+    QVector<SUIT_ViewWindow*>::iterator aViewIt = aViews.begin();
+    for ( ; aViewIt != aViews.end(); ++aViewIt )
+    {
+      disconnectView( *aViewIt );
+    }
+  }
+
+  myIsEnabled = theIsEnabled;
+}
+
+/*!
+  \brief Base-level implementation of event filtering.
+         Routes user input events to associated implementation methods.
+  \param theObject [in] the filtered object.
+  \param theEvent [in] the incoming event.
+*/
+bool OCCViewer_ViewportInputFilter::eventFilter( QObject* theObject, QEvent* theEvent )
+{
+  OCCViewer_ViewPort3d* aViewPort = (OCCViewer_ViewPort3d*) theObject;
+
+  if ( !aViewPort )
+  {
+    return false;
+  }
+
+  switch ( theEvent->type() )
+  {
+    case QEvent::MouseMove           : return mouseMove( (QMouseEvent*)theEvent, aViewPort );
+    case QEvent::MouseButtonPress    : return mousePress( (QMouseEvent*)theEvent, aViewPort );
+    case QEvent::MouseButtonRelease  : return mouseRelease( (QMouseEvent*)theEvent, aViewPort );
+    case QEvent::MouseButtonDblClick : return mouseDoubleClick( (QMouseEvent*)theEvent, aViewPort );
+    case QEvent::KeyPress            : return keyPress( (QKeyEvent*)theEvent, aViewPort );
+    case QEvent::KeyRelease          : return keyRelease( (QKeyEvent*)theEvent, aViewPort );
+    default :
+      return false;
+  }
+}
+
+/*!
+  \brief Connects view to event processing.
+  \param theView [in] the view to connect.
+*/
+void OCCViewer_ViewportInputFilter::connectView( SUIT_ViewWindow* theView )
+{
+  ( (OCCViewer_ViewWindow*) theView )->getViewPort()->installEventFilter( this );
+}
+
+/*!
+  \brief Disconnects view to event processing.
+  \param theView [in] the view to disconnect.
+*/
+void OCCViewer_ViewportInputFilter::disconnectView( SUIT_ViewWindow* theView )
+{
+  ( (OCCViewer_ViewWindow*) theView )->getViewPort()->removeEventFilter( this );
+}
+
+/*!
+  \brief Connects newly created within viewer to event processing.
+  \param theView [in] the view to connect.
+*/
+void OCCViewer_ViewportInputFilter::onViewCreated( SUIT_ViewWindow* theView )
+{
+  connectView( theView );
+}
+
+/*!
+  \brief Disconnects view being removed from viewer.
+  \param theView [in] the view to disconnect.
+*/
+void OCCViewer_ViewportInputFilter::onViewRemoved( SUIT_ViewWindow* theView )
+{
+  disconnectView( theView );
+}
diff --git a/src/OCCViewer/OCCViewer_ViewportInputFilter.h b/src/OCCViewer/OCCViewer_ViewportInputFilter.h
new file mode 100644 (file)
index 0000000..aa5376d
--- /dev/null
@@ -0,0 +1,83 @@
+// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef OCCVIEWER_VIEWPORTINPUTFILTER_H
+#define OCCVIEWER_VIEWPORTINPUTFILTER_H
+
+#include <QObject>
+
+class OCCViewer_ViewManager;
+class OCCViewer_ViewPort3d;
+class OCCViewer_Viewer;
+class SUIT_ViewWindow;
+class QMouseEvent;
+class QKeyEvent;
+
+/*!
+  \class OCCViewer_ViewportInputFilter.
+  \brief The user input filter of OCC viewports. The class can be used
+         to introduce custom interactive operations in OCC viewer,
+         e.g. manipulating IO. The filter receives events in priority
+         to the viewport itself and can bypass some events if it provides
+         custom handling.
+         
+         This class is abstract and required implementation of custom reaction
+         on hooked viewport events. The role of the code behind this class
+         is to properly embed the event filter into OCC viewer's structure.
+*/
+class OCCViewer_ViewportInputFilter : public QObject
+{
+  Q_OBJECT
+
+public:
+  OCCViewer_ViewportInputFilter( OCCViewer_ViewManager*, QObject* );
+  ~OCCViewer_ViewportInputFilter();
+
+public:
+  virtual void   setEnabled( const bool );
+
+protected:
+  virtual bool   mouseMove( QMouseEvent*, OCCViewer_ViewPort3d* ) = 0;
+  virtual bool   mousePress( QMouseEvent*, OCCViewer_ViewPort3d* ) = 0;
+  virtual bool   mouseRelease( QMouseEvent*, OCCViewer_ViewPort3d* ) = 0;
+  virtual bool   mouseDoubleClick( QMouseEvent*, OCCViewer_ViewPort3d* ) = 0;
+  virtual bool   keyPress( QKeyEvent*, OCCViewer_ViewPort3d* ) = 0;
+  virtual bool   keyRelease( QKeyEvent*, OCCViewer_ViewPort3d* ) = 0;
+
+protected:
+  void           connectView( SUIT_ViewWindow* );
+  void           disconnectView( SUIT_ViewWindow* );
+
+protected:
+  bool           eventFilter( QObject*, QEvent* );
+
+protected slots:
+  void           onViewCreated( SUIT_ViewWindow* );
+  void           onViewRemoved( SUIT_ViewWindow* );
+
+protected:
+  OCCViewer_ViewManager*  myVM;
+  OCCViewer_Viewer*       myViewer;
+  bool                    myIsEnabled;
+};
+
+#endif