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