Salome HOME
Merge from BR_new_bop4 (porting to new OCCT BOP) 13/09/2013
[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
29 #include "SUIT_ViewWindow.h"
30 #include "SUIT_ViewManager.h"
31 #include "SUIT_Desktop.h"
32 #include "SUIT_Session.h"
33 #include "SUIT_ResourceMgr.h"
34
35 #include "QtxActionToolMgr.h"
36 #include "QtxBackgroundTool.h"
37
38 #include <QPainter>
39 #include <QApplication>
40 #include <QColorDialog>
41 #include <QFileDialog>
42 #include <QPalette>
43 #include <QKeyEvent>
44 #include <QMenu>
45 #include <QMouseEvent>
46 #include <QToolBar>
47 #include <QDesktopWidget>
48
49 #include <AIS_Axis.hxx>
50 #include <AIS_Drawer.hxx>
51 #include <AIS_ListOfInteractive.hxx>
52 #include <AIS_ListIteratorOfListOfInteractive.hxx>
53
54 #include <Geom_Axis2Placement.hxx>
55 #include <Prs3d_Drawer.hxx>
56 #include <Prs3d_DatumAspect.hxx>
57 #include <Prs3d_LineAspect.hxx>
58 #include <Prs3d_LengthAspect.hxx>
59 #include <Prs3d_AngleAspect.hxx>
60 #include <Prs3d_TextAspect.hxx>
61
62 #include <Visual3d_View.hxx>
63
64 #include <Basics_OCCTVersion.hxx>
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 {
101   // init CasCade viewers
102   myV3dViewer = OCCViewer_VService::CreateViewer( TCollection_ExtendedString("Viewer3d").ToExtString() );
103   myV3dViewer->Init();
104   myV3dCollector = OCCViewer_VService::CreateViewer( TCollection_ExtendedString("Collector3d").ToExtString() );
105   myV3dCollector->Init();
106
107   // init selector
108   myAISContext = new AIS_InteractiveContext( myV3dViewer, myV3dCollector );
109
110   myAISContext->SelectionColor( Quantity_NOC_WHITE );
111   
112   // display isoline on planar faces (box for ex.)
113   myAISContext->IsoOnPlane( true );
114
115   /*
116   double h = QApplication::desktop()->screenGeometry( QApplication::desktop()->primaryScreen() ).height() / 300. ;
117   Handle(Prs3d_Drawer) drawer = myAISContext->DefaultDrawer();
118   Handle(Prs3d_TextAspect) ta = drawer->TextAspect();
119   ta->SetHeight(100); // VSR: workaround for CAS.CADE bug (is it really needed ???)
120   ta->SetHeight(h);
121   drawer->SetTextAspect(ta);
122   drawer->AngleAspect()->SetTextAspect(ta);
123   drawer->LengthAspect()->SetTextAspect(ta);
124   */
125   
126   /* create trihedron */
127   if ( DisplayTrihedron )
128   {
129     Handle(Geom_Axis2Placement) anAxis = new Geom_Axis2Placement(gp::XOY());
130     myTrihedron = new AIS_Trihedron(anAxis);
131     myTrihedron->SetInfiniteState( Standard_True );
132
133     Quantity_Color Col(193/255., 205/255., 193/255., Quantity_TOC_RGB);
134     //myTrihedron->SetColor( Col );
135     myTrihedron->SetArrowColor( Col.Name() );
136     myTrihedron->SetSize(100);
137     Handle(AIS_Drawer) drawer = myTrihedron->Attributes();
138     if (drawer->HasDatumAspect()) {
139       Handle(Prs3d_DatumAspect) daspect = drawer->DatumAspect();
140       daspect->FirstAxisAspect()->SetColor(Quantity_Color(1.0, 0.0, 0.0, Quantity_TOC_RGB));
141       daspect->SecondAxisAspect()->SetColor(Quantity_Color(0.0, 1.0, 0.0, Quantity_TOC_RGB));
142       daspect->ThirdAxisAspect()->SetColor(Quantity_Color(0.0, 0.0, 1.0, Quantity_TOC_RGB));
143     }
144   }
145
146   // set interaction style to standard
147   myInteractionStyle = 0;
148
149   // set zooming style to standard
150   myZoomingStyle = 0;
151
152   // preselection
153   myPreselectionEnabled = true;
154
155   // selection
156   mySelectionEnabled = true;
157   myMultiSelectionEnabled = true;
158   
159   
160   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
161   if(resMgr)
162     myShowStaticTrihedron = resMgr->booleanValue( "3DViewer", "show_static_trihedron", true );
163 }
164
165 /*!
166   Destructor
167 */
168 OCCViewer_Viewer::~OCCViewer_Viewer() 
169 {
170   myAISContext.Nullify();
171   myV3dViewer.Nullify();
172   myV3dCollector.Nullify();
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( !onlyInViewer )
724   {
725     AIS_ListOfInteractive List1;
726     myAISContext->ObjectsInCollector(List1);
727     List.Append(List1);
728   }
729
730   AIS_ListIteratorOfListOfInteractive ite(List);
731   for ( ; ite.More(); ite.Next() )
732     if( ite.Value()==obj )
733       return true;
734
735   return false;
736 }
737
738 /*!
739   \return true if object is displayed in viewer
740   \param obj - object to be checked
741 */
742 bool OCCViewer_Viewer::isVisible( const Handle(AIS_InteractiveObject)& obj )
743 {
744   return myAISContext->IsDisplayed( obj );
745 }
746
747 /*!
748   Sets color of object
749   \param obj - object to be updated
750   \param color - new color
751   \param update - update current viewer
752 */
753 void OCCViewer_Viewer::setColor( const Handle(AIS_InteractiveObject)& obj,
754                                  const QColor& color,
755                                  bool update )
756 {
757   if( !obj.IsNull() )
758   {
759     Quantity_Color CSFColor = Quantity_Color ( color.red() / 255.,
760                                                color.green() / 255.,
761                                                color.blue() / 255.,
762                                                Quantity_TOC_RGB );
763     obj->SetColor( CSFColor );
764   }
765
766   if( update )
767     myV3dViewer->Update();
768 }
769
770 /*!
771   Changes display mode of object
772   \param obj - object to be processed
773   \param mode - new display mode
774   \param update - update current viewer
775 */
776 void OCCViewer_Viewer::switchRepresentation( const Handle(AIS_InteractiveObject)& obj,
777                                              int mode, bool update )
778 {
779   myAISContext->SetDisplayMode( obj, (Standard_Integer)mode, update );
780   if( update )
781     myV3dViewer->Update();
782 }
783
784 /*!
785   Changes transparency of object
786   \param obj - object to be processed
787   \param trans - new transparency
788   \param update - update current viewer
789 */
790 void OCCViewer_Viewer::setTransparency( const Handle(AIS_InteractiveObject)& obj,
791                                         float trans, bool update )
792 {
793   myAISContext->SetTransparency( obj, trans, false );
794   myAISContext->Redisplay( obj, Standard_False, Standard_True );
795   if( update )
796     myV3dViewer->Update();
797 }
798
799 /*!
800   Changes visibility of trihedron to opposite
801 */
802 void OCCViewer_Viewer::toggleTrihedron()
803 {
804   setTrihedronShown( !isTrihedronVisible() );
805 }
806
807 /*!
808   \return true if trihedron is visible
809 */
810 bool OCCViewer_Viewer::isTrihedronVisible() const
811 {
812   return !myTrihedron.IsNull() && !myAISContext.IsNull() && myAISContext->IsDisplayed( myTrihedron );
813 }
814
815 /*!
816   Sets visibility state of trihedron
817   \param on - new state
818 */
819
820 void OCCViewer_Viewer::setTrihedronShown( const bool on )
821 {
822   if ( myTrihedron.IsNull() )
823     return;
824
825   if ( on ) {
826     myAISContext->Display( myTrihedron );
827     myAISContext->Deactivate(myTrihedron);
828   }
829   else {
830     myAISContext->Erase( myTrihedron );
831   }
832 }
833
834 /*!
835   \return trihedron size
836 */
837 double OCCViewer_Viewer::trihedronSize() const
838 {
839   double sz = 0;
840   if ( !myTrihedron.IsNull() )
841     sz = myTrihedron->Size();
842   return sz;
843 }
844
845 /*!
846   Changes trihedron size
847   \param sz - new size
848 */
849 void OCCViewer_Viewer::setTrihedronSize( const double sz, bool isRelative )
850 {
851   if ( myTrihedronSize != sz || isRelative != myIsRelative) {
852     myTrihedronSize = sz; 
853     myIsRelative = isRelative;
854     updateTrihedron();
855   }
856 }
857
858 /*!
859   Set number of isolines
860   \param u - u-isolines (first parametric co-ordinate)
861   \param v - v-isolines (second parametric co-ordinate)
862 */
863 void OCCViewer_Viewer::setIsos( const int u, const int v )
864 {
865   Handle(AIS_InteractiveContext) ic = getAISContext();
866   if ( ic.IsNull() )
867   return;
868
869   ic->SetIsoNumber( u, AIS_TOI_IsoU );
870   ic->SetIsoNumber( v, AIS_TOI_IsoV );
871 }
872
873 /*!
874   \return number of isolines
875   \param u - to return u-isolines (first parametric co-ordinate)
876   \param v - to return v-isolines (second parametric co-ordinate)
877 */
878 void OCCViewer_Viewer::isos( int& u, int& v ) const
879 {
880   Handle(AIS_InteractiveContext) ic = getAISContext();
881   if ( !ic.IsNull() )
882   {
883     u = ic->IsoNumber( AIS_TOI_IsoU );
884     v = ic->IsoNumber( AIS_TOI_IsoV );
885   }
886 }
887
888 /* 
889  * Returns a new OCCViewer_ViewWindow instance which will be placed as a sub window in ViewFrame
890  */
891 OCCViewer_ViewWindow* OCCViewer_Viewer::createSubWindow()
892 {
893   return new OCCViewer_ViewWindow( 0,  this);
894 }
895
896 // obsolete  
897 QColor OCCViewer_Viewer::backgroundColor( int theViewId ) const
898 {
899   return background( theViewId ).color();
900 }
901
902 Qtx::BackgroundData OCCViewer_Viewer::background( int theViewId ) const
903 {
904   return ( theViewId >= 0 && theViewId < myBackgrounds.count() ) ? myBackgrounds[theViewId] : Qtx::BackgroundData();
905 }
906
907 // obsolete
908 void OCCViewer_Viewer::setBackgroundColor( int theViewId, const QColor& theColor )
909 {
910   if ( theColor.isValid() ) {
911     Qtx::BackgroundData bg = background( theViewId );
912     bg.setColor( theColor );
913     setBackground( theViewId, bg );
914   }
915 }
916
917 void OCCViewer_Viewer::setBackground( int theViewId, const Qtx::BackgroundData& theBackground )
918 {
919   if ( theBackground.isValid() && theViewId >= 0 && theViewId < myBackgrounds.count() )
920     myBackgrounds[theViewId] = theBackground;    
921 }
922
923
924 /*!
925   Set the show static trihedron flag
926 */
927 void OCCViewer_Viewer::setStaticTrihedronDisplayed(const bool on) {
928   if(myShowStaticTrihedron != on) {
929     OCCViewer_ViewWindow* aView = (OCCViewer_ViewWindow*)(myViewManager->getActiveView());
930     if(!aView)
931       return;
932
933     OCCViewer_ViewPort3d* vp3d = aView->getViewPort();
934     if(vp3d) {
935       myShowStaticTrihedron = on;
936       vp3d->updateStaticTriedronVisibility();
937     }
938   }
939 }
940
941 /*!
942   Get new and current trihedron size corresponding to the current model size
943 */
944 bool OCCViewer_Viewer::computeTrihedronSize( double& theNewSize, double& theSize )
945 {
946   theNewSize = 100;
947   theSize = 100;
948
949   //SRN: BUG IPAL8996, a usage of method ActiveView without an initialization
950   Handle(V3d_Viewer) viewer = getViewer3d();
951   viewer->InitActiveViews();
952   if(!viewer->MoreActiveViews()) return false;
953
954   Handle(V3d_View) view3d = viewer->ActiveView();
955   //SRN: END of fix
956
957   if ( view3d.IsNull() )
958     return false;
959
960   double Xmin = 0, Ymin = 0, Zmin = 0, Xmax = 0, Ymax = 0, Zmax = 0;
961   double aMaxSide;
962
963   view3d->View()->MinMaxValues( Xmin, Ymin, Zmin, Xmax, Ymax, Zmax );
964
965   if ( Xmin == RealFirst() || Ymin == RealFirst() || Zmin == RealFirst() ||
966        Xmax == RealLast()  || Ymax == RealLast()  || Zmax == RealLast() )
967     return false;
968
969   aMaxSide = Xmax - Xmin;
970   if ( aMaxSide < Ymax -Ymin ) aMaxSide = Ymax -Ymin;
971   if ( aMaxSide < Zmax -Zmin ) aMaxSide = Zmax -Zmin;
972
973   // IPAL21687
974   // The boundary box of the view may be initialized but nullified
975   // (case of infinite objects)
976   if ( aMaxSide < Precision::Confusion() )
977     return false;
978
979   float aSizeInPercents = SUIT_Session::session()->resourceMgr()->doubleValue("3DViewer","trihedron_size", 100.);
980
981   static float EPS = 5.0E-3;
982   theSize = getTrihedron()->Size();
983   theNewSize = aMaxSide*aSizeInPercents / 100.0;
984
985   return fabs( theNewSize - theSize ) > theSize * EPS ||
986          fabs( theNewSize - theSize) > theNewSize * EPS;
987 }
988
989 /*! 
990  * Update the size of the trihedron
991  */
992 void OCCViewer_Viewer::updateTrihedron() {
993   if ( myTrihedron.IsNull() )
994     return;
995
996   if(myIsRelative){
997     double newSz, oldSz;
998     
999     if(computeTrihedronSize(newSz, oldSz))
1000       myTrihedron->SetSize(newSz);
1001     
1002   } else if(myTrihedron->Size() != myTrihedronSize) {
1003     myTrihedron->SetSize(myTrihedronSize);
1004   }
1005 }
1006
1007 /*!
1008   Set number of isolines
1009   \param u - u-isolines (first parametric co-ordinate)
1010   \param v - v-isolines (second parametric co-ordinate)
1011 */
1012 void OCCViewer_Viewer::setSelectionOptions( bool isPreselectionEnabled, bool isSelectionEnabled )
1013 {
1014   myPreselectionEnabled = isPreselectionEnabled;
1015   mySelectionEnabled = isSelectionEnabled;
1016 }