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