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