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