Salome HOME
Merge modifications for HYDRO project (origin/hydro/imps_2017_salome_83 branch)
[modules/gui.git] / src / OCCViewer / OCCViewer_ClipPlaneInteractor.cxx
1 // Copyright (C) 2007-2016  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 < 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( Handle(AIS_InteractiveObject)::DownCast(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 < 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( Handle(AIS_InteractiveObject)::DownCast(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         Standard_Real aDistance2Center = myMouseDragPln.Distance( aPlaneCenter );
327         gp_Pnt aCenterOnMousePln = aMousePlnN * gp_Vec( aPickPoint, aPlaneCenter ) < 0.0
328           ? aPlaneCenter.Translated( aMousePlnN *  aDistance2Center )
329           : aPlaneCenter.Translated( aMousePlnN * -aDistance2Center );
330
331         myRotationAxis = gp_Ax1( myRotationCenter, aMousePlnN );
332       }
333       else
334       {
335         gp_Vec aMousePlnN = gp_Vec( aPlaneY );
336
337         myMouseDragPln = gp_Pln( aPickPoint, aMousePlnN );
338
339         Standard_Real aDistance2Center = myMouseDragPln.Distance( aPlaneCenter );
340         gp_Pnt aCenterOnMousePln = aMousePlnN * gp_Vec( aPickPoint, aPlaneCenter ) < 0.0
341           ? aPlaneCenter.Translated( aMousePlnN *  aDistance2Center )
342           : aPlaneCenter.Translated( aMousePlnN * -aDistance2Center );
343
344         myRotationAxis = gp_Ax1( myRotationCenter, aMousePlnN );
345       }
346
347       myPlaneReferenceCS = gp_Ax3( aPlaneCenter, aPlaneN, aPlaneX );
348
349       return true;
350     }
351   }
352
353   return false;
354 }
355
356 /*!
357   \brief Performs dragging operation on the passed interactive plane.
358   \param theDragPos [in] the position of mouse dragging.
359   \param theDragOp [in] the drag operation to start.
360   \param thePlane [in] the operated plane.
361   \param theView [in] the view.
362 */
363 void OCCViewer_ClipPlaneInteractor::performDragging( const QPoint& theDragPos,
364                                                      const DragOperation theDragOp,
365                                                      const Handle(AIS_Plane)& thePlane,
366                                                      const Handle(V3d_View)& theView )
367 {
368   Standard_Real P[3], D[3];
369   theView->ConvertWithProj( theDragPos.x(), theDragPos.y(), P[0], P[1], P[2], D[0], D[1], D[2] );
370   gp_Lin aProjection = gp_Lin( gp_Pnt( P[0], P[1], P[2] ), gp_Dir( D[0], D[1], D[2] ) );
371
372   // get point on the plane
373   Handle(Geom_Line)  aCrossLine  = new Geom_Line( aProjection );
374   Handle(Geom_Plane) aCrossPlane = new Geom_Plane( myMouseDragPln );
375
376   GeomAPI_IntCS aFindCross( aCrossLine, aCrossPlane );
377   if ( !aFindCross.IsDone() || aFindCross.NbPoints() == 0 )
378   {
379     return;
380   }
381
382   gp_Pnt aDragPoint   = aFindCross.Point( 1 );
383   gp_Pnt aPlaneCenter = myPlaneReferenceCS.Location();
384   gp_Vec aPlaneN      = myPlaneReferenceCS.Direction();
385   gp_Vec aPlaneX      = myPlaneReferenceCS.XDirection();
386   gp_Pln aPlanePln    = gp_Pln( aPlaneCenter, aPlaneN );
387
388   switch ( theDragOp )
389   {
390     // sliding the plane along its normal
391     case DragOperation_Slide:
392     {
393       Standard_Real aTranslation = 
394         gp_Vec( aPlaneCenter, aDragPoint ) * gp_Vec( aPlaneN ) > 0.0
395           ?  aPlanePln.Distance( aDragPoint )
396           : -aPlanePln.Distance( aDragPoint );
397
398       gp_Pnt aNewCenter = aPlaneCenter.Translated( aPlaneN * aTranslation );
399
400       myPlaneReferenceCS = gp_Ax3( aNewCenter, aPlaneN, aPlaneX );
401
402       adjustBounds( myPlaneReferenceCS, myMinMax );
403
404       thePlane->SetComponent( new Geom_Plane( myPlaneReferenceCS ) );
405       thePlane->SetCenter( myPlaneReferenceCS.Location() );
406       thePlane->SetToUpdate();
407       thePlane->UpdateSelection();
408
409       myViewer->getAISContext()->Update( thePlane , Standard_True );
410     }
411     break;
412
413     case DragOperation_Rotate:
414     {
415       // project the dragging point on rotated plane
416       gp_Dir aRotAxis = myRotationAxis.Direction();
417       gp_Pln aDragAtCenterPln = gp_Pln( myRotationCenter, aRotAxis );
418       gp_Pnt aDragAtCenterPnt = gp_Vec( myRotationCenter, aDragPoint ) * gp_Vec( aRotAxis ) < 0.0
419         ? aDragPoint.Translated( gp_Vec( aRotAxis ) *  aDragAtCenterPln.Distance( aDragPoint ) )
420         : aDragPoint.Translated( gp_Vec( aRotAxis ) * -aDragAtCenterPln.Distance( aDragPoint ) );
421
422       gp_Pnt aDragOnPlanePnt = gp_Vec( aPlaneCenter, aDragAtCenterPnt ) * gp_Vec( aPlaneN ) < 0.0
423         ? aDragAtCenterPnt.Translated( gp_Vec( aPlaneN ) *  aPlanePln.Distance( aDragAtCenterPnt ) )
424         : aDragAtCenterPnt.Translated( gp_Vec( aPlaneN ) * -aPlanePln.Distance( aDragAtCenterPnt ) );
425
426       gp_Vec aDragPointVector( myRotationCenter, aDragAtCenterPnt );
427       gp_Vec aProjPointVector( myRotationCenter, aDragOnPlanePnt );
428
429       // check for rotation tolerance
430       if ( aDragPointVector.Magnitude() < 0.01 || aProjPointVector.Magnitude() < 0.01 )
431       {
432         return;
433       }
434
435       Standard_Real aTurnAngle = aProjPointVector.AngleWithRef( aDragPointVector, myRotationAxis.Direction() );
436
437       gp_Trsf aRotationTrsf;
438       aRotationTrsf.SetRotation( myRotationAxis, aTurnAngle );
439       myPlaneReferenceCS.Transform( aRotationTrsf );
440
441       adjustBounds( myPlaneReferenceCS, myMinMax );
442
443       gp_Ax3 aPlaneCS( myPlaneReferenceCS.Location(), myPlaneReferenceCS.Direction() );
444
445       thePlane->SetComponent( new Geom_Plane( aPlaneCS ) );
446       thePlane->SetCenter( myPlaneReferenceCS.Location() );
447       thePlane->SetToUpdate();
448       thePlane->UpdateSelection();
449
450       myViewer->getAISContext()->Update( thePlane , Standard_True );
451     }
452     break;
453   }
454 }
455
456 /*!
457   \brief Adjusts min-max bounds of the plane.
458   \param thePlane [in/out] the plane.
459   \param theMinMax [in] the min max bounds
460 */
461 void OCCViewer_ClipPlaneInteractor::adjustBounds( gp_Ax3& thePlane, const Bnd_Box& theMinMax )
462 {
463   gp_Trsf aRelativeTransform;
464   aRelativeTransform.SetTransformation( gp_Ax3(), thePlane );
465   Bnd_Box aRelativeBounds = theMinMax.Transformed( aRelativeTransform );
466
467   Standard_Real aXmin, aXmax, aYmin, aYmax, aZmin, aZmax;
468   aRelativeBounds.Get( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
469
470   if ( aZmax < 0.0 ) // out in positive direction
471   {
472     thePlane.Translate( gp_Vec( thePlane.Direction() ) * aZmax );
473   }
474   else if ( aZmin > 0.0 ) // out in negative direction
475   {
476     thePlane.Translate( gp_Vec( thePlane.Direction() ) * aZmin );
477   }
478 }
479
480 /*!
481   \brief Handle mouse press events. Starts interaction with detected plane.
482   \param theEvent [in] the user event.
483   \param theViewPort [in] the viewport.
484 */
485 bool OCCViewer_ClipPlaneInteractor::mousePress( QMouseEvent* theEvent,
486                                                 OCCViewer_ViewPort3d* theViewPort )
487 {
488   if ( theEvent->button() != Qt::LeftButton )
489   {
490     return false;
491   }
492
493   Handle(V3d_View) aView3D = theViewPort->getView();
494
495   Handle(AIS_InteractiveContext) anAISContext = myViewer->getAISContext();
496
497   // check detection of plane
498   anAISContext->MoveTo( theEvent->x(), theEvent->y(), aView3D , Standard_True );
499
500   if ( !anAISContext->HasDetected() )
501   {
502     return false;
503   }
504
505   // check that there is only one detected entity
506   anAISContext->InitDetected();
507
508   Handle(AIS_Plane) aPlane;
509   Handle(SelectMgr_EntityOwner) aDetectedOwner = anAISContext->DetectedOwner();
510   if ( !aDetectedOwner.IsNull() )
511   {
512     aPlane = Handle(AIS_Plane)::DownCast( aDetectedOwner->Selectable() );
513   }
514
515   if ( aPlane.IsNull() )
516   {
517     aPlane = Handle(AIS_Plane)::DownCast( anAISContext->DetectedInteractive() );
518   }
519
520   myIsClickable = isClickable( aPlane );
521
522   // process mouse click on the object
523   if ( myIsClickable )
524   {
525     myViewer->getAISContext()->SetSelected( Handle(AIS_InteractiveObject)::DownCast(aPlane) , Standard_True );
526     emit planeClicked( aPlane );
527   }
528
529   myIsDraggable = isDraggable( aPlane );
530
531   if ( !myIsClickable && !myIsDraggable )
532   {
533     return false;
534   }
535
536   myPickPos = theEvent->pos();
537   myInteractedPlane = aPlane;
538
539   return true;
540 }
541
542 /*!
543   \brief Handle mouse move events. Performs dragging if interaction is in progress.
544   \param theEvent [in] the user event.
545   \param theViewPort [in] the viewport.
546 */
547 bool OCCViewer_ClipPlaneInteractor::mouseMove( QMouseEvent* theEvent,
548                                                OCCViewer_ViewPort3d* theViewPort )
549 {
550   if ( !isPerforming() )
551   {
552     return false;
553   }
554
555   // no dragging operation can be performed...
556   if ( !myIsDraggable )
557   {
558     return true;
559   }
560
561   Handle(V3d_View) aView3D = theViewPort->getView();
562
563   myDragPos = theEvent->pos();
564
565   // checking whether it is possible to start dragging operation
566   if ( myPerformingOp == DragOperation_Undef )
567   {
568     int aDx = myDragPos.x() - myPickPos.x();
569     int aDy = myDragPos.y() - myPickPos.y();
570     if ( ( aDx * aDx + aDy * aDy ) < 16 )
571     {
572       return true;
573     }
574
575     DragOperation aDragOp =
576       theEvent->modifiers().testFlag(Qt::ControlModifier)
577         ? DragOperation_Rotate
578         : DragOperation_Slide;
579
580     myIsDraggable = startDragging( myPickPos, myDragPos, aDragOp, myInteractedPlane, aView3D );
581
582     if ( !myIsDraggable )
583     {
584       return true;
585     }
586
587     myPerformingOp = aDragOp;
588   }
589
590   // performing dragging operation
591   performDragging( myDragPos, myPerformingOp, myInteractedPlane, aView3D );
592
593   emit planeDragged( myInteractedPlane );
594
595   return true;
596 }
597
598 /*!
599   \brief Handle mouse release events. Stops interaction.
600   \param theEvent [in] the user event.
601   \param theViewPort [in] the viewport.
602 */
603 bool OCCViewer_ClipPlaneInteractor::mouseRelease( QMouseEvent* theEvent,
604                                                   OCCViewer_ViewPort3d* theViewPort )
605 {
606   if ( !isPerforming() )
607   {
608     return false;
609   }
610
611   myMouseDragPln    = gp_Pln();
612   myPerformingOp    = DragOperation_Undef;
613   myPickPos         = QPoint();
614   myDragPos         = QPoint();
615   myInteractedPlane = NULL;
616   myIsDraggable     = false;
617   myIsClickable     = false;
618   myViewer->getAISContext()->ClearSelected( Standard_True );
619   return true;
620 }
621
622 /*!
623   \brief Handle mouse double clicking events events. Stops the event propagation if
624          interaction with plane is in progress.
625   \param theEvent [in] the user event.
626   \param theViewPort [in] the viewport.
627 */
628 bool OCCViewer_ClipPlaneInteractor::mouseDoubleClick( QMouseEvent* theEvent,
629                                                       OCCViewer_ViewPort3d* theViewPort )
630 {
631   return isPerforming();
632 }
633
634 /*!
635   \brief Handle key pressing events. Stops the event propagation if
636          interaction with plane is in progress.
637   \param theEvent [in] the user event.
638   \param theViewPort [in] the viewport.
639 */
640 bool OCCViewer_ClipPlaneInteractor::keyPress( QKeyEvent* theEvent,
641                                               OCCViewer_ViewPort3d* theViewPort )
642 {
643   // react to pressing & releasing ctrl key modifier
644   if ( !isPerforming() )
645   {
646     return false;
647   }
648
649   DragOperation aDragOp =
650     theEvent->modifiers().testFlag(Qt::ControlModifier)
651       ? DragOperation_Rotate
652       : DragOperation_Slide;
653
654   if ( aDragOp != myPerformingOp )
655   {
656     myPerformingOp = DragOperation_Undef;
657     myIsDraggable  = isDraggable( myInteractedPlane );
658     myPickPos      = theViewPort->mapFromGlobal( QCursor::pos() );
659   }
660
661   return true;
662 }
663
664 /*!
665   \brief Handle key releasing events. Stops the event propagation if
666          interaction with plane is in progress.
667   \param theEvent [in] the user event.
668   \param theViewPort [in] the viewport.
669 */
670 bool OCCViewer_ClipPlaneInteractor::keyRelease( QKeyEvent* theEvent,
671                                                 OCCViewer_ViewPort3d* theViewPort )
672 {
673   // react to pressing & releasing ctrl key modifier
674   if ( !isPerforming() )
675   {
676     return false;
677   }
678
679   DragOperation aDragOp =
680     theEvent->modifiers().testFlag(Qt::ControlModifier)
681       ? DragOperation_Rotate
682       : DragOperation_Slide;
683
684   if ( aDragOp != myPerformingOp )
685   {
686     myPerformingOp = DragOperation_Undef;
687     myIsDraggable  = isDraggable( myInteractedPlane );
688     myPickPos      = theViewPort->mapFromGlobal( QCursor::pos() );
689   }
690
691   return true;
692 }