Salome HOME
Update from BR_V5_DEV 13Feb2009
[modules/gui.git] / src / OCCViewer / OCCViewer_ViewWindow.cxx
1 //  Copyright (C) 2007-2008  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.
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 // File   : OCCViewer_ViewWindow.cxx
23 // Author :
24 //
25 #include "OCCViewer_ViewWindow.h"
26 #include "OCCViewer_ViewModel.h"
27 #include "OCCViewer_ViewPort3d.h"
28 #include "OCCViewer_ViewManager.h"
29 #include "OCCViewer_ViewSketcher.h"
30 #include "OCCViewer_CreateRestoreViewDlg.h"
31 #include "OCCViewer_ClippingDlg.h"
32 #include "OCCViewer_SetRotationPointDlg.h"
33 #include "OCCViewer_AxialScaleDlg.h"
34
35 #include <SUIT_Desktop.h>
36 #include <SUIT_Session.h>
37 #include <SUIT_ViewManager.h>
38 #include <SUIT_Tools.h>
39 #include <SUIT_ResourceMgr.h>
40 #include <SUIT_MessageBox.h>
41
42 #include <QtxActionToolMgr.h>
43 #include <QtxMultiAction.h>
44 #include <QtxRubberBand.h>
45
46 #include <QPainter>
47 #include <QTime>
48 #include <QImage>
49 #include <QMouseEvent>
50 #include <QApplication>
51
52 #include <V3d_Plane.hxx>
53 #include <gp_Dir.hxx>
54 #include <gp_Pln.hxx>
55 #include <TColgp_Array1OfPnt2d.hxx>
56
57 #include <AIS_ListOfInteractive.hxx>
58 #include <AIS_ListIteratorOfListOfInteractive.hxx>
59 #include <AIS_Shape.hxx>
60
61 #include <BRep_Tool.hxx>
62 #include <TopoDS.hxx>
63
64 #include <BRepBndLib.hxx>
65 #include <Graphic3d_MapIteratorOfMapOfStructure.hxx>
66 #include <Visual3d_View.hxx>
67 #include <Graphic3d_MapOfStructure.hxx>
68 #include <Graphic3d_Structure.hxx>
69 #include <Graphic3d_ExportFormat.hxx>
70
71 static QEvent* l_mbPressEvent = 0;
72
73 #ifdef WIN32
74 # include <QWindowsStyle>
75 #endif
76
77 const char* imageZoomCursor[] = {
78 "32 32 3 1",
79 ". c None",
80 "a c #000000",
81 "# c #ffffff",
82 "................................",
83 "................................",
84 ".#######........................",
85 "..aaaaaaa.......................",
86 "................................",
87 ".............#####..............",
88 "...........##.aaaa##............",
89 "..........#.aa.....a#...........",
90 ".........#.a.........#..........",
91 ".........#a..........#a.........",
92 "........#.a...........#.........",
93 "........#a............#a........",
94 "........#a............#a........",
95 "........#a............#a........",
96 "........#a............#a........",
97 ".........#...........#.a........",
98 ".........#a..........#a.........",
99 ".........##.........#.a.........",
100 "........#####.....##.a..........",
101 ".......###aaa#####.aa...........",
102 "......###aa...aaaaa.......#.....",
103 ".....###aa................#a....",
104 "....###aa.................#a....",
105 "...###aa...............#######..",
106 "....#aa.................aa#aaaa.",
107 ".....a....................#a....",
108 "..........................#a....",
109 "...........................a....",
110 "................................",
111 "................................",
112 "................................",
113 "................................"};
114
115 const char* imageRotateCursor[] = {
116 "32 32 3 1",
117 ". c None",
118 "a c #000000",
119 "# c #ffffff",
120 "................................",
121 "................................",
122 "................................",
123 "................................",
124 "........#.......................",
125 ".......#.a......................",
126 "......#######...................",
127 ".......#aaaaa#####..............",
128 "........#..##.a#aa##........##..",
129 ".........a#.aa..#..a#.....##.aa.",
130 ".........#.a.....#...#..##.aa...",
131 ".........#a.......#..###.aa.....",
132 "........#.a.......#a..#aa.......",
133 "........#a.........#..#a........",
134 "........#a.........#a.#a........",
135 "........#a.........#a.#a........",
136 "........#a.........#a.#a........",
137 ".........#.........#a#.a........",
138 "........##a........#a#a.........",
139 "......##.a#.......#.#.a.........",
140 "....##.aa..##.....##.a..........",
141 "..##.aa.....a#####.aa...........",
142 "...aa.........aaa#a.............",
143 "................#.a.............",
144 "...............#.a..............",
145 "..............#.a...............",
146 "...............a................",
147 "................................",
148 "................................",
149 "................................",
150 "................................",
151 "................................"};
152
153 const char* imageCrossCursor[] = {
154   "32 32 3 1",
155   ". c None",
156   "a c #000000",
157   "# c #ffffff",
158   "................................",
159   "................................",
160   "................................",
161   "................................",
162   "................................",
163   "................................",
164   "................................",
165   "...............#................",
166   "...............#a...............",
167   "...............#a...............",
168   "...............#a...............",
169   "...............#a...............",
170   "...............#a...............",
171   "...............#a...............",
172   "...............#a...............",
173   ".......#################........",
174   "........aaaaaaa#aaaaaaaaa.......",
175   "...............#a...............",
176   "...............#a...............",
177   "...............#a...............",
178   "...............#a...............",
179   "...............#a...............",
180   "...............#a...............",
181   "...............#a...............",
182   "................a...............",
183   "................................",
184   "................................",
185   "................................",
186   "................................",
187   "................................",
188   "................................",
189   "................................"};
190
191
192 /*!
193   \brief Constructor
194   \param theDesktop main window of application
195   \param theModel OCC 3D viewer
196 */
197 OCCViewer_ViewWindow::OCCViewer_ViewWindow( SUIT_Desktop*     theDesktop,
198                                             OCCViewer_Viewer* theModel )
199 : SUIT_ViewWindow( theDesktop )
200 {
201   myModel = theModel;
202   myRestoreFlag = 0;
203   myEnableDrawMode = false;
204   updateEnabledDrawMode();
205   myClippingDlg = 0;
206   myScalingDlg = 0;
207   mySetRotationPointDlg = 0;
208   myRectBand = 0;
209
210   mypSketcher = 0;
211   myCurSketch = -1;
212 }
213
214 /*!
215   \brief Destructor.
216 */
217 OCCViewer_ViewWindow::~OCCViewer_ViewWindow()
218 {
219   endDrawRect();
220   qDeleteAll( mySketchers );
221 }
222
223 /*!
224   \brief Internal initialization.
225 */
226 void OCCViewer_ViewWindow::initLayout()
227 {
228   myViewPort = new OCCViewer_ViewPort3d( this, myModel->getViewer3d(), V3d_ORTHOGRAPHIC );
229   myViewPort->setBackgroundColor(Qt::black);
230   myViewPort->installEventFilter(this);
231   setCentralWidget(myViewPort);
232   myOperation = NOTHING;
233
234   myCurrPointType = GRAVITY;
235   myPrevPointType = GRAVITY;
236   mySelectedPoint = gp_Pnt(0.,0.,0.);
237   myRotationPointSelection = false;
238
239   setTransformRequested ( NOTHING );
240   setTransformInProcess ( false );
241
242   createActions();
243   createToolBar();
244 }
245
246 /*!
247   \brief Detect viewer operation according the the mouse button pressed
248   and key modifiers used.
249   \param theEvent mouse event
250   \return type of the operation
251 */
252 OCCViewer_ViewWindow::OperationType
253 OCCViewer_ViewWindow::getButtonState( QMouseEvent* theEvent )
254 {
255   OperationType aOp = NOTHING;
256   if( (theEvent->modifiers() == SUIT_ViewModel::myStateMap[SUIT_ViewModel::ZOOM]) &&
257       (theEvent->button() == SUIT_ViewModel::myButtonMap[SUIT_ViewModel::ZOOM]) )
258     aOp = ZOOMVIEW;
259   else if( (theEvent->modifiers() == SUIT_ViewModel::myStateMap[SUIT_ViewModel::PAN]) &&
260            (theEvent->button() == SUIT_ViewModel::myButtonMap[SUIT_ViewModel::PAN]) )
261     aOp = PANVIEW;
262   else if( (theEvent->modifiers()  == SUIT_ViewModel::myStateMap[SUIT_ViewModel::ROTATE]) &&
263            (theEvent->button() == SUIT_ViewModel::myButtonMap[SUIT_ViewModel::ROTATE]) )
264     aOp = ROTATE;
265
266   return aOp;
267 }
268
269 /*!
270   \brief Customize event handling
271   \param watched event receiver object
272   \param e event
273   \return \c true if the event processing should be stopped
274 */
275 bool OCCViewer_ViewWindow::eventFilter( QObject* watched, QEvent* e )
276 {
277   if ( watched == myViewPort ) {
278     int aType = e->type();
279     switch(aType) {
280     case QEvent::MouseButtonPress:
281       vpMousePressEvent((QMouseEvent*) e);
282       return true;
283
284     case QEvent::MouseButtonRelease:
285       vpMouseReleaseEvent((QMouseEvent*) e);
286       return true;
287
288     case QEvent::MouseMove:
289       vpMouseMoveEvent((QMouseEvent*) e);
290       return true;
291
292     case QEvent::MouseButtonDblClick:
293       emit mouseDoubleClicked(this, (QMouseEvent*)e);
294       return true;
295
296     case QEvent::Wheel:
297       {
298         QWheelEvent* aEvent = (QWheelEvent*) e;
299         double aDelta = aEvent->delta();
300         double aScale = (aDelta < 0) ? 100./(-aDelta) : aDelta/100.;
301         myViewPort->getView()->SetZoom(aScale);
302       }
303       return true;
304
305     case QEvent::ContextMenu:
306       {
307         QContextMenuEvent * aEvent = (QContextMenuEvent*)e;
308         if ( aEvent->reason() != QContextMenuEvent::Mouse )
309           emit contextMenuRequested( aEvent );
310       }
311       return true;
312
313     default:
314       break;
315     }
316   }
317   return SUIT_ViewWindow::eventFilter(watched, e);
318 }
319
320 /*!
321   \brief Update state of enable draw mode state.
322 */
323 void OCCViewer_ViewWindow::updateEnabledDrawMode()
324 {
325   if ( myModel )
326     myEnableDrawMode = myModel->isSelectionEnabled() && myModel->isMultiSelectionEnabled();
327 }
328
329 /*!
330   \brief Handle mouse press event
331   \param theEvent mouse event
332 */
333 void OCCViewer_ViewWindow::vpMousePressEvent( QMouseEvent* theEvent )
334 {
335   myStartX = theEvent->x();
336   myStartY = theEvent->y();
337   switch ( myOperation ) {
338   case WINDOWFIT:
339     if ( theEvent->button() == Qt::LeftButton )
340       emit vpTransformationStarted ( WINDOWFIT );
341     break;
342
343   case PANGLOBAL:
344     if ( theEvent->button() == Qt::LeftButton )
345       emit vpTransformationStarted ( PANGLOBAL );
346     break;
347
348   case ZOOMVIEW:
349     if ( theEvent->button() == Qt::LeftButton )
350       emit vpTransformationStarted ( ZOOMVIEW );
351     break;
352
353   case PANVIEW:
354     if ( theEvent->button() == Qt::LeftButton )
355       emit vpTransformationStarted ( PANVIEW );
356     break;
357
358   case ROTATE:
359     if ( theEvent->button() == Qt::LeftButton ) {
360             myViewPort->startRotation(myStartX, myStartY, myCurrPointType, mySelectedPoint);
361             emit vpTransformationStarted ( ROTATE );
362           }
363     break;
364
365   default:
366   /*  Try to activate a transformation */
367     switch ( getButtonState(theEvent) ) {
368     case ZOOMVIEW:
369             activateZoom();
370       break;
371     case PANVIEW:
372             activatePanning();
373       break;
374     case ROTATE:
375             activateRotation();
376             myViewPort->startRotation(myStartX, myStartY, myCurrPointType, mySelectedPoint);
377       break;
378     default:
379       if ( myRotationPointSelection )
380       {
381         if ( theEvent->button() == Qt::LeftButton )
382         {
383           Handle(AIS_InteractiveContext) ic = myModel->getAISContext();
384           ic->Select();
385           for ( ic->InitSelected(); ic->MoreSelected(); ic->NextSelected() )
386           {
387             TopoDS_Shape aShape = ic->SelectedShape();
388             if ( !aShape.IsNull() && aShape.ShapeType() == TopAbs_VERTEX )
389             {
390               gp_Pnt aPnt = BRep_Tool::Pnt( TopoDS::Vertex( ic->SelectedShape() ) );
391               if ( mySetRotationPointDlg )
392               {
393                 myRotationPointSelection = false;
394                 mySetRotationPointDlg->setCoords(aPnt.X(), aPnt.Y(), aPnt.Z());
395               }
396             }
397             else
398             {
399               myCurrPointType = myPrevPointType;
400               break;
401             }
402           }
403           if ( ic->NbSelected() == 0 ) myCurrPointType = myPrevPointType;
404           if ( mySetRotationPointDlg ) mySetRotationPointDlg->toggleChange();
405           ic->CloseAllContexts();
406           myOperation = NOTHING;
407           myViewPort->setCursor( myCursor );
408           myCursorIsHand = false;
409           myRotationPointSelection = false;
410         }
411       }
412       else
413         emit mousePressed(this, theEvent);
414       break;
415     }
416     /* notify that we start a transformation */
417     if ( transformRequested() )
418             emit vpTransformationStarted ( myOperation );
419   }
420   if ( transformRequested() )
421     setTransformInProcess( true );
422
423   /* we may need it for sketching... */
424   if ( l_mbPressEvent )
425     delete l_mbPressEvent;
426   l_mbPressEvent = new QMouseEvent( *theEvent );
427 }
428
429
430 /*!
431   \brief Start zooming operation.
432
433   Sets the corresponding cursor for the widget.
434 */
435 void OCCViewer_ViewWindow::activateZoom()
436 {
437   if ( !transformRequested() && !myCursorIsHand )
438     myCursor = cursor();                /* save old cursor */
439
440   if ( myOperation != ZOOMVIEW ) {
441     QPixmap zoomPixmap (imageZoomCursor);
442     QCursor zoomCursor (zoomPixmap);
443     setTransformRequested ( ZOOMVIEW );
444     myViewPort->setCursor( zoomCursor );
445   }
446 }
447
448
449 /*!
450   \brief Start panning operation.
451
452   Sets the corresponding cursor for the widget.
453 */
454 void OCCViewer_ViewWindow::activatePanning()
455 {
456   if ( !transformRequested() && !myCursorIsHand )
457     myCursor = cursor();                // save old cursor
458
459   if ( myOperation != PANVIEW ) {
460     QCursor panCursor (Qt::SizeAllCursor);
461     setTransformRequested ( PANVIEW );
462     myViewPort->setCursor( panCursor );
463   }
464 }
465
466 /*!
467   \brief Start rotation operation
468
469   Sets the corresponding cursor for the widget.
470 */
471 void OCCViewer_ViewWindow::activateRotation()
472 {
473   if ( !transformRequested() && !myCursorIsHand )
474     myCursor = cursor();                // save old cursor
475
476   if ( myOperation != ROTATE ) {
477     QPixmap rotatePixmap (imageRotateCursor);
478     QCursor rotCursor (rotatePixmap);
479     setTransformRequested ( ROTATE );
480     myViewPort->setCursor( rotCursor );
481   }
482 }
483
484 /*!
485   \brief Compute the gravity center.
486   \param theX used to return X coordinate of the gravity center
487   \param theY used to return Y coordinate of the gravity center
488   \param theZ used to return Z coordinate of the gravity center
489   \return \c true if the gravity center is computed
490 */
491 bool OCCViewer_ViewWindow::computeGravityCenter( double& theX, double& theY, double& theZ )
492 {
493   Handle(Visual3d_View) aView = myViewPort->getView()->View();
494
495   Standard_Real Xmin,Ymin,Zmin,Xmax,Ymax,Zmax,U,V,W ;
496   Standard_Real Umin,Vmin,Umax,Vmax ;
497   Standard_Integer Nstruct,Npoint ;
498   Graphic3d_MapOfStructure MySetOfStructures;
499
500   aView->DisplayedStructures (MySetOfStructures);
501   Nstruct = MySetOfStructures.Extent() ;
502
503   Graphic3d_MapIteratorOfMapOfStructure MyIterator(MySetOfStructures) ;
504   aView->ViewMapping().WindowLimit(Umin,Vmin,Umax,Vmax) ;
505   Npoint = 0 ; theX = theY = theZ = 0. ;
506   for( ; MyIterator.More(); MyIterator.Next()) {
507     if (!(MyIterator.Key())->IsEmpty()) {
508       (MyIterator.Key())->MinMaxValues(Xmin,Ymin,Zmin,
509                                          Xmax,Ymax,Zmax) ;
510
511       Standard_Real LIM = ShortRealLast() -1.;
512       if (!    (fabs(Xmin) > LIM || fabs(Ymin) > LIM || fabs(Zmin) > LIM
513                 ||  fabs(Xmax) > LIM || fabs(Ymax) > LIM || fabs(Zmax) > LIM )) {
514
515         aView->Projects(Xmin,Ymin,Zmin,U,V,W) ;
516         if( U >= Umin && U <= Umax && V >= Vmin && V <= Vmax ) {
517           Npoint++ ; theX += Xmin ; theY += Ymin ; theZ += Zmin ;
518         }
519         aView->Projects(Xmax,Ymin,Zmin,U,V,W) ;
520         if( U >= Umin && U <= Umax && V >= Vmin && V <= Vmax ) {
521           Npoint++ ; theX += Xmax ; theY += Ymin ; theZ += Zmin ;
522         }
523         aView->Projects(Xmin,Ymax,Zmin,U,V,W) ;
524         if( U >= Umin && U <= Umax && V >= Vmin && V <= Vmax ) {
525           Npoint++ ; theX += Xmin ; theY += Ymax ; theZ += Zmin ;
526         }
527         aView->Projects(Xmax,Ymax,Zmin,U,V,W) ;
528         if( U >= Umin && U <= Umax && V >= Vmin && V <= Vmax ) {
529           Npoint++ ; theX += Xmax ; theY += Ymax ; theZ += Zmin ;
530         }
531         aView->Projects(Xmin,Ymin,Zmax,U,V,W) ;
532         if( U >= Umin && U <= Umax && V >= Vmin && V <= Vmax ) {
533           Npoint++ ; theX += Xmin ; theY += Ymin ; theZ += Zmax ;
534         }
535         aView->Projects(Xmax,Ymin,Zmax,U,V,W) ;
536         if( U >= Umin && U <= Umax && V >= Vmin && V <= Vmax ) {
537           Npoint++ ; theX += Xmax ; theY += Ymin ; theZ += Zmax ;
538         }
539         aView->Projects(Xmin,Ymax,Zmax,U,V,W) ;
540         if( U >= Umin && U <= Umax && V >= Vmin && V <= Vmax ) {
541           Npoint++ ; theX += Xmin ; theY += Ymax ; theZ += Zmax ;
542         }
543         aView->Projects(Xmax,Ymax,Zmax,U,V,W) ;
544         if( U >= Umin && U <= Umax && V >= Vmin && V <= Vmax ) {
545           Npoint++ ; theX += Xmax ; theY += Ymax ; theZ += Zmax ;
546         }
547       }
548     }
549   }
550   if( Npoint > 0 ) {
551     theX /= Npoint ; theY /= Npoint ; theZ /= Npoint ;
552   }
553   return true;
554 }
555
556 /*!
557   \brief Set the gravity center as a rotation point.
558 */
559 void OCCViewer_ViewWindow::activateSetRotationGravity()
560 {
561   if ( myRotationPointSelection )
562   {
563     Handle(AIS_InteractiveContext) ic = myModel->getAISContext();
564     ic->CloseAllContexts();
565     myOperation = NOTHING;
566     myViewPort->setCursor( myCursor );
567     myCursorIsHand = false;
568     myRotationPointSelection = false;
569   }
570
571   myPrevPointType = myCurrPointType;
572   myCurrPointType = GRAVITY;
573
574   Standard_Real Xcenter, Ycenter, Zcenter;
575   if ( computeGravityCenter( Xcenter, Ycenter, Zcenter ) )
576     mySetRotationPointDlg->setCoords( Xcenter, Ycenter, Zcenter );
577 }
578
579 /*!
580   \brief Update gravity center in the "Set Rotation Point" dialog box.
581   \sa OCCViewer_SetRotationPointDlg class
582 */
583 void OCCViewer_ViewWindow::updateGravityCoords()
584 {
585   if ( mySetRotationPointDlg && mySetRotationPointDlg->isVisible() && myCurrPointType == GRAVITY )
586   {
587     Standard_Real Xcenter, Ycenter, Zcenter;
588     if ( computeGravityCenter( Xcenter, Ycenter, Zcenter ) )
589       mySetRotationPointDlg->setCoords( Xcenter, Ycenter, Zcenter );
590   }
591 }
592
593 /*!
594   \brief Set the point selected by the user as a rotation point.
595   \param theX X coordinate of the rotation point
596   \param theY Y coordinate of the rotation point
597   \param theZ Z coordinate of the rotation point
598 */
599 void OCCViewer_ViewWindow::activateSetRotationSelected( double theX, double theY, double theZ )
600 {
601   if ( myRotationPointSelection )
602   {
603     Handle(AIS_InteractiveContext) ic = myModel->getAISContext();
604     ic->CloseAllContexts();
605     myOperation = NOTHING;
606     myViewPort->setCursor( myCursor );
607     myCursorIsHand = false;
608     myRotationPointSelection = false;
609   }
610
611   myPrevPointType = myCurrPointType;
612   myCurrPointType = SELECTED;
613   mySelectedPoint.SetCoord(theX,theY,theZ);
614 }
615
616 /*!
617   \brief Start the point selection process.
618 */
619 void OCCViewer_ViewWindow::activateStartPointSelection()
620 {
621   myPrevPointType = myCurrPointType;
622   myCurrPointType = SELECTED;
623
624   // activate selection ------>
625   Handle(AIS_InteractiveContext) ic = myModel->getAISContext();
626
627   ic->OpenLocalContext();
628
629   AIS_ListOfInteractive aList;
630   ic->DisplayedObjects( aList );
631   for ( AIS_ListIteratorOfListOfInteractive it( aList ); it.More(); it.Next() )
632   {
633     Handle(AIS_InteractiveObject) anObj = it.Value();
634     if ( !anObj.IsNull() && anObj->HasPresentation() &&
635          anObj->IsKind( STANDARD_TYPE(AIS_Shape) ) )
636     {
637       ic->Load(anObj,-1);
638       ic->Activate(anObj,AIS_Shape::SelectionMode(TopAbs_VERTEX));
639      }
640   }
641   // activate selection <------
642
643   if ( !myCursorIsHand )
644   {
645     QCursor handCursor (Qt::PointingHandCursor);
646     myCursorIsHand = true;
647     myCursor = cursor();
648     myViewPort->setCursor( handCursor );
649   }
650   myRotationPointSelection = true;
651 }
652
653 /*!
654   \brief Start global panning operation
655
656   Sets the corresponding cursor for the widget.
657 */
658 void OCCViewer_ViewWindow::activateGlobalPanning()
659 {
660   Handle(V3d_View) aView3d = myViewPort->getView();
661   if ( !aView3d.IsNull() ) {
662     QPixmap globalPanPixmap (imageCrossCursor);
663     QCursor glPanCursor (globalPanPixmap);
664     myCurScale = aView3d->Scale();
665     aView3d->FitAll(0.01, false);
666     myCursor = cursor();                // save old cursor
667     myViewPort->fitAll(); // fits view before selecting a new scene center
668     setTransformRequested( PANGLOBAL );
669     myViewPort->setCursor( glPanCursor );
670   }
671 }
672
673 /*!
674   \brief Starts fit operation.
675
676   Sets the corresponding cursor for the widget.
677 */
678 void OCCViewer_ViewWindow::activateWindowFit()
679 {
680   if ( !transformRequested() && !myCursorIsHand )
681     myCursor = cursor();                /* save old cursor */
682
683   if ( myOperation != WINDOWFIT ) {
684     QCursor handCursor (Qt::PointingHandCursor);
685     setTransformRequested ( WINDOWFIT );
686     myViewPort->setCursor ( handCursor );
687     myCursorIsHand = true;
688   }
689 }
690
691 /*!
692   \brief Start delayed viewer operation.
693 */
694 void OCCViewer_ViewWindow::setTransformRequested( OperationType op )
695 {
696   myOperation = op;
697   myViewPort->setMouseTracking( myOperation == NOTHING );
698 }
699
700
701 /*!
702   \brief Handle mouse move event.
703   \param theEvent mouse event
704 */
705 void OCCViewer_ViewWindow::vpMouseMoveEvent( QMouseEvent* theEvent )
706 {
707   myCurrX = theEvent->x();
708   myCurrY = theEvent->y();
709   switch (myOperation) {
710   case ROTATE:
711     myViewPort->rotate(myCurrX, myCurrY, myCurrPointType, mySelectedPoint);
712     break;
713
714   case ZOOMVIEW:
715     myViewPort->zoom(myStartX, myStartY, myCurrX, myCurrY);
716     myStartX = myCurrX;
717     myStartY = myCurrY;
718     break;
719
720   case PANVIEW:
721     myViewPort->pan(myCurrX - myStartX, myStartY - myCurrY);
722     myStartX = myCurrX;
723     myStartY = myCurrY;
724     break;
725
726 /*    case WINDOWFIT:
727     myDrawRect = true;
728     repaint();
729     break;
730 */
731   case PANGLOBAL:
732     break;
733
734   default:
735     if ( myRotationPointSelection )
736       emit mouseMoving( this, theEvent );
737     else
738     {
739       int aState = theEvent->modifiers();
740       int aButton = theEvent->buttons();
741       if ( aButton == Qt::LeftButton && ( aState == Qt::NoModifier || Qt::ShiftModifier ) ) {
742         myDrawRect = myEnableDrawMode;
743         if ( myDrawRect ) {
744           drawRect();
745           if ( !myCursorIsHand )        {   // we are going to sketch a rectangle
746             QCursor handCursor (Qt::PointingHandCursor);
747             myCursorIsHand = true;
748             myCursor = cursor();
749             myViewPort->setCursor( handCursor );
750           }
751         }
752       }
753       else if ( aButton == Qt::RightButton && ( aState == Qt::NoModifier || Qt::ShiftModifier ) ) {
754         OCCViewer_ViewSketcher* sketcher = 0;
755         QList<OCCViewer_ViewSketcher*>::Iterator it;
756         for ( it = mySketchers.begin(); it != mySketchers.end() && !sketcher; ++it )
757         {
758           OCCViewer_ViewSketcher* sk = (*it);
759           if( sk->isDefault() && sk->sketchButton() == aButton )
760             sketcher = sk;
761         }
762         if ( sketcher && myCurSketch == -1 )
763         {
764           activateSketching( sketcher->type() );
765           if ( mypSketcher )
766           {
767             myCurSketch = mypSketcher->sketchButton();
768
769             if ( l_mbPressEvent )
770             {
771               QApplication::sendEvent( getViewPort(), l_mbPressEvent );
772               delete l_mbPressEvent;
773               l_mbPressEvent = 0;
774             }
775             QApplication::sendEvent( getViewPort(), theEvent );
776           }
777         }
778       }
779       else
780         emit mouseMoving( this, theEvent );
781     }
782   }
783 }
784
785 /*!
786   \brief Handle mouse release event.
787   \param theEvent mouse event
788 */
789 void OCCViewer_ViewWindow::vpMouseReleaseEvent(QMouseEvent* theEvent)
790 {
791   switch ( myOperation ) {
792   case NOTHING:
793     {
794       int prevState = myCurSketch;
795       if(theEvent->button() == Qt::RightButton)
796       {
797         QList<OCCViewer_ViewSketcher*>::Iterator it;
798         for ( it = mySketchers.begin(); it != mySketchers.end() && myCurSketch != -1; ++it )
799         {
800           OCCViewer_ViewSketcher* sk = (*it);
801           if( ( sk->sketchButton() & theEvent->button() ) && sk->sketchButton() == myCurSketch )
802             myCurSketch = -1;
803         }
804       }
805
806       emit mouseReleased(this, theEvent);
807       if(theEvent->button() == Qt::RightButton && prevState == -1)
808       {
809         QContextMenuEvent aEvent( QContextMenuEvent::Mouse,
810                                   theEvent->pos(), theEvent->globalPos() );
811         emit contextMenuRequested( &aEvent );
812       }
813     }
814     break;
815   case ROTATE:
816     myViewPort->endRotation();
817     resetState();
818     break;
819
820   case PANVIEW:
821   case ZOOMVIEW:
822     resetState();
823     break;
824
825   case PANGLOBAL:
826     if ( theEvent->button() == Qt::LeftButton ) {
827       myViewPort->setCenter( theEvent->x(), theEvent->y() );
828       myViewPort->getView()->SetScale(myCurScale);
829       resetState();
830     }
831     break;
832
833   case WINDOWFIT:
834     if ( theEvent->button() == Qt::LeftButton ) {
835       myCurrX = theEvent->x();
836       myCurrY = theEvent->y();
837       drawRect();
838       QRect rect = SUIT_Tools::makeRect(myStartX, myStartY, myCurrX, myCurrY);
839       if ( !rect.isEmpty() ) myViewPort->fitRect(rect);
840       endDrawRect();
841       resetState();
842     }
843     break;
844   }
845
846   // NOTE: viewer 3D detects a rectangle of selection using this event
847   // so we must emit it BEFORE resetting the selection rectangle
848
849   if ( theEvent->button() == Qt::LeftButton && myDrawRect ) {
850     drawRect();
851     endDrawRect();
852     resetState();
853     myViewPort->update();
854   }
855
856   if ( l_mbPressEvent )
857   {
858     delete l_mbPressEvent;
859     l_mbPressEvent = 0;
860   }
861 }
862
863 /*!
864   \brief Reset the viewport to its initial state
865   ( no transformations in process etc. )
866 */
867 void OCCViewer_ViewWindow::resetState()
868 {
869   myDrawRect = false;
870
871   if ( myRotationPointSelection )
872   {
873     QCursor handCursor (Qt::PointingHandCursor);
874     myViewPort->setCursor( handCursor );
875   }
876   else
877   {
878     if ( transformRequested() || myCursorIsHand )
879       myViewPort->setCursor( myCursor );
880     myCursorIsHand = false;
881   }
882
883   if ( transformRequested() )
884     emit vpTransformationFinished (myOperation);
885
886   setTransformInProcess( false );
887   setTransformRequested( NOTHING );
888 }
889
890
891 /*!
892   \brief Draw rubber band rectangle.
893 */
894 void OCCViewer_ViewWindow::drawRect()
895 {
896   if ( !myRectBand ) {
897     myRectBand = new QtxRectRubberBand( myViewPort );
898     //QPalette palette;
899     //palette.setColor(myRectBand->foregroundRole(), Qt::white);
900     //myRectBand->setPalette(palette);
901   }
902   //myRectBand->hide();
903   
904   myRectBand->setUpdatesEnabled ( false );
905   QRect aRect = SUIT_Tools::makeRect(myStartX, myStartY, myCurrX, myCurrY);
906   myRectBand->initGeometry( aRect );
907
908   if ( !myRectBand->isVisible() )
909     myRectBand->show();
910
911   myRectBand->setUpdatesEnabled ( true );
912   //myRectBand->repaint();
913
914   //myRectBand->setVisible( aRect.isValid() );
915   //if ( myRectBand->isVisible() )
916   //  myRectBand->repaint();
917   //else
918   //  myRectBand->show();
919   //myRectBand->repaint();
920 }
921
922 /*!
923   \brief Clear rubber band rectangle on the end on the dragging operation.
924 */
925 void OCCViewer_ViewWindow::endDrawRect()
926 {
927   //delete myRectBand;
928   //myRectBand = 0;
929   if ( myRectBand )
930     {
931       myRectBand->clearGeometry();
932       myRectBand->hide();
933     }
934 }
935
936 /*!
937   \brief Create actions.
938 */
939 void OCCViewer_ViewWindow::createActions()
940 {
941   if( !toolMgr()->isEmpty() )
942     return;
943   
944   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
945
946   QtxAction* aAction;
947
948   // Dump view
949   aAction = new QtxAction(tr("MNU_DUMP_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_DUMP" ) ),
950                            tr( "MNU_DUMP_VIEW" ), 0, this);
951   aAction->setStatusTip(tr("DSC_DUMP_VIEW"));
952   connect(aAction, SIGNAL(triggered()), this, SLOT(onDumpView()));
953   toolMgr()->registerAction( aAction, DumpId );
954
955   // FitAll
956   aAction = new QtxAction(tr("MNU_FITALL"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_FITALL" ) ),
957                            tr( "MNU_FITALL" ), 0, this);
958   aAction->setStatusTip(tr("DSC_FITALL"));
959   connect(aAction, SIGNAL(triggered()), this, SLOT(onFitAll()));
960   toolMgr()->registerAction( aAction, FitAllId );
961
962   // FitRect
963   aAction = new QtxAction(tr("MNU_FITRECT"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_FITAREA" ) ),
964                            tr( "MNU_FITRECT" ), 0, this);
965   aAction->setStatusTip(tr("DSC_FITRECT"));
966   connect(aAction, SIGNAL(triggered()), this, SLOT(activateWindowFit()));
967   toolMgr()->registerAction( aAction, FitRectId );
968   
969   // Zoom
970   aAction = new QtxAction(tr("MNU_ZOOM_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_ZOOM" ) ),
971                            tr( "MNU_ZOOM_VIEW" ), 0, this);
972   aAction->setStatusTip(tr("DSC_ZOOM_VIEW"));
973   connect(aAction, SIGNAL(triggered()), this, SLOT(activateZoom()));
974   toolMgr()->registerAction( aAction, ZoomId );
975
976   // Panning
977   aAction = new QtxAction(tr("MNU_PAN_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_PAN" ) ),
978                            tr( "MNU_PAN_VIEW" ), 0, this);
979   aAction->setStatusTip(tr("DSC_PAN_VIEW"));
980   connect(aAction, SIGNAL(triggered()), this, SLOT(activatePanning()));
981   toolMgr()->registerAction( aAction, PanId );
982
983   // Global Panning
984   aAction = new QtxAction(tr("MNU_GLOBALPAN_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_GLOBALPAN" ) ),
985                            tr( "MNU_GLOBALPAN_VIEW" ), 0, this);
986   aAction->setStatusTip(tr("DSC_GLOBALPAN_VIEW"));
987   connect(aAction, SIGNAL(triggered()), this, SLOT(activateGlobalPanning()));
988   toolMgr()->registerAction( aAction, GlobalPanId );
989
990   // Rotation Point
991   mySetRotationPointAction = new QtxAction(tr("MNU_CHANGINGROTATIONPOINT_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_ROTATION_POINT" ) ),
992                            tr( "MNU_CHANGINGROTATIONPOINT_VIEW" ), 0, this);
993   mySetRotationPointAction->setStatusTip(tr("DSC_CHANGINGROTATIONPOINT_VIEW"));
994   mySetRotationPointAction->setCheckable( true );
995   connect(mySetRotationPointAction, SIGNAL(toggled( bool )), this, SLOT(onSetRotationPoint( bool )));
996   toolMgr()->registerAction( mySetRotationPointAction, ChangeRotationPointId );
997
998   // Rotation
999   aAction = new QtxAction(tr("MNU_ROTATE_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_ROTATE" ) ),
1000                            tr( "MNU_ROTATE_VIEW" ), 0, this);
1001   aAction->setStatusTip(tr("DSC_ROTATE_VIEW"));
1002   connect(aAction, SIGNAL(triggered()), this, SLOT(activateRotation()));
1003   toolMgr()->registerAction( aAction, RotationId );
1004
1005   // Projections
1006   aAction = new QtxAction(tr("MNU_FRONT_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_FRONT" ) ),
1007                            tr( "MNU_FRONT_VIEW" ), 0, this);
1008   aAction->setStatusTip(tr("DSC_FRONT_VIEW"));
1009   connect(aAction, SIGNAL(triggered()), this, SLOT(onFrontView()));
1010   toolMgr()->registerAction( aAction, FrontId );
1011
1012   aAction = new QtxAction(tr("MNU_BACK_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_BACK" ) ),
1013                            tr( "MNU_BACK_VIEW" ), 0, this);
1014   aAction->setStatusTip(tr("DSC_BACK_VIEW"));
1015   connect(aAction, SIGNAL(triggered()), this, SLOT(onBackView()));
1016   toolMgr()->registerAction( aAction, BackId );
1017
1018   aAction = new QtxAction(tr("MNU_TOP_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_TOP" ) ),
1019                            tr( "MNU_TOP_VIEW" ), 0, this);
1020   aAction->setStatusTip(tr("DSC_TOP_VIEW"));
1021   connect(aAction, SIGNAL(triggered()), this, SLOT(onTopView()));
1022   toolMgr()->registerAction( aAction, TopId );
1023
1024   aAction = new QtxAction(tr("MNU_BOTTOM_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_BOTTOM" ) ),
1025                            tr( "MNU_BOTTOM_VIEW" ), 0, this);
1026   aAction->setStatusTip(tr("DSC_BOTTOM_VIEW"));
1027   connect(aAction, SIGNAL(triggered()), this, SLOT(onBottomView()));
1028   toolMgr()->registerAction( aAction, BottomId );
1029
1030   aAction = new QtxAction(tr("MNU_LEFT_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_LEFT" ) ),
1031                            tr( "MNU_LEFT_VIEW" ), 0, this);
1032   aAction->setStatusTip(tr("DSC_LEFT_VIEW"));
1033   connect(aAction, SIGNAL(triggered()), this, SLOT(onLeftView()));
1034   toolMgr()->registerAction( aAction, LeftId );
1035
1036   aAction = new QtxAction(tr("MNU_RIGHT_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_RIGHT" ) ),
1037                            tr( "MNU_RIGHT_VIEW" ), 0, this);
1038   aAction->setStatusTip(tr("DSC_RIGHT_VIEW"));
1039   connect(aAction, SIGNAL(triggered()), this, SLOT(onRightView()));
1040   toolMgr()->registerAction( aAction, RightId );
1041
1042   // Reset
1043   aAction = new QtxAction(tr("MNU_RESET_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_RESET" ) ),
1044                            tr( "MNU_RESET_VIEW" ), 0, this);
1045   aAction->setStatusTip(tr("DSC_RESET_VIEW"));
1046   connect(aAction, SIGNAL(triggered()), this, SLOT(onResetView()));
1047   toolMgr()->registerAction( aAction, ResetId );
1048
1049   // Reset
1050   aAction = new QtxAction(tr("MNU_CLONE_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_CLONE_VIEW" ) ),
1051                            tr( "MNU_CLONE_VIEW" ), 0, this);
1052   aAction->setStatusTip(tr("DSC_CLONE_VIEW"));
1053   connect(aAction, SIGNAL(triggered()), this, SLOT(onCloneView()));
1054   toolMgr()->registerAction( aAction, CloneId );
1055
1056   myClippingAction = new QtxAction(tr("MNU_CLIPPING"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_CLIPPING" ) ),
1057                            tr( "MNU_CLIPPING" ), 0, this);
1058   myClippingAction->setStatusTip(tr("DSC_CLIPPING"));
1059   myClippingAction->setCheckable( true );
1060   connect(myClippingAction, SIGNAL(toggled( bool )), this, SLOT(onClipping( bool )));
1061   toolMgr()->registerAction( myClippingAction, ClippingId );
1062
1063   aAction = new QtxAction(tr("MNU_SHOOT_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_SHOOT_VIEW" ) ),
1064                            tr( "MNU_SHOOT_VIEW" ), 0, this);
1065   aAction->setStatusTip(tr("DSC_SHOOT_VIEW"));
1066   connect(aAction, SIGNAL(triggered()), this, SLOT(onMemorizeView()));
1067   toolMgr()->registerAction( aAction, MemId );
1068
1069   aAction = new QtxAction(tr("MNU_PRESETS_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_PRESETS_VIEW" ) ),
1070                            tr( "MNU_PRESETS_VIEW" ), 0, this);
1071   aAction->setStatusTip(tr("DSC_PRESETS_VIEW"));
1072   connect(aAction, SIGNAL(triggered()), this, SLOT(onRestoreView()));
1073   toolMgr()->registerAction( aAction, RestoreId );
1074
1075   if (myModel->trihedronActivated()) {
1076     aAction = new QtxAction(tr("MNU_SHOW_TRIHEDRE"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_VIEW_TRIHEDRON" ) ),
1077                              tr( "MNU_SHOW_TRIHEDRE" ), 0, this);
1078     aAction->setStatusTip(tr("DSC_SHOW_TRIHEDRE"));
1079     connect(aAction, SIGNAL(triggered()), this, SLOT(onTrihedronShow()));
1080     toolMgr()->registerAction( aAction, TrihedronShowId );
1081   }
1082
1083   // Scale
1084   aAction = new QtxAction(tr("MNU_SCALING"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_SCALING" ) ),
1085                            tr( "MNU_SCALING" ), 0, this);
1086   aAction->setStatusTip(tr("DSC_SCALING"));
1087   connect(aAction, SIGNAL(triggered()), this, SLOT(onAxialScale()));
1088   toolMgr()->registerAction( aAction, AxialScaleId );
1089 }
1090
1091 /*!
1092   \brief Create toolbar.
1093 */
1094 void OCCViewer_ViewWindow::createToolBar()
1095 {
1096   int tid = toolMgr()->createToolBar( tr( "LBL_TOOLBAR_LABEL" ) );
1097
1098   toolMgr()->append( DumpId, tid );
1099   if( myModel->trihedronActivated() ) 
1100     toolMgr()->append( TrihedronShowId, tid );
1101
1102   QtxMultiAction* aScaleAction = new QtxMultiAction( this );
1103   aScaleAction->insertAction( toolMgr()->action( FitAllId ) );
1104   aScaleAction->insertAction( toolMgr()->action( FitRectId ) );
1105   aScaleAction->insertAction( toolMgr()->action( ZoomId ) );
1106   toolMgr()->append( aScaleAction, tid );
1107
1108   QtxMultiAction* aPanningAction = new QtxMultiAction( this );
1109   aPanningAction->insertAction( toolMgr()->action( PanId ) );
1110   aPanningAction->insertAction( toolMgr()->action( GlobalPanId ) );
1111   toolMgr()->append( aPanningAction, tid );
1112
1113   toolMgr()->append( ChangeRotationPointId, tid );
1114   toolMgr()->append( RotationId, tid );
1115
1116   QtxMultiAction* aViewsAction = new QtxMultiAction( this );
1117   aViewsAction->insertAction( toolMgr()->action( FrontId ) );
1118   aViewsAction->insertAction( toolMgr()->action( BackId ) );
1119   aViewsAction->insertAction( toolMgr()->action( TopId ) );
1120   aViewsAction->insertAction( toolMgr()->action( BottomId ) );
1121   aViewsAction->insertAction( toolMgr()->action( LeftId ) );
1122   aViewsAction->insertAction( toolMgr()->action( RightId ) );
1123   toolMgr()->append( aViewsAction, tid );
1124
1125   toolMgr()->append( ResetId, tid );
1126
1127   QtxMultiAction* aMemAction = new QtxMultiAction( this );
1128   aMemAction->insertAction( toolMgr()->action( MemId ) );
1129   aMemAction->insertAction( toolMgr()->action( RestoreId ) );
1130   toolMgr()->append( aMemAction, tid );
1131
1132   toolMgr()->append( toolMgr()->separator(), tid );
1133   toolMgr()->append( CloneId, tid );
1134   
1135   toolMgr()->append( toolMgr()->separator(), tid );
1136   toolMgr()->append( ClippingId, tid );
1137   toolMgr()->append( AxialScaleId, tid );
1138 }
1139
1140 /*!
1141   \brief Perform 'fit all' operation.
1142 */
1143 void OCCViewer_ViewWindow::onViewFitAll()
1144 {
1145   myViewPort->fitAll();
1146 }
1147
1148 /*!
1149   \brief Perform "front view" transformation.
1150 */
1151 void OCCViewer_ViewWindow::onFrontView()
1152 {
1153   emit vpTransformationStarted ( FRONTVIEW );
1154   Handle(V3d_View) aView3d = myViewPort->getView();
1155   if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Xpos);
1156   onViewFitAll();
1157 }
1158
1159 /*!
1160   \brief Perform "back view" transformation.
1161 */
1162 void OCCViewer_ViewWindow::onBackView()
1163 {
1164   emit vpTransformationStarted ( BACKVIEW );
1165   Handle(V3d_View) aView3d = myViewPort->getView();
1166   if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Xneg);
1167   onViewFitAll();
1168 }
1169
1170 /*!
1171   \brief Perform "top view" transformation.
1172 */
1173 void OCCViewer_ViewWindow::onTopView()
1174 {
1175   emit vpTransformationStarted ( TOPVIEW );
1176   Handle(V3d_View) aView3d = myViewPort->getView();
1177   if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Zpos);
1178   onViewFitAll();
1179 }
1180
1181 /*!
1182   \brief Perform "bottom view" transformation.
1183 */
1184 void OCCViewer_ViewWindow::onBottomView()
1185 {
1186   emit vpTransformationStarted ( BOTTOMVIEW );
1187   Handle(V3d_View) aView3d = myViewPort->getView();
1188   if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Zneg);
1189   onViewFitAll();
1190 }
1191
1192 /*!
1193   \brief Perform "left view" transformation.
1194 */
1195 void OCCViewer_ViewWindow::onLeftView()
1196 {
1197   emit vpTransformationStarted ( LEFTVIEW );
1198   Handle(V3d_View) aView3d = myViewPort->getView();
1199   if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Yneg);
1200   onViewFitAll();
1201 }
1202
1203 /*!
1204   \brief Perform "right view" transformation.
1205 */
1206 void OCCViewer_ViewWindow::onRightView()
1207 {
1208   emit vpTransformationStarted ( RIGHTVIEW );
1209   Handle(V3d_View) aView3d = myViewPort->getView();
1210   if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Ypos);
1211   onViewFitAll();
1212 }
1213
1214 /*!
1215   \brief Perform "reset view" transformation.
1216
1217   Sets default orientation of the viewport camera.
1218 */
1219 void OCCViewer_ViewWindow::onResetView()
1220 {
1221   emit vpTransformationStarted( RESETVIEW );
1222   bool upd = myViewPort->getView()->SetImmediateUpdate( false );
1223   myViewPort->getView()->Reset( false );
1224   myViewPort->fitAll( false, true, false );
1225   myViewPort->getView()->SetImmediateUpdate( upd );
1226   myViewPort->getView()->Update();
1227 }
1228
1229 /*!
1230   \brief Perform "fit all" transformation.
1231 */
1232 void OCCViewer_ViewWindow::onFitAll()
1233 {
1234   emit vpTransformationStarted( FITALLVIEW );
1235   myViewPort->fitAll();
1236 }
1237
1238 /*!
1239   \brief Called if 'change rotation point' operation is activated.
1240   \param on action state
1241 */
1242 void OCCViewer_ViewWindow::onSetRotationPoint( bool on )
1243 {
1244   if ( on )
1245     {
1246       if ( !mySetRotationPointDlg )
1247         {
1248           mySetRotationPointDlg = new OCCViewer_SetRotationPointDlg( this, myDesktop );
1249           mySetRotationPointDlg->SetAction( mySetRotationPointAction );
1250         }
1251
1252       if ( !mySetRotationPointDlg->isVisible() )
1253       {
1254         if ( mySetRotationPointDlg->IsFirstShown() )
1255         {
1256           Standard_Real Xcenter, Ycenter, Zcenter;
1257           if ( computeGravityCenter( Xcenter, Ycenter, Zcenter ) )
1258             mySetRotationPointDlg->setCoords( Xcenter, Ycenter, Zcenter );
1259         }
1260         mySetRotationPointDlg->show();
1261       }
1262     }
1263   else
1264     {
1265       if ( mySetRotationPointDlg->isVisible() )
1266         mySetRotationPointDlg->hide();
1267     }
1268 }
1269
1270 /*!
1271    \brief Create one more window with same content.
1272 */
1273 void OCCViewer_ViewWindow::onCloneView()
1274 {
1275   SUIT_ViewWindow* vw = myManager->createViewWindow();
1276   //vw->show();
1277   emit viewCloned( vw );
1278 }
1279
1280 /*!
1281   \brief called if clipping operation is activated.
1282
1283   Enables/disables clipping plane displaying.
1284
1285   \parma on action state
1286 */
1287 void OCCViewer_ViewWindow::onClipping( bool on )
1288 {
1289   /*
1290   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
1291   if ( on )
1292     myActionsMap[ ClippingId ]->setIcon(aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_CLIPPING_PRESSED" )));
1293   else
1294     myActionsMap[ ClippingId ]->setIcon(aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_CLIPPING" )));
1295   */
1296   if ( on )
1297   {
1298     if ( !myClippingDlg )
1299     {
1300       myClippingDlg = new OCCViewer_ClippingDlg( this, myDesktop );
1301       myClippingDlg->SetAction( myClippingAction );
1302     }
1303     
1304     if ( !myClippingDlg->isVisible() )
1305       myClippingDlg->show();
1306   }
1307   else
1308   {
1309     if ( myClippingDlg->isVisible() )
1310       myClippingDlg->hide();
1311     setCuttingPlane(false);
1312   }
1313 }
1314
1315 /*!
1316   Creates one more window with same content
1317 */
1318 void OCCViewer_ViewWindow::onAxialScale()
1319 {
1320   if ( !myScalingDlg )
1321     myScalingDlg = new OCCViewer_AxialScaleDlg( this, myDesktop );
1322   
1323   if ( !myScalingDlg->isVisible() )
1324     myScalingDlg->show();
1325 }
1326
1327 /*!
1328   \brief Store view parameters.
1329 */
1330 void OCCViewer_ViewWindow::onMemorizeView()
1331 {
1332   myModel->appendViewAspect( getViewParams() );
1333 }
1334
1335 /*!
1336   \brief Restore view parameters.
1337 */
1338 void OCCViewer_ViewWindow::onRestoreView()
1339 {
1340   OCCViewer_CreateRestoreViewDlg* aDlg = new OCCViewer_CreateRestoreViewDlg( centralWidget(), myModel );
1341   connect( aDlg, SIGNAL( dlgOk() ), this, SLOT( setRestoreFlag() ) );
1342   aDlg->exec();
1343   myModel->updateViewAspects( aDlg->parameters() );
1344   if( myRestoreFlag && aDlg->parameters().count() )
1345     performRestoring( aDlg->currentItem() );
1346 }
1347
1348 /*!
1349   \brief Restore view parameters.
1350   \param anItem view parameters
1351 */
1352 void OCCViewer_ViewWindow::performRestoring( const viewAspect& anItem )
1353 {
1354   Handle(V3d_View) aView3d = myViewPort->getView();
1355
1356   Standard_Boolean prev = aView3d->SetImmediateUpdate( Standard_False );
1357   aView3d->SetScale( anItem.scale );
1358   aView3d->SetCenter( anItem.centerX, anItem.centerY );
1359   aView3d->SetTwist( anItem.twist );
1360   aView3d->SetAt( anItem.atX, anItem.atY, anItem.atZ );
1361   aView3d->SetImmediateUpdate( prev );
1362   aView3d->SetEye( anItem.eyeX, anItem.eyeY, anItem.eyeZ );
1363   aView3d->SetProj( anItem.projX, anItem.projY, anItem.projZ );
1364   aView3d->SetAxialScale( anItem.scaleX, anItem.scaleY, anItem.scaleZ );
1365   myModel->setTrihedronShown( anItem.isVisible );
1366   myModel->setTrihedronSize( anItem.size );
1367         
1368   myRestoreFlag = 0;
1369 }
1370
1371 /*!
1372   \brief Set restore flag.
1373 */
1374 void OCCViewer_ViewWindow::setRestoreFlag()
1375 {
1376   myRestoreFlag = 1;
1377 }
1378
1379 /*!
1380   \brief Called when action "show/hide trihedron" is activated.
1381 */
1382 void OCCViewer_ViewWindow::onTrihedronShow()
1383 {
1384   myModel->toggleTrihedron();
1385 }
1386
1387 /*!
1388   \brief Dump view window contents to the pixmap.
1389   \return pixmap containing all scene rendered in the window
1390 */
1391 QImage OCCViewer_ViewWindow::dumpView()
1392 {
1393   QPixmap px = QPixmap::grabWindow( myViewPort->winId() );
1394   return px.toImage();
1395 }
1396
1397 bool OCCViewer_ViewWindow::dumpViewToFormat( const QImage& img, 
1398                                              const QString& fileName, 
1399                                              const QString& format )
1400 {
1401   if ( format != "PS" && format != "EPS")
1402     return SUIT_ViewWindow::dumpViewToFormat( img, fileName, format );
1403
1404   Handle(Visual3d_View) a3dView = myViewPort->getView()->View();
1405
1406   if (format == "PS")
1407     a3dView->Export(qPrintable(fileName), Graphic3d_EF_PostScript);
1408   else if (format == "EPS")
1409     a3dView->Export(qPrintable(fileName), Graphic3d_EF_EnhPostScript);
1410
1411   return true;
1412 }
1413
1414
1415 QString OCCViewer_ViewWindow::filter() const
1416 {
1417   return tr( "OCC_IMAGE_FILES" );
1418 }
1419
1420
1421 /*!
1422   \brief Set parameters of the cutting plane
1423   \param on if \c true, cutting plane is enabled
1424   \param x X position of plane point
1425   \param y Y position of plane point
1426   \param z Z position of plane point
1427   \param dx X coordinate of plane normal
1428   \param dy Y coordinate of plane normal
1429   \param dz Z coordinate of plane normal
1430 */
1431 void OCCViewer_ViewWindow::setCuttingPlane( bool on, const double x,  const double y,  const double z,
1432                                             const double dx, const double dy, const double dz )
1433 {
1434   Handle(V3d_View) view = myViewPort->getView();
1435   if ( view.IsNull() )
1436     return;
1437
1438   if ( on ) {
1439     Handle(V3d_Viewer) viewer = myViewPort->getViewer();
1440
1441     // try to use already existing plane or create a new one
1442     Handle(V3d_Plane) clipPlane;
1443     view->InitActivePlanes();
1444     if ( view->MoreActivePlanes() )
1445       clipPlane = view->ActivePlane();
1446     else
1447       clipPlane = new V3d_Plane( viewer );
1448
1449     // set new a,b,c,d values for the plane
1450     gp_Pln pln( gp_Pnt( x, y, z ), gp_Dir( dx, dy, dz ) );
1451     double a, b, c, d;
1452     pln.Coefficients( a, b, c, d );
1453     clipPlane->SetPlane( a, b, c, d );
1454
1455     view->SetPlaneOn( clipPlane );
1456   }
1457   else
1458     view->SetPlaneOff();
1459
1460   view->Update();
1461   view->Redraw();
1462 }
1463
1464 /*!
1465   \brief Check if any cutting plane is enabled
1466   \return \c true if at least one cutting plane is enabled
1467 */
1468 bool OCCViewer_ViewWindow::isCuttingPlane()
1469 {
1470   Handle(V3d_View) view = myViewPort->getView();
1471   view->InitActivePlanes();
1472   return (view->MoreActivePlanes());
1473 }
1474
1475 /*!
1476   \brief Get the visual parameters of the view window.
1477   \return visual parameters of view window
1478 */
1479 viewAspect OCCViewer_ViewWindow::getViewParams() const
1480 {
1481   double centerX, centerY, projX, projY, projZ, twist;
1482   double atX, atY, atZ, eyeX, eyeY, eyeZ;
1483   double aScaleX, aScaleY, aScaleZ;
1484
1485   Handle(V3d_View) aView3d = myViewPort->getView();
1486
1487   aView3d->Center( centerX, centerY );
1488   aView3d->Proj( projX, projY, projZ );
1489   aView3d->At( atX, atY, atZ );
1490   aView3d->Eye( eyeX, eyeY, eyeZ );
1491   twist = aView3d->Twist();
1492
1493   aView3d->AxialScale(aScaleX,aScaleY,aScaleZ);
1494
1495   bool isShown = myModel->isTrihedronVisible();
1496   double size = myModel->trihedronSize();
1497
1498   QString aName = QTime::currentTime().toString() + QString::fromLatin1( " h:m:s" );
1499
1500   viewAspect params;
1501   params.scale    = aView3d->Scale();
1502   params.centerX  = centerX;
1503   params.centerY  = centerY;
1504   params.projX    = projX;
1505   params.projY    = projY;
1506   params.projZ    = projZ;
1507   params.twist    = twist;
1508   params.atX      = atX;
1509   params.atY      = atY;
1510   params.atZ      = atZ;
1511   params.eyeX     = eyeX;
1512   params.eyeY     = eyeY;
1513   params.eyeZ     = eyeZ;
1514   params.scaleX   = aScaleX;
1515   params.scaleY   = aScaleY;
1516   params.scaleZ   = aScaleZ;
1517   params.name     = aName;
1518   params.isVisible= isShown;
1519   params.size     = size;
1520
1521   return params;
1522 }
1523
1524
1525 /*!
1526   \brief Get visual parameters of this view window.
1527   \return visual parameters of view window
1528 */
1529 QString OCCViewer_ViewWindow::getVisualParameters()
1530 {
1531   viewAspect params = getViewParams();
1532   QString retStr;
1533   retStr.sprintf( "%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e*%.12e", params.scale,
1534                   params.centerX, params.centerY, params.projX, params.projY, params.projZ, params.twist,
1535                   params.atX, params.atY, params.atZ, params.eyeX, params.eyeY, params.eyeZ,
1536                   params.scaleX, params.scaleY, params.scaleZ );
1537   retStr += QString().sprintf("*%u*%.2f", params.isVisible, params.size );
1538   return retStr;
1539 }
1540
1541 /*!
1542   \brief Restore visual parameters of the view window.
1543   \param parameters visual parameters of view window
1544 */
1545 void OCCViewer_ViewWindow::setVisualParameters( const QString& parameters )
1546 {
1547   QStringList paramsLst = parameters.split( '*' );
1548   if ( paramsLst.size() >= 15 ) {
1549     viewAspect params;
1550     params.scale    = paramsLst[0].toDouble();
1551     params.centerX  = paramsLst[1].toDouble();
1552     params.centerY  = paramsLst[2].toDouble();
1553     params.projX    = paramsLst[3].toDouble();
1554     params.projY    = paramsLst[4].toDouble();
1555     params.projZ    = paramsLst[5].toDouble();
1556     params.twist    = paramsLst[6].toDouble();
1557     params.atX      = paramsLst[7].toDouble();
1558     params.atY      = paramsLst[8].toDouble();
1559     params.atZ      = paramsLst[9].toDouble();
1560     params.eyeX     = paramsLst[10].toDouble();
1561     params.eyeY     = paramsLst[11].toDouble();
1562     params.eyeZ     = paramsLst[12].toDouble();
1563     if ( paramsLst.size() == 18 ) {
1564       params.scaleX    = paramsLst[13].toDouble();
1565       params.scaleY    = paramsLst[14].toDouble();
1566       params.scaleZ    = paramsLst[15].toDouble();
1567       params.isVisible = paramsLst[16].toDouble();
1568       params.size      = paramsLst[17].toDouble();
1569     } 
1570     else {
1571       params.scaleX    = 1.;
1572       params.scaleY    = 1.;
1573       params.scaleZ    = 1.;
1574     }
1575     performRestoring( params );
1576   }
1577 }
1578
1579 /*!
1580   \brief Handle show event.
1581
1582   Emits Show() signal.
1583
1584   \param theEvent show event
1585 */
1586 void OCCViewer_ViewWindow::showEvent( QShowEvent* theEvent )
1587 {
1588   emit Show( theEvent );
1589 }
1590
1591 /*!
1592   \brief Handle hide event.
1593
1594   Emits Hide() signal.
1595
1596   \param theEvent hide event
1597 */
1598 void OCCViewer_ViewWindow::hideEvent( QHideEvent* theEvent )
1599 {
1600   emit Hide( theEvent );
1601 }
1602
1603
1604 /*!
1605     Creates default sketcher. [ virtual protected ]
1606 */
1607 OCCViewer_ViewSketcher* OCCViewer_ViewWindow::createSketcher( int type )
1608 {
1609   if ( type == Rect )
1610     return new OCCViewer_RectSketcher( this, type );
1611   if ( type == Polygon )
1612     return new OCCViewer_PolygonSketcher( this, type );
1613   return 0;
1614 }
1615
1616 void OCCViewer_ViewWindow::initSketchers()
1617 {
1618   if ( mySketchers.isEmpty() )
1619   {
1620     mySketchers.append( createSketcher( Rect ) );
1621     mySketchers.append( createSketcher( Polygon ) );
1622   }
1623 }
1624
1625 OCCViewer_ViewSketcher* OCCViewer_ViewWindow::getSketcher( const int typ )
1626 {
1627   OCCViewer_ViewSketcher* sketcher = 0;
1628   QList<OCCViewer_ViewSketcher*>::Iterator it;
1629   for ( it = mySketchers.begin(); it != mySketchers.end() && !sketcher; ++it )
1630   {
1631     OCCViewer_ViewSketcher* sk = (*it);
1632     if ( sk->type() == typ )
1633       sketcher = sk;
1634   }
1635   return sketcher;
1636 }
1637
1638 /*!
1639     Handles requests for sketching in the active view. [ virtual public ]
1640 */
1641 void OCCViewer_ViewWindow::activateSketching( int type )
1642 {
1643   OCCViewer_ViewPort3d* vp = getViewPort();
1644   if ( !vp )
1645     return;
1646
1647   if ( !vp->isSketchingEnabled() )
1648     return;
1649
1650   /* Finish current sketching */
1651   if ( type == NoSketching )
1652   {
1653     if ( mypSketcher )
1654     {
1655       onSketchingFinished();
1656       mypSketcher->deactivate();
1657       mypSketcher = 0;
1658     }
1659   }
1660   /* Activate new sketching */
1661   else
1662   {
1663     activateSketching( NoSketching );  /* concurrency not suported */
1664     mypSketcher = getSketcher( type );
1665     if ( mypSketcher )
1666     {
1667       mypSketcher->activate();
1668       onSketchingStarted();
1669     }
1670   }
1671 }
1672
1673 /*!
1674     Unhilights detected entities. [ virtual protected ]
1675 */
1676 void OCCViewer_ViewWindow::onSketchingStarted()
1677 {
1678 }
1679
1680 /*!
1681     Selection by rectangle or polygon. [ virtual protected ]
1682 */
1683 void OCCViewer_ViewWindow::onSketchingFinished()
1684 {
1685   if ( mypSketcher && mypSketcher->result() == OCCViewer_ViewSketcher::Accept )
1686   {
1687     Handle(AIS_InteractiveContext) ic = myModel->getAISContext();
1688     bool append = bool( mypSketcher->buttonState() & Qt::ShiftModifier );
1689     switch( mypSketcher->type() )
1690     {
1691     case Rect:
1692       {
1693         QRect* aRect = (QRect*)mypSketcher->data();
1694         if( aRect )
1695         {
1696           int aLeft = aRect->left();
1697           int aRight = aRect->right();
1698           int aTop = aRect->top();
1699           int aBottom = aRect->bottom();
1700
1701           if( append )
1702             ic->ShiftSelect( aLeft, aBottom, aRight, aTop, getViewPort()->getView(), Standard_False );
1703           else
1704             ic->Select( aLeft, aBottom, aRight, aTop, getViewPort()->getView(), Standard_False );
1705         }
1706       }
1707       break;
1708     case Polygon:
1709       {
1710         QPolygon* aPolygon = (QPolygon*)mypSketcher->data();
1711         if( aPolygon )
1712         {
1713           int size = aPolygon->size();
1714           TColgp_Array1OfPnt2d anArray( 1, size );
1715
1716           QPolygon::Iterator it = aPolygon->begin();
1717           QPolygon::Iterator itEnd = aPolygon->end();
1718           for( int index = 1; it != itEnd; ++it, index++ )
1719           {
1720             QPoint aPoint = *it;
1721             anArray.SetValue( index, gp_Pnt2d( aPoint.x(), aPoint.y() ) );
1722           }
1723
1724           if( append )
1725             ic->ShiftSelect( anArray, getViewPort()->getView(), Standard_False );
1726           else
1727             ic->Select( anArray, getViewPort()->getView(), Standard_False );
1728         }
1729       }
1730       break;
1731     default:
1732       break;
1733     }
1734
1735     OCCViewer_ViewManager* aViewMgr = ( OCCViewer_ViewManager* )getViewManager();
1736     aViewMgr->getOCCViewer()->performSelectionChanged();
1737   }
1738 }
1739
1740 OCCViewer_ViewPort3d* OCCViewer_ViewWindow::getViewPort()
1741 {
1742   return myViewPort;
1743 }
1744
1745 bool OCCViewer_ViewWindow::transformRequested() const
1746 {
1747   return ( myOperation != NOTHING );
1748 }
1749
1750 bool OCCViewer_ViewWindow::transformInProcess() const
1751 {
1752   return myEventStarted;
1753 }
1754
1755 void OCCViewer_ViewWindow::setTransformInProcess( bool bOn )
1756 {
1757   myEventStarted = bOn;
1758 }