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