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