Salome HOME
updated copyright message
[modules/gui.git] / src / OCCViewer / OCCViewer_ClipPlaneInteractor.cxx
1 // Copyright (C) 2007-2023  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "OCCViewer_ClipPlaneInteractor.h"
24 #include "OCCViewer_ViewPort3d.h"
25 #include "OCCViewer_ViewModel.h"
26
27 #include <AIS_InteractiveContext.hxx>
28 #include <SelectMgr_EntityOwner.hxx>
29 #include <V3d_View.hxx>
30 #include <Geom_Line.hxx>
31 #include <Geom_Plane.hxx>
32 #include <GeomAPI_IntCS.hxx>
33 #include <gce_MakeDir.hxx>
34
35 #include <QMouseEvent>
36 #include <QKeyEvent>
37
38 /*!
39   \brief Constructor.
40   \param theVM [in] the view manager.
41   \param theParent [in] the parent object.
42 */
43 OCCViewer_ClipPlaneInteractor::OCCViewer_ClipPlaneInteractor( OCCViewer_ViewManager* theVM,
44                                                               QObject* theParent )
45 : OCCViewer_ViewportInputFilter( theVM, theParent ),
46   myPerformingOp( DragOperation_Undef ),
47   myRotationCenter( gp::Origin() ),
48   myIsDraggable( false ),
49   myIsClickable( false )
50 {
51 }
52
53 /*!
54   \brief Get sequence of planes to interact with.
55   \return the sequence of accepted planes.
56 */
57 const OCCViewer_ClipPlaneInteractor::SeqOfPlanes& OCCViewer_ClipPlaneInteractor::planes() const
58 {
59   return myPlanes;
60 }
61
62 /*!
63   \brief Sets sequence of planes allowed for interaction.
64   \param thePlanes [in] the sequence of accepted planes.
65 */
66 void OCCViewer_ClipPlaneInteractor::setPlanes( const SeqOfPlanes& thePlanes )
67 {
68   myPlanes = thePlanes;
69 }
70
71 /*!
72   \brief Sets center of rotation for the scene.
73   \param theCenter [in] the center of rotation.
74 */
75 void OCCViewer_ClipPlaneInteractor::setRotationCenter( const gp_Pnt& theCenter )
76 {
77   myRotationCenter = theCenter;
78 }
79
80 /*!
81   \brief Sets minimum and maximum bounding of the scene.
82          The sliding movements are limited to minimum
83          and maximum bounds.
84   \param theMinMax [in] the minimum and maximum bounds.
85 */
86 void OCCViewer_ClipPlaneInteractor::setMinMax( const Bnd_Box& theMinMax )
87 {
88   myMinMax = theMinMax;
89 }
90
91 /*!
92   \brief Enables or disables event processing within the viewer.
93 */
94 void OCCViewer_ClipPlaneInteractor::setEnabled( const bool theIsEnabled )
95 {
96   if ( !theIsEnabled )
97   {
98   }
99
100   myMouseDragPln    = gp_Pln();
101   myPerformingOp    = DragOperation_Undef;
102   myPickPos         = QPoint();
103   myDragPos         = QPoint();
104   myInteractedPlane = NULL;
105   myIsDraggable     = false;
106   myIsClickable     = false;
107
108   OCCViewer_ViewportInputFilter::setEnabled( theIsEnabled );
109 }
110
111 /*!
112   \brief Checks whether the interactive operation is in progress.
113   \return \c true if the interaction is performed on IO object meaning
114           that no other operations in viewer should be processed.
115 */
116 bool OCCViewer_ClipPlaneInteractor::isPerforming() const
117 {
118   return !myInteractedPlane.IsNull();
119 }
120
121 /*!
122   \brief Checks whether the interactive plane can be clicked.
123   \return \c true if the click interaction is supported for the plane.
124 */
125 bool OCCViewer_ClipPlaneInteractor::isClickable( const Handle(AIS_Plane)& thePlane )
126 {
127   bool isFound = Standard_False;
128   for ( int aPlaneIt = 0; aPlaneIt < (int)myPlanes.size(); ++aPlaneIt )
129   {
130     if ( myPlanes[aPlaneIt] == thePlane )
131     {
132       isFound = true;
133       break;
134     }
135   }
136
137   if ( !isFound )
138   {
139     return false;
140   }
141
142   Handle(AIS_InteractiveContext) anAISContext = myViewer->getAISContext();
143
144   if ( anAISContext->IsSelected( thePlane ) )
145   {
146     return false;
147   }
148
149   return true;
150 }
151
152 /*!
153   \brief Checks whether the interactive plane can be dragged.
154   \return \c true if the dragging interaction is supported for the plane.
155 */
156 bool OCCViewer_ClipPlaneInteractor::isDraggable( const Handle(AIS_Plane)& thePlane )
157 {
158   bool isFound = Standard_False;
159   for ( int aPlaneIt = 0; aPlaneIt < (int)myPlanes.size(); ++aPlaneIt )
160   {
161     if ( myPlanes[aPlaneIt] == thePlane )
162     {
163       isFound = true;
164       break;
165     }
166   }
167
168   if ( !isFound )
169   {
170     return false;
171   }
172
173   Handle(AIS_InteractiveContext) anAISContext = myViewer->getAISContext();
174
175   if ( !anAISContext->IsSelected( thePlane ) ) 
176   {
177     return false;
178   }
179
180   return true;
181 }
182
183 /*!
184   \brief Checks whether it is possible to start interaction with plane.
185   \param thePickPos [in] the position of mouse picking.
186   \param theDragPos [in] the position of initial mouse dragging.
187   \param theDragOp [in] the drag operation to start.
188   \param thePlane [in] the detected plane.
189   \param theView [in] the view.
190 */
191 bool OCCViewer_ClipPlaneInteractor::startDragging( const QPoint& thePickPos,
192                                                    const QPoint& theDragPos,
193                                                    const DragOperation theDragOp,
194                                                    const Handle(AIS_Plane)& thePlane,
195                                                    const Handle(V3d_View)& theView )
196 {
197   // get point of view plane intersection with the plane
198   Standard_Real P[3], D[3];
199   theView->ConvertWithProj( thePickPos.x(), thePickPos.y(), P[0], P[1], P[2], D[0], D[1], D[2] );
200   gp_Lin aPickProj = gp_Lin( gp_Pnt( P[0], P[1], P[2] ), gp_Dir( D[0], D[1], D[2] ) );
201   gp_Pln aPlanePln = thePlane->Component()->Pln();
202
203   Handle(Geom_Line)  aPickLine   = new Geom_Line( aPickProj );
204   Handle(Geom_Plane) aCrossPlane = new Geom_Plane( aPlanePln );
205
206   GeomAPI_IntCS aFindPick( aPickLine, aCrossPlane );
207   if ( !aFindPick.IsDone() || aFindPick.NbPoints() == 0 )
208   {
209     return false;
210   }
211
212   // check plane geometry
213   Standard_Real aSizeX = 0.0;
214   Standard_Real aSizeY = 0.0;
215   thePlane->Size(aSizeX, aSizeY);
216   if ( aSizeX < Precision::Confusion() || aSizeY < Precision::Confusion() )
217   {
218     return false;
219   }
220
221   gp_Pnt aPickPoint = aFindPick.Point( 1 );
222
223   gp_Dir aPlaneN      = aPlanePln.Axis().Direction();
224   gp_Dir aPlaneX      = aPlanePln.XAxis().Direction();
225   gp_Dir aPlaneY      = aPlanePln.YAxis().Direction();
226   gp_Pnt aPlaneCenter = aPlanePln.Location();
227
228   switch ( theDragOp )
229   {
230     // sliding operation is started
231     case DragOperation_Slide :
232     {
233       if ( aPlaneN.IsParallel( aPickProj.Direction(), M_PI / 180.0 ) )
234       {
235         return false;
236       }
237
238       gp_Dir aMousePlnDir = ( aPickProj.Direction() ^ aPlaneN ) ^ aPlaneN;
239
240       myMouseDragPln     = gp_Pln( aPickPoint, aMousePlnDir );
241       myPlaneReferenceCS = gp_Ax3( aPlaneCenter, aPlaneN, aPlaneX );
242
243       return true;
244     }
245
246     // rotation operation is requested
247     case DragOperation_Rotate :
248     {
249       theView->ConvertWithProj( theDragPos.x(), theDragPos.y(), P[0], P[1], P[2], D[0], D[1], D[2] );
250       gp_Lin aDragProj = gp_Lin( gp_Pnt( P[0], P[1], P[2] ), gp_Dir( D[0], D[1], D[2] ) );
251
252       if ( aPickPoint.Distance( aDragProj.Location() ) < Precision::Confusion() )
253       {
254         return false;
255       }
256
257       // to determine whether we rotate around first or second axis, we
258       // construct a virtual "arm" as vector of from center of rotation
259       // to the picked point. Then we calculate dragging directions for both axes
260       // depending on the difference of picking and dragging mouse coordinates.
261       // The direction which is physically more easy to turn the "arm" is choosen
262       // and the corresponding plane for dragging is selected.
263
264       gp_Vec anArm = gp_Vec( myRotationCenter, aPickPoint );
265       Standard_Real anArmLength = anArm.Magnitude();
266       if ( anArmLength < Precision::Confusion() )
267       {
268         return false;
269       }
270
271       Handle(Geom_Line) aDragLine = new Geom_Line( aDragProj );
272       Standard_Real aMomentArm1 = 0.0;
273       Standard_Real aMomentArm2 = 0.0;
274       Standard_Real anArmLength1 = Abs( anArm * gp_Vec( aPlaneN ^ aPlaneX ) );
275       Standard_Real anArmLength2 = Abs( anArm * gp_Vec( aPlaneN ^ aPlaneY ) );
276
277       // check virtual "arm" dragging moment for first axis of rotation
278       if ( !aPlaneX.IsNormal( aDragProj.Direction(), M_PI / 180.0 ) && ( anArmLength1 / anArmLength > 0.3 ) )
279       {
280         Handle(Geom_Plane) aDragPln = new Geom_Plane( aPickPoint, aPlaneX );
281
282         gp_Pnt aDragPnt = aPickPoint;
283         gp_Vec aDragDir = gp_Vec( 0.0, 0.0, 0.0 );
284         GeomAPI_IntCS aFindCross( aDragLine, aDragPln );
285         if ( aFindCross.IsDone() && aFindCross.NbPoints() != 0 )
286         {
287           aDragPnt = aFindCross.Point( 1 );
288         }
289
290         if ( aDragPnt.Distance( aPickPoint ) > Precision::Confusion() )
291         {
292           aDragDir = gp_Vec( aPickPoint, aDragPnt );
293         }
294
295         aMomentArm1 = anArmLength1 * ( 1.0 - Abs( aDragDir.Normalized() * anArm.Normalized() ) );
296       }
297
298       // check virtual "arm" dragging moment for second axis of rotation
299       if ( !aPlaneY.IsNormal( aDragProj.Direction(), M_PI / 180.0 )&& ( anArmLength2 / anArmLength > 0.3 ) )
300       {
301         Handle(Geom_Plane) aDragPln = new Geom_Plane( aPickPoint, aPlaneY );
302
303         gp_Pnt aDragPnt = aPickPoint;
304         gp_Vec aDragDir = gp_Vec( 0.0, 0.0, 0.0 );
305         GeomAPI_IntCS aFindCross( aDragLine, aDragPln );
306         if ( aFindCross.IsDone() && aFindCross.NbPoints() != 0 )
307         {
308           aDragPnt = aFindCross.Point( 1 );
309         }
310
311         if ( aDragPnt.Distance( aPickPoint ) > Precision::Confusion() )
312         {
313           aDragDir = gp_Vec( aPickPoint, aDragPnt );
314         }
315
316         aMomentArm2 = anArmLength2 * ( 1.0 - Abs( aDragDir.Normalized() * anArm.Normalized() ) );
317       }
318
319       // choose the best plane for dragging
320       if ( aMomentArm1 >= aMomentArm2 )
321       {
322         gp_Vec aMousePlnN = gp_Vec( aPlaneX );
323
324         myMouseDragPln = gp_Pln( aPickPoint, aMousePlnN );
325
326         /* todo: aDistance2Center, aCenterOnMousePln not used
327         Standard_Real aDistance2Center = myMouseDragPln.Distance( aPlaneCenter );
328         gp_Pnt aCenterOnMousePln = aMousePlnN * gp_Vec( aPickPoint, aPlaneCenter ) < 0.0
329           ? aPlaneCenter.Translated( aMousePlnN *  aDistance2Center )
330           : aPlaneCenter.Translated( aMousePlnN * -aDistance2Center );
331         */
332
333         myRotationAxis = gp_Ax1( myRotationCenter, aMousePlnN );
334       }
335       else
336       {
337         gp_Vec aMousePlnN = gp_Vec( aPlaneY );
338
339         myMouseDragPln = gp_Pln( aPickPoint, aMousePlnN );
340
341         /* todo: aDistance2Center, aCenterOnMousePln not used
342         Standard_Real aDistance2Center = myMouseDragPln.Distance( aPlaneCenter );
343         gp_Pnt aCenterOnMousePln = aMousePlnN * gp_Vec( aPickPoint, aPlaneCenter ) < 0.0
344           ? aPlaneCenter.Translated( aMousePlnN *  aDistance2Center )
345           : aPlaneCenter.Translated( aMousePlnN * -aDistance2Center );
346         */
347
348         myRotationAxis = gp_Ax1( myRotationCenter, aMousePlnN );
349       }
350
351       myPlaneReferenceCS = gp_Ax3( aPlaneCenter, aPlaneN, aPlaneX );
352
353       return true;
354     }
355     default:
356     {
357       break;
358     }
359   }
360
361   return false;
362 }
363
364 /*!
365   \brief Performs dragging operation on the passed interactive plane.
366   \param theDragPos [in] the position of mouse dragging.
367   \param theDragOp [in] the drag operation to start.
368   \param thePlane [in] the operated plane.
369   \param theView [in] the view.
370 */
371 void OCCViewer_ClipPlaneInteractor::performDragging( const QPoint& theDragPos,
372                                                      const DragOperation theDragOp,
373                                                      const Handle(AIS_Plane)& thePlane,
374                                                      const Handle(V3d_View)& theView )
375 {
376   Standard_Real P[3], D[3];
377   theView->ConvertWithProj( theDragPos.x(), theDragPos.y(), P[0], P[1], P[2], D[0], D[1], D[2] );
378   gp_Lin aProjection = gp_Lin( gp_Pnt( P[0], P[1], P[2] ), gp_Dir( D[0], D[1], D[2] ) );
379
380   // get point on the plane
381   Handle(Geom_Line)  aCrossLine  = new Geom_Line( aProjection );
382   Handle(Geom_Plane) aCrossPlane = new Geom_Plane( myMouseDragPln );
383
384   GeomAPI_IntCS aFindCross( aCrossLine, aCrossPlane );
385   if ( !aFindCross.IsDone() || aFindCross.NbPoints() == 0 )
386   {
387     return;
388   }
389
390   gp_Pnt aDragPoint   = aFindCross.Point( 1 );
391   gp_Pnt aPlaneCenter = myPlaneReferenceCS.Location();
392   gp_Vec aPlaneN      = myPlaneReferenceCS.Direction();
393   gp_Vec aPlaneX      = myPlaneReferenceCS.XDirection();
394   gp_Pln aPlanePln    = gp_Pln( aPlaneCenter, aPlaneN );
395
396   switch ( theDragOp )
397   {
398     // sliding the plane along its normal
399     case DragOperation_Slide:
400     {
401       Standard_Real aTranslation = 
402         gp_Vec( aPlaneCenter, aDragPoint ) * gp_Vec( aPlaneN ) > 0.0
403           ?  aPlanePln.Distance( aDragPoint )
404           : -aPlanePln.Distance( aDragPoint );
405
406       gp_Pnt aNewCenter = aPlaneCenter.Translated( aPlaneN * aTranslation );
407
408       myPlaneReferenceCS = gp_Ax3( aNewCenter, aPlaneN, aPlaneX );
409
410       adjustBounds( myPlaneReferenceCS, myMinMax );
411
412       thePlane->SetComponent( new Geom_Plane( myPlaneReferenceCS ) );
413       thePlane->SetCenter( myPlaneReferenceCS.Location() );
414       thePlane->SetToUpdate();
415       thePlane->UpdateSelection();
416
417       myViewer->getAISContext()->Update( thePlane , Standard_True );
418     }
419     break;
420
421     case DragOperation_Rotate:
422     {
423       // project the dragging point on rotated plane
424       gp_Dir aRotAxis = myRotationAxis.Direction();
425       gp_Pln aDragAtCenterPln = gp_Pln( myRotationCenter, aRotAxis );
426       gp_Pnt aDragAtCenterPnt = gp_Vec( myRotationCenter, aDragPoint ) * gp_Vec( aRotAxis ) < 0.0
427         ? aDragPoint.Translated( gp_Vec( aRotAxis ) *  aDragAtCenterPln.Distance( aDragPoint ) )
428         : aDragPoint.Translated( gp_Vec( aRotAxis ) * -aDragAtCenterPln.Distance( aDragPoint ) );
429
430       gp_Pnt aDragOnPlanePnt = gp_Vec( aPlaneCenter, aDragAtCenterPnt ) * gp_Vec( aPlaneN ) < 0.0
431         ? aDragAtCenterPnt.Translated( gp_Vec( aPlaneN ) *  aPlanePln.Distance( aDragAtCenterPnt ) )
432         : aDragAtCenterPnt.Translated( gp_Vec( aPlaneN ) * -aPlanePln.Distance( aDragAtCenterPnt ) );
433
434       gp_Vec aDragPointVector( myRotationCenter, aDragAtCenterPnt );
435       gp_Vec aProjPointVector( myRotationCenter, aDragOnPlanePnt );
436
437       // check for rotation tolerance
438       if ( aDragPointVector.Magnitude() < 0.01 || aProjPointVector.Magnitude() < 0.01 )
439       {
440         return;
441       }
442
443       Standard_Real aTurnAngle = aProjPointVector.AngleWithRef( aDragPointVector, myRotationAxis.Direction() );
444
445       gp_Trsf aRotationTrsf;
446       aRotationTrsf.SetRotation( myRotationAxis, aTurnAngle );
447       myPlaneReferenceCS.Transform( aRotationTrsf );
448
449       adjustBounds( myPlaneReferenceCS, myMinMax );
450
451       gp_Ax3 aPlaneCS( myPlaneReferenceCS.Location(), myPlaneReferenceCS.Direction() );
452
453       thePlane->SetComponent( new Geom_Plane( aPlaneCS ) );
454       thePlane->SetCenter( myPlaneReferenceCS.Location() );
455       thePlane->SetToUpdate();
456       thePlane->UpdateSelection();
457
458       myViewer->getAISContext()->Update( thePlane , Standard_True );
459     }
460     break;
461   default:
462     break;
463   }
464 }
465
466 /*!
467   \brief Adjusts min-max bounds of the plane.
468   \param thePlane [in/out] the plane.
469   \param theMinMax [in] the min max bounds
470 */
471 void OCCViewer_ClipPlaneInteractor::adjustBounds( gp_Ax3& thePlane, const Bnd_Box& theMinMax )
472 {
473   gp_Trsf aRelativeTransform;
474   aRelativeTransform.SetTransformation( gp_Ax3(), thePlane );
475   Bnd_Box aRelativeBounds = theMinMax.Transformed( aRelativeTransform );
476
477   Standard_Real aXmin, aXmax, aYmin, aYmax, aZmin, aZmax;
478   aRelativeBounds.Get( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
479
480   if ( aZmax < 0.0 ) // out in positive direction
481   {
482     thePlane.Translate( gp_Vec( thePlane.Direction() ) * aZmax );
483   }
484   else if ( aZmin > 0.0 ) // out in negative direction
485   {
486     thePlane.Translate( gp_Vec( thePlane.Direction() ) * aZmin );
487   }
488 }
489
490 /*!
491   \brief Handle mouse press events. Starts interaction with detected plane.
492   \param theEvent [in] the user event.
493   \param theViewPort [in] the viewport.
494 */
495 bool OCCViewer_ClipPlaneInteractor::mousePress( QMouseEvent* theEvent,
496                                                 OCCViewer_ViewPort3d* theViewPort )
497 {
498   if ( theEvent->button() != Qt::LeftButton )
499   {
500     return false;
501   }
502
503   Handle(V3d_View) aView3D = theViewPort->getView();
504
505   Handle(AIS_InteractiveContext) anAISContext = myViewer->getAISContext();
506
507   // check detection of plane
508   anAISContext->MoveTo( theEvent->x(), theEvent->y(), aView3D , Standard_True );
509
510   if ( !anAISContext->HasDetected() )
511   {
512     return false;
513   }
514
515   // check that there is only one detected entity
516   anAISContext->InitDetected();
517
518   Handle(AIS_Plane) aPlane;
519   Handle(SelectMgr_EntityOwner) aDetectedOwner = anAISContext->DetectedOwner();
520   if ( !aDetectedOwner.IsNull() )
521   {
522     aPlane = Handle(AIS_Plane)::DownCast( aDetectedOwner->Selectable() );
523   }
524
525   if ( aPlane.IsNull() )
526   {
527     aPlane = Handle(AIS_Plane)::DownCast( anAISContext->DetectedInteractive() );
528   }
529
530   myIsClickable = isClickable( aPlane );
531
532   // process mouse click on the object
533   if ( myIsClickable )
534   {
535     myViewer->getAISContext()->SetSelected( aPlane, Standard_True );
536     emit planeClicked( aPlane );
537   }
538
539   myIsDraggable = isDraggable( aPlane );
540
541   if ( !myIsClickable && !myIsDraggable )
542   {
543     return false;
544   }
545
546   myPickPos = theEvent->pos();
547   myInteractedPlane = aPlane;
548
549   return true;
550 }
551
552 /*!
553   \brief Handle mouse move events. Performs dragging if interaction is in progress.
554   \param theEvent [in] the user event.
555   \param theViewPort [in] the viewport.
556 */
557 bool OCCViewer_ClipPlaneInteractor::mouseMove( QMouseEvent* theEvent,
558                                                OCCViewer_ViewPort3d* theViewPort )
559 {
560   if ( !isPerforming() )
561   {
562     return false;
563   }
564
565   // no dragging operation can be performed...
566   if ( !myIsDraggable )
567   {
568     return true;
569   }
570
571   Handle(V3d_View) aView3D = theViewPort->getView();
572
573   myDragPos = theEvent->pos();
574
575   // checking whether it is possible to start dragging operation
576   if ( myPerformingOp == DragOperation_Undef )
577   {
578     int aDx = myDragPos.x() - myPickPos.x();
579     int aDy = myDragPos.y() - myPickPos.y();
580     if ( ( aDx * aDx + aDy * aDy ) < 16 )
581     {
582       return true;
583     }
584
585     DragOperation aDragOp =
586       theEvent->modifiers().testFlag(Qt::ControlModifier)
587         ? DragOperation_Rotate
588         : DragOperation_Slide;
589
590     myIsDraggable = startDragging( myPickPos, myDragPos, aDragOp, myInteractedPlane, aView3D );
591
592     if ( !myIsDraggable )
593     {
594       return true;
595     }
596
597     myPerformingOp = aDragOp;
598   }
599
600   // performing dragging operation
601   performDragging( myDragPos, myPerformingOp, myInteractedPlane, aView3D );
602
603   emit planeDragged( myInteractedPlane );
604
605   return true;
606 }
607
608 /*!
609   \brief Handle mouse release events. Stops interaction.
610   \param theEvent [in] the user event.
611   \param theViewPort [in] the viewport.
612 */
613 bool OCCViewer_ClipPlaneInteractor::mouseRelease( QMouseEvent* /*theEvent*/,
614                                                   OCCViewer_ViewPort3d* /*theViewPort*/ )
615 {
616   if ( !isPerforming() )
617   {
618     return false;
619   }
620
621   myMouseDragPln    = gp_Pln();
622   myPerformingOp    = DragOperation_Undef;
623   myPickPos         = QPoint();
624   myDragPos         = QPoint();
625   myInteractedPlane = NULL;
626   myIsDraggable     = false;
627   myIsClickable     = false;
628   myViewer->getAISContext()->ClearSelected( Standard_True );
629   return true;
630 }
631
632 /*!
633   \brief Handle mouse double clicking events events. Stops the event propagation if
634          interaction with plane is in progress.
635   \param theEvent [in] the user event.
636   \param theViewPort [in] the viewport.
637 */
638 bool OCCViewer_ClipPlaneInteractor::mouseDoubleClick( QMouseEvent* /*theEvent*/,
639                                                       OCCViewer_ViewPort3d* /*theViewPort*/ )
640 {
641   return isPerforming();
642 }
643
644 /*!
645   \brief Handle key pressing events. Stops the event propagation if
646          interaction with plane is in progress.
647   \param theEvent [in] the user event.
648   \param theViewPort [in] the viewport.
649 */
650 bool OCCViewer_ClipPlaneInteractor::keyPress( QKeyEvent* theEvent,
651                                               OCCViewer_ViewPort3d* theViewPort )
652 {
653   // react to pressing & releasing ctrl key modifier
654   if ( !isPerforming() )
655   {
656     return false;
657   }
658
659   DragOperation aDragOp =
660     theEvent->modifiers().testFlag(Qt::ControlModifier)
661       ? DragOperation_Rotate
662       : DragOperation_Slide;
663
664   if ( aDragOp != myPerformingOp )
665   {
666     myPerformingOp = DragOperation_Undef;
667     myIsDraggable  = isDraggable( myInteractedPlane );
668     myPickPos      = theViewPort->mapFromGlobal( QCursor::pos() );
669   }
670
671   return true;
672 }
673
674 /*!
675   \brief Handle key releasing events. Stops the event propagation if
676          interaction with plane is in progress.
677   \param theEvent [in] the user event.
678   \param theViewPort [in] the viewport.
679 */
680 bool OCCViewer_ClipPlaneInteractor::keyRelease( QKeyEvent* theEvent,
681                                                 OCCViewer_ViewPort3d* theViewPort )
682 {
683   // react to pressing & releasing ctrl key modifier
684   if ( !isPerforming() )
685   {
686     return false;
687   }
688
689   DragOperation aDragOp =
690     theEvent->modifiers().testFlag(Qt::ControlModifier)
691       ? DragOperation_Rotate
692       : DragOperation_Slide;
693
694   if ( aDragOp != myPerformingOp )
695   {
696     myPerformingOp = DragOperation_Undef;
697     myIsDraggable  = isDraggable( myInteractedPlane );
698     myPickPos      = theViewPort->mapFromGlobal( QCursor::pos() );
699   }
700
701   return true;
702 }