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