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