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