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