Salome HOME
Moved some functionality to VTKViewer_Utilities.h
[modules/kernel.git] / src / OCCViewer / OCCViewer_Viewer3d.cxx
1 //  SALOME OCCViewer : build OCC Viewer into Salome desktop
2 //
3 //  Copyright (C) 2003  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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : OCCViewer_Viewer3d.cxx
25 //  Author : Nicolas REJNERI
26 //  Module : SALOME
27 //  $Header$
28
29 /*!
30   \class OCCViewer_Viewer3d OCCViewer_Viewer3d.h
31   \brief Open CASCADE Viewer 3D with viewport 3D and selection.
32 */
33
34 #include "OCCViewer_Viewer3d.h"
35 #include "OCCViewer_ViewFrame.h"
36 #include "OCCViewer_AISSelector.h"
37 #include "QAD.h"
38 #include "QAD_Config.h"
39 #include "QAD_Desktop.h"
40 #include "QAD_Settings.h"
41 #include "QAD_LeftFrame.h"
42 #include "OCCViewer_ViewPort3d.h"
43 #include "QAD_RightFrame.h"
44 #include "QAD_MessageBox.h"
45 #include "QAD_Application.h"
46
47 #include "SALOME_Selection.h"
48 #include "SALOME_InteractiveObject.hxx"
49 #include "SALOME_ListIteratorOfListIO.hxx"
50
51 #include "SALOME_AISShape.hxx"
52 #include "SALOME_AISObject.hxx"
53
54 #include "utilities.h"
55
56 // Open CASCADE Includes
57 #include <Geom_Axis2Placement.hxx>
58 #include <AIS_ListOfInteractive.hxx>
59 #include <AIS_ListIteratorOfListOfInteractive.hxx>
60 #include <SelectMgr_EntityOwner.hxx>
61 #include <TopTools_IndexedMapOfShape.hxx>
62 #include <TopExp.hxx>
63 #include <TColStd_IndexedMapOfInteger.hxx>
64 #include <NCollection_DefineBaseCollection.hxx>
65 #include <NCollection_DefineDataMap.hxx>
66
67 using namespace std;
68
69 DEFINE_BASECOLLECTION( OCCViewer_CollectionOfIndexedMapOfShapes, TopTools_IndexedMapOfShape )
70 DEFINE_DATAMAP( OCCViewer_MapOfIOIndexedMapOfShape, OCCViewer_CollectionOfIndexedMapOfShapes, Handle_SALOME_InteractiveObject, TopTools_IndexedMapOfShape)
71
72 DEFINE_BASECOLLECTION( OCCViewer_CollectionOfMapOfInteger, TColStd_MapOfInteger )
73 DEFINE_DATAMAP( OCCViewer_MapOfIOMapOfInteger, OCCViewer_CollectionOfMapOfInteger, Handle_SALOME_InteractiveObject, TColStd_MapOfInteger )
74
75 /*!
76     Constructor
77 */
78 OCCViewer_Viewer3d::OCCViewer_Viewer3d(OCCViewer_ViewFrame* vf) :
79   myAISContext( NULL ),
80   myAISSelector( NULL )
81 {
82   if ( myV3dViewer.IsNull() )
83     createViewer3d();   /* create viewer */
84
85   QString BackgroundColorRed   = QAD_CONFIG->getSetting("OCCViewer:BackgroundColorRed");
86   QString BackgroundColorGreen = QAD_CONFIG->getSetting("OCCViewer:BackgroundColorGreen");
87   QString BackgroundColorBlue  = QAD_CONFIG->getSetting("OCCViewer:BackgroundColorBlue");
88
89   if( !BackgroundColorRed.isEmpty() && !BackgroundColorGreen.isEmpty() && !BackgroundColorBlue.isEmpty() )
90     myBackColor = QColor(BackgroundColorRed.toInt(),
91                          BackgroundColorGreen.toInt(),
92                          BackgroundColorBlue.toInt());
93   else
94     myBackColor = QColor(35, 136, 145);
95
96   myViewFrame = vf;
97   myViewFrame->setViewPort ( new OCCViewer_ViewPort3d( myViewFrame, myV3dViewer ) );
98   myViewFrame->setViewer(this);
99
100   /* properties settings */
101   //    if ( !myIcon.isNull() )
102   //      myStudyFrame->setIcon( myIcon );
103
104   myViewFrame->setCursor( myCursor );
105   myViewFrame->setBackgroundColor( myBackColor );
106
107   if ( myAISContext.IsNull() ) {
108     /* create interactive manager */
109     myAISContext = new AIS_InteractiveContext ( myV3dViewer, myV3dCollector );
110
111     myAISContext->IsoOnPlane(true) ;
112
113     /* create trihedron */
114     Handle(Geom_Axis2Placement) anAxis=new Geom_Axis2Placement(gp::XOY());
115     myTrihedron=new AIS_Trihedron(anAxis);
116     myTrihedron->SetInfiniteState( Standard_True );
117
118     Quantity_Color Col(193/255., 205/255., 193/255., Quantity_TOC_RGB);
119     myTrihedron->SetColor( Col );
120     myTrihedron->SetArrowColor( Col.Name() );
121
122     float dim = 100;
123     QString Size = QAD_CONFIG->getSetting("Viewer:TrihedronSize");
124     if (!Size. isEmpty() ) dim = Size.toFloat(); //get size from preferences
125    
126     myTrihedron->SetSize(dim);
127
128     myAISContext->Display(myTrihedron);
129     myAISContext->Deactivate(myTrihedron);
130
131     /* create selector */
132     myAISSelector = new OCCViewer_AISSelector ( myAISContext );
133     QAD_ASSERT ( connect (myAISSelector, SIGNAL(selSelectionDone(bool)),
134                           this, SLOT(onSelectionDone(bool))) );
135     QAD_ASSERT ( connect (myAISSelector, SIGNAL(selSelectionCancel(bool)),
136                           this, SLOT(onSelectionCancel(bool))) );
137     myEnableSelection = true;
138   }
139
140   QAD_ASSERT ( connect(myViewFrame,
141                        SIGNAL(vfKeyPress(QKeyEvent*)),
142                        this, SLOT(onKeyPress(QKeyEvent*))) );
143
144   /* mouse events of the view */
145   QAD_ASSERT ( QObject::connect(myViewFrame,
146                                 SIGNAL(vfMousePress(QMouseEvent*)),
147                                 this, SLOT(onMousePress(QMouseEvent*))) );
148   QAD_ASSERT ( QObject::connect(myViewFrame,
149                                 SIGNAL(vfMouseRelease(QMouseEvent*)),
150                                 this, SLOT(onMouseRelease (QMouseEvent*))) );
151   QAD_ASSERT ( QObject::connect(myViewFrame,
152                                 SIGNAL(vfMouseMove(QMouseEvent*)),
153                                 this, SLOT(onMouseMove (QMouseEvent*))) );
154   QAD_ASSERT ( QObject::connect(myViewFrame,
155                                 SIGNAL(vfMouseDoubleClick(QMouseEvent*)),
156                                 this, SLOT(onMouseDoubleClick (QMouseEvent*))) );
157
158   /* transformation events */
159   QAD_ASSERT ( QObject::connect(myViewFrame,
160                                 SIGNAL(vfTransformationStarted(OCCViewer_ViewPort::OperationType)),
161                                 this, SLOT(onTransformationStarted (OCCViewer_ViewPort::OperationType))) );
162   QAD_ASSERT ( QObject::connect(myViewFrame,
163                                 SIGNAL(vfTransformationFinished(OCCViewer_ViewPort::OperationType)),
164                                 this, SLOT(onTransformationFinished (OCCViewer_ViewPort::OperationType))) );
165
166   /* set popup manager for the viewport */
167   myViewFrame->getViewPort()->setPopupServer ( this );
168
169 }
170
171
172 /*!
173     Destructor
174 */
175 OCCViewer_Viewer3d::~OCCViewer_Viewer3d()
176 {
177   delete myAISSelector;
178 }
179
180
181 /* trihedron */
182 Handle(AIS_Trihedron) OCCViewer_Viewer3d::getTrihedron() const
183 {
184   return myTrihedron;
185 }
186
187 void OCCViewer_Viewer3d::setTrihedronSize( float size )
188 {
189   AIS_ListOfInteractive aList;
190   myAISContext->DisplayedObjects( aList );
191   myAISContext->ObjectsInCollector( aList );
192
193   AIS_ListIteratorOfListOfInteractive anIter( aList );
194   for ( ; anIter.More(); anIter.Next() )
195   {
196     Handle(AIS_Trihedron) aTrh = Handle(AIS_Trihedron)::DownCast( anIter.Value() );
197     if ( !aTrh.IsNull() )
198       aTrh->SetSize( aTrh == myTrihedron ? size : 0.5 *size );
199   }
200
201   myAISContext->UpdateCurrentViewer();
202 }
203
204 bool OCCViewer_Viewer3d::isTrihedronDisplayed()
205
206 {
207   return myAISContext->IsDisplayed(myTrihedron);
208 }
209
210 void OCCViewer_Viewer3d::rename( const Handle(SALOME_InteractiveObject)& IObject, QString newName )
211 {
212   AIS_ListOfInteractive List;
213   myAISContext->DisplayedObjects(List);
214   
215   AIS_ListIteratorOfListOfInteractive ite(List);
216   while (ite.More())
217   {
218     if (ite.Value()->IsKind(STANDARD_TYPE(SALOME_AISShape)))
219     {
220       Handle(SALOME_AISShape) aSh = Handle(SALOME_AISShape)::DownCast(ite.Value());
221       
222       if ( aSh->hasIO() )
223       {
224         Handle(SALOME_InteractiveObject) IO = aSh->getIO();
225         if ( IO->isSame( IObject ) )
226         {
227           char* aCopyName = CORBA::string_dup(newName.latin1());
228           aSh->setName( aCopyName );
229           delete( aCopyName );
230           break;
231         }
232       }
233     }
234     else if ( ite.Value()->IsKind( STANDARD_TYPE( SALOME_AISObject ) ) )
235     {
236       Handle(SALOME_AISObject) aSh = Handle(SALOME_AISObject)::DownCast( ite.Value() );
237
238       // Add code here, if someone create a MODULE_AISObject.
239     }
240     ite.Next();
241   }
242 }
243
244 void OCCViewer_Viewer3d::SetColor(const Handle(SALOME_InteractiveObject)& IObject,
245                                   QColor thecolor)
246 {
247   AIS_ListOfInteractive List;
248   myAISContext->DisplayedObjects(List);
249   
250   AIS_ListIteratorOfListOfInteractive ite(List);
251   for ( ; ite.More(); ite.Next() )
252   {
253     Handle(SALOME_InteractiveObject) anObj =
254         Handle(SALOME_InteractiveObject)::DownCast( ite.Value()->GetOwner() );
255
256     if ( !anObj.IsNull() && anObj->hasEntry() && anObj->isSame( IObject ) )
257     {
258       Quantity_Color CSFColor = Quantity_Color ( thecolor.red() / 255.,
259                                                  thecolor.green() / 255.,
260                                                  thecolor.blue() / 255.,
261                                                  Quantity_TOC_RGB );
262       ite.Value()->SetColor( CSFColor );
263       break;
264     }
265   }
266
267   myV3dViewer->Update();
268 }
269
270 void OCCViewer_Viewer3d::SwitchRepresentation( const Handle(SALOME_InteractiveObject)& IObject,
271                                                int mode )
272 {  
273   AIS_ListOfInteractive List;
274   myAISContext->DisplayedObjects(List);
275   
276   AIS_ListIteratorOfListOfInteractive ite(List);
277   for ( ; ite.More(); ite.Next() )
278   {
279     Handle(SALOME_InteractiveObject) anObj =
280         Handle(SALOME_InteractiveObject)::DownCast( ite.Value()->GetOwner() );
281
282     if ( !anObj.IsNull() && anObj->hasEntry() && anObj->isSame( IObject ) )
283       myAISContext->SetDisplayMode( ite.Value(), (Standard_Integer)mode ,true );
284   }
285
286   myV3dViewer->Update();
287 }
288
289 void OCCViewer_Viewer3d::SetTransparency( const Handle(SALOME_InteractiveObject)& IObject,
290                                           float transp )
291 {
292   AIS_ListOfInteractive List;
293   myAISContext->DisplayedObjects( List );
294   
295   AIS_ListIteratorOfListOfInteractive ite( List );
296   for ( ; ite.More(); ite.Next() )
297   {
298     Handle(SALOME_InteractiveObject) anObj =
299         Handle(SALOME_InteractiveObject)::DownCast( ite.Value()->GetOwner() );
300
301     if ( !anObj.IsNull() && anObj->hasEntry() && anObj->isSame( IObject ) )
302     {
303       myAISContext->SetTransparency( ite.Value(), transp, false );
304       myAISContext->Redisplay( ite.Value(), Standard_False, Standard_True );
305     }
306   }
307   
308   myV3dViewer->Update();  
309 }
310
311 /*!
312     Highlights 'obj' in viewer, returns 'true' when selected successfully
313 */
314 bool OCCViewer_Viewer3d::highlight( const Handle(SALOME_InteractiveObject)& IObject, bool highlight, bool update )
315 {
316   bool isInLocal = myAISContext->HasOpenedContext();
317   QAD_Study* ActiveStudy = QAD_Application::getDesktop()->getActiveStudy();
318   SALOME_Selection* Sel = SALOME_Selection::Selection( ActiveStudy->getSelection() );
319
320   AIS_ListOfInteractive List;
321   myAISContext->DisplayedObjects(List);
322   
323   AIS_ListIteratorOfListOfInteractive ite(List);
324   for ( ; ite.More(); ite.Next() )
325   {
326     Handle(SALOME_InteractiveObject) anObj =
327       Handle(SALOME_InteractiveObject)::DownCast( ite.Value()->GetOwner() );
328
329     if ( !anObj.IsNull() && anObj->hasEntry() && anObj->isSame( IObject ) )
330     {
331       if ( !isInLocal )
332       {
333         if ( highlight && !myAISContext->IsSelected( ite.Value() ) )
334           myAISContext->AddOrRemoveCurrentObject( ite.Value(), false );
335         else if ( !highlight && myAISContext->IsSelected( ite.Value() ) )
336           myAISContext->AddOrRemoveCurrentObject( ite.Value(), false );
337       }
338       // highlight subshapes only when local selection is active
339       else
340       {
341         if ( ite.Value()->IsKind( STANDARD_TYPE( SALOME_AISShape ) ) )
342         {
343           Handle(SALOME_AISShape) aSh = Handle(SALOME_AISShape)::DownCast( ite.Value() );
344           TColStd_IndexedMapOfInteger MapIndex;
345           Sel->GetIndex( IObject, MapIndex );
346           aSh->highlightSubShapes( MapIndex, highlight );
347         }
348       }
349       break;
350     }
351   }
352     
353   if ( update )
354     myV3dViewer->Redraw();
355     
356   return false;
357 }
358
359 /*!
360     Unhighlight all selected objects
361 */
362 bool OCCViewer_Viewer3d::unHighlightAll()
363 {
364   if ( myAISContext->HasOpenedContext() )
365     myAISContext->ClearSelected();
366   else
367     myAISContext->ClearCurrents();
368   return false;
369 }
370
371 /*!
372   Returns true if the IObject has a Graphical Object in this viewer. Returns FALSE otherwise.
373 */
374 bool OCCViewer_Viewer3d::isInViewer( const Handle(SALOME_InteractiveObject)& IObject, bool onlyInViewer)
375 {
376   AIS_ListOfInteractive List;
377   myAISContext->DisplayedObjects(List);
378
379   if ( onlyInViewer ) {
380     AIS_ListOfInteractive List1;
381     myAISContext->ObjectsInCollector(List1);
382     List.Append(List1);
383   }
384
385   AIS_ListIteratorOfListOfInteractive ite(List);
386   for ( ; ite.More(); ite.Next() )
387   {
388     Handle(SALOME_InteractiveObject) anObj =
389         Handle(SALOME_InteractiveObject)::DownCast( ite.Value()->GetOwner() );
390
391     if ( !anObj.IsNull() && anObj->hasEntry() && anObj->isSame( IObject ) )
392       return true;
393   }
394   return false;
395 }
396
397 bool OCCViewer_Viewer3d::isVisible( const Handle(SALOME_InteractiveObject)& IObject )
398 {
399   AIS_ListOfInteractive List;
400   myAISContext->DisplayedObjects( List );
401
402   AIS_ListIteratorOfListOfInteractive ite( List );
403   for ( ; ite.More(); ite.Next() )
404   {
405     Handle(SALOME_InteractiveObject) anObj =
406       Handle(SALOME_InteractiveObject)::DownCast( ite.Value()->GetOwner() );
407
408     if ( !anObj.IsNull() && anObj->hasEntry() && anObj->isSame( IObject ) )
409       return myAISContext->IsDisplayed( ite.Value() );
410   }
411   
412   return false;
413 }
414
415 /*!
416     Returns the interactive context
417 */
418 Handle (AIS_InteractiveContext) OCCViewer_Viewer3d::getAISContext() const
419 {
420   return myAISContext;
421 }
422
423 OCCViewer_AISSelector* OCCViewer_Viewer3d::getAISSelector() const
424 {
425   return myAISSelector;
426 }
427
428 /*!
429     Returns 'true' if selection is enabled in this viewer,
430     'false' otherwise.
431 */
432 bool OCCViewer_Viewer3d::enabledSelection() const
433 {
434   return myEnableSelection;
435 }
436
437 /*!
438     Enables/disables selection in the viewer
439 */
440 void OCCViewer_Viewer3d::enableSelection( bool enable )
441 {
442   myEnableSelection = enable;
443   myAISSelector->enableSelection( enable );
444
445   /* send notification */
446   emit vw3dSelectionEnabled( enable );
447 }
448
449 /*!
450     Enables/disables ordinary and multiple selection
451     ( by 'Shift' key or with a rectangle ) in this viewer.
452 */
453 void OCCViewer_Viewer3d::enableMultipleSelection( bool enable )
454 {
455   /*  Enable/disable rectangle skectching which
456       is used for multiple selection */
457   myAISSelector->enableMultipleSelection( enable );
458
459   myViewFrame->getViewPort()->enableDrawMode( enable );
460
461   /* Enable non-multiple selection as well */
462   if ( !myEnableSelection && enable )
463     enableSelection( enable );
464 }
465
466 /*!
467     Key handler
468 */
469 void OCCViewer_Viewer3d::onKeyPress( QKeyEvent* pe )
470 {
471   if (!QAD_Application::getDesktop()->getActiveComponent().isEmpty()) {
472     QAD_Application::getDesktop()->onKeyPress( pe );
473   }
474 }
475
476 /*!
477     Mouse handler
478 */
479 void OCCViewer_Viewer3d::onMousePress( QMouseEvent* pe )
480 {
481   if ( pe->button() == Qt::LeftButton ) {
482     if ( !QAD_Application::getDesktop()->onMousePress( pe ) ) {
483
484       QAD_ASSERT_DEBUG_ONLY ( myAISSelector );
485       if ( pe->state() & Qt::ShiftButton )
486         myAISSelector->shiftSelect();  /* append selection */
487       else
488         myAISSelector->select();       /* new selection */
489     }
490   }
491 }
492
493 /*!
494     Mouse handler
495 */
496 void OCCViewer_Viewer3d::onMouseMove( QMouseEvent* pe )
497 {
498   /* activate hilighting only if no MB pressed */
499   if ( ! ( pe->state() & ( Qt::LeftButton | Qt::MidButton | Qt::RightButton ) ) ) {
500     QAD_Application::getDesktop()->onMouseMove( pe );
501     OCCViewer_ViewPort* vp = myViewFrame->getViewPort();
502     myAISSelector->moveTo ( pe->x(), pe->y(), ((OCCViewer_ViewPort3d*)vp)->getView() );
503   }
504 }
505
506 /*!
507     Mouse handler
508 */
509 void OCCViewer_Viewer3d::onMouseRelease( QMouseEvent* pe )
510 {
511   /* Selection with a rectangle ( multiple ) */
512   OCCViewer_ViewPort* vp = myViewFrame->getViewPort();
513   QAD_ASSERT_DEBUG_ONLY ( vp );
514   QRect selRect = vp->getSelectionRect ();
515   if ( selRect.isValid() ) {
516     QAD_ASSERT_DEBUG_ONLY ( myAISSelector );
517     QAD_ASSERT_DEBUG_ONLY ( vp->inherits("OCCViewer_ViewPort3d") );
518     if ( pe->state() & Qt::ShiftButton )
519       myAISSelector->shiftSelect ( selRect.left(), selRect.top(),
520                                    selRect.right(), selRect.bottom(),
521                                    ((OCCViewer_ViewPort3d*)vp)->getView() );
522     else
523       myAISSelector->select ( selRect.left(), selRect.top(),
524                               selRect.right(), selRect.bottom(),
525                               ((OCCViewer_ViewPort3d*)vp)->getView() );
526   }
527 }
528
529 /*!
530     Mouse handler
531 */
532 void OCCViewer_Viewer3d::onMouseDoubleClick( QMouseEvent* pe )
533 {
534 }
535
536 /*!
537     Called when a transformation in viewport is started
538 */
539 void OCCViewer_Viewer3d::onTransformationStarted( OCCViewer_ViewPort::OperationType type )
540 {
541   QAD_ASSERT_DEBUG_ONLY ( myAISSelector );
542   if ( myEnableSelection )
543     myAISSelector->enableSelection ( false );   // lock until the end of transform
544
545   if ( type == OCCViewer_ViewPort::PANGLOBAL ||
546        type == OCCViewer_ViewPort::WINDOWFIT )
547     {
548       /*  Start watching 'global panning' and 'window fit'.
549           These operations require additional user's actions
550           in viewport and we have to reset the operations if
551           instead of these actions a user does something else.
552       */
553       qApp->installEventFilter( this );
554     }
555 }
556
557 /*!
558     Called when a transformation in viewport is finished
559 */
560 void OCCViewer_Viewer3d::onTransformationFinished( OCCViewer_ViewPort::OperationType type )
561 {
562   QAD_ASSERT_DEBUG_ONLY ( myAISSelector );
563   if ( myEnableSelection )
564     myAISSelector->enableSelection ( true );    // unlock
565
566   if ( type == OCCViewer_ViewPort::PANGLOBAL ||
567        type == OCCViewer_ViewPort::WINDOWFIT )
568     {
569       /* stop watching 'global panning' and 'window fit'*/
570       qApp->removeEventFilter( this );
571     }
572 }
573
574 /*!
575     Called when an object is selected
576 */
577 void OCCViewer_Viewer3d::onSelectionDone( bool bAdded )
578 {
579   emit vw3dSelectionDone( bAdded );
580
581 //  QAD_Study*    myActiveStudy  = QAD_Application::getDesktop()->getActiveStudy();
582 //  QAD_StudyFrame* myActiveSFrame = myActiveStudy->getActiveStudyFrame();
583  // SALOME_Selection*       Sel  = SALOME_Selection::Selection( myActiveStudy->getSelection() );
584 //  MESSAGE ( "OCCViewer_Viewer3d - NB SELECTED INTERACTIVE OBJECT : " << Sel->IObjectCount() )
585
586   QString ActiveComp = QAD_Application::getDesktop()->getActiveComponent();
587
588   if ( ActiveComp.isEmpty() )
589   {
590     unHighlightAll();
591     return;
592   }
593
594   if ( myAISContext->IndexOfCurrentLocal() <= 0 )
595     globalSelectionDone( bAdded );
596   else
597     localSelectionDone( bAdded );
598   
599   myV3dViewer->Update();
600 }
601
602 /*!
603   Called when an object is selected and there is no opened local context
604 */
605 void OCCViewer_Viewer3d::globalSelectionDone( const bool bAdded )
606 {
607   SALOME_Selection* Sel = SALOME_Selection::Selection(
608     QAD_Application::getDesktop()->getActiveStudy()->getSelection() );
609
610   MESSAGE ( "OCCViewer_Viewer3d - NB SELECTED INTERACTIVE OBJECT : " << Sel->IObjectCount() )
611   
612   SALOME_ListIO DeltaPos;
613   DeltaPos.Clear();
614   SALOME_ListIO DeltaNeg;
615   DeltaNeg.Clear();
616
617   if ( !bAdded )
618   { 
619     for ( myAISContext->InitCurrent(); myAISContext->MoreCurrent(); myAISContext->NextCurrent() )
620     {
621       Handle(SALOME_InteractiveObject) anObj =
622         Handle(SALOME_InteractiveObject)::DownCast( myAISContext->Current()->GetOwner() );
623
624       if ( !anObj.IsNull() )
625       {
626         bool itemAllreadySelected = false;
627         int nbSel = Sel->IObjectCount();
628         if ( nbSel == 0 )
629           DeltaPos.Append( anObj );
630         else
631         {
632           SALOME_ListIteratorOfListIO It( Sel->StoredIObjects() );
633           for( ; It.More(); It.Next() )
634           {
635             Handle( SALOME_InteractiveObject) IO1 = It.Value();
636             if ( anObj->isSame( IO1 ) )
637             {
638               itemAllreadySelected = true;
639               break;
640             }
641           }
642           if ( !itemAllreadySelected )
643             DeltaPos.Append( anObj );
644         }
645       }
646       else if ( myAISContext->Current()->IsKind( STANDARD_TYPE( SALOME_AISObject ) ) )
647       {
648         //Handle(SALOME_AISObject) aSh =
649         //  Handle(SALOME_AISObject)::DownCast( myAISContext->Current() );
650         // Add code here, if someone create a MODULE_AISObject.
651       }
652     }
653
654     if ( DeltaPos.Extent() > 0 )
655       Sel->ClearIObjects();
656
657   }
658   else
659   { /* shift select */
660     SALOME_ListIteratorOfListIO It( Sel->StoredIObjects() );
661     for ( ;It.More(); It.Next() )
662     {
663       Handle( SALOME_InteractiveObject) IO1 = It.Value();
664
665       bool itemAllreadySelected = false;
666       for ( myAISContext->InitCurrent(); myAISContext->MoreCurrent(); myAISContext->NextCurrent() )
667       {
668         Handle(SALOME_InteractiveObject) anObj =
669           Handle(SALOME_InteractiveObject)::DownCast( myAISContext->Current()->GetOwner() );
670
671         if ( !anObj.IsNull() && anObj->isSame( IO1 ) )
672         {
673           itemAllreadySelected = true;
674           break;
675         }
676         else if ( myAISContext->Current()->IsKind( STANDARD_TYPE( SALOME_AISObject ) ) )
677         {
678           //Handle(SALOME_AISObject) aSh =
679           //  Handle(SALOME_AISObject)::DownCast(myAISContext->Current());
680           // Add code here, if someone create a MODULE_AISObject.
681         }
682       }
683
684       if ( !itemAllreadySelected )
685         DeltaNeg.Append( IO1 );
686     }
687
688     myAISContext->InitCurrent();
689     for ( myAISContext->InitCurrent(); myAISContext->MoreCurrent(); myAISContext->NextCurrent() )
690     {
691       Handle(SALOME_InteractiveObject) anObj =
692         Handle(SALOME_InteractiveObject)::DownCast( myAISContext->Current()->GetOwner() );
693
694       if ( !anObj.IsNull() )
695       {
696         bool itemAllreadySelected = false;
697         SALOME_ListIteratorOfListIO It( Sel->StoredIObjects() );
698         for ( ;It.More(); It.Next() )
699         {
700           Handle( SALOME_InteractiveObject) IO1 = It.Value();
701
702           if ( anObj->isSame( IO1 ) )
703           {
704             itemAllreadySelected = true;
705             break;
706           }
707         }
708
709         if ( !itemAllreadySelected )
710           DeltaPos.Append( anObj );
711       }
712       else if ( myAISContext->Current()->IsKind(STANDARD_TYPE(SALOME_AISObject)))
713       {
714         //Handle(SALOME_AISObject) aSh =
715         //  Handle(SALOME_AISObject)::DownCast(myAISContext->Current());
716         // Add code here, if someone create a MODULE_AISObject.
717       }
718     }
719   }
720
721   //  MESSAGE ( "VIEWER onSelectionDone DeltaNeg.count() == " << DeltaNeg.count() )
722   SALOME_ListIteratorOfListIO ItNeg( DeltaNeg );
723   for( ;ItNeg.More();ItNeg.Next() )
724   {
725     Sel->RemoveIObject( ItNeg.Value(), false );
726   }
727
728   //  MESSAGE ( "VIEWER onSelectionDone DeltaPos.count() == " << DeltaPos.Extent() )
729   SALOME_ListIteratorOfListIO ItPos( DeltaPos );
730   for ( ;ItPos.More();ItPos.Next() )
731   {
732     Sel->AddIObject( ItPos.Value(), false );
733   }
734 }
735
736 /*!
737   Called when an object is selected and there is opened local context
738 */
739 void OCCViewer_Viewer3d::localSelectionDone( const bool /*bAdded*/ )
740 {
741   SALOME_Selection* aSelection = SALOME_Selection::Selection(
742     QAD_Application::getDesktop()->getActiveStudy()->getSelection() );
743
744   aSelection->BlockSignals( true );
745
746   OCCViewer_MapOfIOIndexedMapOfShape aMapsOfShapes;   // SALOME_InteractiveObject <--> TopTools_IndexedMapOfShape
747   OCCViewer_MapOfIOMapOfInteger      aMapsOfIndexes; // SALOME_InteractiveObject <--> TColStd_MapOfInteger
748
749
750   // Iterate through selected objects and add them to selection
751   for( myAISContext->InitSelected(); myAISContext->MoreSelected(); myAISContext->NextSelected() )
752   {
753     // Retrive selected shape and subshape
754     Handle(SelectMgr_EntityOwner) anOwner = myAISContext->SelectedOwner();
755     if ( anOwner.IsNull() )
756       continue;
757       
758     Handle(AIS_InteractiveObject) anIO =
759       Handle(AIS_InteractiveObject)::DownCast( myAISContext->SelectedInteractive() );
760     if ( anIO.IsNull() )
761       continue;
762
763     Handle(SALOME_InteractiveObject) anObj =
764       Handle(SALOME_InteractiveObject)::DownCast( anIO->GetOwner() );
765     if ( anObj.IsNull() )
766       continue;
767     
768     if ( anIO->IsKind( STANDARD_TYPE( AIS_Shape ) ) )
769     {
770       Handle(AIS_Shape) anAISShape = Handle(AIS_Shape)::DownCast( anIO );
771       TopoDS_Shape aShape = anAISShape->Shape();
772       TopoDS_Shape aSubShape = anOwner->Shape();
773       if ( aShape.IsNull() || aSubShape.IsNull() )
774         continue;
775
776       // Get index of selected shape
777       if ( aMapsOfShapes.IsBound( anObj ) )
778       {
779         const TopTools_IndexedMapOfShape& aShapes = aMapsOfShapes( anObj );
780         int anIndex = aShapes.FindIndex( aSubShape );
781
782         aMapsOfIndexes( anObj ).Add( anIndex );
783       }
784       else
785       {
786         TopTools_IndexedMapOfShape aShapes;
787         TopExp::MapShapes( aShape, aShapes );
788         int anIndex = aShapes.FindIndex( aSubShape );
789
790         TColStd_MapOfInteger anIndexes;
791         anIndexes.Add( anIndex );
792
793         aMapsOfShapes.Bind( anObj, aShapes );
794         aMapsOfIndexes.Bind( anObj, anIndexes );
795       }
796     }
797     else
798     {
799       aMapsOfShapes.Bind( anObj, TopTools_IndexedMapOfShape() );
800       aMapsOfIndexes.Bind( anObj, TColStd_MapOfInteger() );
801     }
802   }
803
804   // Clear selection
805   aSelection->ClearIObjects();
806
807   // Add object in selection
808   OCCViewer_MapOfIOMapOfInteger::Iterator anIter( aMapsOfIndexes );
809   for ( ; anIter.More(); anIter.Next() )
810   {
811     if ( anIter.Value().IsEmpty() )
812       aSelection->AddIObject( anIter.Key(), false );
813     else
814     {
815       aSelection->AddIObject( anIter.Key(), false );
816       aSelection->AddOrRemoveIndex( anIter.Key(), anIter.Value(), false, false );
817     }
818   }
819
820   aSelection->BlockSignals( false );
821   aSelection->SelectionChanged();
822 }
823
824 /*!
825     Called when an object is unselected
826 */
827 void OCCViewer_Viewer3d::onSelectionCancel( bool bAdded )
828 {
829   emit vw3dSelectionCancel();
830
831   QAD_Study*  myActiveStudy      = QAD_Application::getDesktop()->getActiveStudy();
832   SALOME_Selection*  Sel         = SALOME_Selection::Selection( myActiveStudy->getSelection() );
833
834   SALOME_ListIO DeltaPos;
835   DeltaPos.Clear();
836   SALOME_ListIO DeltaNeg;
837   DeltaNeg.Clear();
838   
839   if ( !bAdded )
840   { /* select */
841     Sel->ClearIObjects();
842   }
843   else
844   { /* shiftselect */
845     SALOME_ListIteratorOfListIO It( Sel->StoredIObjects() );
846     for ( ; It.More(); It.Next() )
847     {
848       Handle( SALOME_InteractiveObject) IO1 = It.Value();
849
850       bool itemAllreadySelected = false;
851       myAISContext->InitCurrent();
852       for ( myAISContext->InitCurrent(); myAISContext->MoreCurrent(); myAISContext->NextCurrent() )
853       {
854         Handle(SALOME_InteractiveObject) anObj =
855           Handle(SALOME_InteractiveObject)::DownCast( myAISContext->Current()->GetOwner() );
856           
857         if ( !anObj.IsNull() && anObj->isSame( IO1 ) )
858         {
859           itemAllreadySelected = true;
860           break;
861         }
862         else if ( myAISContext->Current()->IsKind( STANDARD_TYPE( SALOME_AISObject ) ) )
863         {
864           Handle(SALOME_AISObject) aSh =
865             Handle(SALOME_AISObject)::DownCast(myAISContext->Current());
866           // Add code here, if someone create a MODULE_AISObject.
867         }
868       }
869       
870       // only if isknown
871       if ( !itemAllreadySelected )
872         DeltaNeg.Append( IO1 );
873     }
874   }
875
876   //  MESSAGE ( "VIEWER onSelectionCancel DeltaNeg.count() == " << DeltaNeg.Extent() )
877   SALOME_ListIteratorOfListIO ItNeg( DeltaNeg );
878   for ( ; ItNeg.More(); ItNeg.Next() ) 
879     Sel->RemoveIObject( ItNeg.Value(), false);
880
881   myV3dViewer->Update();
882 }
883
884 /*!
885     Installed while 'fit area' and 'global panning'
886     operations are active
887 */
888 bool OCCViewer_Viewer3d::eventFilter( QObject * po, QEvent * pe)
889 {
890   if ( ( pe->type() == QEvent::MouseButtonPress &&
891          po != myViewFrame->getViewPort() ) ||
892        pe->type() == QEvent::KeyPress ) {
893     /* user press any key or a MB outside the viewport */
894     myViewFrame->getViewPort()->resetState();
895   }
896   return QObject::eventFilter( po, pe );
897 }
898
899 /*!
900   Creates CasCade viewer 3D
901 */
902 void OCCViewer_Viewer3d::createViewer3d()
903 {
904   myV3dViewer = OCCViewer_VService::Viewer ( "", (short*) "Viewer3d", "", 1000.,
905                                              V3d_XposYnegZpos, true, true);
906   myV3dViewer->Init();
907
908   myV3dCollector = OCCViewer_VService::Viewer ( "", (short*) "Collector3d", "", 1000.,
909                                                 V3d_XposYnegZpos, true, true);
910   myV3dCollector->Init();
911 }
912
913 /*!
914   Returns CasCade viewer 3D
915 */
916 Handle(V3d_Viewer) OCCViewer_Viewer3d::getViewer3d() const
917 {
918   return myV3dViewer;
919 }
920
921 /*!
922     Sets a new cursor on all its studyframes
923 */
924 void OCCViewer_Viewer3d::setCursor( const QCursor& cursor)
925 {
926   myCursor = cursor;
927 }
928
929 /*!
930     Returns the current cursor
931 */
932 inline const QCursor& OCCViewer_Viewer3d::cursor() const
933 {
934   return myCursor;
935 }
936
937 /*!
938     Sets default background color on all its studyframes
939 */
940 void OCCViewer_Viewer3d::setBackgroundColor( const QColor& aColor )
941 {
942   myBackColor = aColor;
943 }
944
945 /*!
946     Returns the current background
947 */
948 inline const QColor& OCCViewer_Viewer3d::backgroundColor() const
949 {
950   return myBackColor;
951 }
952
953 /*!
954     Sets a new icon to all its studyframes
955 */
956 void OCCViewer_Viewer3d::setIcon( const QPixmap& icon )
957 {
958   myIcon = icon;
959 }
960
961 /*!
962   Returns current icon
963 */
964 inline const QPixmap& OCCViewer_Viewer3d::icon() const
965 {
966   return myIcon;
967 }
968
969 /*!
970     Builds popup menu
971 */
972 void OCCViewer_Viewer3d::onCreatePopup()
973 {
974 }
975