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