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