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