]> SALOME platform Git repositories - modules/shaper.git/blob - src/XGUI/XGUI_ViewWindow.cpp
Salome HOME
8370775d9a813b8af9c8fcb950df90563c9241b7
[modules/shaper.git] / src / XGUI / XGUI_ViewWindow.cpp
1 #include "XGUI_ViewWindow.h"
2 #include "XGUI_ViewPort.h"
3 #include "XGUI_Viewer.h"
4 #include "XGUI_Tools.h"
5 #include "XGUI_RubberBand.h"
6
7 #include <QLayout>
8 #include <QLabel>
9 #include <QToolBar>
10 #include <QAction>
11 #include <QResizeEvent>
12 #include <QApplication>
13 #include <QMdiArea>
14 #include <QMdiSubWindow>
15 #include <QPainter>
16 //#include <QTime>
17 #include <QFileDialog>
18
19 #include <TopoDS_Shape.hxx>
20 #include <BRep_Tool.hxx>
21 #include <TopoDS.hxx>
22 #include <Visual3d_View.hxx>
23
24 #define BORDER_SIZE 2
25
26 const char* imageZoomCursor[] = {
27 "32 32 3 1",
28 ". c None",
29 "a c #000000",
30 "# c #ffffff",
31 "................................",
32 "................................",
33 ".#######........................",
34 "..aaaaaaa.......................",
35 "................................",
36 ".............#####..............",
37 "...........##.aaaa##............",
38 "..........#.aa.....a#...........",
39 ".........#.a.........#..........",
40 ".........#a..........#a.........",
41 "........#.a...........#.........",
42 "........#a............#a........",
43 "........#a............#a........",
44 "........#a............#a........",
45 "........#a............#a........",
46 ".........#...........#.a........",
47 ".........#a..........#a.........",
48 ".........##.........#.a.........",
49 "........#####.....##.a..........",
50 ".......###aaa#####.aa...........",
51 "......###aa...aaaaa.......#.....",
52 ".....###aa................#a....",
53 "....###aa.................#a....",
54 "...###aa...............#######..",
55 "....#aa.................aa#aaaa.",
56 ".....a....................#a....",
57 "..........................#a....",
58 "...........................a....",
59 "................................",
60 "................................",
61 "................................",
62 "................................"};
63
64 const char* imageRotateCursor[] = {
65 "32 32 3 1",
66 ". c None",
67 "a c #000000",
68 "# c #ffffff",
69 "................................",
70 "................................",
71 "................................",
72 "................................",
73 "........#.......................",
74 ".......#.a......................",
75 "......#######...................",
76 ".......#aaaaa#####..............",
77 "........#..##.a#aa##........##..",
78 ".........a#.aa..#..a#.....##.aa.",
79 ".........#.a.....#...#..##.aa...",
80 ".........#a.......#..###.aa.....",
81 "........#.a.......#a..#aa.......",
82 "........#a.........#..#a........",
83 "........#a.........#a.#a........",
84 "........#a.........#a.#a........",
85 "........#a.........#a.#a........",
86 ".........#.........#a#.a........",
87 "........##a........#a#a.........",
88 "......##.a#.......#.#.a.........",
89 "....##.aa..##.....##.a..........",
90 "..##.aa.....a#####.aa...........",
91 "...aa.........aaa#a.............",
92 "................#.a.............",
93 "...............#.a..............",
94 "..............#.a...............",
95 "...............a................",
96 "................................",
97 "................................",
98 "................................",
99 "................................",
100 "................................"};
101
102 const char* imageCrossCursor[] = {
103   "32 32 3 1",
104   ". c None",
105   "a c #000000",
106   "# c #ffffff",
107   "................................",
108   "................................",
109   "................................",
110   "................................",
111   "................................",
112   "................................",
113   "................................",
114   "...............#................",
115   "...............#a...............",
116   "...............#a...............",
117   "...............#a...............",
118   "...............#a...............",
119   "...............#a...............",
120   "...............#a...............",
121   "...............#a...............",
122   ".......#################........",
123   "........aaaaaaa#aaaaaaaaa.......",
124   "...............#a...............",
125   "...............#a...............",
126   "...............#a...............",
127   "...............#a...............",
128   "...............#a...............",
129   "...............#a...............",
130   "...............#a...............",
131   "................a...............",
132   "................................",
133   "................................",
134   "................................",
135   "................................",
136   "................................",
137   "................................",
138   "................................"};
139
140
141 //**************************************************************************
142 void ViewerToolbar::paintEvent( QPaintEvent* theEvent)
143 {
144     //QTime aTime;
145     //aTime.start();
146     QRect aRect = rect();
147     QRect aVPRect = myVPort->rect();
148     QPoint aGlobPnt = mapToGlobal(aRect.topLeft());
149     QPoint aPnt = myVPort->mapFromGlobal(aGlobPnt);
150
151     QRect aImgRect(QRect(aPnt.x(), aPnt.y() + aVPRect.height() - aRect.height(), aRect.width(), aRect.height()));
152     QPainter(this).drawImage(aRect, myVPort->dumpView(aImgRect, false));
153     //QString aMsg = QString("### Painted in %1").arg(aTime.elapsed());
154     //qDebug(qPrintable(aMsg));
155 }
156
157 //**************************************************************************
158 void ViewerLabel::paintEvent( QPaintEvent* theEvent)
159 {
160     QRect aRect = rect();
161     QRect aVPRect = myVPort->rect();
162     QPoint aGlobPnt = mapToGlobal(aRect.topLeft());
163     QPoint aPnt = myVPort->mapFromGlobal(aGlobPnt);
164
165     QRect aImgRect(QRect(aPnt.x(), aPnt.y() + aVPRect.height() - aRect.height(), aRect.width(), aRect.height()));
166     QPainter(this).drawImage(aRect, myVPort->dumpView(aImgRect, false));
167     QLabel::paintEvent(theEvent);
168 }
169
170 //**************************************************************************
171 //**************************************************************************
172 //**************************************************************************
173 XGUI_ViewWindow::XGUI_ViewWindow(XGUI_Viewer* theViewer, 
174                                  V3d_TypeOfView theType):
175 QFrame(),
176     myViewer(theViewer),
177     myMoving(false),
178     MinimizeIco(":pictures/wnd_minimize.png"),
179     MaximizeIco(":pictures/wnd_maximize.png"),
180     CloseIco(":pictures/wnd_close.png"),
181     RestoreIco(":pictures/wnd_restore.png"),
182     myInteractionStyle(XGUI::STANDARD),
183     myRectBand(0),
184     myIsKeyFree(false),
185     my2dMode(XGUI::No2dMode),
186     myCurrPointType(XGUI::GRAVITY),
187     myPrevPointType(XGUI::GRAVITY),
188     myRotationPointSelection(false),
189     myClosable(false)
190 {
191     mySelectedPoint = gp_Pnt(0.,0.,0.);
192     setFrameStyle(QFrame::Raised);
193     setFrameShape(QFrame::Panel);
194     setLineWidth(BORDER_SIZE);
195     setMouseTracking(true);
196
197     QVBoxLayout* aLay = new QVBoxLayout(this);
198     aLay->setContentsMargins(BORDER_SIZE,BORDER_SIZE,BORDER_SIZE,BORDER_SIZE);
199     myViewPort = new XGUI_ViewPort(this, myViewer->v3dViewer(), theType);
200     myViewPort->installEventFilter(this);
201     aLay->addWidget(myViewPort);
202
203     myPicture = new QLabel(this);
204     myPicture->setFrameStyle(QFrame::Sunken);
205     myPicture->setFrameShape(QFrame::Panel);
206     myPicture->setMouseTracking(true);
207     myPicture->installEventFilter(this);
208     aLay->addWidget(myPicture);
209     myPicture->hide();
210
211     myGripWgt = new ViewerLabel(this, myViewPort);
212     myGripWgt->setPixmap(QPixmap(":pictures/wnd_grip.png"));
213     myGripWgt->setGeometry(BORDER_SIZE + 2, BORDER_SIZE + 2, 19, 32);
214     myGripWgt->setMouseTracking(true);
215     myGripWgt->installEventFilter(this);
216     connect(myViewPort, SIGNAL(vpTransformed()), myGripWgt, SLOT(update()));
217     connect(myViewPort, SIGNAL(vpUpdated()), myGripWgt, SLOT(update()));
218
219     // Create Viewer management buttons
220     myViewBar = new ViewerToolbar(this, myViewPort);
221
222     QAction* aBtn;
223
224     // Dump view
225     aBtn = new QAction(QIcon(":pictures/occ_view_camera_dump.png"), tr("DUMP_VIEW"), myViewBar);
226     connect(aBtn, SIGNAL(triggered()), SLOT(dumpView()));
227     myViewBar->addAction(aBtn);
228     // Fit all
229     aBtn = new QAction(QIcon(":pictures/occ_view_fitall.png"), tr("FIT_ALL"), myViewBar);
230     connect(aBtn, SIGNAL(triggered()), SLOT(fitAll()));
231     myViewBar->addAction(aBtn);
232     // Fit area
233     aBtn = new QAction(QIcon(":pictures/occ_view_fitarea.png"), tr("FIT_AREA"), myViewBar);
234     connect(aBtn, SIGNAL(triggered()), SLOT(activateWindowFit()));
235     myViewBar->addAction(aBtn);
236     // Zoom
237     aBtn = new QAction(QIcon(":pictures/occ_view_zoom.png"), tr("ZOOM_VIEW"), myViewBar);
238     connect(aBtn, SIGNAL(triggered()), SLOT(activateZoom()));
239     myViewBar->addAction(aBtn);
240     // Pan
241     aBtn = new QAction(QIcon(":pictures/occ_view_pan.png"), tr("PAN_VIEW"), myViewBar);
242     connect(aBtn, SIGNAL(triggered()), SLOT(activatePanning()));
243     myViewBar->addAction(aBtn);
244     // Global Panning
245     aBtn = new QAction(QIcon(":pictures/occ_view_glpan.png"), tr("GLOB_PAN_VIEW"), myViewBar);
246     connect(aBtn, SIGNAL(triggered()), SLOT(activateGlobalPanning()));
247     myViewBar->addAction(aBtn);
248     // Rotation
249     aBtn = new QAction(QIcon(":pictures/occ_view_rotate.png"), tr("ROTATE_VIEW"), myViewBar);
250     connect(aBtn, SIGNAL(triggered()), SLOT(activateRotation()));
251     myViewBar->addAction(aBtn);
252     // Front view
253     aBtn = new QAction(QIcon(":pictures/occ_view_front.png"), tr("FRONT_VIEW"), myViewBar);
254     connect(aBtn, SIGNAL(triggered()), SLOT(frontView()));
255     myViewBar->addAction(aBtn);
256     // Back view
257     aBtn = new QAction(QIcon(":pictures/occ_view_back.png"), tr("BACK_VIEW"), myViewBar);
258     connect(aBtn, SIGNAL(triggered()), SLOT(backView()));
259     myViewBar->addAction(aBtn);
260     // Top view
261     aBtn = new QAction(QIcon(":pictures/occ_view_top.png"), tr("TOP_VIEW"), myViewBar);
262     connect(aBtn, SIGNAL(triggered()), SLOT(topView()));
263     myViewBar->addAction(aBtn);
264     // Bottom view
265     aBtn = new QAction(QIcon(":pictures/occ_view_bottom.png"), tr("BOTTOM_VIEW"), myViewBar);
266     connect(aBtn, SIGNAL(triggered()), SLOT(bottomView()));
267     myViewBar->addAction(aBtn);
268     // Left view
269     aBtn = new QAction(QIcon(":pictures/occ_view_left.png"), tr("LEFT_VIEW"), myViewBar);
270     connect(aBtn, SIGNAL(triggered()), SLOT(leftView()));
271     myViewBar->addAction(aBtn);
272     // Right view
273     aBtn = new QAction(QIcon(":pictures/occ_view_right.png"), tr("RIGHT_VIEW"), myViewBar);
274     connect(aBtn, SIGNAL(triggered()), SLOT(rightView()));
275     myViewBar->addAction(aBtn);
276     // Clone view
277     aBtn = new QAction(QIcon(":pictures/occ_view_clone.png"), tr("CLONE_VIEW"), myViewBar);
278     connect(aBtn, SIGNAL(triggered()), SLOT(cloneView()));
279     myViewBar->addAction(aBtn);
280
281     //Support copy of background on updating of viewer
282     connect(myViewPort, SIGNAL(vpTransformed()), myViewBar, SLOT(update()));
283     connect(myViewPort, SIGNAL(vpUpdated()), myViewBar, SLOT(update()));
284
285     // Create Window management buttons
286     myWindowBar = new ViewerToolbar(this, myViewPort);
287     connect(myViewPort, SIGNAL(vpTransformed()), myWindowBar, SLOT(update()));
288     connect(myViewPort, SIGNAL(vpUpdated()), myWindowBar, SLOT(update()));
289
290     myMinimizeBtn = new QAction(myWindowBar);
291     myMinimizeBtn->setIcon(MinimizeIco);
292     myWindowBar->addAction(myMinimizeBtn);
293     connect(myMinimizeBtn, SIGNAL(triggered()), SLOT(onMinimize()));
294
295     myMaximizeBtn = new QAction(myWindowBar);
296     myMaximizeBtn->setIcon(MaximizeIco);
297     myWindowBar->addAction(myMaximizeBtn);
298     connect(myMaximizeBtn, SIGNAL(triggered()), SLOT(onMaximize()));
299
300     aBtn = new QAction(myWindowBar);
301     aBtn->setIcon(CloseIco);
302     myWindowBar->addAction(aBtn);
303     connect(aBtn, SIGNAL(triggered()), SLOT(onClose()));
304
305     myViewBar->hide();
306     myWindowBar->hide();
307     myGripWgt->hide();
308 }
309
310 //****************************************************************
311 XGUI_ViewWindow::~XGUI_ViewWindow()
312 {
313 }
314
315 //****************************************************************
316 void XGUI_ViewWindow::resizeEvent(QResizeEvent* theEvent)
317 {
318     QSize aSize = theEvent->size();
319     QSize aWndBarSize = myWindowBar->sizeHint();
320     QSize myViewBarSize = myViewBar->sizeHint();
321
322     myWindowBar->move(aSize.width() - aWndBarSize.width() - BORDER_SIZE - 4, BORDER_SIZE + 2);
323     int aViewBarWidth = aSize.width() - aWndBarSize.width() - myGripWgt->width() - 8;
324     if (aViewBarWidth > myViewBarSize.width())
325         aViewBarWidth = myViewBarSize.width();
326     myViewBar->setGeometry(BORDER_SIZE + 18, BORDER_SIZE + 2, aViewBarWidth, myViewBarSize.height());
327 }
328
329 //****************************************************************
330 void XGUI_ViewWindow::changeEvent(QEvent* theEvent)
331 {
332
333     if (theEvent->type() == QEvent::WindowStateChange) {
334         if (isMinimized()) {
335             myViewBar->hide();
336             myGripWgt->hide(); 
337             myWindowBar->hide();
338             myViewPort->hide();
339             myPicture->show();
340         } else {
341             myPicture->hide();
342             myViewPort->show();
343             if (isMaximized()) {
344                 myMinimizeBtn->setIcon(MinimizeIco);
345                 myMaximizeBtn->setIcon(RestoreIco);
346             }
347         }
348     } else
349         QWidget::changeEvent(theEvent);
350 }
351
352
353 //****************************************************************
354 void XGUI_ViewWindow::onClose()
355 {
356     if (parentWidget()) {
357         emit tryClosing(this);
358         if (closable()) {
359             emit closed(static_cast<QMdiSubWindow*>(parentWidget()));
360             parentWidget()->close();
361         }
362     }
363 }
364
365 //****************************************************************
366 void XGUI_ViewWindow::enterEvent(QEvent* theEvent)
367 {
368     if (!isMinimized()) {
369         myViewBar->show();
370         myWindowBar->show();
371         if (!isMaximized())
372             myGripWgt->show(); 
373     }
374 }
375
376 //****************************************************************
377 void XGUI_ViewWindow::leaveEvent(QEvent* theEvent)
378 {
379     myViewBar->hide();
380     myGripWgt->hide(); 
381     myWindowBar->hide();
382 }
383
384 //****************************************************************
385 void XGUI_ViewWindow::onMinimize()
386 {
387     QPixmap aPMap = QPixmap::fromImage(myViewPort->dumpView());
388     int aW = width();
389     int aH = height();
390     double aR = aW / 100.;
391     int aNewH = int(aH / aR);
392     myPicture->setPixmap(aPMap.scaled(100,  aNewH));
393     
394     myLastState = isMaximized()? MaximizedState : NormalState;
395     showMinimized();
396     parentWidget()->setGeometry(parentWidget()->x(), parentWidget()->y(),
397                                 100, aNewH);
398 }
399
400 //****************************************************************
401 void XGUI_ViewWindow::onMaximize()
402 {
403     if (isMaximized()) {
404         myMaximizeBtn->setIcon(MaximizeIco);
405         myGripWgt->show();
406         showNormal();
407     } else {
408         myMaximizeBtn->setIcon(RestoreIco);
409         myGripWgt->hide();
410         showMaximized();
411     }
412     myMinimizeBtn->setIcon(MinimizeIco);
413 }
414
415 //****************************************************************
416 bool XGUI_ViewWindow::processWindowControls(QObject *theObj, QEvent *theEvent)
417 {
418     switch (theEvent->type()) {
419     case QEvent::MouseButtonPress: 
420         {
421             QMouseEvent* aEvent = static_cast<QMouseEvent*>(theEvent);
422             if ((aEvent->button() == Qt::LeftButton) && (!myMoving)){
423                 myMoving = true;
424                 myMousePnt = aEvent->globalPos();
425                 return true;
426             }
427         }
428         break;
429     case QEvent::MouseButtonRelease: 
430         {
431             QMouseEvent* aEvent = static_cast<QMouseEvent*>(theEvent);
432             if ((aEvent->button() == Qt::LeftButton) && myMoving) {
433                 myMoving = false;
434                 return true;
435             }
436         }
437         break;
438     case QEvent::MouseMove: 
439         {
440             QMouseEvent* aEvent = static_cast<QMouseEvent*>(theEvent);
441             if (myMoving) {
442                 QMdiSubWindow* aParent = static_cast<QMdiSubWindow*>(parentWidget());
443                 QMdiArea* aMDIArea = aParent->mdiArea();
444                     
445                 QPoint aPnt = aEvent->globalPos();
446                 QPoint aMDIPnt = aMDIArea->mapFromGlobal(aPnt);
447                 if (aMDIArea->rect().contains(aMDIPnt)) {
448                     int aX = aParent->x() + (aPnt.x() - myMousePnt.x());
449                     int aY = aParent->y() + (aPnt.y() - myMousePnt.y());
450                     aParent->move(aX, aY);
451                     myMousePnt = aPnt;
452                 }
453                 return true;
454             }
455         }
456         break;
457     case QEvent::MouseButtonDblClick:
458         if (theObj == myPicture) {
459             myMoving = false;
460             if (myLastState == MaximizedState)
461                 showMaximized();
462             else
463                 showNormal();
464             return true;
465         }
466     }
467     return false;
468 }
469
470 //****************************************************************
471 bool XGUI_ViewWindow::processViewPort(QEvent *theEvent)
472 {
473     switch(theEvent->type()) {
474     case QEvent::MouseButtonPress:
475         vpMousePressEvent((QMouseEvent*) theEvent);
476         return true;
477
478     case QEvent::MouseButtonRelease:
479         vpMouseReleaseEvent((QMouseEvent*) theEvent);
480         return true;
481
482     case QEvent::MouseMove:
483         vpMouseMoveEvent((QMouseEvent*) theEvent);
484         return true;
485
486     case QEvent::MouseButtonDblClick:
487         emit mouseDoubleClicked(this, (QMouseEvent*)theEvent);
488         return true;
489     case QEvent::Wheel:
490         {
491             QWheelEvent* aEvent = (QWheelEvent*) theEvent;
492             myViewPort->startZoomAtPoint( aEvent->x(), aEvent->y() );
493             double aDelta = (double)( aEvent->delta() ) / ( 15 * 8 );
494             int x  = aEvent->x();
495             int y  = aEvent->y();
496             int x1 = (int)( aEvent->x() + width()*aDelta/100 );
497             int y1 = (int)( aEvent->y() + height()*aDelta/100 );
498             myViewPort->zoom( x, y, x1, y1 );
499         }
500         return true;
501     }
502     return false;
503 }
504
505 //****************************************************************
506 bool XGUI_ViewWindow::eventFilter(QObject *theObj, QEvent *theEvent)
507 {
508     if ((theObj == myGripWgt) || (theObj == myPicture)) {
509         if (processWindowControls(theObj, theEvent) )
510             return true;
511     } else if (theObj == myViewPort) {
512         if (processViewPort(theEvent))
513             return true;
514     }
515     return QFrame::eventFilter(theObj, theEvent);
516 }
517
518 //****************************************************************
519 XGUI_ViewWindow::OperationType XGUI_ViewWindow::getButtonState(QMouseEvent* theEvent, 
520                                 XGUI::InteractionStyle theInteractionStyle)
521 {
522   OperationType aOp = NOTHING;
523   XGUI::InteractionStyle aStyle = (XGUI::InteractionStyle)theInteractionStyle;
524   if( (theEvent->modifiers() == XGUI_Viewer::myStateMap[aStyle][XGUI::ZOOM]) &&
525       (theEvent->buttons() == XGUI_Viewer::myButtonMap[aStyle][XGUI::ZOOM]) )
526     aOp = ZOOMVIEW;
527   else if( (theEvent->modifiers() == XGUI_Viewer::myStateMap[aStyle][XGUI::PAN]) &&
528            (theEvent->buttons() == XGUI_Viewer::myButtonMap[aStyle][XGUI::PAN]) )
529     aOp = PANVIEW;
530   else if( (theEvent->modifiers()  == XGUI_Viewer::myStateMap[aStyle][XGUI::ROTATE]) &&
531            (theEvent->buttons() == XGUI_Viewer::myButtonMap[aStyle][XGUI::ROTATE]) &&
532            (my2dMode == XGUI::No2dMode))
533     aOp = ROTATE;
534
535   return aOp;
536 }
537
538 //****************************************************************
539 void XGUI_ViewWindow::vpMousePressEvent(QMouseEvent* theEvent)
540 {
541     myStartX = theEvent->x();
542     myStartY = theEvent->y();
543     XGUI::InteractionStyle anInteractionStyle = interactionStyle();
544
545     // in "key free" interaction style zoom operation is activated by two buttons (simultaneously pressed),
546     // which are assigned for pan and rotate - these operations are activated immediately after pressing 
547     // of the first button, so it is necessary to switch to zoom when the second button is pressed
548     bool aSwitchToZoom = false;
549     if ((anInteractionStyle == XGUI::KEY_FREE) && (myOperation == PANVIEW || myOperation == ROTATE)) {
550         aSwitchToZoom = getButtonState( theEvent, anInteractionStyle ) == ZOOMVIEW;
551     }
552
553     switch ( myOperation ) {
554     case WINDOWFIT:
555         if ( theEvent->button() == Qt::LeftButton )
556             emit vpTransformationStarted ( WINDOWFIT );
557         break;
558
559     case PANGLOBAL:
560         if ( theEvent->button() == Qt::LeftButton )
561             emit vpTransformationStarted ( PANGLOBAL );
562         break;
563
564     case ZOOMVIEW:
565         if ( theEvent->button() == Qt::LeftButton ) {
566             myViewPort->startZoomAtPoint( myStartX, myStartY );
567             emit vpTransformationStarted ( ZOOMVIEW );
568         }
569         break;
570
571     case PANVIEW:
572         if ( aSwitchToZoom ) {
573             myViewPort->startZoomAtPoint( myStartX, myStartY );
574             activateZoom();
575         } else if ( theEvent->button() == Qt::LeftButton )
576             emit vpTransformationStarted ( PANVIEW );
577         break;
578
579     case ROTATE:
580         if ( aSwitchToZoom ) {
581             myViewPort->startZoomAtPoint( myStartX, myStartY );
582             activateZoom();
583         } else if ( theEvent->button() == Qt::LeftButton ) {
584             myViewPort->startRotation(myStartX, myStartY, myCurrPointType, mySelectedPoint);
585             emit vpTransformationStarted ( ROTATE );
586         }
587         break;
588
589     default:
590         /*  Try to activate a transformation */
591         OperationType aState;
592         if ( interactionStyle() == XGUI::STANDARD )
593             aState = getButtonState(theEvent, anInteractionStyle);
594         else {
595             aState = XGUI_ViewWindow::NOTHING;
596             myIsKeyFree = true;
597         }
598         switch ( aState ) {
599         case ZOOMVIEW:
600             myViewPort->startZoomAtPoint( myStartX, myStartY );
601             activateZoom();
602             break;
603         case PANVIEW:
604             activatePanning();
605             break;
606         case ROTATE:
607             activateRotation();
608             myViewPort->startRotation(myStartX, myStartY, myCurrPointType, mySelectedPoint);
609             break;
610         default:
611             if ( myRotationPointSelection ) {
612                 if ( theEvent->button() == Qt::LeftButton ) {
613                     Handle(AIS_InteractiveContext) ic = myViewer->AISContext();
614                     ic->Select();
615                     for ( ic->InitSelected(); ic->MoreSelected(); ic->NextSelected() ) {
616                         TopoDS_Shape aShape = ic->SelectedShape();
617                         if ( !aShape.IsNull() && aShape.ShapeType() == TopAbs_VERTEX ) {
618                             gp_Pnt aPnt = BRep_Tool::Pnt( TopoDS::Vertex( ic->SelectedShape() ) );
619                             /*if ( mySetRotationPointDlg ) {
620                                 myRotationPointSelection = false;
621                                 mySetRotationPointDlg->setCoords(aPnt.X(), aPnt.Y(), aPnt.Z());
622                             }*/
623                         } else {
624                             myCurrPointType = myPrevPointType;
625                             break;
626                         }
627                     }
628                     if ( ic->NbSelected() == 0 ) myCurrPointType = myPrevPointType;
629                     //if ( mySetRotationPointDlg ) mySetRotationPointDlg->toggleChange();
630                     ic->CloseAllContexts();
631                     myOperation = NOTHING;
632                     myViewPort->setCursor( myCursor );
633                     myCursorIsHand = false;
634                     myRotationPointSelection = false;
635                 }
636             } else
637                 emit mousePressed(this, theEvent);
638             break;
639         }
640         /* notify that we start a transformation */
641         if ( transformRequested() )
642             emit vpTransformationStarted ( myOperation );
643     }
644     if ( transformRequested() )
645         setTransformInProcess( true );
646
647     /* we may need it for sketching... */
648 /*    if ( l_mbPressEvent )
649         delete l_mbPressEvent;
650     l_mbPressEvent = new QMouseEvent( *theEvent );*/
651 }
652
653 //****************************************************************
654 void XGUI_ViewWindow::vpMouseReleaseEvent(QMouseEvent* theEvent)
655 {
656     switch ( myOperation ) {
657     case NOTHING:
658         {
659             int prevState = myCurSketch;
660 /*            if(theEvent->button() == Qt::RightButton) {
661                 QList<OCCViewer_ViewSketcher*>::Iterator it;
662                 for ( it = mySketchers.begin(); it != mySketchers.end() && myCurSketch != -1; ++it ) {
663                     OCCViewer_ViewSketcher* sk = (*it);
664                     if( ( sk->sketchButton() & theEvent->button() ) && sk->sketchButton() == myCurSketch )
665                         myCurSketch = -1;
666                 }
667             }
668             */
669             emit mouseReleased(this, theEvent);
670             if (theEvent->button() == Qt::RightButton && prevState == -1) {
671                 QContextMenuEvent aEvent( QContextMenuEvent::Mouse,
672                                           theEvent->pos(), theEvent->globalPos() );
673                 emit contextMenuRequested( &aEvent );
674             }
675         }
676         break;
677     case ROTATE:
678         myViewPort->endRotation();
679         resetState();
680         break;
681
682     case PANVIEW:
683     case ZOOMVIEW:
684         resetState();
685         break;
686
687     case PANGLOBAL:
688         if ( theEvent->button() == Qt::LeftButton ) {
689             myViewPort->setCenter( theEvent->x(), theEvent->y() );
690             myViewPort->getView()->SetScale(myCurScale);
691             resetState();
692         }
693         break;
694
695     case WINDOWFIT:
696         if ( theEvent->button() == Qt::LeftButton ) {
697             myCurrX = theEvent->x();
698             myCurrY = theEvent->y();
699             drawRect();
700             QRect rect = makeRect(myStartX, myStartY, myCurrX, myCurrY);
701             if ( !rect.isEmpty() ) myViewPort->fitRect(rect);
702             endDrawRect();
703             resetState();
704         }
705         break;
706     }
707
708     // NOTE: viewer 3D detects a rectangle of selection using this event
709     // so we must emit it BEFORE resetting the selection rectangle
710     if ( theEvent->button() == Qt::LeftButton && myDrawRect ) {
711         drawRect();
712         endDrawRect();
713         resetState();
714         myViewPort->update();
715     }
716 /*    if ( l_mbPressEvent ) {
717         delete l_mbPressEvent;
718         l_mbPressEvent = 0;
719     }*/
720 }
721
722 //****************************************************************
723 void XGUI_ViewWindow::vpMouseMoveEvent(QMouseEvent* theEvent)
724 {
725     if ( myIsKeyFree && interactionStyle() == XGUI::KEY_FREE ) {
726         myIsKeyFree = false;
727         switch ( getButtonState( theEvent, interactionStyle() ) ) {
728         case ZOOMVIEW:
729             myViewPort->startZoomAtPoint( myStartX, myStartY );
730             activateZoom();
731             break;
732         case PANVIEW:
733             activatePanning();
734             break;
735         case ROTATE:
736             activateRotation();
737             myViewPort->startRotation(myStartX, myStartY, myCurrPointType, mySelectedPoint);
738             break;
739         default:
740         break;
741         }
742     }
743
744     myCurrX = theEvent->x();
745     myCurrY = theEvent->y();
746     switch (myOperation) {
747     case ROTATE:
748         myViewPort->rotate(myCurrX, myCurrY, myCurrPointType, mySelectedPoint);
749         break;
750
751     case ZOOMVIEW:
752         myViewPort->zoom(myStartX, myStartY, myCurrX, myCurrY);
753         myStartX = myCurrX;
754         myStartY = myCurrY;
755         break;
756
757     case PANVIEW:
758         myViewPort->pan(myCurrX - myStartX, myStartY - myCurrY);
759         myStartX = myCurrX;
760         myStartY = myCurrY;
761         break;
762
763     case PANGLOBAL:
764         break;
765
766     default:
767         if ( myRotationPointSelection /*|| isSketcherStyle()*/ )  {
768             emit mouseMoving( this, theEvent );
769         } else {
770             int aState = theEvent->modifiers();
771             int aButton = theEvent->buttons();
772             int anInteractionStyle = interactionStyle();
773             if ( ( (anInteractionStyle == XGUI::STANDARD) &&
774                    (aButton == Qt::LeftButton) && 
775                    (aState == Qt::NoModifier || Qt::ShiftModifier) ) ||
776                  ( (anInteractionStyle == XGUI::KEY_FREE) &&
777                    (aButton == Qt::LeftButton) && 
778                  ( aState == Qt::ControlModifier || aState == (Qt::ControlModifier|Qt::ShiftModifier) ) ) ) {
779                 myDrawRect = myEnableDrawMode;
780                 if ( myDrawRect ) {
781                     drawRect();
782                     if ( !myCursorIsHand ) {   // we are going to sketch a rectangle
783                         QCursor handCursor (Qt::PointingHandCursor);
784                         myCursorIsHand = true;
785                         myCursor = cursor();
786                         myViewPort->setCursor( handCursor );
787                     }
788                 }
789                 emit mouseMoving( this, theEvent );
790             } /* else if ( ( (anInteractionStyle == XGUI::STANDARD) &&
791                           (aButton == Qt::RightButton) && 
792                          ( aState == Qt::NoModifier || Qt::ShiftModifier ) ) ||
793                          ( (anInteractionStyle == XGUI::KEY_FREE) &&
794                            (aButton == Qt::RightButton) && 
795                          ( aState == Qt::ControlModifier || aState == ( Qt::ControlModifier|Qt::ShiftModifier ) ) ) ) {
796                 OCCViewer_ViewSketcher* sketcher = 0;
797                 QList<OCCViewer_ViewSketcher*>::Iterator it;
798                 for ( it = mySketchers.begin(); it != mySketchers.end() && !sketcher; ++it ) {
799                     OCCViewer_ViewSketcher* sk = (*it);
800                     if( sk->isDefault() && sk->sketchButton() == aButton )
801                         sketcher = sk;
802                 }
803                 if ( sketcher && myCurSketch == -1 ) {
804                     activateSketching( sketcher->type() );
805                     if ( mypSketcher ) {
806                         myCurSketch = mypSketcher->sketchButton();
807
808                         if ( l_mbPressEvent )  {
809                             QApplication::sendEvent( getViewPort(), l_mbPressEvent );
810                             delete l_mbPressEvent;
811                             l_mbPressEvent = 0;
812                         }
813                         QApplication::sendEvent( getViewPort(), theEvent );
814                     }
815                 }
816             } */else
817                 emit mouseMoving( this, theEvent );
818         }
819     }
820 }
821
822
823 /*!
824   \brief Draw rubber band rectangle.
825 */
826 void XGUI_ViewWindow::drawRect()
827 {
828     if ( !myRectBand ) {
829         myRectBand = new XGUI_RectRubberBand( myViewPort );
830     }
831
832     myRectBand->setUpdatesEnabled ( false );
833     QRect aRect = makeRect(myStartX, myStartY, myCurrX, myCurrY);
834     myRectBand->initGeometry( aRect );
835
836     if ( !myRectBand->isVisible() )
837         myRectBand->show();
838
839     myRectBand->setUpdatesEnabled ( true );
840 }
841
842 /*!
843   \brief Clear rubber band rectangle on the end on the dragging operation.
844 */
845 void XGUI_ViewWindow::endDrawRect()
846 {
847     if ( myRectBand ) {
848         myRectBand->clearGeometry();
849         myRectBand->hide();
850     }
851 }
852
853 void XGUI_ViewWindow::activateZoom()
854 {
855     if ( !transformRequested() && !myCursorIsHand )
856         myCursor = cursor();                /* save old cursor */
857
858     if ( myOperation != ZOOMVIEW ) {
859         QPixmap zoomPixmap (imageZoomCursor);
860         QCursor zoomCursor (zoomPixmap);
861         if( setTransformRequested ( ZOOMVIEW ) )
862             myViewPort->setCursor( zoomCursor );
863     }
864 }
865
866 bool XGUI_ViewWindow::transformRequested() const
867 {
868   return ( myOperation != NOTHING );
869 }
870
871 /*!
872   \brief Start delayed viewer operation.
873 */
874 bool XGUI_ViewWindow::setTransformRequested( OperationType op )
875 {
876   bool ok = transformEnabled( op );
877   myOperation = ok ? op : NOTHING;
878   myViewPort->setMouseTracking( myOperation == NOTHING );  
879   return ok;
880 }
881
882 /*!
883   Set enabled state of transformation (rotate, zoom, etc)
884 */
885 void XGUI_ViewWindow::setTransformEnabled( const OperationType id, const bool on )
886 {
887     if ( id != NOTHING ) myStatus.insert( id, on );
888 }
889
890 /*!
891   \return enabled state of transformation (rotate, zoom, etc)
892 */
893 bool XGUI_ViewWindow::transformEnabled( const OperationType id ) const
894 {
895     return myStatus.contains( id ) ? myStatus[ id ] : true;
896 }
897
898
899 /*!
900   \brief Start panning operation.
901
902   Sets the corresponding cursor for the widget.
903 */
904 void XGUI_ViewWindow::activatePanning()
905 {
906     if ( !transformRequested() && !myCursorIsHand )
907         myCursor = cursor();                // save old cursor
908
909     if ( myOperation != PANVIEW ) {
910         QCursor panCursor (Qt::SizeAllCursor);
911         if( setTransformRequested ( PANVIEW ) )
912             myViewPort->setCursor( panCursor );
913     }
914 }
915
916 /*!
917   \brief Start global panning operation
918
919   Sets the corresponding cursor for the widget.
920 */
921 void XGUI_ViewWindow::activateGlobalPanning()
922 {
923   Handle(V3d_View) aView3d = myViewPort->getView();
924   if ( !aView3d.IsNull() ) {
925     QPixmap globalPanPixmap (imageCrossCursor);
926     QCursor glPanCursor (globalPanPixmap);
927     myCurScale = aView3d->Scale();
928     aView3d->FitAll(0.01, false);
929     myCursor = cursor();                // save old cursor
930     myViewPort->fitAll(); // fits view before selecting a new scene center
931     if( setTransformRequested( PANGLOBAL ) )
932       myViewPort->setCursor( glPanCursor );
933   }
934 }
935
936 /*!
937   \brief Start rotation operation
938
939   Sets the corresponding cursor for the widget.
940 */
941 void XGUI_ViewWindow::activateRotation()
942 {
943     if ( !transformRequested() && !myCursorIsHand )
944         myCursor = cursor();                // save old cursor
945
946     if ( myOperation != ROTATE ) {
947         QPixmap rotatePixmap (imageRotateCursor);
948         QCursor rotCursor (rotatePixmap);
949         if( setTransformRequested ( ROTATE ) )
950         myViewPort->setCursor( rotCursor );
951     }
952 }
953
954 /*!
955   \brief Reset the viewport to its initial state
956   ( no transformations in process etc. )
957 */
958 void XGUI_ViewWindow::resetState()
959 {
960     myDrawRect = false;
961
962     if ( myRotationPointSelection ) {
963         QCursor handCursor (Qt::PointingHandCursor);
964         myViewPort->setCursor( handCursor );
965     } else {
966         if ( transformRequested() || myCursorIsHand )
967             myViewPort->setCursor( myCursor );
968         myCursorIsHand = false;
969     }
970
971     if ( transformRequested() )
972         emit vpTransformationFinished (myOperation);
973
974     setTransformInProcess( false );
975     setTransformRequested( NOTHING );
976 }
977
978 XGUI_ViewBackground XGUI_ViewWindow::background() const
979 {
980   return myViewPort ? myViewPort->background() : XGUI_ViewBackground();
981 }
982    
983 void XGUI_ViewWindow::setBackground( const XGUI_ViewBackground& theBackground )
984 {
985   if ( myViewPort ) myViewPort->setBackground( theBackground );
986 }
987
988 /*!
989    \brief Create one more window with same content.
990 */
991 void XGUI_ViewWindow::cloneView()
992 {
993   QMdiSubWindow* vw = myViewer->createView();
994   //vw->show();
995   emit viewCloned( vw );
996 }
997
998 void XGUI_ViewWindow::dumpView()
999 {
1000     QString aFilter(tr("OCC_IMAGE_FILES"));
1001     QString aSelectedFilter;
1002     QString aFileName = QFileDialog::getSaveFileName(this, "Save picture", QString(), aFilter, &aSelectedFilter);
1003     if (!aFileName.isNull()) {
1004         QApplication::setOverrideCursor( Qt::WaitCursor );
1005         QImage aPicture = myViewPort->dumpView();
1006
1007         QString aFmt = extension(aFileName).toUpper();
1008         if( aFmt.isEmpty() )
1009             aFmt = QString( "BMP" ); // default format
1010         else if( aFmt == "JPG" )
1011             aFmt = "JPEG";
1012           
1013         Handle(Visual3d_View) a3dView = myViewPort->getView()->View();
1014         if (aFmt == "PS")
1015             a3dView->Export(strdup(qPrintable(aFileName)), Graphic3d_EF_PostScript);
1016         else if (aFmt == "EPS")
1017             a3dView->Export(strdup(qPrintable(aFileName)), Graphic3d_EF_EnhPostScript);
1018         else
1019             aPicture.save( aFileName, aFmt.toLatin1() );
1020         QApplication::restoreOverrideCursor();
1021     }
1022 }
1023
1024 void XGUI_ViewWindow::fitAll()
1025 {
1026     emit vpTransformationStarted( FITALLVIEW );
1027     myViewPort->fitAll();
1028     emit vpTransformationFinished( FITALLVIEW );
1029 }
1030
1031 /*!
1032   \brief Starts fit operation.
1033
1034   Sets the corresponding cursor for the widget.
1035 */
1036 void XGUI_ViewWindow::activateWindowFit()
1037 {
1038   if ( !transformRequested() && !myCursorIsHand )
1039     myCursor = cursor();                /* save old cursor */
1040
1041   if ( myOperation != WINDOWFIT ) {
1042     QCursor handCursor (Qt::PointingHandCursor);
1043     if( setTransformRequested ( WINDOWFIT ) )
1044     {
1045       myViewPort->setCursor ( handCursor );
1046       myCursorIsHand = true;
1047     }
1048   }
1049 }
1050
1051
1052 /*!
1053   \brief Perform "front view" transformation.
1054 */
1055 void XGUI_ViewWindow::frontView()
1056 {
1057   emit vpTransformationStarted ( FRONTVIEW );
1058   Handle(V3d_View) aView3d = myViewPort->getView();
1059   if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Xpos);
1060   myViewPort->fitAll();
1061   emit vpTransformationFinished ( FRONTVIEW );
1062 }
1063
1064 /*!
1065   \brief Perform "back view" transformation.
1066 */
1067 void XGUI_ViewWindow::backView()
1068 {
1069   emit vpTransformationStarted ( BACKVIEW );
1070   Handle(V3d_View) aView3d = myViewPort->getView();
1071   if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Xneg);
1072   myViewPort->fitAll();
1073   emit vpTransformationFinished ( BACKVIEW );
1074 }
1075
1076 /*!
1077   \brief Perform "top view" transformation.
1078 */
1079 void XGUI_ViewWindow::topView()
1080 {
1081   emit vpTransformationStarted ( TOPVIEW );
1082   Handle(V3d_View) aView3d = myViewPort->getView();
1083   if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Zpos);
1084   myViewPort->fitAll();
1085   emit vpTransformationFinished ( TOPVIEW );
1086 }
1087
1088 /*!
1089   \brief Perform "bottom view" transformation.
1090 */
1091 void XGUI_ViewWindow::bottomView()
1092 {
1093   emit vpTransformationStarted ( BOTTOMVIEW );
1094   Handle(V3d_View) aView3d = myViewPort->getView();
1095   if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Zneg);
1096   myViewPort->fitAll();
1097   emit vpTransformationFinished ( BOTTOMVIEW );
1098 }
1099
1100 /*!
1101   \brief Perform "left view" transformation.
1102 */
1103 void XGUI_ViewWindow::leftView()
1104 {
1105   emit vpTransformationStarted ( LEFTVIEW );
1106   Handle(V3d_View) aView3d = myViewPort->getView();
1107   if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Yneg);
1108   myViewPort->fitAll();
1109   emit vpTransformationFinished ( LEFTVIEW );
1110 }
1111
1112 /*!
1113   \brief Perform "right view" transformation.
1114 */
1115 void XGUI_ViewWindow::rightView()
1116 {
1117   emit vpTransformationStarted ( RIGHTVIEW );
1118   Handle(V3d_View) aView3d = myViewPort->getView();
1119   if ( !aView3d.IsNull() ) aView3d->SetProj (V3d_Ypos);
1120   myViewPort->fitAll();
1121   emit vpTransformationFinished ( RIGHTVIEW );
1122 }