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