Salome HOME
0c05bd6acab4a1279db5a5e38a84a961555b83ff
[modules/gui.git] / src / OCCViewer / OCCViewer_ViewModel.cxx
1 // Copyright (C) 2007-2023  CEA, EDF, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "OCCViewer_ViewModel.h"
24 #include "OCCViewer_ViewFrame.h"
25 #include "OCCViewer_VService.h"
26 #include "OCCViewer_ViewPort3d.h"
27 #include "OCCViewer_ClippingDlg.h"
28 #include "OCCViewer_Utilities.h"
29
30 #include "SUIT_ViewWindow.h"
31 #include "SUIT_ViewManager.h"
32 #include "SUIT_Desktop.h"
33 #include "SUIT_Session.h"
34 #include "SUIT_ResourceMgr.h"
35
36 #include "ViewerData_AISShape.hxx"
37
38 #include "QtxActionToolMgr.h"
39 #include "QtxBackgroundTool.h"
40
41 #include <QPainter>
42 #include <QApplication>
43 #include <QColorDialog>
44 #include <QFileDialog>
45 #include <QPalette>
46 #include <QKeyEvent>
47 #include <QMenu>
48 #include <QMouseEvent>
49 #include <QToolBar>
50 #include <QDesktopWidget>
51
52 #include <AIS_Axis.hxx>
53 #include <Prs3d_Drawer.hxx>
54 #include <AIS_ListIteratorOfListOfInteractive.hxx>
55 #include <StdSelect_ViewerSelector3d.hxx>
56
57 #include <Graphic3d_Texture2Dmanual.hxx>
58 #include <Graphic3d_MaterialAspect.hxx>
59 #include <Graphic3d_TextureParams.hxx>
60
61 #include <Geom_Axis2Placement.hxx>
62 #include <Prs3d_Drawer.hxx>
63 #include <Prs3d_DatumAspect.hxx>
64 #include <Prs3d_LineAspect.hxx>
65 #include <Prs3d_TextAspect.hxx>
66
67 #include <V3d_DirectionalLight.hxx>
68 #include <V3d_AmbientLight.hxx>
69
70 #include <Basics_OCCTVersion.hxx>
71
72 namespace
73 {
74   void setCappingColor(const Handle(Graphic3d_ClipPlane)& plane, const QColor& color)
75   {
76     Quantity_Color qcolor( color.redF(), color.greenF(), color.blueF(), Quantity_TOC_RGB );
77 #if OCC_VERSION_LARGE < 0x07040000
78     Graphic3d_MaterialAspect aspect;
79     aspect.SetColor( qcolor );
80     plane->SetCappingMaterial( aspect );
81 #else
82     plane->SetCappingColor( qcolor );
83 #endif
84   }
85 }
86
87 /*!
88   Get data for supported background modes: gradient types, identifiers and supported image formats
89 */
90 QString OCCViewer_Viewer::backgroundData( QStringList& gradList, QIntList& idList, QIntList& txtList )
91 {
92   gradList << tr("GT_HORIZONTALGRADIENT")    << tr("GT_VERTICALGRADIENT")       <<
93               tr("GT_FIRSTDIAGONALGRADIENT") << tr("GT_SECONDDIAGONALGRADIENT") <<
94               tr("GT_FIRSTCORNERGRADIENT")   << tr("GT_SECONDCORNERGRADIENT")   <<
95               tr("GT_THIRDCORNERGRADIENT")   << tr("GT_FORTHCORNERGRADIENT");
96   idList   << HorizontalGradient             << VerticalGradient  <<
97               Diagonal1Gradient              << Diagonal2Gradient <<
98               Corner1Gradient                << Corner2Gradient   <<
99               Corner3Gradient                << Corner4Gradient;
100   txtList  << Qtx::CenterTexture << Qtx::TileTexture << Qtx::StretchTexture;
101   return tr("BG_IMAGE_FILES");
102 }
103
104 /*!
105   Get data for supported stereo pair modes: stereo types and identifiers
106 */
107 void OCCViewer_Viewer::stereoData( QStringList& typeList, QIntList& idList)
108 {
109   typeList << tr("ST_QUADBUFFER")    << tr("ST_ANAGLYPH")         <<
110               tr("ST_ROWINTERLACED") << tr("ST_COLUMNINTERLACED") <<
111               tr("ST_CHESSBOARD")    << tr("ST_SIDEBYSIDE")       <<
112               tr("ST_OVERUNDER");
113   idList   << QuadBufferType    << AnaglyphType         <<
114               RowInterlacedType << ColumnInterlacedType <<
115               ChessBoardType    << SideBySideType       <<
116               OverUnderType;
117 }
118
119 /*!
120   Constructor
121   \param DisplayTrihedron - is trihedron displayed
122 */
123 OCCViewer_Viewer::OCCViewer_Viewer( bool DisplayTrihedron)
124 : SUIT_ViewModel(),
125   myIsRelative(true),
126   myTopLayerId(0),
127   myTrihedronSize(100),
128   myBackgrounds(4, Qtx::BackgroundData(Qt::black)),
129   myClippingDlg(0),
130   myFitter(0)
131 {
132   // init CasCade viewers
133   myV3dViewer = OCCViewer_VService::CreateViewer();
134   //myV3dViewer->Init(); // to avoid creation of the useless perspective view (see OCCT issue 0024267)
135   setDefaultLights();
136
137   // init selector
138   myAISContext = new AIS_InteractiveContext( myV3dViewer );
139   myAISContext->HighlightStyle(Prs3d_TypeOfHighlight_LocalSelected)->SetColor( Quantity_NOC_WHITE );
140   myAISContext->HighlightStyle(Prs3d_TypeOfHighlight_Selected)->SetColor( Quantity_NOC_WHITE );
141
142   // display isoline on planar faces (box for ex.)
143   myAISContext->IsoOnPlane( true );
144
145   // create color scale
146   myColorScale = new AIS_ColorScale();
147   myColorScale->SetZLayer( Graphic3d_ZLayerId_TopOSD );
148 #if OCC_VERSION_LARGE < 0x07070000
149   myColorScale->SetTransformPersistence( Graphic3d_TransformPers::FromDeprecatedParams( Graphic3d_TMF_2d, gp_Pnt(-1, -1, 0) ) );
150 #else
151   myColorScale->SetTransformPersistence( new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER) );
152 #endif
153
154   /* create trihedron */
155   if ( DisplayTrihedron )
156   {
157     Handle(Geom_Axis2Placement) anAxis = new Geom_Axis2Placement(gp::XOY());
158     myTrihedron = new AIS_Trihedron(anAxis);
159     myTrihedron->SetInfiniteState( Standard_True );
160
161     Quantity_Color Col(193/255., 205/255., 193/255., Quantity_TOC_RGB);
162     //myTrihedron->SetColor( Col );
163     myTrihedron->SetArrowColor( Col.Name() );
164     myTrihedron->SetSize(100);
165     Handle(Prs3d_Drawer) drawer = myTrihedron->Attributes();
166     if (drawer->HasOwnDatumAspect()) {
167       Handle(Prs3d_DatumAspect) daspect = drawer->DatumAspect();
168       daspect->LineAspect(Prs3d_DP_XAxis)->SetColor(Quantity_Color(1.0, 0.0, 0.0, Quantity_TOC_RGB));
169       daspect->LineAspect(Prs3d_DP_YAxis)->SetColor(Quantity_Color(0.0, 1.0, 0.0, Quantity_TOC_RGB));
170       daspect->LineAspect(Prs3d_DP_ZAxis)->SetColor(Quantity_Color(0.0, 0.0, 1.0, Quantity_TOC_RGB));
171     }
172   }
173
174   /* create view cube */
175   myViewCube  = new AIS_ViewCube();
176   setViewCubeParamsFromPreferences();
177
178   // set interaction style to standard
179   myInteractionStyle = 0;
180
181   // set zooming style to standard
182   myZoomingStyle = 0;
183
184   // preselection
185   myPreselectionEnabled = true;
186
187   // selection
188   mySelectionEnabled = true;
189   myMultiSelectionEnabled = true;
190
191   // set projection type to orthographic
192   myProjectionType = 0;
193   mySelectionStyle = OCCViewer_ViewWindow::RectStyle;
194   // set stereo parameters
195   myStereoType = 0;
196   myAnaglyphFilter = 0;
197   myToReverseStereo = 0;
198   myVSyncMode = 1;
199   myQuadBufferSupport = 0;
200   myStereographicFocusType = 1;
201   myInterocularDistanceType = 1;
202   myStereographicFocusValue = 1.0;
203   myInterocularDistanceValue = 0.05;
204   //set clipping color and texture to standard
205   myClippingColor = QColor( 50, 50, 50 );
206   myDefaultTextureUsed = true;
207   myClippingTexture = QString();
208   myTextureModulated = true;
209   myClippingTextureScale = 1.0;
210
211 }
212
213 /*!
214   Destructor
215 */
216 OCCViewer_Viewer::~OCCViewer_Viewer() 
217 {
218   myAISContext.Nullify();
219   myV3dViewer.Nullify();
220 }
221
222 /*!
223   [obsolete]
224   \return background color of viewer
225 */
226 QColor OCCViewer_Viewer::backgroundColor() const
227 {
228   return backgroundColor(0);
229 }
230
231 /*!
232   \return background data of viewer
233 */
234 Qtx::BackgroundData OCCViewer_Viewer::background() const
235 {
236   return background(0);
237 }
238
239 /*!
240   Sets background color [obsolete]
241   \param c - new background color
242 */
243 void OCCViewer_Viewer::setBackgroundColor( const QColor& c )
244 {
245   setBackgroundColor( 0, c );
246 }
247
248 /*!
249   Sets background data
250   \param d - new background data
251 */
252 void OCCViewer_Viewer::setBackground( const Qtx::BackgroundData& theBackground )
253 {
254   setBackground( 0, theBackground );
255 }
256
257 /*!
258   Start initialization of view window
259   \param view - view window to be initialized
260 */
261 void OCCViewer_Viewer::initView( OCCViewer_ViewWindow* view )
262 {
263   if ( view ) {
264     view->initLayout();
265     view->initSketchers();
266     view->setInteractionStyle( interactionStyle() );
267     view->setProjectionType( projectionType() );
268     view->setSelectionStyle( selectionStyle() );
269     view->setStereoType( stereoType() );
270     view->setAnaglyphFilter( anaglyphFilter() );
271     view->setStereographicFocus( stereographicFocusType(), stereographicFocusValue() );
272     view->setInterocularDistance( interocularDistanceType(), interocularDistanceValue() );
273     view->setReverseStereo( isReverseStereo() );
274     view->setVSync( isVSync() );
275     view->setQuadBufferSupport( isQuadBufferSupport() );
276     view->setZoomingStyle( zoomingStyle() );
277     view->enablePreselection( isPreselectionEnabled() );
278     view->enableSelection( isSelectionEnabled() );
279
280     OCCViewer_ViewPort3d* vp3d = view->getViewPort();
281     if ( vp3d )
282     {
283       // connect signal from viewport
284       connect(vp3d, SIGNAL(vpClosed(OCCViewer_ViewPort3d*)), this, SLOT(onViewClosed(OCCViewer_ViewPort3d*)));
285       connect(vp3d, SIGNAL(vpMapped(OCCViewer_ViewPort3d*)), this, SLOT(onViewMapped(OCCViewer_ViewPort3d*)));
286     }
287   }
288 }
289
290 /*!
291   Creates new view window
292   \param theDesktop - main window of application
293 */
294 SUIT_ViewWindow* OCCViewer_Viewer::createView( SUIT_Desktop* theDesktop )
295 {
296   // create view frame
297   OCCViewer_ViewFrame* view = new OCCViewer_ViewFrame(theDesktop, this);
298   // get main view window (created by view frame)
299   OCCViewer_ViewWindow* vw = view->getView(OCCViewer_ViewFrame::MAIN_VIEW);
300   // initialize main view window
301   initView( vw );
302   // set default background for view window
303   vw->setBackground( background(0) ); // 0 means MAIN_VIEW (other views are not yet created here)
304
305   return view;
306 }
307
308 /*!
309   Sets new view manager
310   \param theViewManager - new view manager
311 */
312 void OCCViewer_Viewer::setViewManager(SUIT_ViewManager* theViewManager)
313 {
314   SUIT_ViewModel::setViewManager(theViewManager);
315   if (theViewManager) {
316     connect(theViewManager, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)), 
317             this, SLOT(onMousePress(SUIT_ViewWindow*, QMouseEvent*)));
318
319     connect(theViewManager, SIGNAL(mouseMove(SUIT_ViewWindow*, QMouseEvent*)), 
320             this, SLOT(onMouseMove(SUIT_ViewWindow*, QMouseEvent*)));
321
322     connect(theViewManager, SIGNAL(mouseRelease(SUIT_ViewWindow*, QMouseEvent*)), 
323             this, SLOT(onMouseRelease(SUIT_ViewWindow*, QMouseEvent*)));
324
325     connect(theViewManager, SIGNAL(keyPress(SUIT_ViewWindow*, QKeyEvent*)), 
326             this, SLOT(onKeyPress(SUIT_ViewWindow*, QKeyEvent*)));
327   }
328 }
329
330 /*!
331   SLOT: called on mouse button press, stores current mouse position as start point for transformations
332 */
333 void OCCViewer_Viewer::onMousePress(SUIT_ViewWindow* /*theWindow*/, QMouseEvent* theEvent)
334 {
335   myStartPnt.setX(theEvent->x()); myStartPnt.setY(theEvent->y());
336 }
337
338 /*!
339   SLOT: called on mouse move, processes transformation or hilighting
340 */
341 void OCCViewer_Viewer::onMouseMove(SUIT_ViewWindow* theWindow, QMouseEvent* theEvent)
342 {
343   if (!mySelectionEnabled) return;
344   if (!theWindow->inherits("OCCViewer_ViewWindow")) return;
345
346   OCCViewer_ViewWindow* aView = (OCCViewer_ViewWindow*) theWindow;
347
348   myCurPnt.setX(theEvent->x()); myCurPnt.setY(theEvent->y());
349
350   if ( isSelectionEnabled() && isPreselectionEnabled() ) {
351     if (aView->getViewPort()->isBusy()) {
352       QCoreApplication::processEvents();
353       return; // Check that the ViewPort initialization completed
354                                                 // To Prevent call move event if the View port is not initialized
355                                                 // IPAL 20883
356     }
357     Handle(V3d_View) aView3d = aView->getViewPort()->getView();
358     if ( !aView3d.IsNull() ) {
359       myAISContext->MoveTo( theEvent->x(), theEvent->y(), aView3d, Standard_True );
360     }
361   }
362 }
363
364
365 /*!
366   SLOT: called on mouse button release, finishes transformation or selection
367 */
368 void OCCViewer_Viewer::onMouseRelease(SUIT_ViewWindow* theWindow, QMouseEvent* theEvent)
369 {
370   if (!mySelectionEnabled) return;
371   if (theEvent->button() != Qt::LeftButton) return;
372   if (!theWindow->inherits("OCCViewer_ViewWindow")) return;
373
374   OCCViewer_ViewWindow* aView = (OCCViewer_ViewWindow*) theWindow;
375   if (!aView )
376     return;
377
378   myEndPnt.setX(theEvent->x()); myEndPnt.setY(theEvent->y());
379   bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
380   
381   if (myStartPnt == myEndPnt)
382   {
383     if (!aHasShift) {
384       myAISContext->ClearCurrents( false ); // todo: ClearCurrents is deprecated
385       emit deselection();
386     }
387     if ( !isPreselectionEnabled() ) {
388       Handle(V3d_View) aView3d = aView->getViewPort()->getView();
389       if ( !aView3d.IsNull() ) {
390               myAISContext->MoveTo( myEndPnt.x(), myEndPnt.y(), aView3d, Standard_True );
391       }
392     }
393
394     if (aHasShift && myMultiSelectionEnabled)
395       myAISContext->ShiftSelect( Standard_True );
396     else 
397       myAISContext->Select( Standard_True );
398     emit selectionChanged();
399   }
400
401   //else
402   //{
403   //  if (aHasShift && myMultiSelectionEnabled)
404   //    myAISContext->ShiftSelect(myStartPnt.x(), myStartPnt.y(),
405   //                              myEndPnt.x(), myEndPnt.y(),
406   //                              aView->getViewPort()->getView(), Standard_False );
407   //  else
408   //    myAISContext->Select(myStartPnt.x(), myStartPnt.y(),
409   //                         myEndPnt.x(), myEndPnt.y(),
410   //                         aView->getViewPort()->getView(), Standard_False );
411
412   //  int Nb = myAISContext->NbSelected();
413   //  if( Nb>1 && !myMultiSelectionEnabled )
414   //  {
415   //      myAISContext->InitSelected();
416   //      Handle( SelectMgr_EntityOwner ) anOwner = myAISContext->SelectedOwner();
417   //      if( !anOwner.IsNull() )
418   //      {
419   //          myAISContext->ClearSelected( Standard_False );
420   //          myAISContext->AddOrRemoveSelected( anOwner, Standard_False );
421   //      }
422   //  }
423
424   //  myAISContext->UpdateCurrentViewer();
425   //}
426 }
427
428 /*!
429   SLOT: called on key press, processes selection in "key free" interaction style
430 */
431 void OCCViewer_Viewer::onKeyPress(SUIT_ViewWindow* theWindow, QKeyEvent* theEvent)
432 {
433   if (!mySelectionEnabled) return;
434
435   OCCViewer_ViewWindow* aView = qobject_cast<OCCViewer_ViewWindow*>( theWindow );
436   if ( !aView ) return;
437
438   bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
439
440   switch ( theEvent->key() ) {
441   case  Qt::Key_S:
442     if (!aHasShift) {
443       myAISContext->ClearCurrents( false ); // todo: ClearCurrents is deprecated
444       emit deselection();
445     }
446
447     if ( !isPreselectionEnabled() ) {
448       Handle(V3d_View) aView3d = aView->getViewPort()->getView();
449       if ( !aView3d.IsNull() ) {
450         myAISContext->MoveTo(myCurPnt.x(), myCurPnt.y(), aView3d, Standard_True );
451       }
452     }
453
454     if (aHasShift && myMultiSelectionEnabled)
455       myAISContext->ShiftSelect( Standard_True );
456     else
457       myAISContext->Select( Standard_True );
458
459     emit selectionChanged();
460
461     break;
462   case  Qt::Key_N:
463     if ( isPreselectionEnabled() ) {
464       getAISContext()->HilightNextDetected( aView->getViewPort()->getView() );
465     }
466     break;
467   case  Qt::Key_P:
468     if ( isPreselectionEnabled() ) {
469       getAISContext()->HilightPreviousDetected( aView->getViewPort()->getView() );
470     }
471     break;
472   default:
473     break;
474   }
475 }
476
477 void OCCViewer_Viewer::onViewClosed(OCCViewer_ViewPort3d*)
478 {
479   Standard_Integer aViewsNb = 0;
480   for ( myV3dViewer->InitActiveViews(); myV3dViewer->MoreActiveViews(); myV3dViewer->NextActiveViews())
481     ++aViewsNb;
482   if ( aViewsNb < 2 ) {
483     //clean up presentations before last view is closed
484     myAISContext->RemoveAll(Standard_False);
485   }
486 }
487
488 void OCCViewer_Viewer::onViewMapped(OCCViewer_ViewPort3d* viewPort)
489 {
490   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
491
492   setTrihedronShown( true );
493
494   bool showViewCube = true;
495   if ( resMgr ) showViewCube = resMgr->booleanValue( "OCCViewer", "viewcube_show", true );
496   setViewCubeShown( showViewCube );
497
498   bool showStaticTrihedron = true;
499   if ( resMgr ) showStaticTrihedron = resMgr->booleanValue( "3DViewer", "show_static_trihedron", true );
500   viewPort->showStaticTrihedron( showStaticTrihedron );
501 }
502
503 int OCCViewer_Viewer::getTopLayerId()
504 {
505   if ( myTopLayerId == 0 && !myAISContext->CurrentViewer().IsNull() )    
506     myAISContext->CurrentViewer()->AddZLayer( myTopLayerId );
507
508   return myTopLayerId;
509 }
510
511 /*!
512   \return interaction style
513 */
514 int OCCViewer_Viewer::interactionStyle() const
515 {
516   return myInteractionStyle;
517 }
518
519 /*!
520   Sets interaction style: 0 - standard, 1 - keyboard free interaction
521   \param theStyle - new interaction style
522 */
523 void OCCViewer_Viewer::setInteractionStyle( const int theStyle )
524 {
525   myInteractionStyle = theStyle;
526   //!! To be done for view windows
527   if ( !myViewManager )
528     return;
529
530   QVector<SUIT_ViewWindow*> wins = myViewManager->getViews();
531   for ( int i = 0; i < (int)wins.count(); i++ )
532   {
533     OCCViewer_ViewWindow* win = ::qobject_cast<OCCViewer_ViewWindow*>( wins.at( i ) );
534     if ( win )
535       win->setInteractionStyle( theStyle );
536   }
537 }
538
539 /*!
540   \return projection type
541 */
542 int OCCViewer_Viewer::projectionType() const
543 {
544   return myProjectionType;
545 }
546
547 /*!
548   Sets projection type: 0 - orthographic, 1 - perspective
549   \param theType - new projection type
550 */
551 void OCCViewer_Viewer::setProjectionType( const int theType )
552 {
553   if ( myProjectionType != theType ) {
554     if ( theType != OCCViewer_ViewWindow::Stereo )
555       myProjectionType = theType;
556
557     if ( !myViewManager )
558       return;
559
560     QVector<SUIT_ViewWindow*> wins = myViewManager->getViews();
561     for ( int i = 0; i < (int)wins.count(); i++ )
562     {
563       OCCViewer_ViewWindow* win = ::qobject_cast<OCCViewer_ViewWindow*>( wins.at( i ) );
564       if ( win )
565         win->setProjectionType( (OCCViewer_ViewWindow::ProjectionType)theType );
566     }
567   }
568 }
569
570
571 OCCViewer_ViewWindow::SelectionStyle OCCViewer_Viewer::selectionStyle() const
572 {
573   return mySelectionStyle;
574 }
575
576 void OCCViewer_Viewer::setSelectionStyle(OCCViewer_ViewWindow::SelectionStyle theMode)
577 {
578   if (mySelectionStyle != theMode) {
579     mySelectionStyle = theMode;
580     if (!myViewManager)
581       return;
582
583     QVector<SUIT_ViewWindow*> wins = myViewManager->getViews();
584     for (int i = 0; i < (int)wins.count(); i++)
585     {
586       OCCViewer_ViewWindow* win = ::qobject_cast<OCCViewer_ViewWindow*>(wins.at(i));
587       if (win)
588         win->setSelectionStyle(theMode);
589     }
590   }
591 }
592
593
594
595 /*!
596   \return stereo type
597 */
598 int OCCViewer_Viewer::stereoType() const
599 {
600   return myStereoType;
601 }
602
603 /*!
604   Sets stereo type
605   \param theType - new stereo type
606 */
607 void OCCViewer_Viewer::setStereoType( const int theType )
608 {
609   myStereoType = theType;
610
611   if ( !myViewManager )
612     return;
613
614   QVector<SUIT_ViewWindow*> wins = myViewManager->getViews();
615   for ( int i = 0; i < (int)wins.count(); i++ )
616   {
617     OCCViewer_ViewWindow* win = ::qobject_cast<OCCViewer_ViewWindow*>( wins.at( i ) );
618     if ( win )
619       win->setStereoType( (OCCViewer_ViewWindow::StereoType)theType );
620   }
621 }
622
623 /*!
624   \return stereographic focus type
625 */
626 int OCCViewer_Viewer::stereographicFocusType() const
627 {
628   return myStereographicFocusType;
629 }
630
631 /*!
632   \return stereographic focus value
633 */
634 double OCCViewer_Viewer::stereographicFocusValue() const
635 {
636   return myStereographicFocusValue;
637 }
638
639 /*!
640   Sets stereographic focus parameters
641   \param theType - new stereographic focus type
642   \param theValue - new stereographic focus value
643 */
644 void OCCViewer_Viewer::setStereographicFocus( const int theType, const double theValue )
645 {
646   myStereographicFocusType = theType;
647   myStereographicFocusValue = theValue;
648
649   if ( !myViewManager )
650     return;
651
652   QVector<SUIT_ViewWindow*> wins = myViewManager->getViews();
653   for ( int i = 0; i < (int)wins.count(); i++ )
654   {
655     OCCViewer_ViewWindow* win = ::qobject_cast<OCCViewer_ViewWindow*>( wins.at( i ) );
656     if ( win )
657       win->setStereographicFocus( (OCCViewer_ViewWindow::FocusIODType)theType, theValue );
658   }
659 }
660
661 /*!
662   \return stereographic focus type
663 */
664 int OCCViewer_Viewer::interocularDistanceType() const
665 {
666   return myInterocularDistanceType;
667 }
668
669 /*!
670   \return stereographic focus value
671 */
672 double OCCViewer_Viewer::interocularDistanceValue() const
673 {
674   return myInterocularDistanceValue;
675 }
676
677 /*!
678   Sets interocular distance parameters
679   \param theType - new IOD type
680   \param theValue - new IOD value
681 */
682 void OCCViewer_Viewer::setInterocularDistance( const int theType, const double theValue )
683 {
684   myInterocularDistanceType = theType;
685   myInterocularDistanceValue = theValue;
686
687   if ( !myViewManager )
688     return;
689
690   QVector<SUIT_ViewWindow*> wins = myViewManager->getViews();
691   for ( int i = 0; i < (int)wins.count(); i++ )
692   {
693     OCCViewer_ViewWindow* win = ::qobject_cast<OCCViewer_ViewWindow*>( wins.at( i ) );
694     if ( win )
695       win->setInterocularDistance( (OCCViewer_ViewWindow::FocusIODType)theType, theValue );
696   }
697 }
698
699 /*!
700   \return anaglyph filter
701 */
702 int OCCViewer_Viewer::anaglyphFilter() const
703 {
704   return myAnaglyphFilter;
705 }
706
707 /*!
708   Sets anaglyph filter
709   \param theType - new anaglyph filter
710 */
711 void OCCViewer_Viewer::setAnaglyphFilter( const int theType )
712 {
713   myAnaglyphFilter = theType;
714
715   if ( !myViewManager )
716     return;
717
718   QVector<SUIT_ViewWindow*> wins = myViewManager->getViews();
719   for ( int i = 0; i < (int)wins.count(); i++ )
720   {
721     OCCViewer_ViewWindow* win = ::qobject_cast<OCCViewer_ViewWindow*>( wins.at( i ) );
722     if ( win )
723       win->setAnaglyphFilter( (OCCViewer_ViewWindow::AnaglyphFilter)theType );
724   }
725 }
726
727 /*!
728   \return reverse stereo
729 */
730 bool OCCViewer_Viewer::isReverseStereo() const
731 {
732   return myToReverseStereo;
733 }
734
735 /*!
736   Sets reverse stereo
737   \param theReverse - enable/disable reverse mode
738 */
739 void OCCViewer_Viewer::setReverseStereo( const bool theReverse )
740 {
741   myToReverseStereo = theReverse;
742
743   if ( !myViewManager )
744     return;
745
746   QVector<SUIT_ViewWindow*> wins = myViewManager->getViews();
747   for ( int i = 0; i < (int)wins.count(); i++ )
748   {
749     OCCViewer_ViewWindow* win = ::qobject_cast<OCCViewer_ViewWindow*>( wins.at( i ) );
750     if ( win )
751       win->setReverseStereo( theReverse );
752   }
753 }
754
755 /*!
756   \return V-Sync mode
757 */
758 bool OCCViewer_Viewer::isVSync() const
759 {
760   return myVSyncMode;
761 }
762
763 /*!
764   Set V-Sync mode
765   \param theEnable - enable/disable V-Sync mode
766 */
767 void OCCViewer_Viewer::setVSync( const bool theEnable )
768 {
769   myVSyncMode = theEnable;
770
771   if ( !myViewManager )
772     return;
773
774   QVector<SUIT_ViewWindow*> wins = myViewManager->getViews();
775   for ( int i = 0; i < (int)wins.count(); i++ )
776   {
777     OCCViewer_ViewWindow* win = ::qobject_cast<OCCViewer_ViewWindow*>( wins.at( i ) );
778     if ( win )
779       win->setVSync( theEnable );
780   }
781 }
782
783 /*!
784   \return support quad-buffered stereo
785 */
786 bool OCCViewer_Viewer::isQuadBufferSupport() const
787 {
788   return myQuadBufferSupport;
789 }
790
791 /*!
792   Set support quad-buffered stereo
793   \param theEnable - enable/disable support quad-buffered stereo
794 */
795 void OCCViewer_Viewer::setQuadBufferSupport( const bool theEnable )
796 {
797   myQuadBufferSupport = theEnable;
798
799   if ( !myViewManager )
800     return;
801
802   QVector<SUIT_ViewWindow*> wins = myViewManager->getViews();
803   for ( int i = 0; i < (int)wins.count(); i++ )
804   {
805     OCCViewer_ViewWindow* win = ::qobject_cast<OCCViewer_ViewWindow*>( wins.at( i ) );
806     if ( win )
807       win->setQuadBufferSupport( theEnable );
808   }
809 }
810
811 /*!
812   \return zooming style
813 */
814 int OCCViewer_Viewer::zoomingStyle() const
815 {
816   return myZoomingStyle;
817 }
818
819 /*!
820   Sets zooming style: 0 - standard, 1 - advanced (at cursor)
821   \param theStyle - new zooming style
822 */
823 void OCCViewer_Viewer::setZoomingStyle( const int theStyle )
824 {
825   myZoomingStyle = theStyle;
826   //!! To be done for view windows
827   if ( !myViewManager )
828     return;
829
830   QVector<SUIT_ViewWindow*> wins = myViewManager->getViews();
831   for ( int i = 0; i < (int)wins.count(); i++ )
832   {
833     OCCViewer_ViewWindow* win = ::qobject_cast<OCCViewer_ViewWindow*>( wins.at( i ) );
834     if ( win )
835       win->setZoomingStyle( theStyle );
836   }
837 }
838
839 /*!
840   \return true if preselection is enabled
841 */
842 bool OCCViewer_Viewer::isPreselectionEnabled() const 
843
844   return myPreselectionEnabled; 
845 }
846
847 /*!
848   Enables/disables preselection
849   \param isEnabled - new status
850 */
851 void OCCViewer_Viewer::enablePreselection(bool isEnabled)
852 {
853   myPreselectionEnabled = isEnabled;
854
855   if ( !myViewManager )
856     return;
857
858   QVector<SUIT_ViewWindow*> wins = myViewManager->getViews();
859   for ( int i = 0; i < (int)wins.count(); i++ )
860   {
861     OCCViewer_ViewWindow* win = ::qobject_cast<OCCViewer_ViewWindow*>( wins.at( i ) );
862     if ( win ) {
863       win->enablePreselection( isEnabled );
864     }
865   }
866 }
867
868 /*!
869   \return true if selection is enabled
870 */
871 bool OCCViewer_Viewer::isSelectionEnabled() const 
872
873   return mySelectionEnabled; 
874 }
875
876 /*!
877   Enables/disables selection
878   \param isEnabled - new status
879 */
880 void OCCViewer_Viewer::enableSelection(bool isEnabled)
881 {
882   mySelectionEnabled = isEnabled;
883
884   //!! To be done for view windows
885   if ( !myViewManager )
886     return;
887
888   QVector<SUIT_ViewWindow*> wins = myViewManager->getViews();
889   for ( int i = 0; i < (int)wins.count(); i++ )
890   {
891     OCCViewer_ViewWindow* win = ::qobject_cast<OCCViewer_ViewWindow*>( wins.at( i ) );
892     if ( win ) {
893       win->updateEnabledDrawMode();
894       win->enableSelection( isEnabled );
895     }
896   }
897
898   
899   //clear current selection in the viewer
900   if(!isEnabled) {
901     myAISContext->ClearSelected( Standard_True );
902   }
903
904 }
905
906 /*!
907   Sets multiselection enabled status
908   \param isEnabled - new status
909 */
910 void OCCViewer_Viewer::enableMultiselection(bool isEnable)
911 {
912   myMultiSelectionEnabled = isEnable;
913   //!! To be done for view windows
914   if ( !myViewManager )
915     return;
916
917   QVector<SUIT_ViewWindow*> wins = myViewManager->getViews();
918   for ( int i = 0; i < (int)wins.count(); i++ )
919   {
920     OCCViewer_ViewWindow* win = ::qobject_cast<OCCViewer_ViewWindow*>( wins.at( i ) );
921     if ( win )
922       win->updateEnabledDrawMode();
923   }
924 }
925
926 /*!
927   Sets a color of the clipped region
928   \param theColor - a new color of the clipped region
929 */
930 void OCCViewer_Viewer::setClippingColor( const QColor& theColor )
931 {
932   myClippingColor = theColor;
933
934   if( myInternalClipPlanes.IsEmpty() )
935     return;
936
937   for ( Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt ( myInternalClipPlanes ); aPlaneIt.More(); aPlaneIt.Next() )
938     setCappingColor( aPlaneIt.Value(), theColor );
939
940   update();
941 }
942
943 /*!
944   \return clipping color
945 */
946 QColor OCCViewer_Viewer::clippingColor() const
947 {
948   return myClippingColor;
949 }
950
951 // initialize a texture for clipped region
952 Handle(Graphic3d_Texture2Dmanual) initClippingTexture( const bool isDefault, const QString& theTexture,
953                                                        const bool isModulate, const double theScale )
954 {
955   QString aTextureFile = isDefault ? ":images/hatch.png" : theTexture;
956   QPixmap px( aTextureFile );
957   const Handle(Image_PixMap) aPixmap = OCCViewer_Utilities::imageToPixmap( px.toImage() );
958   Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual( aPixmap );
959   if( aTexture->IsDone() ) {
960     aTexture->EnableRepeat();
961     isModulate ? aTexture->EnableModulate() : aTexture->DisableModulate();
962     aTexture->GetParams()->SetScale( Graphic3d_Vec2( 1/( theScale*100 ), -1 / ( theScale*100 ) ) );
963   }
964   return aTexture;
965 }
966
967 /*!
968   Sets default texture parameters
969   \param isDefault - use/non-use default texture
970   \param theTexture - new texture of the clipped region
971   \param isModulate - enable/disable texture modulate mode
972   \param theScale - scale factor.
973 */
974 void OCCViewer_Viewer::setClippingTextureParams( const bool isDefault, const QString& theTexture,
975                                                  const bool isModulate, const double theScale )
976 {
977   myDefaultTextureUsed = isDefault;
978   myClippingTexture = theTexture;
979   myTextureModulated = isModulate;
980   myClippingTextureScale = theScale;
981
982   if( myInternalClipPlanes.IsEmpty() )
983     return;
984
985   Handle(Graphic3d_Texture2Dmanual) aTexture =
986     initClippingTexture( myDefaultTextureUsed, myClippingTexture,
987                          myTextureModulated, myClippingTextureScale );
988   for ( Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt ( myInternalClipPlanes ); aPlaneIt.More(); aPlaneIt.Next() )
989     aPlaneIt.Value()->SetCappingTexture( aTexture );
990
991   update();
992 }
993
994 /*!
995   \return true if default texture is used
996 */
997 bool OCCViewer_Viewer::isDefaultTextureUsed() const
998 {
999   return myDefaultTextureUsed;
1000 }
1001
1002 /*!
1003   \return clipping texture
1004 */
1005 QString OCCViewer_Viewer::clippingTexture() const
1006 {
1007   return myClippingTexture;
1008 }
1009
1010 /*!
1011   \return true if texture is modulated
1012 */
1013 bool OCCViewer_Viewer::isTextureModulated() const
1014 {
1015   return myTextureModulated;
1016 }
1017
1018 /*!
1019   \return scale factor of texture
1020 */
1021 double OCCViewer_Viewer::clippingTextureScale() const
1022 {
1023   return myClippingTextureScale;
1024 }
1025
1026 /*!
1027   Builds popup for occ viewer
1028 */
1029 void OCCViewer_Viewer::contextMenuPopup(QMenu* thePopup)
1030 {
1031   thePopup->addAction( tr( "MEN_DUMP_VIEW" ), this, SLOT( onDumpView() ) );
1032   thePopup->addAction( tr( "MEN_CHANGE_BACKGROUND" ), this, SLOT( onChangeBackground() ) );
1033
1034   thePopup->addSeparator();
1035
1036   OCCViewer_ViewWindow* aView = (OCCViewer_ViewWindow*)(myViewManager->getActiveView());
1037
1038   //Support of several toolbars in the popup menu
1039   QList<QToolBar*> lst = aView->findChildren<QToolBar*>();
1040   QList<QToolBar*>::const_iterator it = lst.begin(), last = lst.end();
1041   for ( ; it!=last; it++ ) {
1042     if ( (*it)->parentWidget()->isVisible() )
1043       thePopup->addAction( (*it)->toggleViewAction() );
1044   }
1045 }
1046
1047 /*!
1048   SLOT: called on dump view operation is activated, stores scene to raster file
1049 */
1050 void OCCViewer_Viewer::onDumpView()
1051 {
1052   OCCViewer_ViewWindow* aView = (OCCViewer_ViewWindow*)(myViewManager->getActiveView());
1053   if ( aView )
1054     aView->onDumpView();
1055 }
1056
1057 /*!
1058   SLOT: called if background color is to be changed changed, passes new color to view port
1059 */
1060 void OCCViewer_Viewer::onChangeBackground()
1061 {
1062   OCCViewer_ViewWindow* aView = dynamic_cast<OCCViewer_ViewWindow*>(myViewManager->getActiveView());
1063   if ( !aView )
1064     return;
1065
1066   // get supported gradient types
1067   QStringList gradList;
1068   QIntList    idList, txtList;
1069   QString     formats = backgroundData( gradList, idList, txtList );
1070
1071   // invoke dialog box
1072   Qtx::BackgroundData bgData = QtxBackgroundDialog::getBackground( aView->background(),  // initial background
1073                                                                    aView,                // parent for dialog box
1074                                                                    txtList,              // allowed texture modes
1075                                                                    true,                 // enable solid color mode
1076                                                                    true,                 // enable gradient mode
1077                                                                    false,                // disable custom gradient mode
1078                                                                    !txtList.isEmpty(),   // enable/disable texture mode
1079                                                                    gradList,             // gradient names
1080                                                                    idList,               // gradient identifiers
1081                                                                    formats );            // image formats
1082
1083   // set chosen background data to the viewer
1084   if ( bgData.isValid() )
1085     aView->setBackground( bgData );
1086 }
1087
1088 /*!
1089   Updates OCC 3D viewer
1090 */
1091 void OCCViewer_Viewer::update()
1092 {
1093   if (!myV3dViewer.IsNull())
1094     myV3dViewer->Update();
1095
1096   OCCViewer_ViewWindow* aView = (OCCViewer_ViewWindow*)(myViewManager->getActiveView());
1097   if ( aView )
1098     aView->updateGravityCoords();
1099 }
1100
1101 /*!
1102   \return objects selected in 3D viewer
1103   \param theList - list to be filled with selected objects
1104 */
1105 void OCCViewer_Viewer::getSelectedObjects(AIS_ListOfInteractive& theList)
1106 {
1107   theList.Clear();
1108   for (myAISContext->InitSelected(); myAISContext->MoreSelected(); myAISContext->NextSelected())
1109     theList.Append(myAISContext->SelectedInteractive());
1110 }
1111
1112 /*!
1113   Selects objects in 3D viewer. Other selected objects are left as selected
1114   \param theList - list objects to be selected
1115 */
1116 void OCCViewer_Viewer::setObjectsSelected(const AIS_ListOfInteractive& theList)
1117 {
1118   AIS_ListIteratorOfListOfInteractive aIt;
1119   for (aIt.Initialize(theList); aIt.More(); aIt.Next())
1120     myAISContext->AddOrRemoveSelected(aIt.Value(), false);
1121   myAISContext->UpdateCurrentViewer();
1122 }
1123
1124 /*!
1125   Auxiliary method to emit signal selectionChanged()
1126 */
1127 void OCCViewer_Viewer::performSelectionChanged()
1128 {
1129     emit selectionChanged();
1130 }
1131
1132 /*
1133  * Defines default lights
1134  */
1135 void OCCViewer_Viewer::setDefaultLights()
1136 {
1137   // clear all light sources
1138   myV3dViewer->InitDefinedLights();
1139   while ( myV3dViewer->MoreDefinedLights() )
1140   {
1141     myV3dViewer->DelLight( myV3dViewer->DefinedLight() );
1142     myV3dViewer->InitDefinedLights();
1143   }
1144
1145   // get light source parameters from preferences
1146   QColor aColor = SUIT_Session::session()->resourceMgr()->colorValue( "OCCViewer", "light_color", QColor( 0, 0, 0 ) );
1147   double aDx = SUIT_Session::session()->resourceMgr()->doubleValue( "OCCViewer", "light_dx", 0.0 );
1148   double aDy = SUIT_Session::session()->resourceMgr()->doubleValue( "OCCViewer", "light_dy", 0.0 );
1149   double aDz = SUIT_Session::session()->resourceMgr()->doubleValue( "OCCViewer", "light_dz", -1.0 );
1150
1151   Handle(V3d_DirectionalLight) aLight =
1152     new V3d_DirectionalLight( V3d_Zneg, OCCViewer::color( aColor ).Name(), Standard_True );
1153   myV3dViewer->AddLight( aLight );
1154   if( !( aDx == 0 && aDy == 0 && aDz == 0 ) )
1155     aLight->SetDirection( aDx, aDy, aDz );
1156   myV3dViewer->SetLightOn( aLight );
1157   Handle(V3d_AmbientLight) ambLight = new V3d_AmbientLight();
1158   myV3dViewer->AddLight( ambLight );
1159   myV3dViewer->SetLightOn( ambLight );
1160 }
1161
1162 /*!
1163   Hilights/unhilights object in viewer
1164   \param obj - object to be updated
1165   \param hilight - if it is true, object will be hilighted, otherwise it will be unhilighted
1166   \param update - update current viewer
1167 */
1168 bool OCCViewer_Viewer::highlight( const Handle(AIS_InteractiveObject)& obj,
1169                                   bool hilight, bool update )
1170 {
1171   if( !obj.IsNull() ) {
1172     if ( hilight && !myAISContext->IsSelected( obj ) )
1173       myAISContext->AddOrRemoveSelected( obj, false );
1174     else if ( !hilight && myAISContext->IsSelected( obj ) )
1175       myAISContext->AddOrRemoveSelected( obj, false );
1176   }
1177
1178   if ( update )
1179     myV3dViewer->Redraw();
1180   
1181   return false;
1182 }
1183
1184 /*!
1185   Unhilights all objects in viewer
1186   \param updateviewer - update current viewer
1187 */
1188 bool OCCViewer_Viewer::unHighlightAll( bool updateviewer, bool unselect )
1189 {
1190   if ( unselect ) {
1191     myAISContext->ClearSelected( updateviewer );
1192   } else {
1193     myAISContext->UnhilightSelected( updateviewer );
1194   }
1195   return false;
1196 }
1197
1198 /*!
1199   \return true if object is in viewer or in collector
1200   \param obj - object to be checked
1201   \param onlyInViewer - search object only in viewer (so object must be displayed)
1202 */
1203 bool OCCViewer_Viewer::isInViewer( const Handle(AIS_InteractiveObject)& obj,
1204                                    bool /*onlyInViewer*/ )
1205 {
1206   AIS_ListOfInteractive List;
1207   myAISContext->DisplayedObjects(List);
1208
1209   AIS_ListIteratorOfListOfInteractive ite(List);
1210   for ( ; ite.More(); ite.Next() )
1211     if( ite.Value()==obj )
1212       return true;
1213
1214   return false;
1215 }
1216
1217 /*!
1218   \return true if object is displayed in viewer
1219   \param obj - object to be checked
1220 */
1221 bool OCCViewer_Viewer::isVisible( const Handle(AIS_InteractiveObject)& obj )
1222 {
1223   return myAISContext->IsDisplayed( obj );
1224 }
1225
1226 /*!
1227   Sets color of object
1228   \param obj - object to be updated
1229   \param color - new color
1230   \param update - update current viewer
1231 */
1232 void OCCViewer_Viewer::setColor( const Handle(AIS_InteractiveObject)& obj,
1233                                  const QColor& color,
1234                                  bool update )
1235 {
1236   if( !obj.IsNull() )
1237   {
1238     Quantity_Color CSFColor = Quantity_Color ( color.red() / 255.,
1239                                                color.green() / 255.,
1240                                                color.blue() / 255.,
1241                                                Quantity_TOC_RGB );
1242     obj->SetColor( CSFColor );
1243   }
1244
1245   if( update )
1246     myV3dViewer->Update();
1247 }
1248
1249 /*!
1250   Changes display mode of object
1251   \param obj - object to be processed
1252   \param mode - new display mode
1253   \param update - update current viewer
1254 */
1255 void OCCViewer_Viewer::switchRepresentation( const Handle(AIS_InteractiveObject)& obj,
1256                                              int mode, bool update )
1257 {
1258   myAISContext->SetDisplayMode( obj, (Standard_Integer)mode, update );
1259   if( update )
1260     myV3dViewer->Update();
1261 }
1262
1263 /*!
1264   Changes transparency of object
1265   \param obj - object to be processed
1266   \param trans - new transparency
1267   \param update - update current viewer
1268 */
1269 void OCCViewer_Viewer::setTransparency( const Handle(AIS_InteractiveObject)& obj,
1270                                         float trans, bool update )
1271 {
1272   myAISContext->SetTransparency( obj, trans, false );
1273   myAISContext->Redisplay( obj, Standard_False, Standard_True );
1274   if( update )
1275     myV3dViewer->Update();
1276 }
1277
1278 bool OCCViewer_Viewer::isColorScaleVisible() const
1279 {
1280   return !myColorScale.IsNull() && !myAISContext.IsNull() && myAISContext->IsDisplayed( myColorScale );
1281 }
1282
1283 void OCCViewer_Viewer::setColorScaleShown( const bool on )
1284 {
1285   if ( myColorScale.IsNull() )
1286     return;
1287   if ( on )
1288   {
1289     if ( !myAISContext->IsDisplayed( myColorScale ) )
1290       myAISContext->Display( myColorScale, Standard_True );
1291     myAISContext->Redisplay( myColorScale, Standard_True, Standard_True );
1292   }
1293   else
1294   {
1295     if ( myAISContext->IsDisplayed( myColorScale ) )
1296       myAISContext->Erase( myColorScale, Standard_True );
1297   }
1298 }
1299
1300 /*!
1301   \return true if trihedron is visible
1302 */
1303 bool OCCViewer_Viewer::isTrihedronVisible() const
1304 {
1305   return !myTrihedron.IsNull() && !myAISContext.IsNull() && myAISContext->IsDisplayed( myTrihedron );
1306 }
1307
1308 /*!
1309   \return true if view cube is visible
1310 */
1311 bool OCCViewer_Viewer::isViewCubeVisible() const
1312 {
1313   return !myViewCube.IsNull() && !myAISContext.IsNull() && myAISContext->IsDisplayed( myViewCube );
1314 }
1315
1316 /*!
1317   Sets visibility state of trihedron
1318   \param on - new state
1319 */
1320
1321 void OCCViewer_Viewer::setTrihedronShown( const bool on )
1322 {
1323   if ( myTrihedron.IsNull() )
1324     return;
1325
1326   if ( on ) {
1327     myAISContext->Display( myTrihedron,
1328                            0 /*wireframe*/,
1329                            -1 /* selection mode */,
1330                            Standard_True /* update viewer*/,
1331                            AIS_DS_Displayed /* display status */);
1332     myAISContext->Deactivate( myTrihedron );
1333   }
1334   else {
1335     myAISContext->Erase( myTrihedron , Standard_True );
1336   }
1337 }
1338
1339 /*!
1340   Sets visibility state of view cube
1341   \param on - new state
1342 */
1343
1344 void OCCViewer_Viewer::setViewCubeShown( const bool on )
1345 {
1346   if ( myViewCube.IsNull() )
1347     return;
1348
1349   if ( on ) {
1350     myAISContext->Display( myViewCube,
1351                            0 /*wireframe*/,
1352                            0 /* selection mode */,
1353                            Standard_True /* update viewer*/,
1354                            AIS_DS_Displayed /* display status */);
1355   }
1356   else {
1357     myAISContext->Erase( myViewCube, Standard_True );
1358   }
1359 }
1360
1361 /*!
1362   Set View Cube parameters from preferences
1363 */
1364 void OCCViewer_Viewer::setViewCubeParamsFromPreferences()
1365 {
1366   // Resource manager
1367   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1368   if (!resMgr || myViewCube.IsNull())
1369     return;
1370
1371   bool isVisibleVC = isVisible(myViewCube);
1372
1373   if (resMgr->booleanValue("OCCViewer", "viewcube_custom", false)) {
1374     // Use custom settings from preferences
1375     QColor aColor;
1376
1377     // Box color
1378     aColor = resMgr->colorValue("OCCViewer", "viewcube_color", QColor(255, 255, 255));
1379     myViewCube->SetBoxColor(OCCViewer::color(aColor));
1380
1381     // Size
1382     myViewCube->SetSize(resMgr->doubleValue("OCCViewer", "viewcube_size", 70.0));
1383
1384     // Text color
1385     aColor = resMgr->colorValue("OCCViewer", "viewcube_text_color", QColor(0, 0, 0));
1386     myViewCube->SetTextColor(OCCViewer::color(aColor));
1387   }
1388   else {
1389     myViewCube->ResetStyles();
1390   }
1391
1392   // Axes
1393   myViewCube->SetDrawAxes(resMgr->booleanValue("OCCViewer", "viewcube_axes", false));
1394
1395   // Animation duration (sec)
1396   myViewCube->SetDuration(resMgr->doubleValue("OCCViewer", "viewcube_duration", 0.5));
1397
1398   // Update the viewer
1399   if (isVisibleVC)
1400     myAISContext->Redisplay( myViewCube, Standard_True);
1401 }
1402
1403 /*!
1404   \return trihedron size
1405 */
1406 double OCCViewer_Viewer::trihedronSize() const
1407 {
1408   double sz = 0;
1409   if ( !myTrihedron.IsNull() )
1410     sz = myTrihedron->Size();
1411   return sz;
1412 }
1413
1414 /*!
1415   Changes trihedron size
1416   \param sz - new size
1417 */
1418 void OCCViewer_Viewer::setTrihedronSize( const double sz, bool isRelative )
1419 {
1420   if ( myTrihedronSize != sz || isRelative != myIsRelative) {
1421     myTrihedronSize = sz; 
1422     myIsRelative = isRelative;
1423     updateTrihedron();
1424   }
1425 }
1426
1427 /*!
1428   Set number of isolines
1429   \param u - u-isolines (first parametric co-ordinate)
1430   \param v - v-isolines (second parametric co-ordinate)
1431 */
1432 void OCCViewer_Viewer::setIsos( const int u, const int v )
1433 {
1434   Handle(AIS_InteractiveContext) ic = getAISContext();
1435   if ( ic.IsNull() )
1436   return;
1437
1438   ic->SetIsoNumber( u, AIS_TOI_IsoU );
1439   ic->SetIsoNumber( v, AIS_TOI_IsoV );
1440 }
1441
1442 /*!
1443   \return number of isolines
1444   \param u - to return u-isolines (first parametric co-ordinate)
1445   \param v - to return v-isolines (second parametric co-ordinate)
1446 */
1447 void OCCViewer_Viewer::isos( int& u, int& v ) const
1448 {
1449   Handle(AIS_InteractiveContext) ic = getAISContext();
1450   if ( !ic.IsNull() )
1451   {
1452     u = ic->IsoNumber( AIS_TOI_IsoU );
1453     v = ic->IsoNumber( AIS_TOI_IsoV );
1454   }
1455 }
1456
1457 /* 
1458  * Returns a new OCCViewer_ViewWindow instance which will be placed as a sub window in ViewFrame
1459  */
1460 OCCViewer_ViewWindow* OCCViewer_Viewer::createSubWindow()
1461 {
1462   return new OCCViewer_ViewWindow(0,  this);
1463 }
1464
1465 // obsolete  
1466 QColor OCCViewer_Viewer::backgroundColor( int theViewId ) const
1467 {
1468   return background( theViewId ).color();
1469 }
1470
1471 Qtx::BackgroundData OCCViewer_Viewer::background( int theViewId ) const
1472 {
1473   return ( theViewId >= 0 && theViewId < myBackgrounds.count() ) ? myBackgrounds[theViewId] : Qtx::BackgroundData();
1474 }
1475
1476 // obsolete
1477 void OCCViewer_Viewer::setBackgroundColor( int theViewId, const QColor& theColor )
1478 {
1479   if ( theColor.isValid() ) {
1480     Qtx::BackgroundData bg = background( theViewId );
1481     bg.setColor( theColor );
1482     setBackground( theViewId, bg );
1483   }
1484 }
1485
1486 void OCCViewer_Viewer::setBackground( int theViewId, const Qtx::BackgroundData& theBackground )
1487 {
1488   if ( theBackground.isValid() && theViewId >= 0 && theViewId < myBackgrounds.count() )
1489     myBackgrounds[theViewId] = theBackground;    
1490 }
1491
1492
1493 /*!
1494   Set the show static trihedron flag
1495 */
1496 void OCCViewer_Viewer::setStaticTrihedronDisplayed(const bool on)
1497 {
1498   OCCViewer_ViewWindow* aView = (OCCViewer_ViewWindow*)(myViewManager->getActiveView());
1499   if ( aView ) aView->showStaticTrihedron( on );
1500 }
1501
1502 /*!
1503   Get new and current trihedron size corresponding to the current model size
1504 */
1505 bool OCCViewer_Viewer::computeTrihedronSize( double& theNewSize, double& theSize )
1506 {
1507   theNewSize = 100;
1508   theSize = 100;
1509
1510   //SRN: BUG IPAL8996, a usage of method ActiveView without an initialization
1511   Handle(V3d_Viewer) viewer = getViewer3d();
1512   viewer->InitActiveViews();
1513   if(!viewer->MoreActiveViews()) return false;
1514
1515   Handle(V3d_View) view3d = viewer->ActiveView();
1516   //SRN: END of fix
1517
1518   if ( view3d.IsNull() )
1519     return false;
1520
1521   double aMaxSide = computeSceneSize( view3d );
1522
1523   // IPAL21687
1524   // The boundary box of the view may be initialized but nullified
1525   // (case of infinite objects)
1526   if ( aMaxSide < Precision::Confusion() )
1527     return false;
1528
1529   float aSizeInPercents = SUIT_Session::session()->resourceMgr()->doubleValue("3DViewer","trihedron_size", 100.);
1530
1531   static float EPS = 5.0E-3f;
1532   theSize = getTrihedron()->Size();
1533   theNewSize = aMaxSide*aSizeInPercents / 100.0;
1534
1535   return fabs( theNewSize - theSize ) > theSize    * EPS ||
1536          fabs( theNewSize - theSize ) > theNewSize * EPS;
1537 }
1538
1539 /*!
1540  * Compute scene size
1541  */
1542 double OCCViewer_Viewer::computeSceneSize(const Handle(V3d_View)& view3d) const
1543 {
1544   double aMaxSide = 0;
1545   double Xmin = 0, Ymin = 0, Zmin = 0, Xmax = 0, Ymax = 0, Zmax = 0;
1546
1547   Bnd_Box aBox = view3d->View()->MinMaxValues();
1548   Xmin = aBox.IsVoid() ? RealFirst() : aBox.CornerMin().X();
1549   Ymin = aBox.IsVoid() ? RealFirst() : aBox.CornerMin().Y();
1550   Zmin = aBox.IsVoid() ? RealFirst() : aBox.CornerMin().Z();
1551   Xmax = aBox.IsVoid() ? RealLast()  : aBox.CornerMax().X();
1552   Ymax = aBox.IsVoid() ? RealLast()  : aBox.CornerMax().Y();
1553   Zmax = aBox.IsVoid() ? RealLast()  : aBox.CornerMax().Z();
1554
1555   if ( Xmin != RealFirst() && Ymin != RealFirst() && Zmin != RealFirst() &&
1556        Xmax != RealLast()  && Ymax != RealLast()  && Zmax != RealLast() )
1557   {
1558     aMaxSide = Xmax - Xmin;
1559     if ( aMaxSide < Ymax -Ymin ) aMaxSide = Ymax -Ymin;
1560     if ( aMaxSide < Zmax -Zmin ) aMaxSide = Zmax -Zmin;
1561   }
1562
1563   return aMaxSide;
1564 }
1565
1566 /*! 
1567  * Update the size of the trihedron
1568  */
1569 void OCCViewer_Viewer::updateTrihedron() {
1570   if ( myTrihedron.IsNull() )
1571     return;
1572
1573   if(myIsRelative){
1574     double newSz, oldSz;
1575     
1576     if(computeTrihedronSize(newSz, oldSz))
1577       myTrihedron->SetSize(newSz);
1578     
1579   } else if(myTrihedron->Size() != myTrihedronSize) {
1580     myTrihedron->SetSize(myTrihedronSize);
1581   }
1582 }
1583
1584 /*!
1585   Set number of isolines
1586   \param u - u-isolines (first parametric co-ordinate)
1587   \param v - v-isolines (second parametric co-ordinate)
1588 */
1589 void OCCViewer_Viewer::setSelectionOptions( bool isPreselectionEnabled, bool isSelectionEnabled )
1590 {
1591   myPreselectionEnabled = isPreselectionEnabled;
1592   mySelectionEnabled = isSelectionEnabled;
1593   //clear current selection in the viewer
1594   
1595   if(!mySelectionEnabled) {
1596     myAISContext->ClearSelected( Standard_True );
1597   }
1598 }
1599
1600 /*!
1601   Creates clipping plane based on the incoming plane
1602 */
1603 Handle(Graphic3d_ClipPlane) OCCViewer_Viewer::createClipPlane(const gp_Pln& thePlane, const Standard_Boolean theIsOn)
1604 {
1605   Handle(Graphic3d_ClipPlane) aGraphic3dPlane = new Graphic3d_ClipPlane( thePlane );
1606   aGraphic3dPlane->SetOn( theIsOn );
1607   aGraphic3dPlane->SetCapping( Standard_True );
1608
1609   // set capping color
1610   setCappingColor( aGraphic3dPlane, myClippingColor );
1611
1612   // set capping texture
1613   aGraphic3dPlane->SetCappingTexture( initClippingTexture( myDefaultTextureUsed, myClippingTexture,
1614                                                            myTextureModulated, myClippingTextureScale ) );
1615
1616   return aGraphic3dPlane;
1617 }
1618 /*!
1619   Applies clipping planes to clippable objects
1620 */
1621 void OCCViewer_Viewer::setClipPlanes(ClipPlanesList theList)
1622 {
1623   // 1. Remove existing clipping planes
1624   myClipPlanes.clear();
1625   myInternalClipPlanes.Clear();
1626
1627   // 2. Create new clipping planes
1628   ClipPlanesList::iterator inIt = theList.begin();
1629   for (;inIt != theList.end(); inIt++ )
1630   {
1631     OCCViewer_ClipPlane aPlane = *inIt;
1632
1633     double aDx = 0.0, aDy = 0.0, aDz = 0.0;
1634     aPlane.OrientationToXYZ( aDx, aDy, aDz );
1635
1636     gp_Pnt anOrigin( aPlane.X, aPlane.Y, aPlane.Z );
1637     gp_Dir aDirection( aDx, aDy, aDz );
1638
1639     myInternalClipPlanes.Append( createClipPlane( gp_Pln( anOrigin, aDirection ), aPlane.IsOn ) );
1640     myClipPlanes.push_back( aPlane );
1641   }
1642
1643   // 3. Apply clipping planes
1644   AIS_ListOfInteractive aList;
1645   myAISContext->DisplayedObjects (aList);
1646   for ( AIS_ListIteratorOfListOfInteractive anIter (aList); anIter.More(); anIter.Next() ) {
1647     Handle(AIS_InteractiveObject) anObj = anIter.Value();
1648     Handle(ViewerData_AISShape) aShape = Handle(ViewerData_AISShape)::DownCast (anObj);
1649     if (!aShape.IsNull() && aShape->IsClippable()) {
1650       aShape->SetClipPlanes(new Graphic3d_SequenceOfHClipPlane(myInternalClipPlanes)); // todo: store clipping planes in a handle?
1651     }
1652   }
1653 }
1654
1655 /*!
1656   Returns the clipping planes applied to the displayed objects.
1657 */
1658 ClipPlanesList OCCViewer_Viewer::getClipPlanes() const {
1659   return myClipPlanes;
1660 }
1661 /*!
1662   Applies clipping planes to given object objects
1663 */
1664 void OCCViewer_Viewer::applyExistingClipPlanesToObject (const Handle(AIS_InteractiveObject)& theObject)
1665 {
1666   Handle(ViewerData_AISShape) aShape = Handle(ViewerData_AISShape)::DownCast (theObject);
1667   if (!aShape.IsNull() && aShape->IsClippable())
1668   {
1669     aShape->SetClipPlanes (new Graphic3d_SequenceOfHClipPlane(myInternalClipPlanes)); // todo: store clipping planes in a handle?
1670   }
1671 }
1672
1673 /*!
1674   Returns the pointer to the clipping dialog box.
1675 */
1676 OCCViewer_ClippingDlg* OCCViewer_Viewer::getClippingDlg() const{
1677   return myClippingDlg;
1678 }
1679
1680
1681 /*!
1682   Stores pointer to the clipping dialog box.
1683 */
1684 void OCCViewer_Viewer::setClippingDlg(OCCViewer_ClippingDlg* theDlg) {
1685   if(myClippingDlg != theDlg) {
1686     myClippingDlg = theDlg;
1687   }
1688 }
1689
1690
1691 bool OCCViewer_Viewer::enableDrawMode( bool on )
1692 {
1693   //!! To be done for view windows
1694   if ( !myViewManager )
1695     return false;
1696
1697   bool prev = false;
1698   QVector<SUIT_ViewWindow*> wins = myViewManager->getViews();
1699   for ( int i = 0; i < (int)wins.count(); i++ )
1700   {
1701     OCCViewer_ViewWindow* win = ::qobject_cast<OCCViewer_ViewWindow*>( wins.at( i ) );
1702     if ( win ) {
1703       prev = prev || win->enableDrawMode( on ); 
1704     }
1705   }
1706   return prev;
1707 }