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