Salome HOME
Merge branch 'master' into V9_dev
[modules/gui.git] / src / SOCC / SOCC_ViewModel.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "SOCC_ViewModel.h"
24
25 #include "SOCC_Prs.h"
26 #include "SOCC_ViewWindow.h"
27
28 #include "SUIT_Session.h"
29 #include "SUIT_ResourceMgr.h"
30 //#include "SUIT_Application.h"
31
32 //#include "ToolsGUI.h"
33
34 // Temporarily commented to avoid awful dependecy on SALOMEDS
35 // TODO: better mechanism of storing display/erse status in a study
36 // should be provided...
37 //#include <SALOMEconfig.h>
38 //#include CORBA_CLIENT_HEADER(SALOMEDS)
39
40 #include <AIS_ListIteratorOfListOfInteractive.hxx>
41
42 #include <SALOME_AISShape.hxx>
43 #include <SALOME_AISObject.hxx>
44 #include <SALOME_InteractiveObject.hxx>
45 #include <SALOME_ListIO.hxx>
46
47 #include <AIS_TypeOfIso.hxx>
48 #include <Precision.hxx>
49
50 #include <algorithm>
51
52 /*!
53   Constructor
54   \param DisplayTrihedron - is trihedron displayed
55 */
56 SOCC_Viewer::SOCC_Viewer( bool DisplayTrihedron )
57 : OCCViewer_Viewer( DisplayTrihedron )
58 {
59 }
60
61 /*!
62   Destructor
63 */
64 SOCC_Viewer::~SOCC_Viewer()
65 {
66 }
67
68 /*!
69   Hilights/unhilights object in viewer
70   \param obj - object to be updated
71   \param hilight - if it is true, object will be hilighted, otherwise it will be unhilighted
72   \param update - update current viewer
73 */
74 bool SOCC_Viewer::highlight( const Handle(SALOME_InteractiveObject)& obj,
75                              bool hilight, bool upd )
76 {
77   bool isInLocal = getAISContext()->HasOpenedContext();
78   //SUIT_Study* ActiveStudy = SUIT_Application::getDesktop()->getActiveStudy();
79   //SALOME_Selection* Sel = SALOME_Selection::Selection( ActiveStudy->getSelection() );
80
81   AIS_ListOfInteractive List;
82   getAISContext()->DisplayedObjects(List);
83   
84   AIS_ListIteratorOfListOfInteractive ite(List);
85   for ( ; ite.More(); ite.Next() )
86   {
87     Handle(SALOME_InteractiveObject) anObj =
88       Handle(SALOME_InteractiveObject)::DownCast( ite.Value()->GetOwner() );
89
90     if ( !anObj.IsNull() && anObj->hasEntry() && anObj->isSame( obj ) )
91     {
92       if ( !isInLocal )
93           OCCViewer_Viewer::highlight( ite.Value(), hilight, false );
94       // highlight sub-shapes only when local selection is active
95       else
96       {
97         /*if ( ite.Value()->IsKind( STANDARD_TYPE( SALOME_AISShape ) ) )
98         {
99           Handle(SALOME_AISShape) aSh = Handle(SALOME_AISShape)::DownCast( ite.Value() );
100           TColStd_IndexedMapOfInteger MapIndex;
101           Sel->GetIndex( IObject, MapIndex );
102           aSh->highlightSubShapes( MapIndex, highlight );
103         }*/
104       }
105       break;
106     }
107   }
108     
109   if( upd )
110     update();
111     
112   return false;
113 }
114
115 /*!
116   \return true if object is in viewer or in collector
117   \param obj - object to be checked
118   \param onlyInViewer - search object only in viewer (so object must be displayed)
119 */
120 bool SOCC_Viewer::isInViewer( const Handle(SALOME_InteractiveObject)& obj,
121                               bool onlyInViewer )
122 {
123   AIS_ListOfInteractive List;
124   getAISContext()->DisplayedObjects(List);
125   AIS_ListIteratorOfListOfInteractive ite(List);
126   for ( ; ite.More(); ite.Next() )
127   {
128     Handle(SALOME_InteractiveObject) anObj =
129         Handle(SALOME_InteractiveObject)::DownCast( ite.Value()->GetOwner() );
130
131     if ( !anObj.IsNull() && anObj->hasEntry() && anObj->isSame( obj ) )
132       return true;
133   }
134   return false;
135 }
136
137 /*!
138   \return true if object is displayed in viewer
139   \param obj - object to be checked
140 */
141 bool SOCC_Viewer::isVisible( const Handle(SALOME_InteractiveObject)& obj )
142 {
143
144   std::map< std::string , std::vector<Handle(AIS_InteractiveObject)> >::iterator it=entry2aisobjects.find(obj->getEntry());
145   if(it != entry2aisobjects.end())
146     {
147       // get context
148       Handle (AIS_InteractiveContext) ic = getAISContext();
149       std::vector<Handle(AIS_InteractiveObject)>& List = it->second;
150       for( unsigned int ind = 0; ind < List.size(); ind++ )
151         {
152           Handle(AIS_InteractiveObject) anAIS=List[ind];
153           if(ic->IsDisplayed(anAIS))
154             return true;
155         }
156   }
157   
158   return false;
159 }
160
161 /*!
162   Sets color of object
163   \param obj - object to be updated
164   \param color - new color
165   \param update - update current viewer
166 */
167 void SOCC_Viewer::setColor( const Handle(SALOME_InteractiveObject)& obj,
168                             const QColor& color, bool update )
169 {
170   if(obj.IsNull() || !obj->hasEntry() )
171     return;
172
173   if(entry2aisobjects.count(obj->getEntry())>0)
174     {
175       // get context
176       Handle (AIS_InteractiveContext) ic = getAISContext();
177       std::vector<Handle(AIS_InteractiveObject)>& List = entry2aisobjects[obj->getEntry()];
178       for( unsigned int ind = 0; ind < List.size(); ind++ )
179         {
180           Handle(AIS_InteractiveObject) anAIS=List[ind];
181           if( !anAIS.IsNull() && ic->IsDisplayed(anAIS))
182             OCCViewer_Viewer::setColor( anAIS, color, update );
183         }
184     }
185 }
186
187 /*!
188   Changes display mode of object
189   \param obj - object to be processed
190   \param mode - new display mode
191   \param update - update current viewer
192 */
193 void SOCC_Viewer::switchRepresentation( const Handle(SALOME_InteractiveObject)& obj,
194                                         int mode, bool update )
195 {
196   if(obj.IsNull() || !obj->hasEntry() )
197     return;
198
199   if(entry2aisobjects.count(obj->getEntry())>0)
200     {
201       // get context
202       Handle (AIS_InteractiveContext) ic = getAISContext();
203       std::vector<Handle(AIS_InteractiveObject)>& List = entry2aisobjects[obj->getEntry()];
204       for( unsigned int ind = 0; ind < List.size(); ind++ )
205         {
206           Handle(AIS_InteractiveObject) anAIS=List[ind];
207           if( !anAIS.IsNull() && ic->IsDisplayed(anAIS))
208             OCCViewer_Viewer::switchRepresentation( anAIS, mode, update );
209         }
210     }
211 }
212
213 /*!
214   Changes transparency of object
215   \param obj - object to be processed
216   \param trans - new transparency
217   \param update - update current viewer
218 */
219 void SOCC_Viewer::setTransparency( const Handle(SALOME_InteractiveObject)& obj,
220                                    float trans, bool update )
221 {
222   if(obj.IsNull() || !obj->hasEntry() )
223     return;
224
225   if(entry2aisobjects.count(obj->getEntry())>0)
226     {
227       // get context
228       Handle (AIS_InteractiveContext) ic = getAISContext();
229       std::vector<Handle(AIS_InteractiveObject)>& List = entry2aisobjects[obj->getEntry()];
230       for( unsigned int ind = 0; ind < List.size(); ind++ )
231         {
232           Handle(AIS_InteractiveObject) anAIS=List[ind];
233           if( !anAIS.IsNull() && ic->IsDisplayed(anAIS))
234             OCCViewer_Viewer::setTransparency( anAIS, trans, update );
235         }
236     }
237 }
238
239 /*!
240   Changes name of object
241   \param obj - object to be renamed
242   \param name - new name
243 */
244 void SOCC_Viewer::rename( const Handle(SALOME_InteractiveObject)& obj,
245                           const QString& name )
246 {
247   AIS_ListOfInteractive List;
248   getAISContext()->DisplayedObjects(List);
249   
250   AIS_ListIteratorOfListOfInteractive ite(List);
251   while (ite.More())
252   {
253     if (ite.Value()->IsKind(STANDARD_TYPE(SALOME_AISShape)))
254     {
255       Handle(SALOME_AISShape) aSh = Handle(SALOME_AISShape)::DownCast(ite.Value());
256       
257       if ( aSh->hasIO() )
258       {
259         Handle(SALOME_InteractiveObject) IO = aSh->getIO();
260         if ( IO->isSame( obj ) )
261         {
262           aSh->setName( name.toLatin1().data() );
263           break;
264         }
265       }
266     }
267     else if ( ite.Value()->IsKind( STANDARD_TYPE( SALOME_AISObject ) ) )
268     {
269       Handle(SALOME_AISObject) aSh = Handle(SALOME_AISObject)::DownCast( ite.Value() );
270
271       // Add code here, if someone create a MODULE_AISObject.
272     }
273     ite.Next();
274   }
275 }
276
277
278 /*!
279   Display presentation
280   \param prs - presentation
281 */
282 void SOCC_Viewer::Display( const SALOME_OCCPrs* prs )
283 {
284   // try do downcast object
285   const SOCC_Prs* anOCCPrs = dynamic_cast<const SOCC_Prs*>( prs );
286   if ( !anOCCPrs || anOCCPrs->IsNull() )
287     return;
288
289   // get context
290   Handle (AIS_InteractiveContext) ic = getAISContext();
291
292   // get objects to be displayed
293   AIS_ListOfInteractive anAISObjects;
294   anOCCPrs->GetObjects( anAISObjects );
295
296   AIS_ListIteratorOfListOfInteractive aIter( anAISObjects );
297   for ( ; aIter.More(); aIter.Next() )
298   {
299     Handle(AIS_InteractiveObject) anAIS = aIter.Value();
300     if ( !anAIS.IsNull() )
301     {
302       // try to find presentation in the viewer
303
304       // if the object is already displayed - nothing to do more
305       if(ic->IsDisplayed(anAIS))
306         {
307           // Deactivate object if necessary
308           if ( !anOCCPrs->ToActivate() )
309             ic->Deactivate( anAIS );
310           continue;
311         }
312
313       // if object is not displayed and not found in the collector - display it
314       if ( anAIS->IsKind( STANDARD_TYPE(AIS_Trihedron) ) )
315       {
316         Handle(AIS_Trihedron) aTrh = Handle(AIS_Trihedron)::DownCast( anAIS );
317         double aNewSize = 100, aSize = 100;
318         computeTrihedronSize( aNewSize, aSize );
319         aTrh->SetSize( aTrh == getTrihedron() ? aNewSize : 0.5 * aNewSize );
320       }
321
322       ic->Display( anAIS, false );
323       Handle(SALOME_AISShape) aSh = Handle(SALOME_AISShape)::DownCast (anAIS);
324       if (!aSh.IsNull())
325       {
326         aSh->SetClippable (prs->IsClippable());
327         applyExistingClipPlanesToObject (anAIS);
328         bool top = (aSh->isTopLevel() && aSh->switchTopLevel());
329               ic->SetZLayer( aSh, top ? getTopLayerId() : 0 );
330                     if(!aSh->toActivate())
331         {
332                             ic->Deactivate( aSh );
333                     }
334       }
335
336       //Register anAIS (if it has an entry) in entry2aisobjects map
337       Handle(SALOME_InteractiveObject) anObj = Handle(SALOME_InteractiveObject)::DownCast( anAIS->GetOwner() );
338       if ( !anObj.IsNull() && anObj->hasEntry())
339         {
340           std::vector<Handle(AIS_InteractiveObject)>& List = entry2aisobjects[anObj->getEntry()];
341           int found=0;
342           for ( unsigned int ind = 0; ind < List.size(); ind++ )
343           {
344             if(List[ind] == anAIS)
345               {
346                 found=1;
347                 break;
348               }
349           }
350           if(!found)
351             {
352               List.push_back(anAIS);
353             }
354         }
355
356       // Set visibility flag
357       // Temporarily commented to avoid awful dependecy on SALOMEDS
358       // TODO: better mechanism of storing display/erse status in a study
359       // should be provided...
360       //Handle(SALOME_InteractiveObject) anObj =
361       //  Handle(SALOME_InteractiveObject)::DownCast( anAIS->GetOwner() );
362       //if ( !anObj.IsNull() && anObj->hasEntry() )
363       //{
364       //  ToolsGUI::SetVisibility( anObj->getEntry(), true, this );
365       //}
366
367       // Deactivate object if necessary
368       if ( !anOCCPrs->ToActivate() )
369         ic->Deactivate( anAIS );
370     }
371   }
372   updateTrihedron();
373 }
374
375
376 /*!
377   Erase presentation
378   \param prs - presentation
379   \param forced - removes object from context
380 */
381 void SOCC_Viewer::Erase( const SALOME_OCCPrs* prs, const bool forced )
382 {
383   // try do downcast object
384   const SOCC_Prs* anOCCPrs = dynamic_cast<const SOCC_Prs*>( prs );
385   if ( !anOCCPrs || anOCCPrs->IsNull() )
386     return;
387
388   // get context
389   Handle(AIS_InteractiveContext) ic = getAISContext();
390
391   // get objects to be erased
392   AIS_ListOfInteractive anAISObjects;
393   anOCCPrs->GetObjects( anAISObjects );
394
395   AIS_ListIteratorOfListOfInteractive aIter( anAISObjects );
396   for ( ; aIter.More(); aIter.Next() ) {
397     Handle(AIS_InteractiveObject) anAIS = aIter.Value();
398     if ( !anAIS.IsNull() ) {
399       // erase the object from context : move it to collector
400       ic->Erase( anAIS, false );
401       // Set visibility flag if necessary
402       // Temporarily commented to avoid awful dependecy on SALOMEDS
403       // TODO: better mechanism of storing display/erse status in a study
404       // should be provided...
405       //if ( !forced )
406       //{
407       //  Handle(SALOME_InteractiveObject) anObj =
408       //    Handle(SALOME_InteractiveObject)::DownCast( anAIS->GetOwner() );
409       //  if ( !anObj.IsNull() && anObj->hasEntry() )
410       //  {
411       //    ToolsGUI::SetVisibility( anObj->getEntry(), true, this );
412       //  }
413       //}
414     }
415   }
416   updateTrihedron();
417 }
418
419
420 /*!
421   Erase all presentations
422   \param forced - removes all objects from context
423 */
424 void SOCC_Viewer::EraseAll( SALOME_Displayer* d, const bool forced )
425 {
426   // get context
427   Handle(AIS_InteractiveContext) ic = getAISContext();
428
429   // check if trihedron is displayed
430   Standard_Boolean isTrihedronDisplayed = ic->IsDisplayed( getTrihedron() );
431
432   // get objects to be erased (all currently displayed objects)
433   AIS_ListOfInteractive aList;
434   ic->DisplayedObjects( aList );
435   AIS_ListIteratorOfListOfInteractive anIter( aList );
436   for ( ; anIter.More(); anIter.Next() ) {
437     if ( (isTrihedronDisplayed && anIter.Value()->DynamicType() == STANDARD_TYPE( AIS_Trihedron ) ) )
438       continue;
439
440     // erase an object
441     Handle(AIS_InteractiveObject) anIO = anIter.Value();
442     ic->Erase( anIO, false );
443     
444     // Set visibility flag if necessary
445     // Temporarily commented to avoid awful dependecy on SALOMEDS
446     // TODO: better mechanism of storing display/erse status in a study
447     // should be provided...
448     //if ( !forced ) {
449     //  Handle(SALOME_InteractiveObject) anObj =
450     //  Handle(SALOME_InteractiveObject)::DownCast( anIO->GetOwner() );
451
452     //  if ( !anObj.IsNull() && anObj->hasEntry() ) {
453     //    ToolsGUI::SetVisibility( anObj->getEntry(), true, this );
454     //  }
455     //}
456   }
457
458   SALOME_View::EraseAll( d, forced );
459
460   Repaint();
461   updateTrihedron();
462 }
463
464 /*!
465   Create presentation corresponding to the entry
466   \param entry - entry
467 */
468 SALOME_Prs* SOCC_Viewer::CreatePrs( const char* entry )
469 {
470   SOCC_Prs* prs = new SOCC_Prs(entry);
471   if ( entry )
472   {
473     if(entry2aisobjects.count(entry)>0)
474       {
475         //ais object exists
476         std::vector<Handle(AIS_InteractiveObject)> List = entry2aisobjects[entry];
477         // get context
478         Handle(AIS_InteractiveContext) ic = getAISContext();
479         //add all ais
480         for ( unsigned int ind = 0; ind < List.size(); ind++ )
481           {
482             Handle(AIS_InteractiveObject) anAIS=List[ind];
483             if(ic->IsDisplayed(anAIS))
484               {
485                 prs->AddObject( anAIS );
486               }
487           }
488       }
489   }
490   return prs;
491 }
492
493 /*!
494   Activates selection of sub-shapes
495 */
496 void SOCC_Viewer::LocalSelection( const SALOME_OCCPrs* thePrs, const std::list<int> modes )
497 {
498   Handle(AIS_InteractiveContext) ic = getAISContext();
499   
500   const SOCC_Prs* anOCCPrs = dynamic_cast<const SOCC_Prs*>( thePrs );
501   if ( ic.IsNull() )
502     return;
503   
504   // Open local context if there is no one
505   bool allObjects = thePrs == 0 || thePrs->IsNull();
506   if ( !ic->HasOpenedContext() ) {
507     ic->ClearCurrents( false );
508     ic->OpenLocalContext( Standard_False, Standard_True, Standard_True );
509   }
510
511   AIS_ListOfInteractive anObjs;
512   // Get objects to be activated
513   if ( allObjects ) 
514     ic->DisplayedObjects( anObjs );
515   else
516     anOCCPrs->GetObjects( anObjs );
517
518   std::list<int> sel_modes;
519   for ( int i = TopAbs_COMPOUND; i < TopAbs_SHAPE; i++ )
520     if ( std::find(modes.begin(), modes.end(), (int)TopAbs_SHAPE) != modes.end() || std::find(modes.begin(), modes.end(), i) != modes.end())
521       sel_modes.push_back(i);
522
523   // Activate selection of objects from prs
524   AIS_ListIteratorOfListOfInteractive aIter( anObjs );
525   for ( ; aIter.More(); aIter.Next() ) {
526     Handle(AIS_InteractiveObject) anAIS = aIter.Value();
527     if ( !anAIS.IsNull() )
528     {
529       std::list<int>::const_iterator it;
530       if ( anAIS->IsKind( STANDARD_TYPE( AIS_Shape ) ) )
531       {
532         ic->Load( anAIS, -1, false );
533         for( it = sel_modes.begin(); it != sel_modes.end(); ++it )
534           ic->Activate( anAIS, AIS_Shape::SelectionMode( (TopAbs_ShapeEnum)*it ) );
535       }
536       else if ( anAIS->DynamicType() != STANDARD_TYPE(AIS_Trihedron) )
537       {
538         ic->Load( anAIS, -1, false );
539         for( it = sel_modes.begin(); it != sel_modes.end(); ++it )
540           ic->Activate( anAIS, *it );
541       }
542     }
543   }
544 }
545
546 /*!
547   Activates selection of sub-shapes
548 */
549 void SOCC_Viewer::LocalSelection( const SALOME_OCCPrs* thePrs, const int theMode )
550 {
551   std::list<int> modes;
552   modes.push_back( theMode );
553   LocalSelection( thePrs, modes );
554 }
555
556 /*!
557   Deactivates selection of sub-shapes
558 */
559 void SOCC_Viewer::GlobalSelection( const bool update ) const
560 {
561   Handle(AIS_InteractiveContext) ic = getAISContext();
562   if ( !ic.IsNull() )
563   {
564     ic->CloseAllContexts( false );
565     if ( update )
566       ic->CurrentViewer()->Redraw();
567   }
568 }
569
570
571 /*!
572   \Collect objects visible in viewer
573   \param theList - visible objects collection
574 */
575 void SOCC_Viewer::GetVisible( SALOME_ListIO& theList )
576 {
577   AIS_ListOfInteractive List;
578   getAISContext()->DisplayedObjects(List);
579   
580   AIS_ListIteratorOfListOfInteractive ite(List);
581   for ( ; ite.More(); ite.Next() )
582   {
583     Handle(SALOME_InteractiveObject) anObj =
584         Handle(SALOME_InteractiveObject)::DownCast( ite.Value()->GetOwner() );
585
586     if ( !anObj.IsNull() && anObj->hasEntry() )
587       theList.Append( anObj );
588   }
589 }
590
591 /*!
592   Updates current viewer
593 */
594 void SOCC_Viewer::Repaint()
595 {
596 //  onAdjustTrihedron();
597   getViewer3d()->Update();
598 }
599
600
601 /*!
602   create SOCC_ViewWindow
603 */
604 /*SUIT_ViewWindow* SOCC_Viewer::createView( SUIT_Desktop* theDesktop )
605 {
606   SOCC_ViewWindow* view = new SOCC_ViewWindow(theDesktop, this);
607   //initView( view );
608   initView( view->getView(OCCViewer_ViewFrame::MAIN_VIEW) );
609   return view;
610   }*/
611
612 /* 
613  * Returns a new OCCViewer_ViewWindow instance which will be placed as a sub window in ViewFrame
614  */
615 OCCViewer_ViewWindow* SOCC_Viewer::createSubWindow()
616 {
617   return new SOCC_ViewWindow( 0,  this);
618 }