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