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