Salome HOME
47100f7c463e0e33c472f6c372d8978e939ce7f1
[modules/shaper.git] / src / XGUI / XGUI_Viewer.cpp
1 #include "XGUI_Viewer.h"
2 #include "XGUI_MainWindow.h"
3 #include "XGUI_ViewWindow.h"
4 #include "XGUI_ViewPort.h"
5 #include "XGUI_Preferences.h"
6
7 #include <SUIT_ResourceMgr.h>
8
9 #include <QMdiArea>
10 #include <QMdiSubWindow>
11 #include <QApplication>
12 #include <QMouseEvent>
13 #include <QMenu>
14
15 #include <V3d_View.hxx>
16
17 #include <Aspect_DisplayConnection.hxx>
18 #include <Graphic3d.hxx>
19 #include <Graphic3d_GraphicDriver.hxx>
20 #include <Geom_Axis2Placement.hxx>
21 #include <AIS_Drawer.hxx>
22 #include <Prs3d_DatumAspect.hxx>
23 #include <Prs3d_LineAspect.hxx>
24 #include <V3d_View.hxx>
25 #include <Visual3d_View.hxx>
26 #include <AIS_ListOfInteractive.hxx>
27 #include <AIS_ListIteratorOfListOfInteractive.hxx>
28 #include <AIS_Shape.hxx>
29
30 #ifdef WIN32
31 #include <WNT_Window.hxx>
32 #else
33 #include <Xw_Window.hxx>
34 #endif
35
36 XGUI_Viewer::InteractionStyle2StatesMap XGUI_Viewer::myStateMap;
37 XGUI_Viewer::InteractionStyle2ButtonsMap XGUI_Viewer::myButtonMap;
38 static bool isInitialized = false;
39
40 /*!
41  Creates viewer 3d [ static ]
42  */
43 Handle(V3d_Viewer) CreateViewer(const Standard_ExtString name, const Standard_CString displayName,
44                                 const Standard_CString domain, const Standard_Real viewSize,
45                                 const V3d_TypeOfOrientation viewProjection,
46                                 const Standard_Boolean computedMode,
47                                 const Standard_Boolean defaultComputedMode)
48 {
49   static Handle(Graphic3d_GraphicDriver) aGraphicDriver;
50   if (aGraphicDriver.IsNull()) {
51     Handle(Aspect_DisplayConnection) aDisplayConnection;
52 #ifndef WIN32
53     aDisplayConnection = new Aspect_DisplayConnection( displayName );
54 #else
55     aDisplayConnection = new Aspect_DisplayConnection();
56 #endif
57     aGraphicDriver = Graphic3d::InitGraphicDriver(aDisplayConnection);
58   }
59
60   return new V3d_Viewer(aGraphicDriver, name, domain, viewSize, viewProjection, Quantity_NOC_GRAY30,
61                         V3d_ZBUFFER, V3d_GOURAUD, V3d_WAIT, computedMode, defaultComputedMode,
62                         V3d_TEX_NONE);
63 }
64
65 // VSR: Uncomment below line to allow texture background support in OCC viewer
66 #define OCC_ENABLE_TEXTURED_BACKGROUND
67
68 /*!
69  Get data for supported background modes: gradient types, identifiers and supported image formats
70  */
71 QString XGUI_Viewer::backgroundData(QStringList& gradList, QIntList& idList, QIntList& txtList)
72 {
73   gradList << tr("Horizontal gradient") << tr("Vertical gradient") << tr("First diagonal gradient")
74            << tr("Second diagonal gradient") << tr("First corner gradient")
75            << tr("Second corner gradient") << tr("Third corner gradient")
76            << tr("Fourth corner gradient");
77   idList << XGUI::HorizontalGradient << XGUI::VerticalGradient << XGUI::Diagonal1Gradient
78          << XGUI::Diagonal2Gradient << XGUI::Corner1Gradient << XGUI::Corner2Gradient
79          << XGUI::Corner3Gradient << XGUI::Corner4Gradient;
80 #ifdef OCC_ENABLE_TEXTURED_BACKGROUND
81   txtList << XGUI::CenterTexture << XGUI::TileTexture << XGUI::StretchTexture;
82 #endif
83   return tr("Image files (*.bmp *.gif *.pix *.xwd *.rgb *.rs)");
84 }
85
86 XGUI_Viewer::XGUI_Viewer(XGUI_MainWindow* theParent, bool DisplayTrihedron)
87     : QObject(theParent),
88       myMainWindow(theParent),
89       myPreselectionEnabled(true),
90       mySelectionEnabled(true),
91       myMultiSelectionEnabled(true),
92       myIsRelative(true),
93       myInteractionStyle(XGUI::STANDARD),
94       myTrihedronSize(100),
95       myActiveView(0),
96       myWndIdCount(0)
97 {
98   if (!isInitialized) {
99     isInitialized = true;
100
101     // standard interaction style
102     XGUI_Viewer::myStateMap[XGUI::STANDARD][XGUI::ZOOM] = Qt::ControlModifier;
103     XGUI_Viewer::myButtonMap[XGUI::STANDARD][XGUI::ZOOM] = Qt::LeftButton;
104
105     XGUI_Viewer::myStateMap[XGUI::STANDARD][XGUI::PAN] = Qt::ControlModifier;
106     XGUI_Viewer::myButtonMap[XGUI::STANDARD][XGUI::PAN] = Qt::MidButton;
107
108     XGUI_Viewer::myStateMap[XGUI::STANDARD][XGUI::ROTATE] = Qt::ControlModifier;
109     XGUI_Viewer::myButtonMap[XGUI::STANDARD][XGUI::ROTATE] = Qt::RightButton;
110
111     XGUI_Viewer::myStateMap[XGUI::STANDARD][XGUI::FIT_AREA] = Qt::ControlModifier;
112     XGUI_Viewer::myButtonMap[XGUI::STANDARD][XGUI::FIT_AREA] = Qt::RightButton;
113
114     // "key free" interaction style
115     XGUI_Viewer::myStateMap[XGUI::KEY_FREE][XGUI::ZOOM] = Qt::NoModifier;
116     XGUI_Viewer::myButtonMap[XGUI::KEY_FREE][XGUI::ZOOM] = Qt::RightButton;
117
118     XGUI_Viewer::myStateMap[XGUI::KEY_FREE][XGUI::PAN] = Qt::NoModifier;
119     XGUI_Viewer::myButtonMap[XGUI::KEY_FREE][XGUI::PAN] = Qt::MidButton;
120
121     XGUI_Viewer::myStateMap[XGUI::KEY_FREE][XGUI::ROTATE] = Qt::NoModifier;
122     XGUI_Viewer::myButtonMap[XGUI::KEY_FREE][XGUI::ROTATE] = Qt::LeftButton;
123
124     XGUI_Viewer::myStateMap[XGUI::KEY_FREE][XGUI::FIT_AREA] = Qt::NoModifier;  // unused
125     XGUI_Viewer::myButtonMap[XGUI::KEY_FREE][XGUI::FIT_AREA] = Qt::NoButton;  // unused
126   }
127
128   // init CasCade viewers
129   myV3dViewer = CreateViewer(TCollection_ExtendedString("Viewer3d").ToExtString(), "", "", 1000.0,
130                              V3d_XposYnegZpos, Standard_True, Standard_True);
131   myV3dViewer->SetDefaultLights();
132
133   // init selector
134   myAISContext = new AIS_InteractiveContext(myV3dViewer);
135   myAISContext->SelectionColor(Quantity_NOC_WHITE);
136
137   // display isoline on planar faces (box for ex.)
138   myAISContext->IsoOnPlane(true);
139
140   if (DisplayTrihedron) {
141     Handle(Geom_Axis2Placement) anAxis = new Geom_Axis2Placement(gp::XOY());
142     myTrihedron = new AIS_Trihedron(anAxis);
143     myTrihedron->SetInfiniteState( Standard_True);
144
145     Quantity_Color Col(193 / 255., 205 / 255., 193 / 255., Quantity_TOC_RGB);
146     myTrihedron->SetArrowColor(Col.Name());
147     myTrihedron->SetSize(myTrihedronSize);
148     Handle(AIS_Drawer) drawer = myTrihedron->Attributes();
149     if (drawer->HasDatumAspect()) {
150       Handle(Prs3d_DatumAspect) daspect = drawer->DatumAspect();
151       daspect->FirstAxisAspect()->SetColor(Quantity_Color(1.0, 0.0, 0.0, Quantity_TOC_RGB));
152       daspect->SecondAxisAspect()->SetColor(Quantity_Color(0.0, 1.0, 0.0, Quantity_TOC_RGB));
153       daspect->ThirdAxisAspect()->SetColor(Quantity_Color(0.0, 0.0, 1.0, Quantity_TOC_RGB));
154     }
155   }
156   // set zooming style to standard
157   //myZoomingStyle = 0;
158
159   QMdiArea* aMDI = myMainWindow->mdiArea();
160   connect(aMDI, SIGNAL(subWindowActivated(QMdiSubWindow*)), this,
161           SLOT(onWindowActivated(QMdiSubWindow*)));
162
163 }
164
165 XGUI_Viewer::~XGUI_Viewer(void)
166 {
167   myAISContext.Nullify();
168   myV3dViewer.Nullify();
169 }
170
171 QMdiSubWindow* XGUI_Viewer::createView(V3d_TypeOfView theType)
172 {
173   // create view frame
174   XGUI_ViewWindow* view = new XGUI_ViewWindow(this, theType);
175   // get main view window (created by view frame)
176   //OCCViewer_ViewWindow* vw = view->getView(OCCViewer_ViewFrame::MAIN_VIEW);
177   // initialize main view window
178   //initView( vw );
179   // set default background for view window
180   //vw->setBackground( background(0) ); // 0 means MAIN_VIEW (other views are not yet created here)
181   // connect signal from viewport
182   //connect(view->viewPort(), SIGNAL(vpClosed()), this, SLOT(onViewClosed()));
183   //connect(view->viewPort(), SIGNAL(vpMapped()), this, SLOT(onViewMapped()));
184   if (myViews.size() == 0)
185     setTrihedronShown(true);
186
187   Qtx::BackgroundData aBk = XGUI_Preferences::resourceMgr()->backgroundValue("Viewer",
188                                                                              "background");
189   view->setBackground(aBk);
190   view->updateEnabledDrawMode();
191
192   QMdiArea* aMDI = myMainWindow->mdiArea();
193   QMdiSubWindow* aWnd = aMDI->addSubWindow(view, Qt::FramelessWindowHint);
194   addView(aWnd);
195   aWnd->setGeometry(0, 0, aMDI->width() / 2, aMDI->height() / 2);
196   aWnd->show();
197   aWnd->setWindowTitle(QString("Viewer #%1").arg(++myWndIdCount));
198   emit viewCreated(view);
199   return aWnd;
200 }
201
202 void XGUI_Viewer::updateFromResources()
203 {
204   Qtx::BackgroundData aBk = XGUI_Preferences::resourceMgr()->backgroundValue("Viewer",
205                                                                              "background");
206   foreach (QMdiSubWindow* aWnd, myViews)
207   {
208     XGUI_ViewWindow* aView = dynamic_cast<XGUI_ViewWindow*>(aWnd->widget());
209     if (aView)
210       aView->setBackground(aBk);
211   }
212 }
213
214 XGUI_ViewWindow* XGUI_Viewer::activeViewWindow() const
215 {
216   if (myActiveView)
217     return dynamic_cast<XGUI_ViewWindow*>(myActiveView->widget());
218   return 0;
219 }
220
221 void XGUI_Viewer::getSelectedObjects(AIS_ListOfInteractive& theList)
222 {
223   theList.Clear();
224   for (myAISContext->InitSelected(); myAISContext->MoreSelected(); myAISContext->NextSelected())
225     theList.Append(myAISContext->SelectedInteractive());
226 }
227
228 void XGUI_Viewer::getSelectedShapes(NCollection_List<TopoDS_Shape>& theList)
229 {
230   Handle(AIS_InteractiveContext) ic = AISContext();
231
232   for (ic->InitSelected(); ic->MoreSelected(); ic->NextSelected()) {
233     TopoDS_Shape aShape = ic->SelectedShape();
234     if (!aShape.IsNull())
235       theList.Append(aShape);
236   }
237 }
238
239 void XGUI_Viewer::setObjectsSelected(const AIS_ListOfInteractive& theList)
240 {
241   AIS_ListIteratorOfListOfInteractive aIt;
242   for (aIt.Initialize(theList); aIt.More(); aIt.Next())
243     myAISContext->AddOrRemoveSelected(aIt.Value(), false);
244   myAISContext->UpdateCurrentViewer();
245 }
246
247 /*! Sets hot button
248  *\param theOper - hot operation
249  *\param theState - adding state to state map operations.
250  *\param theButton - adding state to button map operations.
251  */
252 void XGUI_Viewer::setHotButton(XGUI::InteractionStyle theInteractionStyle,
253                                XGUI::HotOperation theOper, Qt::KeyboardModifiers theState,
254                                Qt::MouseButtons theButton)
255 {
256   myStateMap[theInteractionStyle][theOper] = theState;
257   myButtonMap[theInteractionStyle][theOper] = theButton;
258 }
259
260 /*! Gets hot button for operation \a theOper.
261  *\param theOper - input hot operation
262  *\param theState - output state from state map operations.
263  *\param theButton - output state from button map operations.
264  */
265 void XGUI_Viewer::getHotButton(XGUI::InteractionStyle theInteractionStyle,
266                                XGUI::HotOperation theOper, Qt::KeyboardModifiers& theState,
267                                Qt::MouseButtons& theButton)
268 {
269   theState = myStateMap[theInteractionStyle][theOper];
270   theButton = myButtonMap[theInteractionStyle][theOper];
271 }
272
273 /*!
274  Changes visibility of trihedron to opposite
275  */
276 void XGUI_Viewer::toggleTrihedron()
277 {
278   setTrihedronShown(!isTrihedronVisible());
279 }
280
281 /*!
282  \return true if trihedron is visible
283  */
284 bool XGUI_Viewer::isTrihedronVisible() const
285 {
286   return !myTrihedron.IsNull() && !myAISContext.IsNull() && myAISContext->IsDisplayed(myTrihedron);
287 }
288
289 /*!
290  Sets visibility state of trihedron
291  \param on - new state
292  */
293
294 void XGUI_Viewer::setTrihedronShown(bool on)
295 {
296   if (myTrihedron.IsNull())
297     return;
298
299   if (on) {
300     myAISContext->Display(myTrihedron);
301     myAISContext->Deactivate(myTrihedron);
302   } else {
303     myAISContext->Erase(myTrihedron);
304   }
305 }
306
307 /*!
308  \return trihedron size
309  */
310 double XGUI_Viewer::trihedronSize() const
311 {
312   double sz = 0;
313   if (!myTrihedron.IsNull())
314     sz = myTrihedron->Size();
315   return sz;
316 }
317
318 /*!
319  Changes trihedron size
320  \param sz - new size
321  */
322 void XGUI_Viewer::setTrihedronSize(const double sz, bool isRelative)
323 {
324   if (myTrihedronSize != sz || isRelative != myIsRelative) {
325     myTrihedronSize = sz;
326     myIsRelative = isRelative;
327     updateTrihedron();
328   }
329 }
330
331 /*! 
332  * Update the size of the trihedron
333  */
334 void XGUI_Viewer::updateTrihedron()
335 {
336   if (myTrihedron.IsNull())
337     return;
338
339   if (myIsRelative) {
340     double newSz, oldSz;
341
342     if (computeTrihedronSize(newSz, oldSz))
343       myTrihedron->SetSize(newSz);
344
345   } else if (myTrihedron->Size() != myTrihedronSize) {
346     myTrihedron->SetSize(myTrihedronSize);
347   }
348 }
349
350 /*!
351  Get new and current trihedron size corresponding to the current model size
352  */
353 bool XGUI_Viewer::computeTrihedronSize(double& theNewSize, double& theSize)
354 {
355   theNewSize = 100;
356   theSize = 100;
357
358   //SRN: BUG IPAL8996, a usage of method ActiveView without an initialization
359   Handle(V3d_Viewer) viewer = v3dViewer();
360   viewer->InitActiveViews();
361   if (!viewer->MoreActiveViews())
362     return false;
363
364   Handle(V3d_View) view3d = viewer->ActiveView();
365   //SRN: END of fix
366
367   if (view3d.IsNull())
368     return false;
369
370   double Xmin = 0, Ymin = 0, Zmin = 0, Xmax = 0, Ymax = 0, Zmax = 0;
371   double aMaxSide;
372
373   view3d->View()->MinMaxValues(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
374
375   if (Xmin == RealFirst() || Ymin == RealFirst() || Zmin == RealFirst() || Xmax == RealLast()
376       || Ymax == RealLast() || Zmax == RealLast())
377     return false;
378
379   aMaxSide = Xmax - Xmin;
380   if (aMaxSide < Ymax - Ymin)
381     aMaxSide = Ymax - Ymin;
382   if (aMaxSide < Zmax - Zmin)
383     aMaxSide = Zmax - Zmin;
384
385   // IPAL21687
386   // The boundary box of the view may be initialized but nullified
387   // (case of infinite objects)
388   if (aMaxSide < Precision::Confusion())
389     return false;
390
391   static float EPS = (float) 5.0E-3;
392   theSize = trihedron()->Size();
393   //theNewSize = aMaxSide*aSizeInPercents / 100.0;
394
395   return fabs(theNewSize - theSize) > theSize * EPS || fabs(theNewSize - theSize) > theNewSize * EPS;
396 }
397
398 void XGUI_Viewer::onViewClosed(QMdiSubWindow* theView)
399 {
400   if (!theView)
401     return;
402
403   emit deleteView(static_cast<XGUI_ViewWindow*>(theView->widget()));
404   removeView(theView);
405
406   // if this is last view
407   if (myViews.size() == 0) {
408     Standard_Integer aViewsNb = 0;
409     for (myV3dViewer->InitActiveViews(); myV3dViewer->MoreActiveViews();
410         myV3dViewer->NextActiveViews())
411       ++aViewsNb;
412     if (aViewsNb < 2) {
413       //clean up presentations before last view is closed
414       myAISContext->RemoveAll(Standard_False);
415     }
416   }
417 }
418
419 /*!Remove view window \a theView from view manager.
420  *And close the last view, if it has \a theView.
421  */
422 void XGUI_Viewer::removeView(QMdiSubWindow* theView)
423 {
424   XGUI_ViewWindow* aWindow = static_cast<XGUI_ViewWindow*>(theView->widget());
425
426   aWindow->disconnect(this);
427   myViews.removeAt(myViews.indexOf(theView));
428   if (myActiveView == theView)
429     myActiveView = 0;
430   if (myViews.size() == 0)
431     emit lastViewClosed();
432 }
433
434 /*void XGUI_Viewer::onViewMapped()
435  {
436  setTrihedronShown(true);
437  }*/
438
439 void XGUI_Viewer::addView(QMdiSubWindow* theView)
440 {
441   XGUI_ViewWindow* aWindow = dynamic_cast<XGUI_ViewWindow*>(theView->widget());
442
443   connect(aWindow, SIGNAL(closed(QMdiSubWindow*)), this, SLOT(onViewClosed(QMdiSubWindow*)));
444
445   connect(aWindow, SIGNAL(tryClosing(XGUI_ViewWindow*)), this,
446           SIGNAL(tryCloseView(XGUI_ViewWindow*)));
447
448   connect(aWindow, SIGNAL(mousePressed(XGUI_ViewWindow*, QMouseEvent*)), this,
449           SLOT(onMousePressed(XGUI_ViewWindow*, QMouseEvent*)));
450
451   connect(aWindow, SIGNAL(mouseDoubleClicked(XGUI_ViewWindow*, QMouseEvent*)), this,
452           SIGNAL(mouseDoubleClick(XGUI_ViewWindow*, QMouseEvent*)));
453
454   connect(aWindow, SIGNAL(mouseMoving(XGUI_ViewWindow*, QMouseEvent*)), this,
455           SIGNAL(mouseMove(XGUI_ViewWindow*, QMouseEvent*)));
456
457   connect(aWindow, SIGNAL(keyPressed(XGUI_ViewWindow*, QKeyEvent*)), this,
458           SIGNAL(keyPress(XGUI_ViewWindow*, QKeyEvent*)));
459
460   connect(aWindow, SIGNAL(keyReleased(XGUI_ViewWindow*, QKeyEvent*)), this,
461           SLOT(onKeyRelease(XGUI_ViewWindow*, QKeyEvent*)));
462
463   //connect(aWindow, SIGNAL(contextMenuRequested( QContextMenuEvent* )),
464   //        this,    SLOT  (onContextMenuRequested( QContextMenuEvent* )));
465   connect(aWindow, SIGNAL(contextMenuRequested(QContextMenuEvent*)), this,
466           SIGNAL(contextMenuRequested(QContextMenuEvent*)));
467
468   connect(aWindow, SIGNAL(mouseMoving(XGUI_ViewWindow*, QMouseEvent*)), this,
469           SLOT(onMouseMove(XGUI_ViewWindow*, QMouseEvent*)));
470
471   connect(aWindow, SIGNAL(mouseReleased(XGUI_ViewWindow*, QMouseEvent*)), this,
472           SLOT(onMouseReleased(XGUI_ViewWindow*, QMouseEvent*)));
473
474   myViews.append(theView);
475 }
476
477 /*!
478  Emit activated for view \a view.
479  */
480 void XGUI_Viewer::onWindowActivated(QMdiSubWindow* view)
481 {
482   if (view && (view != myActiveView) && (!view->isMinimized())) {
483     myActiveView = view;
484     ((XGUI_ViewWindow*) myActiveView->widget())->windowActivated();
485     QList<QMdiSubWindow*>::iterator aIt;
486     for (aIt = myViews.begin(); aIt != myViews.end(); ++aIt) {
487       if ((*aIt) != myActiveView) {
488         ((XGUI_ViewWindow*) (*aIt)->widget())->windowDeactivated();
489       }
490     }
491   }
492 }
493
494 void XGUI_Viewer::onWindowMinimized(QMdiSubWindow* theWnd)
495 {
496   if (myActiveView == theWnd) {
497     myActiveView = 0;
498     QList<QMdiSubWindow*>::iterator aIt;
499     for (aIt = myViews.begin(); aIt != myViews.end(); ++aIt) {
500       if (!(*aIt)->widget()->isMinimized()) {
501         (*aIt)->raise();
502         onWindowActivated(*aIt);
503         break;
504       }
505     }
506   }
507 }
508
509 /*!
510  SLOT: called on mouse button press, stores current mouse position as start point for transformations
511  */
512 void XGUI_Viewer::onMousePressed(XGUI_ViewWindow* theWindow, QMouseEvent* theEvent)
513 {
514   myStartPnt.setX(theEvent->x());
515   myStartPnt.setY(theEvent->y());
516   emit mousePress(theWindow, theEvent);
517 }
518
519 /*!
520  SLOT: called on mouse move, processes hilighting
521  */
522 void XGUI_Viewer::onMouseMove(XGUI_ViewWindow* theWindow, QMouseEvent* theEvent)
523 {
524   myCurPnt.setX(theEvent->x());
525   myCurPnt.setY(theEvent->y());
526   if (!mySelectionEnabled)
527     return;
528
529   Handle(V3d_View) aView3d = theWindow->viewPort()->getView();
530   if (!aView3d.IsNull()) {
531     myAISContext->MoveTo(theEvent->x(), theEvent->y(), aView3d);
532     if (myAISContext->HasDetected())
533       theWindow->viewPort()->setFocus(Qt::MouseFocusReason);
534   }
535 }
536
537 /*!
538  SLOT: called on mouse button release, finishes selection
539  */
540 void XGUI_Viewer::onMouseReleased(XGUI_ViewWindow* theWindow, QMouseEvent* theEvent)
541 {
542   if (!mySelectionEnabled || theEvent->button() != Qt::LeftButton) {
543     emit mouseRelease(theWindow, theEvent);
544     return;
545   }
546
547   myEndPnt.setX(theEvent->x());
548   myEndPnt.setY(theEvent->y());
549   bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
550
551   //if (!aHasShift) 
552   //  emit deselection();
553
554   if (myStartPnt == myEndPnt) {
555     // the MoveTo is necessary for the second click in the same point. Otherwise the selection is lost.
556     //Handle(V3d_View) aView3d = theWindow->viewPort()->getView();
557     //if (!aView3d.IsNull()) {
558     //  myAISContext->MoveTo(theEvent->x(), theEvent->y(), aView3d);
559     //}
560     if (aHasShift && myMultiSelectionEnabled)
561       myAISContext->ShiftSelect();
562     else
563       myAISContext->Select();
564   } else {
565     if (aHasShift && myMultiSelectionEnabled)
566       myAISContext->ShiftSelect(myStartPnt.x(), myStartPnt.y(), myEndPnt.x(), myEndPnt.y(),
567                                 theWindow->viewPort()->getView(), false);
568     else
569       myAISContext->Select(myStartPnt.x(), myStartPnt.y(), myEndPnt.x(), myEndPnt.y(),
570                            theWindow->viewPort()->getView(), false);
571
572     int Nb = myAISContext->NbSelected();
573     if (Nb > 1 && !myMultiSelectionEnabled) {
574       myAISContext->InitSelected();
575       Handle( SelectMgr_EntityOwner ) anOwner = myAISContext->SelectedOwner();
576       if (!anOwner.IsNull()) {
577         myAISContext->ClearSelected( Standard_False);
578         myAISContext->AddOrRemoveSelected(anOwner, Standard_False);
579       }
580     }
581
582     myAISContext->UpdateCurrentViewer();
583   }
584   emit mouseRelease(theWindow, theEvent);
585   emit selectionChanged();
586 }
587
588 //******************************************************
589 void XGUI_Viewer::setMultiSelectionEnabled(bool toEnable)
590 {
591   myMultiSelectionEnabled = toEnable;
592   updateViewsDrawMode();
593 }
594
595 //******************************************************
596 void XGUI_Viewer::setSelectionEnabled(bool toEnable)
597 {
598   mySelectionEnabled = toEnable;
599   updateViewsDrawMode();
600 }
601
602 //******************************************************
603 void XGUI_Viewer::updateViewsDrawMode() const
604 {
605   foreach(QMdiSubWindow* aWnd, myViews)
606   {
607     XGUI_ViewWindow* aView = static_cast<XGUI_ViewWindow*>(aWnd->widget());
608     aView->updateEnabledDrawMode();
609   }
610 }
611
612 //******************************************************
613 void XGUI_Viewer::onKeyRelease(XGUI_ViewWindow* theView, QKeyEvent* theKey)
614 {
615   Handle(V3d_View) aView = theView->viewPort()->getView();
616   bool noModifiers = (theKey->modifiers() == Qt::NoModifier);
617   if ((theKey->key() == Qt::Key_N) && noModifiers) {
618     myAISContext->HilightNextDetected(aView);
619   } else if ((theKey->key() == Qt::Key_P) && noModifiers) {
620     myAISContext->HilightPreviousDetected(aView);
621   } else {
622     emit keyRelease(theView, theKey);
623   }
624 }
625
626 //******************************************************
627 //void XGUI_Viewer::onContextMenuRequested(QContextMenuEvent* theEvent)
628 //{
629 //  XGUI_ViewWindow* aWnd = dynamic_cast<XGUI_ViewWindow*>(sender());
630 //  if (!aWnd) return;
631 //
632 //  QMenu aMenu;
633 //
634 //  // Include Viewer actions
635 //  if (myActions.size() > 0) {
636 //    aMenu.addActions(myActions);
637 //    aMenu.addSeparator();
638 //  }
639 //  if (aWnd->actions().size() > 0) {
640 //    aMenu.addActions(aWnd->actions());
641 //    aMenu.addSeparator();
642 //  }
643 //
644 //  QMdiArea* aMDI = myMainWindow->mdiArea();
645 //  if (aMenu.actions().size() > 0) {
646 //    QMenu* aSubMenu = aMenu.addMenu(tr("Windows"));
647 //    aSubMenu->addActions(aMDI->actions());
648 //  } else {
649 //    aMenu.addActions(aMDI->actions());
650 //  }
651 //  aMenu.exec(theEvent->globalPos());
652 //}