Salome HOME
Merge from BR_V5_DEV 16Feb09
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_VTKUtils.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 // SMESH SMESHGUI : GUI for SMESH component
23 // File   : SMESHGUI_VTKUtils.cxx
24 // Author : Open CASCADE S.A.S.
25 // SMESH includes
26 //
27 #include "SMESHGUI_VTKUtils.h"
28
29 #include "SMESHGUI.h"
30 #include "SMESHGUI_Utils.h"
31 #include "SMESHGUI_Filter.h"
32
33 #include <SMESH_Actor.h>
34 #include <SMESH_ActorUtils.h>
35 #include <SMESH_ObjectDef.h>
36 #include <SMDS_Mesh.hxx>
37
38 // SALOME GUI includes
39 #include <SUIT_Desktop.h>
40 #include <SUIT_Session.h>
41 #include <SUIT_MessageBox.h>
42 #include <SUIT_ViewManager.h>
43 #include <SUIT_ResourceMgr.h>
44
45 #include <SALOME_ListIO.hxx>
46 #include <SALOME_ListIteratorOfListIO.hxx>
47
48 #include <SVTK_Selector.h>
49 #include <SVTK_ViewModel.h>
50 #include <SVTK_ViewWindow.h>
51
52 #include <LightApp_SelectionMgr.h>
53 #include <SalomeApp_Application.h>
54 #include <SalomeApp_Study.h>
55
56 // SALOME KERNEL includes
57 #include <utilities.h>
58
59 // IDL includes
60 #include <SALOMEconfig.h>
61 #include CORBA_CLIENT_HEADER(SMESH_Mesh)
62 #include CORBA_CLIENT_HEADER(SMESH_Group)
63
64 // VTK includes
65 #include <vtkRenderer.h>
66 #include <vtkActorCollection.h>
67 #include <vtkUnstructuredGrid.h>
68
69 // OCCT includes
70 #include <TColStd_IndexedMapOfInteger.hxx>
71 #include <Standard_ErrorHandler.hxx>
72
73 namespace SMESH
74 {
75   typedef std::map<TKeyOfVisualObj,TVisualObjPtr> TVisualObjCont;
76   static TVisualObjCont VISUAL_OBJ_CONT;
77
78   //=============================================================================
79   /*!
80    * \brief Allocate some memory at construction and release it at destruction.
81    * Is used to be able to continue working after mesh generation or visualization
82    * break due to lack of memory
83    */
84   //=============================================================================
85
86   struct MemoryReserve
87   {
88     char* myBuf;
89     MemoryReserve(): myBuf( new char[1024*1024*1] ){} // 1M
90     void Free() { if (myBuf) { delete [] myBuf; myBuf = 0; }}
91     ~MemoryReserve() { Free(); }
92   };
93   static MemoryReserve* theVISU_MemoryReserve = new MemoryReserve;
94
95   //================================================================================
96   /*!
97    * \brief Remove VisualObj and its actor from all views
98    */
99   //================================================================================
100
101   void RemoveVisualObjectWithActors( const char* theEntry )
102   {
103     SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>
104       ( SUIT_Session::session()->activeApplication() );
105     SUIT_ViewManager* aViewManager =
106       app ? app->getViewManager(SVTK_Viewer::Type(), true) : 0;
107     if ( aViewManager ) {
108       QVector<SUIT_ViewWindow*> views = aViewManager->getViews();
109       for ( int iV = 0; iV < views.count(); ++iV ) {
110         if ( SMESH_Actor* actor = FindActorByEntry( views[iV], theEntry)) {
111           if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(views[iV]))
112             vtkWnd->RemoveActor(actor);
113           actor->Delete();
114         }
115       }
116       int aStudyId = aViewManager->study()->id();
117       TVisualObjCont::key_type aKey(aStudyId,theEntry);
118       TVisualObjCont::iterator anIter = VISUAL_OBJ_CONT.find(aKey);
119       if(anIter != VISUAL_OBJ_CONT.end()) {
120         // for unknown reason, object destructor is not called, so clear object manually
121         anIter->second->GetUnstructuredGrid()->SetCells(0,0,0);
122         anIter->second->GetUnstructuredGrid()->SetPoints(0);
123       }
124       VISUAL_OBJ_CONT.erase(aKey);
125     }
126   }
127   //================================================================================
128   /*!
129    * \brief Remove all VisualObjs and their actors from all views
130    */
131   //================================================================================
132
133   void RemoveAllObjectsWithActors()
134   {
135     SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>
136       ( SUIT_Session::session()->activeApplication() );
137     if (!app) return;
138     ViewManagerList viewMgrs = app->viewManagers();
139     for ( int iM = 0; iM < viewMgrs.count(); ++iM ) {
140       SUIT_ViewManager* aViewManager = viewMgrs.at( iM );
141       if ( aViewManager && aViewManager->getType() == SVTK_Viewer::Type()) {
142         QVector<SUIT_ViewWindow*> views = aViewManager->getViews();
143         for ( int iV = 0; iV < views.count(); ++iV ) {
144           if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(views[iV])) {
145             vtkRenderer *aRenderer = vtkWnd->getRenderer();
146             vtkActorCollection *actors = aRenderer->GetActors();
147             for (int i = 0; i < actors->GetNumberOfItems(); ++i ) {
148               // size of actors changes inside the loop
149               while (SMESH_Actor *actor = dynamic_cast<SMESH_Actor*>(actors->GetItemAsObject(i)))
150               {
151                 vtkWnd->RemoveActor(actor);
152                 actor->Delete();
153               }
154             }
155           }
156         }
157       }
158     }
159     TVisualObjCont::iterator anIter = VISUAL_OBJ_CONT.begin();
160     for ( ; anIter != VISUAL_OBJ_CONT.end(); ++anIter ) {
161       // for unknown reason, object destructor is not called, so clear object manually
162       anIter->second->GetUnstructuredGrid()->SetCells(0,0,0);
163       anIter->second->GetUnstructuredGrid()->SetPoints(0);
164     }
165     VISUAL_OBJ_CONT.clear();
166   }
167
168   //================================================================================
169   /*!
170    * \brief Remove all VisualObjs of a study
171    */
172   //================================================================================
173
174   void RemoveVisuData(int studyID)
175   {
176     SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>
177       ( SUIT_Session::session()->activeApplication() );
178     if (!app) return;
179     ViewManagerList viewMgrs = app->viewManagers();
180     for ( int iM = 0; iM < viewMgrs.count(); ++iM ) {
181       SUIT_ViewManager* aViewManager = viewMgrs.at( iM );
182       if ( aViewManager && aViewManager->getType() == SVTK_Viewer::Type() &&
183            aViewManager->study()->id() == studyID ) {
184         QVector<SUIT_ViewWindow*> views = aViewManager->getViews();
185         for ( int iV = 0; iV < views.count(); ++iV ) {
186           if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(views[iV])) {
187             vtkRenderer *aRenderer = vtkWnd->getRenderer();
188             vtkActorCollection *actors = aRenderer->GetActors();
189             for (int i = 0; i < actors->GetNumberOfItems(); ++i ) {
190               // size of actors changes inside the loop
191               while(SMESH_Actor *actor = dynamic_cast<SMESH_Actor*>(actors->GetItemAsObject(i)))
192               {
193                 vtkWnd->RemoveActor(actor);
194                 actor->Delete();
195               }
196             }
197           }
198         }
199       }
200     }
201     TVisualObjCont::iterator anIter = VISUAL_OBJ_CONT.begin();
202     for ( ; anIter != VISUAL_OBJ_CONT.end(); ++anIter ) {
203       int curId = anIter->first.first;
204       if ( curId == studyID ) {
205         // for unknown reason, object destructor is not called, so clear object manually
206         anIter->second->GetUnstructuredGrid()->SetCells(0,0,0);
207         anIter->second->GetUnstructuredGrid()->SetPoints(0);
208         VISUAL_OBJ_CONT.erase( anIter-- );  // dercement occures before erase()
209       }
210     }
211   }
212
213   //================================================================================
214   /*!
215    * \brief Notify the user on problems during visualization
216    */
217   //================================================================================
218
219   void OnVisuException()
220   {
221     try {
222 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
223       OCC_CATCH_SIGNALS;
224 #endif
225       // PAL16774 (Crash after display of many groups). Salome sometimes crashes just
226       // after or at showing this message, so we do an additional check of available memory
227 //       char* buf = new char[100*1024];
228 //       delete [] buf;
229       SUIT_MessageBox::warning(SMESHGUI::desktop(), QObject::tr("SMESH_WRN_WARNING"),
230                                QObject::tr("SMESH_VISU_PROBLEM"));
231     } catch (...) {
232       // no more memory at all: last resort
233       MESSAGE_BEGIN ( "SMESHGUI_VTKUtils::OnVisuException(), exception even at showing a message!!!" <<
234                       std::endl << "Try to remove all visual data..." );
235       if (theVISU_MemoryReserve) {
236         delete theVISU_MemoryReserve;
237         theVISU_MemoryReserve = 0;
238       }
239       RemoveAllObjectsWithActors();
240       SUIT_MessageBox::warning(SMESHGUI::desktop(), QObject::tr("SMESH_WRN_WARNING"),
241                                QObject::tr("SMESH_VISU_PROBLEM_CLEAR"));
242       MESSAGE_END ( "...done" );
243     }
244   }
245   //================================================================================
246   /*!
247    * \brief Returns an updated visual object
248    */
249   //================================================================================
250
251   TVisualObjPtr GetVisualObj(int theStudyId, const char* theEntry){
252     TVisualObjPtr aVisualObj;
253     TVisualObjCont::key_type aKey(theStudyId,theEntry);
254     try{
255 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
256       OCC_CATCH_SIGNALS;
257 #endif
258       TVisualObjCont::iterator anIter = VISUAL_OBJ_CONT.find(aKey);
259       if(anIter != VISUAL_OBJ_CONT.end()){
260         aVisualObj = anIter->second;
261       }else{
262         SalomeApp_Application* app =
263           dynamic_cast<SalomeApp_Application*>( SMESHGUI::activeStudy()->application() );
264         _PTR(Study) aStudy = SMESHGUI::activeStudy()->studyDS();
265         _PTR(SObject) aSObj = aStudy->FindObjectID(theEntry);
266         if(aSObj){
267           _PTR(GenericAttribute) anAttr;
268           if(aSObj->FindAttribute(anAttr,"AttributeIOR")){
269             _PTR(AttributeIOR) anIOR = anAttr;
270             CORBA::String_var aVal = anIOR->Value().c_str();
271             CORBA::Object_var anObj = app->orb()->string_to_object( aVal.in() );
272             if(!CORBA::is_nil(anObj)){
273               //Try narrow to SMESH_Mesh interface
274               SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_narrow(anObj);
275               if(!aMesh->_is_nil()){
276                 aVisualObj.reset(new SMESH_MeshObj(aMesh));
277                 TVisualObjCont::value_type aValue(aKey,aVisualObj);
278                 VISUAL_OBJ_CONT.insert(aValue);
279               }
280               //Try narrow to SMESH_Group interface
281               SMESH::SMESH_GroupBase_var aGroup = SMESH::SMESH_GroupBase::_narrow(anObj);
282               if(!aGroup->_is_nil()){
283                 _PTR(SObject) aFatherSObj = aSObj->GetFather();
284                 if(!aFatherSObj) return aVisualObj;
285                 aFatherSObj = aFatherSObj->GetFather();
286                 if(!aFatherSObj) return aVisualObj;
287                 CORBA::String_var anEntry = aFatherSObj->GetID().c_str();
288                 TVisualObjPtr aVisObj = GetVisualObj(theStudyId,anEntry.in());
289                 if(SMESH_MeshObj* aMeshObj = dynamic_cast<SMESH_MeshObj*>(aVisObj.get())){
290                   aVisualObj.reset(new SMESH_GroupObj(aGroup,aMeshObj));
291                   TVisualObjCont::value_type aValue(aKey,aVisualObj);
292                   VISUAL_OBJ_CONT.insert(aValue);
293                 }
294               }
295               //Try narrow to SMESH_subMesh interface
296               SMESH::SMESH_subMesh_var aSubMesh = SMESH::SMESH_subMesh::_narrow(anObj);
297               if(!aSubMesh->_is_nil()){
298                 _PTR(SObject) aFatherSObj = aSObj->GetFather();
299                 if(!aFatherSObj) return aVisualObj;
300                 aFatherSObj = aFatherSObj->GetFather();
301                 if(!aFatherSObj) return aVisualObj;
302                 CORBA::String_var anEntry = aFatherSObj->GetID().c_str();
303                 TVisualObjPtr aVisObj = GetVisualObj(theStudyId,anEntry.in());
304                 if(SMESH_MeshObj* aMeshObj = dynamic_cast<SMESH_MeshObj*>(aVisObj.get())){
305                   aVisualObj.reset(new SMESH_subMeshObj(aSubMesh,aMeshObj));
306                   TVisualObjCont::value_type aValue(aKey,aVisualObj);
307                   VISUAL_OBJ_CONT.insert(aValue);
308                 }
309               }
310             }
311           }
312         }
313       }
314     }catch(...){
315       INFOS("GetMeshObj - There is no SMESH_Mesh object for the SALOMEDS::Strudy and Entry!!!");
316       return TVisualObjPtr();
317     }
318     // Update object
319     bool objModified = false;
320     if ( aVisualObj ) {
321       try {
322 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
323         OCC_CATCH_SIGNALS;
324 #endif
325         objModified = aVisualObj->Update();
326       }
327       catch (...) {
328 #ifdef _DEBUG_
329         MESSAGE ( "Exception in SMESHGUI_VTKUtils::GetVisualObj()" );
330 #endif
331         RemoveVisualObjectWithActors( theEntry ); // remove this object
332         OnVisuException();
333         aVisualObj.reset();
334       }
335     }
336
337     if ( objModified ) {
338       // PAL16631. Mesurements showed that to show aVisualObj in SHADING(default) mode,
339       // ~10 times more memory is used than it occupies.
340       // Warn the user if there is less free memory than 30 sizes of a grid
341       // TODO: estimate memory usage in other modes and take current mode into account
342       int freeMB = SMDS_Mesh::CheckMemory(true);
343       int usedMB = aVisualObj->GetUnstructuredGrid()->GetActualMemorySize() / 1024;
344       if ( freeMB > 0 && usedMB * 30 > freeMB ) {
345 #ifdef _DEBUG_
346         MESSAGE ( "SMESHGUI_VTKUtils::GetVisualObj(), freeMB=" << freeMB
347                << ", usedMB=" << usedMB );
348 #endif
349         bool continu = false;
350         if ( usedMB * 10 > freeMB )
351           // even dont try to show
352           SUIT_MessageBox::warning(SMESHGUI::desktop(), QObject::tr("SMESH_WRN_WARNING"),
353                                    QObject::tr("SMESH_NO_MESH_VISUALIZATION"));
354         else
355           // there is a chance to succeed
356           continu = SUIT_MessageBox::warning
357             (SMESHGUI::desktop(),
358              QObject::tr("SMESH_WRN_WARNING"),
359              QObject::tr("SMESH_CONTINUE_MESH_VISUALIZATION"),
360              SUIT_MessageBox::Yes | SUIT_MessageBox::No, 
361              SUIT_MessageBox::Yes ) == SUIT_MessageBox::Yes;
362         if ( !continu ) {
363           // remove the corresponding actors from all views
364           RemoveVisualObjectWithActors( theEntry );
365           aVisualObj.reset();
366         }
367       }
368     }
369
370     return aVisualObj;
371   }
372
373
374   /*! Return active view window, if it instantiates SVTK_ViewWindow class,
375    *  overwise find or create corresponding view window, make it active and return it.
376    *  \note Active VVTK_ViewWindow can be returned, because it inherits SVTK_ViewWindow.
377    */
378   SVTK_ViewWindow* GetViewWindow (const SalomeApp_Module* theModule,
379                                   bool createIfNotFound)
380   {
381     SalomeApp_Application* anApp;
382     if (theModule)
383       anApp = theModule->getApp();
384     else
385       anApp = dynamic_cast<SalomeApp_Application*>
386         (SUIT_Session::session()->activeApplication());
387
388     if (anApp) {
389       if (SVTK_ViewWindow* aView = dynamic_cast<SVTK_ViewWindow*>(anApp->desktop()->activeWindow()))
390         return aView;
391
392       SUIT_ViewManager* aViewManager =
393         anApp->getViewManager(SVTK_Viewer::Type(), createIfNotFound);
394       if (aViewManager) {
395         if (SUIT_ViewWindow* aViewWindow = aViewManager->getActiveView()) {
396           if (SVTK_ViewWindow* aView = dynamic_cast<SVTK_ViewWindow*>(aViewWindow)) {
397             aViewWindow->raise();
398             aViewWindow->setFocus();
399             return aView;
400           }
401         }
402       }
403     }
404     return NULL;
405   }
406
407   SVTK_ViewWindow* FindVtkViewWindow (SUIT_ViewManager* theMgr,
408                                       SUIT_ViewWindow * theWindow)
409   {
410     if( !theMgr )
411       return NULL;
412
413     QVector<SUIT_ViewWindow*> views = theMgr->getViews();
414     if( views.contains( theWindow ) )
415       return GetVtkViewWindow( theWindow );
416     else
417       return NULL;
418   }
419
420   SVTK_ViewWindow* GetVtkViewWindow(SUIT_ViewWindow* theWindow){
421     return dynamic_cast<SVTK_ViewWindow*>(theWindow);
422   }
423
424 /*  SUIT_ViewWindow* GetActiveWindow()
425   {
426     SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
427     if( !app )
428       return NULL;
429     SUIT_ViewManager* mgr = app->activeViewManager();
430     if( mgr )
431       return mgr->getActiveView();
432     else
433       return NULL;
434   }*/
435
436   SVTK_ViewWindow* GetCurrentVtkView(){
437     return GetVtkViewWindow( GetActiveWindow() );
438   }
439
440
441   void RepaintCurrentView()
442   {
443     if (SVTK_ViewWindow* wnd = GetCurrentVtkView())
444     {
445       try {
446 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
447         OCC_CATCH_SIGNALS;
448 #endif
449         wnd->getRenderer()->Render();
450         wnd->Repaint(false);
451       }
452       catch (...) {
453 #ifdef _DEBUG_
454         MESSAGE ( "Exception in SMESHGUI_VTKUtils::RepaintCurrentView()" );
455 #endif
456         OnVisuException();
457       }
458     }
459   }
460
461   void RepaintViewWindow(SVTK_ViewWindow* theWindow)
462   {
463     try {
464 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
465       OCC_CATCH_SIGNALS;
466 #endif
467       theWindow->getRenderer()->Render();
468       theWindow->Repaint();
469     }
470     catch (...) {
471 #ifdef _DEBUG_
472       MESSAGE ( "Exception in SMESHGUI_VTKUtils::RepaintViewWindow(SVTK_ViewWindow*)" );
473 #endif
474       OnVisuException();
475     }
476   }
477
478   void RenderViewWindow(SVTK_ViewWindow* theWindow)
479   {
480     try {
481 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
482       OCC_CATCH_SIGNALS;
483 #endif
484       theWindow->getRenderer()->Render();
485       theWindow->Repaint();
486     }
487     catch (...) {
488 #ifdef _DEBUG_
489       MESSAGE ( "Exception in SMESHGUI_VTKUtils::RenderViewWindow(SVTK_ViewWindow*)" );
490 #endif
491       OnVisuException();
492     }
493   }
494
495   void FitAll(){
496     if(SVTK_ViewWindow* wnd = GetCurrentVtkView() ){
497       try {
498 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
499         OCC_CATCH_SIGNALS;
500 #endif
501         wnd->onFitAll();
502         wnd->Repaint();
503       }
504       catch (...) {
505 #ifdef _DEBUG_
506         MESSAGE ( "Exception in SMESHGUI_VTKUtils::FitAll()" );
507 #endif
508         OnVisuException();
509       }
510     }
511   }
512
513
514   SMESH_Actor* FindActorByEntry(SUIT_ViewWindow *theWindow,
515                                 const char* theEntry)
516   {
517     if(SVTK_ViewWindow* aViewWindow = GetVtkViewWindow(theWindow)){
518       vtkRenderer *aRenderer = aViewWindow->getRenderer();
519       vtkActorCollection *aCollection = aRenderer->GetActors();
520       aCollection->InitTraversal();
521       while(vtkActor *anAct = aCollection->GetNextActor()){
522         if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)){
523           if(anActor->hasIO()){
524             Handle(SALOME_InteractiveObject) anIO = anActor->getIO();
525             if(anIO->hasEntry() && strcmp(anIO->getEntry(),theEntry) == 0){
526               return anActor;
527             }
528           }
529         }
530       }
531     }
532     return NULL;
533   }
534
535
536   SMESH_Actor* FindActorByEntry(const char* theEntry){
537     return FindActorByEntry(GetActiveWindow(),theEntry);
538   }
539
540
541   SMESH_Actor* FindActorByObject(CORBA::Object_ptr theObject){
542     SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
543     if( !app )
544       return NULL;
545
546     if(!CORBA::is_nil(theObject)){
547       _PTR(Study) aStudy = GetActiveStudyDocument();
548       CORBA::String_var anIOR = app->orb()->object_to_string( theObject );
549       _PTR(SObject) aSObject = aStudy->FindObjectIOR(anIOR.in());
550       if(aSObject){
551         CORBA::String_var anEntry = aSObject->GetID().c_str();
552         return FindActorByEntry(anEntry.in());
553       }
554     }
555     return NULL;
556   }
557
558
559   SMESH_Actor* CreateActor(_PTR(Study) theStudy,
560                            const char* theEntry,
561                            int theIsClear)
562   {
563     SMESH_Actor *anActor = NULL;
564     CORBA::Long anId = theStudy->StudyId();
565     if(TVisualObjPtr aVisualObj = GetVisualObj(anId,theEntry)){
566       _PTR(SObject) aSObj = theStudy->FindObjectID(theEntry);
567       if(aSObj){
568         _PTR(GenericAttribute) anAttr;
569         if(aSObj->FindAttribute(anAttr,"AttributeName")){
570           _PTR(AttributeName) aName = anAttr;
571           std::string aNameVal = aName->Value();
572           anActor = SMESH_Actor::New(aVisualObj,theEntry,aNameVal.c_str(),theIsClear);
573         }
574
575         SMESH::SMESH_GroupBase_var aGroup = SMESH::SMESH_GroupBase::_narrow( SMESH::SObjectToObject( aSObj ));
576         if(!CORBA::is_nil(aGroup))
577         {
578           SALOMEDS::Color aColor = aGroup->GetColor();
579           if( !( aColor.R > 0 || aColor.G > 0 || aColor.B > 0 ) )
580           {
581             int r = 0, g = 0, b = 0;
582             SMESH::GetColor( "SMESH", "fill_color", r, g, b, QColor( 0, 170, 255 ) );
583             aColor.R = (float)r / 255.0;
584             aColor.G = (float)g / 255.0;
585             aColor.B = (float)b / 255.0;
586             aGroup->SetColor( aColor );
587           }
588           if( aGroup->GetType() == SMESH::NODE )
589             anActor->SetNodeColor( aColor.R, aColor.G, aColor.B );
590           else if( aGroup->GetType() == SMESH::EDGE )
591             anActor->SetEdgeColor( aColor.R, aColor.G, aColor.B );
592           else
593             anActor->SetSufaceColor( aColor.R, aColor.G, aColor.B );
594         }
595       }
596     }
597     return anActor;
598   }
599
600
601   void DisplayActor( SUIT_ViewWindow *theWnd, SMESH_Actor* theActor){
602     if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(theWnd)){
603       try {
604 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
605         OCC_CATCH_SIGNALS;
606 #endif
607         vtkWnd->AddActor(theActor);
608         vtkWnd->Repaint();
609       }
610       catch (...) {
611 #ifdef _DEBUG_
612         MESSAGE ( "Exception in SMESHGUI_VTKUtils::DisplayActor()" );
613 #endif
614         OnVisuException();
615       }
616     }
617   }
618
619
620   void RemoveActor( SUIT_ViewWindow *theWnd, SMESH_Actor* theActor){
621     if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(theWnd)){
622       vtkWnd->RemoveActor(theActor);
623       if(theActor->hasIO()){
624         Handle(SALOME_InteractiveObject) anIO = theActor->getIO();
625         if(anIO->hasEntry()){
626           std::string anEntry = anIO->getEntry();
627           SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( vtkWnd->getViewManager()->study() );
628           int aStudyId = aStudy->id();
629           TVisualObjCont::key_type aKey(aStudyId,anEntry);
630           VISUAL_OBJ_CONT.erase(aKey);
631         }
632       }
633       theActor->Delete();
634       vtkWnd->Repaint();
635     }
636   }
637
638   //================================================================================
639   /*!
640    * \brief Return true if there are no SMESH actors in a view
641    */
642   //================================================================================
643
644   bool noSmeshActors(SUIT_ViewWindow *theWnd)
645   {
646     if(SVTK_ViewWindow* aViewWindow = GetVtkViewWindow(theWnd)) {
647       vtkRenderer *aRenderer = aViewWindow->getRenderer();
648       vtkActorCollection *aCollection = aRenderer->GetActors();
649       aCollection->InitTraversal();
650       while(vtkActor *anAct = aCollection->GetNextActor())
651         if(dynamic_cast<SMESH_Actor*>(anAct))
652           return false;
653     }
654     return true;
655   }
656
657   bool UpdateView(SUIT_ViewWindow *theWnd, EDisplaing theAction, const char* theEntry)
658   {
659     bool OK = false;
660     SVTK_ViewWindow* aViewWnd = GetVtkViewWindow(theWnd);
661     if (!aViewWnd)
662       return OK;
663
664     {
665       OK = true;
666       vtkRenderer *aRenderer = aViewWnd->getRenderer();
667       vtkActorCollection *aCollection = aRenderer->GetActors();
668       aCollection->InitTraversal();
669
670       switch (theAction) {
671       case eDisplayAll: {
672         while (vtkActor *anAct = aCollection->GetNextActor()) {
673           if (SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)) {
674             anActor->SetVisibility(true);
675           }
676         }
677         break;
678       }
679       case eDisplayOnly:
680       case eEraseAll: {
681         while (vtkActor *anAct = aCollection->GetNextActor()) {
682           if (SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)) {
683             anActor->SetVisibility(false);
684           }
685         }
686       }
687       default: {
688         if (SMESH_Actor *anActor = FindActorByEntry(theWnd,theEntry)) {
689           switch (theAction) {
690             case eDisplay:
691             case eDisplayOnly:
692               anActor->SetVisibility(true);
693               if (theAction == eDisplayOnly) aRenderer->ResetCameraClippingRange();
694               break;
695             case eErase:
696               anActor->SetVisibility(false);
697               break;
698           }
699         } else {
700           switch (theAction) {
701           case eDisplay:
702           case eDisplayOnly:
703             {
704               SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(theWnd->getViewManager()->study());
705               _PTR(Study) aDocument = aStudy->studyDS();
706               // Pass non-visual objects (hypotheses, etc.), return true in this case
707               CORBA::Long anId = aDocument->StudyId();
708               if (TVisualObjPtr aVisualObj = GetVisualObj(anId,theEntry))
709               {
710                 if ((anActor = CreateActor(aDocument,theEntry,true))) {
711                   bool needFitAll = noSmeshActors(theWnd); // fit for the first object only
712                   DisplayActor(theWnd,anActor);
713                   // FitAll(); - PAL16770(Display of a group performs an automatic fit all)
714                   if (needFitAll) FitAll();
715                 } else {
716                   OK = false;
717                 }
718               }
719               break;
720             }
721           }
722         }
723       }
724       }
725     }
726     return OK;
727   }
728
729
730   bool UpdateView(EDisplaing theAction, const char* theEntry){
731     SalomeApp_Study* aStudy = dynamic_cast< SalomeApp_Study* >( GetActiveStudy() );
732     SalomeApp_Application* app = dynamic_cast< SalomeApp_Application* >( aStudy->application() );
733     SUIT_ViewWindow *aWnd = app->activeViewManager()->getActiveView();
734     return UpdateView(aWnd,theAction,theEntry);
735   }
736
737   void UpdateView(){
738     if(SVTK_ViewWindow* aWnd = SMESH::GetCurrentVtkView()){
739       LightApp_SelectionMgr* mgr = SMESHGUI::selectionMgr();
740       SALOME_ListIO selected; mgr->selectedObjects( selected );
741
742       if( selected.Extent() == 0){
743         vtkRenderer* aRenderer = aWnd->getRenderer();
744         vtkActorCollection *aCollection = aRenderer->GetActors();
745         aCollection->InitTraversal();
746         while(vtkActor *anAct = aCollection->GetNextActor()){
747           if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)){
748             if(anActor->hasIO())
749               if (!Update(anActor->getIO(),anActor->GetVisibility()))
750                 break; // avoid multiple warinings if visu failed
751           }
752         }
753       }else{
754         SALOME_ListIteratorOfListIO anIter( selected );
755         for( ; anIter.More(); anIter.Next()){
756           Handle(SALOME_InteractiveObject) anIO = anIter.Value();
757           if ( !Update(anIO,true) )
758             break; // avoid multiple warinings if visu failed
759         }
760       }
761       RepaintCurrentView();
762     }
763   }
764
765
766   bool Update(const Handle(SALOME_InteractiveObject)& theIO, bool theDisplay)
767   {
768     _PTR(Study) aStudy = GetActiveStudyDocument();
769     CORBA::Long anId = aStudy->StudyId();
770     if ( TVisualObjPtr aVisualObj = SMESH::GetVisualObj(anId,theIO->getEntry())) {
771       if ( theDisplay )
772         UpdateView(SMESH::eDisplay,theIO->getEntry());
773       return true;
774     }
775     return false;
776   }
777
778
779   void UpdateSelectionProp( SMESHGUI* theModule ) {
780     if( !theModule )
781       return;
782
783     SalomeApp_Application* app = dynamic_cast< SalomeApp_Application* >( theModule->application() );
784     if( !app )
785     {
786       MESSAGE( "UpdateSelectionProp: Application is null" );
787       return;
788     }
789
790     SUIT_ViewManager* vm = app->activeViewManager();
791     if( !vm )
792     {
793       MESSAGE( "UpdateSelectionProp: View manager is null" );
794       return;
795     }
796
797     QVector<SUIT_ViewWindow*> views = vm->getViews();
798
799     SUIT_ResourceMgr* mgr = SMESH::GetResourceMgr( theModule );
800     if( !mgr )
801     {
802       MESSAGE( "UpdateSelectionProp: Resource manager is null" );
803       return;
804     }
805
806     QColor aHiColor = mgr->colorValue( "SMESH", "selection_object_color", Qt::white ),
807            aSelColor = mgr->colorValue( "SMESH", "selection_element_color", Qt::yellow ),
808            aPreColor = mgr->colorValue( "SMESH", "highlight_color", Qt::cyan );
809
810     int SW = mgr->integerValue( "SMESH", "selection_width", 5 ),
811         PW = mgr->integerValue( "SMESH", "highlight_width", 5 );
812
813     double SP1 = mgr->doubleValue( "SMESH", "selection_precision_node", 0.025 ),
814            SP2 = mgr->doubleValue( "SMESH", "selection_precision_element", 0.001 ),
815            SP3 = mgr->doubleValue( "SMESH", "selection_precision_object", 0.025 );
816
817     for ( int i=0, n=views.count(); i<n; i++ ){
818       // update VTK viewer properties
819       if(SVTK_ViewWindow* aVtkView = GetVtkViewWindow( views[i] )){
820         // mesh element selection
821         aVtkView->SetSelectionProp(aSelColor.red()/255.,
822                                    aSelColor.green()/255.,
823                                    aSelColor.blue()/255.,
824                                    SW );
825         // tolerances
826         aVtkView->SetSelectionTolerance(SP1, SP2, SP3);
827
828         // pre-selection
829         aVtkView->SetPreselectionProp(aPreColor.red()/255.,
830                                       aPreColor.green()/255.,
831                                       aPreColor.blue()/255.,
832                                       PW);
833         // update actors
834         vtkRenderer* aRenderer = aVtkView->getRenderer();
835         vtkActorCollection *aCollection = aRenderer->GetActors();
836         aCollection->InitTraversal();
837         while(vtkActor *anAct = aCollection->GetNextActor()){
838           if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)){
839             anActor->SetHighlightColor(aHiColor.red()/255.,
840                                        aHiColor.green()/255.,
841                                        aHiColor.blue()/255.);
842             anActor->SetPreHighlightColor(aPreColor.red()/255.,
843                                           aPreColor.green()/255.,
844                                           aPreColor.blue()/255.);
845           }
846         }
847       }
848     }
849   }
850
851
852   //----------------------------------------------------------------------------
853   SVTK_Selector*
854   GetSelector(SUIT_ViewWindow *theWindow)
855   {
856     if(SVTK_ViewWindow* aWnd = GetVtkViewWindow(theWindow))
857       return aWnd->GetSelector();
858
859     return NULL;
860   }
861
862   void SetFilter(const Handle(VTKViewer_Filter)& theFilter,
863                  SVTK_Selector* theSelector)
864   {
865     if (theSelector)
866       theSelector->SetFilter(theFilter);
867   }
868
869   Handle(VTKViewer_Filter) GetFilter(int theId, SVTK_Selector* theSelector)
870   {
871     return theSelector->GetFilter(theId);
872   }
873
874   bool IsFilterPresent(int theId, SVTK_Selector* theSelector)
875   {
876     return theSelector->IsFilterPresent(theId);
877   }
878
879   void RemoveFilter(int theId, SVTK_Selector* theSelector)
880   {
881     theSelector->RemoveFilter(theId);
882   }
883
884   void RemoveFilters(SVTK_Selector* theSelector)
885   {
886     for ( int id = SMESH::NodeFilter; theSelector && id < SMESH::LastFilter; id++ )
887       theSelector->RemoveFilter( id );
888   }
889
890   bool IsValid(SALOME_Actor* theActor, int theCellId,
891                SVTK_Selector* theSelector)
892   {
893     return theSelector->IsValid(theActor,theCellId);
894   }
895
896
897   //----------------------------------------------------------------------------
898   void SetPointRepresentation(bool theIsVisible){
899     if(SVTK_ViewWindow* aViewWindow = GetCurrentVtkView()){
900       vtkRenderer *aRenderer = aViewWindow->getRenderer();
901       vtkActorCollection *aCollection = aRenderer->GetActors();
902       aCollection->InitTraversal();
903       while(vtkActor *anAct = aCollection->GetNextActor()){
904         if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)){
905           if(anActor->GetVisibility()){
906             anActor->SetPointRepresentation(theIsVisible);
907           }
908         }
909       }
910       RepaintCurrentView();
911     }
912   }
913
914
915   void SetPickable(SMESH_Actor* theActor){
916     if(SVTK_ViewWindow* aWnd = GetCurrentVtkView()){
917       int anIsAllPickable = (theActor == NULL);
918       vtkRenderer *aRenderer = aWnd->getRenderer();
919       vtkActorCollection *aCollection = aRenderer->GetActors();
920       aCollection->InitTraversal();
921       while(vtkActor *anAct = aCollection->GetNextActor()){
922         if(SALOME_Actor *anActor = dynamic_cast<SALOME_Actor*>(anAct)){
923           if(anActor->GetVisibility()){
924             anActor->SetPickable(anIsAllPickable);
925           }
926         }
927       }
928       if(theActor)
929         theActor->SetPickable(!anIsAllPickable);
930       RepaintCurrentView();
931     }
932   }
933
934
935   //----------------------------------------------------------------------------
936   int GetNameOfSelectedNodes(SVTK_Selector* theSelector,
937                              const Handle(SALOME_InteractiveObject)& theIO,
938                              QString& theName)
939   {
940     theName = "";
941     TColStd_IndexedMapOfInteger aMapIndex;
942     theSelector->GetIndex(theIO,aMapIndex);
943
944     for(int i = 1; i <= aMapIndex.Extent(); i++)
945       theName += QString(" %1").arg(aMapIndex(i));
946
947     return aMapIndex.Extent();
948   }
949
950   int GetNameOfSelectedElements(SVTK_Selector* theSelector,
951                                 const Handle(SALOME_InteractiveObject)& theIO,
952                                 QString& theName)
953   {
954     theName = "";
955     TColStd_IndexedMapOfInteger aMapIndex;
956     theSelector->GetIndex(theIO,aMapIndex);
957
958     typedef std::set<int> TIdContainer;
959     TIdContainer anIdContainer;
960     for( int i = 1; i <= aMapIndex.Extent(); i++)
961       anIdContainer.insert(aMapIndex(i));
962
963     TIdContainer::const_iterator anIter = anIdContainer.begin();
964     for( ; anIter != anIdContainer.end(); anIter++)
965       theName += QString(" %1").arg(*anIter);
966
967     return aMapIndex.Extent();
968   }
969
970
971   int GetEdgeNodes(SVTK_Selector* theSelector,
972                    const TVisualObjPtr& theVisualObject,
973                    int& theId1,
974                    int& theId2)
975   {
976     const SALOME_ListIO& selected = theSelector->StoredIObjects();
977
978     if ( selected.Extent() != 1 )
979       return -1;
980
981     Handle(SALOME_InteractiveObject) anIO = selected.First();
982     if ( anIO.IsNull() || !anIO->hasEntry() )
983       return -1;
984
985     TColStd_IndexedMapOfInteger aMapIndex;
986     theSelector->GetIndex( anIO, aMapIndex );
987     if ( aMapIndex.Extent() != 2 )
988       return -1;
989
990     int anObjId = -1, anEdgeNum = -1;
991     for ( int i = 1; i <= aMapIndex.Extent(); i++ ) {
992       int aVal = aMapIndex( i );
993       if ( aVal > 0 )
994         anObjId = aVal;
995       else
996         anEdgeNum = abs( aVal ) - 1;
997     }
998
999     if ( anObjId == -1 || anEdgeNum == -1 )
1000       return -1;
1001
1002     return theVisualObject->GetEdgeNodes( anObjId, anEdgeNum, theId1, theId2 ) ? 1 : -1;
1003   }
1004
1005   //----------------------------------------------------------------------------
1006   int GetNameOfSelectedNodes(LightApp_SelectionMgr *theMgr,
1007                              const Handle(SALOME_InteractiveObject)& theIO,
1008                              QString& theName)
1009   {
1010     theName = "";
1011     if(theIO->hasEntry()){
1012       if(FindActorByEntry(theIO->getEntry())){
1013         TColStd_IndexedMapOfInteger aMapIndex;
1014         theMgr->GetIndexes(theIO,aMapIndex);
1015         for(int i = 1; i <= aMapIndex.Extent(); i++){
1016           theName += QString(" %1").arg(aMapIndex(i));
1017         }
1018         return aMapIndex.Extent();
1019       }
1020     }
1021     return -1;
1022   }
1023
1024   int GetNameOfSelectedNodes(LightApp_SelectionMgr *theMgr, QString& theName){
1025     theName = "";
1026     SALOME_ListIO selected; theMgr->selectedObjects( selected );
1027     if(selected.Extent() == 1){
1028       Handle(SALOME_InteractiveObject) anIO = selected.First();
1029       return GetNameOfSelectedNodes(theMgr,anIO,theName);
1030     }
1031     return -1;
1032   }
1033
1034
1035   int GetNameOfSelectedElements(LightApp_SelectionMgr *theMgr,
1036                                 const Handle(SALOME_InteractiveObject)& theIO,
1037                                 QString& theName)
1038   {
1039     theName = "";
1040     if(theIO->hasEntry()){
1041       if(FindActorByEntry(theIO->getEntry())){
1042         TColStd_IndexedMapOfInteger aMapIndex;
1043         theMgr->GetIndexes(theIO,aMapIndex);
1044         typedef std::set<int> TIdContainer;
1045         TIdContainer anIdContainer;
1046         for( int i = 1; i <= aMapIndex.Extent(); i++)
1047           anIdContainer.insert(aMapIndex(i));
1048         TIdContainer::const_iterator anIter = anIdContainer.begin();
1049         for( ; anIter != anIdContainer.end(); anIter++){
1050           theName += QString(" %1").arg(*anIter);
1051         }
1052         return aMapIndex.Extent();
1053       }
1054     }
1055     return -1;
1056   }
1057
1058
1059   int GetNameOfSelectedElements(LightApp_SelectionMgr *theMgr, QString& theName)
1060   {
1061     theName = "";
1062     SALOME_ListIO selected; theMgr->selectedObjects( selected );
1063
1064     if( selected.Extent() == 1){
1065       Handle(SALOME_InteractiveObject) anIO = selected.First();
1066       return GetNameOfSelectedElements(theMgr,anIO,theName);
1067     }
1068     return -1;
1069   }
1070
1071   int GetSelected(LightApp_SelectionMgr*       theMgr,
1072                   TColStd_IndexedMapOfInteger& theMap,
1073                   const bool                   theIsElement)
1074   {
1075     theMap.Clear();
1076     SALOME_ListIO selected; theMgr->selectedObjects( selected );
1077
1078     if ( selected.Extent() == 1 )
1079     {
1080       Handle(SALOME_InteractiveObject) anIO = selected.First();
1081       if ( anIO->hasEntry() ) {
1082         theMgr->GetIndexes( anIO, theMap );
1083       }
1084     }
1085     return theMap.Extent();
1086   }
1087
1088
1089   int GetEdgeNodes( LightApp_SelectionMgr* theMgr, int& theId1, int& theId2 )
1090   {
1091     SALOME_ListIO selected; theMgr->selectedObjects( selected );
1092
1093     if ( selected.Extent() != 1 )
1094       return -1;
1095
1096     Handle(SALOME_InteractiveObject) anIO = selected.First();
1097     if ( anIO.IsNull() || !anIO->hasEntry() )
1098       return -1;
1099
1100     SMESH_Actor *anActor = SMESH::FindActorByEntry( anIO->getEntry() );
1101     if ( anActor == 0 )
1102       return -1;
1103
1104     TColStd_IndexedMapOfInteger aMapIndex;
1105     theMgr->GetIndexes( anIO, aMapIndex );
1106     if ( aMapIndex.Extent() != 2 )
1107       return -1;
1108
1109     int anObjId = -1, anEdgeNum = -1;
1110     for ( int i = 1; i <= aMapIndex.Extent(); i++ ) {
1111       int aVal = aMapIndex( i );
1112       if ( aVal > 0 )
1113         anObjId = aVal;
1114       else
1115         anEdgeNum = abs( aVal );
1116     }
1117
1118     if ( anObjId == -1 || anEdgeNum == -1 )
1119       return -1;
1120
1121     return anActor->GetObject()->GetEdgeNodes( anObjId, anEdgeNum, theId1, theId2 ) ? 1 : -1;
1122   }
1123
1124   void SetControlsPrecision( const long theVal )
1125   {
1126     if( SVTK_ViewWindow* aWnd = SMESH::GetCurrentVtkView() )
1127     {
1128       vtkRenderer *aRenderer = aWnd->getRenderer();
1129       vtkActorCollection *aCollection = aRenderer->GetActors();
1130       aCollection->InitTraversal();
1131
1132       while ( vtkActor *anAct = aCollection->GetNextActor())
1133       {
1134         if ( SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>( anAct ) )
1135         {
1136           anActor->SetControlsPrecision( theVal );
1137           anActor->SetControlMode( anActor->GetControlMode() );
1138         }
1139       }
1140
1141     }
1142   }
1143 } // end of namespace SMESH