Salome HOME
Remove obsolete staff; redesign Handle-based and CDL-generated classes
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_VTKUtils.cxx
1 // Copyright (C) 2007-2014  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 // SMESH SMESHGUI : GUI for SMESH component
24 // File   : SMESHGUI_VTKUtils.cxx
25 // Author : Open CASCADE S.A.S.
26 // SMESH includes
27 //
28 #include "SMESHGUI_VTKUtils.h"
29
30 #include "SMESHGUI.h"
31 #include "SMESHGUI_Utils.h"
32 #include "SMESHGUI_Filter.h"
33 #include "SMESH_ControlsDef.hxx"
34
35 #include <SMESH_Actor.h>
36 #include <SMESH_ActorUtils.h>
37 #include "SMESH_NodeLabelActor.h"
38 #include "SMESH_CellLabelActor.h"
39 #include <SMESH_ObjectDef.h>
40 #include <SMDS_Mesh.hxx>
41
42 // SALOME GUI includes
43 #include <SUIT_Desktop.h>
44 #include <SUIT_Session.h>
45 #include <SUIT_MessageBox.h>
46 #include <SUIT_ViewManager.h>
47 #include <SUIT_ResourceMgr.h>
48
49 #include <SALOME_ListIO.hxx>
50
51 #include <SVTK_Selector.h>
52 #include <SVTK_ViewModel.h>
53 #include <SVTK_ViewWindow.h>
54
55 #include <VTKViewer_Algorithm.h>
56
57 #include <LightApp_SelectionMgr.h>
58 #include <SalomeApp_Application.h>
59 #include <SalomeApp_Study.h>
60
61 // SALOME KERNEL includes
62 #include <utilities.h>
63
64 // IDL includes
65 #include <SALOMEconfig.h>
66 #include CORBA_CLIENT_HEADER(SMESH_Mesh)
67 #include CORBA_CLIENT_HEADER(SMESH_Group)
68
69 // VTK includes
70 #include <vtkMath.h>
71 #include <vtkRenderer.h>
72 #include <vtkActorCollection.h>
73 #include <vtkUnstructuredGrid.h>
74
75 // OCCT includes
76 #include <TColStd_IndexedMapOfInteger.hxx>
77 #include <Standard_ErrorHandler.hxx>
78
79 namespace SMESH
80 {
81   typedef std::map<TKeyOfVisualObj,TVisualObjPtr> TVisualObjCont;
82   static TVisualObjCont VISUAL_OBJ_CONT;
83
84   //=============================================================================
85   /*!
86    * \brief Allocate some memory at construction and release it at destruction.
87    * Is used to be able to continue working after mesh generation or visualization
88    * break due to lack of memory
89    */
90   //=============================================================================
91
92   struct MemoryReserve
93   {
94     char* myBuf;
95     MemoryReserve(): myBuf( new char[1024*1024*1] ){} // 1M
96     void Free() { if (myBuf) { delete [] myBuf; myBuf = 0; }}
97     ~MemoryReserve() { Free(); }
98   };
99   static MemoryReserve* theVISU_MemoryReserve = new MemoryReserve;
100
101   //================================================================================
102   /*!
103    * \brief Remove VisualObj and its actor from all views
104    */
105   //================================================================================
106
107   void RemoveVisualObjectWithActors( const char* theEntry, bool fromAllViews )
108   {
109     SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>(SUIT_Session::session()->activeApplication());
110     if(!app)
111       return;
112     SalomeApp_Study* aStudy  = dynamic_cast<SalomeApp_Study*>(app->activeStudy());
113     if(!aStudy)
114       return;
115     ViewManagerList aList;
116
117     if(fromAllViews) {
118       app->viewManagers(SVTK_Viewer::Type() , aList);
119     } else {
120       SUIT_ViewManager* aVM = app->getViewManager(SVTK_Viewer::Type(), true);
121       if(aVM)
122         aList.append(aVM);
123     }    
124     bool actorRemoved = false;
125     ViewManagerList::ConstIterator it = aList.begin();
126     SUIT_ViewManager* aViewManager = 0;
127     for( ; it!=aList.end();it++) {
128       aViewManager = *it;
129       QVector<SUIT_ViewWindow*> views = aViewManager->getViews();
130       for ( int iV = 0; iV < views.count(); ++iV ) {
131         if ( SMESH_Actor* actor = FindActorByEntry( views[iV], theEntry)) {
132           if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(views[iV])) {
133             vtkWnd->RemoveActor(actor);
134             actorRemoved = true;
135           }
136           actor->Delete();
137         }
138       }
139     }
140     
141     if (aViewManager ) {
142       int aStudyId = aViewManager->study()->id();
143       TVisualObjCont::key_type aKey(aStudyId,theEntry);
144       TVisualObjCont::iterator anIter = VISUAL_OBJ_CONT.find(aKey);
145       if(anIter != VISUAL_OBJ_CONT.end()) {
146         // for unknown reason, object destructor is not called, so clear object manually
147         anIter->second->GetUnstructuredGrid()->SetCells(0,0,0,0,0);
148         anIter->second->GetUnstructuredGrid()->SetPoints(0);
149       }
150       VISUAL_OBJ_CONT.erase(aKey);
151     }
152
153     if(actorRemoved)
154       aStudy->setVisibilityState(theEntry, Qtx::HiddenState);
155   }
156   //================================================================================
157   /*!
158    * \brief Remove all VisualObjs and their actors from all views
159    */
160   //================================================================================
161
162   void RemoveAllObjectsWithActors()
163   {
164     SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>
165       ( SUIT_Session::session()->activeApplication() );
166     if (!app) return;
167     ViewManagerList viewMgrs = app->viewManagers();
168     for ( int iM = 0; iM < viewMgrs.count(); ++iM ) {
169       SUIT_ViewManager* aViewManager = viewMgrs.at( iM );
170       if ( aViewManager && aViewManager->getType() == SVTK_Viewer::Type()) {
171         QVector<SUIT_ViewWindow*> views = aViewManager->getViews();
172         for ( int iV = 0; iV < views.count(); ++iV ) {
173           if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(views[iV])) {
174             vtkRenderer *aRenderer = vtkWnd->getRenderer();
175             VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
176             vtkActorCollection *actors = aCopy.GetActors();
177             for (int i = 0; i < actors->GetNumberOfItems(); ++i ) {
178               // size of actors changes inside the loop
179               if (SMESH_Actor *actor = dynamic_cast<SMESH_Actor*>(actors->GetItemAsObject(i)))
180               {
181                 vtkWnd->RemoveActor(actor);
182                 actor->Delete();
183               }
184             }
185           }
186         }
187       }
188     }
189     TVisualObjCont::iterator anIter = VISUAL_OBJ_CONT.begin();
190     for ( ; anIter != VISUAL_OBJ_CONT.end(); ++anIter ) {
191       // for unknown reason, object destructor is not called, so clear object manually
192       anIter->second->GetUnstructuredGrid()->SetCells(0,0,0,0,0);
193       anIter->second->GetUnstructuredGrid()->SetPoints(0);
194     }
195     VISUAL_OBJ_CONT.clear();
196   }
197
198   //================================================================================
199   /*!
200    * \brief Remove all VisualObjs of a study
201    */
202   //================================================================================
203
204   void RemoveVisuData(int studyID)
205   {
206     SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>
207       ( SUIT_Session::session()->activeApplication() );
208     if (!app) return;
209     ViewManagerList viewMgrs = app->viewManagers();
210     for ( int iM = 0; iM < viewMgrs.count(); ++iM ) {
211       SUIT_ViewManager* aViewManager = viewMgrs.at( iM );
212       if ( aViewManager && aViewManager->getType() == SVTK_Viewer::Type() &&
213            aViewManager->study()->id() == studyID ) {
214         QVector<SUIT_ViewWindow*> views = aViewManager->getViews();
215         for ( int iV = 0; iV < views.count(); ++iV ) {
216           if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(views[iV])) {
217             vtkRenderer *aRenderer = vtkWnd->getRenderer();
218             VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
219             vtkActorCollection *actors = aCopy.GetActors();
220             for (int i = 0; i < actors->GetNumberOfItems(); ++i ) {
221               // size of actors changes inside the loop
222               if(SMESH_Actor *actor = dynamic_cast<SMESH_Actor*>(actors->GetItemAsObject(i)))
223               {
224                 vtkWnd->RemoveActor(actor);
225                 actor->Delete();
226               }
227             }
228           }
229         }
230       }
231     }
232     TVisualObjCont::iterator anIter = VISUAL_OBJ_CONT.begin();
233     for ( ; anIter != VISUAL_OBJ_CONT.end(); ) {
234       int curId = anIter->first.first;
235       if ( curId == studyID ) {
236         // for unknown reason, object destructor is not called, so clear object manually
237         anIter->second->GetUnstructuredGrid()->SetCells(0,0,0,0,0);
238         anIter->second->GetUnstructuredGrid()->SetPoints(0);
239         VISUAL_OBJ_CONT.erase( anIter++ ); // anIter++ returns a copy of self before incrementing
240       }
241       else {
242         anIter++;
243       }
244     }
245   }
246
247   //================================================================================
248   /*!
249    * \brief Notify the user on problems during visualization
250    */
251   //================================================================================
252
253   void OnVisuException()
254   {
255     try {
256 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
257       OCC_CATCH_SIGNALS;
258 #endif
259       // PAL16774 (Crash after display of many groups). Salome sometimes crashes just
260       // after or at showing this message, so we do an additional check of available memory
261 //       char* buf = new char[100*1024];
262 //       delete [] buf;
263       SUIT_MessageBox::warning(SMESHGUI::desktop(), QObject::tr("SMESH_WRN_WARNING"),
264                                QObject::tr("SMESH_VISU_PROBLEM"));
265     } catch (...) {
266       // no more memory at all: last resort
267       MESSAGE_BEGIN ( "SMESHGUI_VTKUtils::OnVisuException(), exception even at showing a message!!!" <<
268                       std::endl << "Try to remove all visual data..." );
269       if (theVISU_MemoryReserve) {
270         delete theVISU_MemoryReserve;
271         theVISU_MemoryReserve = 0;
272       }
273       RemoveAllObjectsWithActors();
274       SUIT_MessageBox::warning(SMESHGUI::desktop(), QObject::tr("SMESH_WRN_WARNING"),
275                                QObject::tr("SMESH_VISU_PROBLEM_CLEAR"));
276       MESSAGE_END ( "...done" );
277     }
278   }
279   //================================================================================
280   /*!
281    * \brief Returns an updated visual object
282    */
283   //================================================================================
284
285   TVisualObjPtr GetVisualObj(int theStudyId, const char* theEntry, bool nulData){
286     TVisualObjPtr aVisualObj;
287     TVisualObjCont::key_type aKey(theStudyId,theEntry);
288     try{
289 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
290       OCC_CATCH_SIGNALS;
291 #endif
292       TVisualObjCont::iterator anIter = VISUAL_OBJ_CONT.find(aKey);
293       if(anIter != VISUAL_OBJ_CONT.end()){
294         aVisualObj = anIter->second;
295       }else{
296         SalomeApp_Application* app =
297           dynamic_cast<SalomeApp_Application*>( SMESHGUI::activeStudy()->application() );
298         _PTR(Study) aStudy = SMESHGUI::activeStudy()->studyDS();
299         _PTR(SObject) aSObj = aStudy->FindObjectID(theEntry);
300         if(aSObj){
301           _PTR(GenericAttribute) anAttr;
302           if(aSObj->FindAttribute(anAttr,"AttributeIOR")){
303             _PTR(AttributeIOR) anIOR = anAttr;
304             CORBA::String_var aVal = anIOR->Value().c_str();
305             CORBA::Object_var anObj = app->orb()->string_to_object( aVal.in() );
306             if(!CORBA::is_nil(anObj)){
307               //Try narrow to SMESH_Mesh interface
308               SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_narrow(anObj);
309               if(!aMesh->_is_nil()){
310                 aVisualObj.reset(new SMESH_MeshObj(aMesh));
311                 TVisualObjCont::value_type aValue(aKey,aVisualObj);
312                 VISUAL_OBJ_CONT.insert(aValue);
313               }
314               //Try narrow to SMESH_Group interface
315               SMESH::SMESH_GroupBase_var aGroup = SMESH::SMESH_GroupBase::_narrow(anObj);
316               if(!aGroup->_is_nil()){
317                 _PTR(SObject) aFatherSObj = aSObj->GetFather();
318                 if(!aFatherSObj) return aVisualObj;
319                 aFatherSObj = aFatherSObj->GetFather();
320                 if(!aFatherSObj) return aVisualObj;
321                 CORBA::String_var anEntry = aFatherSObj->GetID().c_str();
322                 TVisualObjPtr aVisObj = GetVisualObj(theStudyId,anEntry.in());
323                 if(SMESH_MeshObj* aMeshObj = dynamic_cast<SMESH_MeshObj*>(aVisObj.get())){
324                   aVisualObj.reset(new SMESH_GroupObj(aGroup,aMeshObj));
325                   TVisualObjCont::value_type aValue(aKey,aVisualObj);
326                   VISUAL_OBJ_CONT.insert(aValue);
327                 }
328               }
329               //Try narrow to SMESH_subMesh interface
330               SMESH::SMESH_subMesh_var aSubMesh = SMESH::SMESH_subMesh::_narrow(anObj);
331               if(!aSubMesh->_is_nil()){
332                 _PTR(SObject) aFatherSObj = aSObj->GetFather();
333                 if(!aFatherSObj) return aVisualObj;
334                 aFatherSObj = aFatherSObj->GetFather();
335                 if(!aFatherSObj) return aVisualObj;
336                 CORBA::String_var anEntry = aFatherSObj->GetID().c_str();
337                 TVisualObjPtr aVisObj = GetVisualObj(theStudyId,anEntry.in());
338                 if(SMESH_MeshObj* aMeshObj = dynamic_cast<SMESH_MeshObj*>(aVisObj.get())){
339                   aVisualObj.reset(new SMESH_subMeshObj(aSubMesh,aMeshObj));
340                   TVisualObjCont::value_type aValue(aKey,aVisualObj);
341                   VISUAL_OBJ_CONT.insert(aValue);
342                 }
343               }
344             }
345           }
346         }
347       }
348     }catch(...){
349       INFOS("GetMeshObj - There is no SMESH_Mesh object for the SALOMEDS::Strudy and Entry!!!");
350       return TVisualObjPtr();
351     }
352     // Update object
353     bool objModified = false;
354     if ( aVisualObj ) {
355       try {
356 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
357         OCC_CATCH_SIGNALS;
358 #endif
359         //MESSAGE("GetVisualObj");
360         if (nulData)
361                 objModified = aVisualObj->NulData();
362         else
363           objModified = aVisualObj->Update();
364       }
365       catch (...) {
366 #ifdef _DEBUG_
367         MESSAGE ( "Exception in SMESHGUI_VTKUtils::GetVisualObj()" );
368 #endif
369         RemoveVisualObjectWithActors( theEntry ); // remove this object
370         OnVisuException();
371         aVisualObj.reset();
372       }
373     }
374
375     if ( objModified ) {
376       // PAL16631. Mesurements showed that to show aVisualObj in SHADING(default) mode,
377       // ~5 times more memory is used than it occupies.
378       // Warn the user if there is less free memory than 30 sizes of a grid
379       // TODO: estimate memory usage in other modes and take current mode into account
380       int freeMB = SMDS_Mesh::CheckMemory(true);
381       int usedMB = aVisualObj->GetUnstructuredGrid()->GetActualMemorySize() / 1024;
382       MESSAGE("SMESHGUI_VTKUtils::GetVisualObj(), freeMB=" << freeMB << ", usedMB=" <<usedMB);
383       if ( freeMB > 0 && usedMB * 5 > freeMB ) {
384        bool continu = false;
385        if ( usedMB * 3 > freeMB )
386          // even dont try to show
387          SUIT_MessageBox::warning(SMESHGUI::desktop(), QObject::tr("SMESH_WRN_WARNING"),
388                                   QObject::tr("SMESH_NO_MESH_VISUALIZATION"));
389        else
390          // there is a chance to succeed
391          continu = SUIT_MessageBox::warning
392            (SMESHGUI::desktop(),
393             QObject::tr("SMESH_WRN_WARNING"),
394             QObject::tr("SMESH_CONTINUE_MESH_VISUALIZATION"),
395             SUIT_MessageBox::Yes | SUIT_MessageBox::No,
396             SUIT_MessageBox::Yes ) == SUIT_MessageBox::Yes;
397        if ( !continu ) {
398          // remove the corresponding actors from all views
399          RemoveVisualObjectWithActors( theEntry );
400          aVisualObj.reset();
401        }
402       }
403     }
404
405     return aVisualObj;
406   }
407
408
409   /*! Return active view window, if it instantiates SVTK_ViewWindow class,
410    *  overwise find or create corresponding view window, make it active and return it.
411    *  \note Active VVTK_ViewWindow can be returned, because it inherits SVTK_ViewWindow.
412    */
413   SVTK_ViewWindow* GetViewWindow (const SalomeApp_Module* theModule,
414                                   bool createIfNotFound)
415   {
416     SalomeApp_Application* anApp;
417     if (theModule)
418       anApp = theModule->getApp();
419     else
420       anApp = dynamic_cast<SalomeApp_Application*>
421         (SUIT_Session::session()->activeApplication());
422
423     if (anApp) {
424       if (SVTK_ViewWindow* aView = dynamic_cast<SVTK_ViewWindow*>(anApp->desktop()->activeWindow()))
425         return aView;
426
427       SUIT_ViewManager* aViewManager =
428         anApp->getViewManager(SVTK_Viewer::Type(), createIfNotFound);
429       if (aViewManager) {
430         if (SUIT_ViewWindow* aViewWindow = aViewManager->getActiveView()) {
431           if (SVTK_ViewWindow* aView = dynamic_cast<SVTK_ViewWindow*>(aViewWindow)) {
432             aViewWindow->raise();
433             aViewWindow->setFocus();
434             return aView;
435           }
436         }
437       }
438     }
439     return NULL;
440   }
441
442   SVTK_ViewWindow* FindVtkViewWindow (SUIT_ViewManager* theMgr,
443                                       SUIT_ViewWindow * theWindow)
444   {
445     if( !theMgr )
446       return NULL;
447
448     QVector<SUIT_ViewWindow*> views = theMgr->getViews();
449     if( views.contains( theWindow ) )
450       return GetVtkViewWindow( theWindow );
451     else
452       return NULL;
453   }
454
455   SVTK_ViewWindow* GetVtkViewWindow(SUIT_ViewWindow* theWindow){
456     return dynamic_cast<SVTK_ViewWindow*>(theWindow);
457   }
458
459 /*  SUIT_ViewWindow* GetActiveWindow()
460   {
461     SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
462     if( !app )
463       return NULL;
464     SUIT_ViewManager* mgr = app->activeViewManager();
465     if( mgr )
466       return mgr->getActiveView();
467     else
468       return NULL;
469   }*/
470
471   SVTK_ViewWindow* GetCurrentVtkView(){
472     return GetVtkViewWindow( GetActiveWindow() );
473   }
474
475
476   void RepaintCurrentView()
477   {
478     if (SVTK_ViewWindow* wnd = GetCurrentVtkView())
479     {
480       try {
481 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
482         OCC_CATCH_SIGNALS;
483 #endif
484         wnd->getRenderer()->Render();
485         wnd->Repaint(false);
486       }
487       catch (...) {
488 #ifdef _DEBUG_
489         MESSAGE ( "Exception in SMESHGUI_VTKUtils::RepaintCurrentView()" );
490 #endif
491         OnVisuException();
492       }
493     }
494   }
495
496   void RepaintViewWindow(SVTK_ViewWindow* theWindow)
497   {
498     try {
499 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
500       OCC_CATCH_SIGNALS;
501 #endif
502       theWindow->getRenderer()->Render();
503       theWindow->Repaint();
504     }
505     catch (...) {
506 #ifdef _DEBUG_
507       MESSAGE ( "Exception in SMESHGUI_VTKUtils::RepaintViewWindow(SVTK_ViewWindow*)" );
508 #endif
509       OnVisuException();
510     }
511   }
512
513   void RenderViewWindow(SVTK_ViewWindow* theWindow)
514   {
515     try {
516 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
517       OCC_CATCH_SIGNALS;
518 #endif
519       theWindow->getRenderer()->Render();
520       theWindow->Repaint();
521     }
522     catch (...) {
523 #ifdef _DEBUG_
524       MESSAGE ( "Exception in SMESHGUI_VTKUtils::RenderViewWindow(SVTK_ViewWindow*)" );
525 #endif
526       OnVisuException();
527     }
528   }
529
530   void FitAll(){
531     if(SVTK_ViewWindow* wnd = GetCurrentVtkView() ){
532       try {
533 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
534         OCC_CATCH_SIGNALS;
535 #endif
536         wnd->onFitAll();
537         wnd->Repaint();
538       }
539       catch (...) {
540 #ifdef _DEBUG_
541         MESSAGE ( "Exception in SMESHGUI_VTKUtils::FitAll()" );
542 #endif
543         OnVisuException();
544       }
545     }
546   }
547
548
549   SMESH_Actor* FindActorByEntry(SUIT_ViewWindow *theWindow,
550                                 const char* theEntry)
551   {
552     if(SVTK_ViewWindow* aViewWindow = GetVtkViewWindow(theWindow)){
553       vtkRenderer *aRenderer = aViewWindow->getRenderer();
554       VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
555       vtkActorCollection *aCollection = aCopy.GetActors();
556       aCollection->InitTraversal();
557       while(vtkActor *anAct = aCollection->GetNextActor()){
558         if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)){
559           if(anActor->hasIO()){
560             Handle(SALOME_InteractiveObject) anIO = anActor->getIO();
561             if(anIO->hasEntry() && strcmp(anIO->getEntry(),theEntry) == 0){
562               return anActor;
563             }
564           }
565         }
566       }
567     }
568     return NULL;
569   }
570
571
572   SMESH_Actor* FindActorByEntry(const char* theEntry){
573     return FindActorByEntry(GetActiveWindow(),theEntry);
574   }
575
576
577   SMESH_Actor* FindActorByObject(CORBA::Object_ptr theObject){
578     SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
579     if( !app )
580       return NULL;
581
582     if(!CORBA::is_nil(theObject)){
583       _PTR(Study) aStudy = GetActiveStudyDocument();
584       CORBA::String_var anIOR = app->orb()->object_to_string( theObject );
585       _PTR(SObject) aSObject = aStudy->FindObjectIOR(anIOR.in());
586       if(aSObject){
587         CORBA::String_var anEntry = aSObject->GetID().c_str();
588         return FindActorByEntry(anEntry.in());
589       }
590     }
591     return NULL;
592   }
593
594
595   SMESH_Actor* CreateActor(_PTR(Study) theStudy,
596                            const char* theEntry,
597                            int theIsClear)
598   {
599     SMESH_Actor *anActor = NULL;
600     CORBA::Long anId = theStudy->StudyId();
601     if(TVisualObjPtr aVisualObj = GetVisualObj(anId,theEntry)){
602       _PTR(SObject) aSObj = theStudy->FindObjectID(theEntry);
603       if(aSObj){
604         _PTR(GenericAttribute) anAttr;
605         if(aSObj->FindAttribute(anAttr,"AttributeName")){
606           _PTR(AttributeName) aName = anAttr;
607           std::string aNameVal = aName->Value();
608           anActor = SMESH_Actor::New(aVisualObj,theEntry,aNameVal.c_str(),theIsClear);
609         }
610
611         SMESH::SMESH_GroupBase_var aGroup = SMESH::SMESH_GroupBase::_narrow( SMESH::SObjectToObject( aSObj ));
612         if(!CORBA::is_nil(aGroup) && anActor)
613         {
614           QColor c;
615           int deltaF, deltaV;
616           SMESH::GetColor( "SMESH", "fill_color", c, deltaF, "0,170,255|-100"  );
617           SMESH::GetColor( "SMESH", "volume_color", c, deltaV, "255,0,170|-100"  );
618           c = SMESH::GetColor( "SMESH", "default_grp_color", c );
619           SALOMEDS::Color aColor = aGroup->GetColor();
620           if( !( aColor.R > 0 || aColor.G > 0 || aColor.B > 0 ))
621           {
622             aColor.R = c.redF();
623             aColor.G = c.greenF();
624             aColor.B = c.blueF();
625             aGroup->SetColor( aColor );
626           }
627           if( aGroup->GetType() == SMESH::NODE )
628             anActor->SetNodeColor( aColor.R, aColor.G, aColor.B );
629           else if( aGroup->GetType() == SMESH::EDGE )
630             anActor->SetEdgeColor( aColor.R, aColor.G, aColor.B );
631           else if( aGroup->GetType() == SMESH::ELEM0D )
632             anActor->Set0DColor( aColor.R, aColor.G, aColor.B );
633           else if( aGroup->GetType() == SMESH::BALL )
634             anActor->SetBallColor( aColor.R, aColor.G, aColor.B );
635           else if( aGroup->GetType() == SMESH::VOLUME )
636             anActor->SetVolumeColor( aColor.R, aColor.G, aColor.B, deltaV );
637           else
638             anActor->SetSufaceColor( aColor.R, aColor.G, aColor.B, deltaF );
639         }
640       }
641     }
642     MESSAGE("CreateActor " << anActor);
643     if( anActor )
644       if( SMESHGUI* aSMESHGUI = SMESHGUI::GetSMESHGUI() )
645         aSMESHGUI->addActorAsObserver( anActor );
646     return anActor;
647   }
648
649
650   void DisplayActor( SUIT_ViewWindow *theWnd, SMESH_Actor* theActor){
651     if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(theWnd)){
652       try {
653 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
654         OCC_CATCH_SIGNALS;
655 #endif
656         MESSAGE("DisplayActor " << theActor);
657         vtkWnd->AddActor(theActor);
658         vtkWnd->Repaint();
659       }
660       catch (...) {
661 #ifdef _DEBUG_
662         MESSAGE ( "Exception in SMESHGUI_VTKUtils::DisplayActor()" );
663 #endif
664         OnVisuException();
665       }
666     }
667   }
668
669
670   void RemoveActor( SUIT_ViewWindow *theWnd, SMESH_Actor* theActor){
671     if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(theWnd)){
672         MESSAGE("RemoveActor " << theActor);
673       vtkWnd->RemoveActor(theActor);
674       if(theActor->hasIO()){
675         Handle(SALOME_InteractiveObject) anIO = theActor->getIO();
676         if(anIO->hasEntry()){
677           std::string anEntry = anIO->getEntry();
678           SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( vtkWnd->getViewManager()->study() );
679           int aStudyId = aStudy->id();
680           TVisualObjCont::key_type aKey(aStudyId,anEntry);
681           VISUAL_OBJ_CONT.erase(aKey);
682         }
683       }
684       theActor->Delete();
685       vtkWnd->Repaint();
686     }
687   }
688
689   //================================================================================
690   /*!
691    * \brief Return true if there are no SMESH actors in a view
692    */
693   //================================================================================
694
695   bool noSmeshActors(SUIT_ViewWindow *theWnd)
696   {
697     if(SVTK_ViewWindow* aViewWindow = GetVtkViewWindow(theWnd)) {
698       vtkRenderer *aRenderer = aViewWindow->getRenderer();
699       VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
700       vtkActorCollection *aCollection = aCopy.GetActors();
701       aCollection->InitTraversal();
702       while(vtkActor *anAct = aCollection->GetNextActor())
703         if(dynamic_cast<SMESH_Actor*>(anAct))
704           return false;
705     }
706     return true;
707   }
708
709   bool UpdateView(SUIT_ViewWindow *theWnd, EDisplaing theAction, const char* theEntry)
710   {
711         //MESSAGE("UpdateView");
712     bool OK = false;
713     SVTK_ViewWindow* aViewWnd = GetVtkViewWindow(theWnd);
714     if (!aViewWnd)
715       return OK;
716
717     SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(theWnd);
718     if (!vtkWnd)
719       return OK;
720
721     SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( vtkWnd->getViewManager()->study() );
722     
723     if (!aStudy)
724       return OK;
725
726     {
727       OK = true;
728       vtkRenderer *aRenderer = aViewWnd->getRenderer();
729       VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
730       vtkActorCollection *aCollection = aCopy.GetActors();
731       aCollection->InitTraversal();
732
733       switch (theAction) {
734       case eDisplayAll: {
735         while (vtkActor *anAct = aCollection->GetNextActor()) {
736           if (SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)) {
737                 MESSAGE("--- display " << anActor);
738             anActor->SetVisibility(true);
739
740             if(anActor->hasIO()){
741               Handle(SALOME_InteractiveObject) anIO = anActor->getIO();
742               if(anIO->hasEntry()){
743                 aStudy->setVisibilityState(anIO->getEntry(), Qtx::ShownState);
744               }
745             }
746           }
747         }
748         break;
749       }
750       case eDisplayOnly:
751       case eEraseAll: {
752         //MESSAGE("---case eDisplayOnly");
753         while (vtkActor *anAct = aCollection->GetNextActor()) {
754           if (SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)) {
755                 //MESSAGE("--- erase " << anActor);
756             anActor->SetVisibility(false);
757           }
758         }
759         aStudy->setVisibilityStateForAll(Qtx::HiddenState);
760       }
761       default: {
762         if (SMESH_Actor *anActor = FindActorByEntry(theWnd,theEntry)) {
763           switch (theAction) {
764             case eDisplay:
765             case eDisplayOnly:
766                 //MESSAGE("--- display " << anActor);
767               anActor->Update();
768               anActor->SetVisibility(true);
769               if (theAction == eDisplayOnly) aRenderer->ResetCameraClippingRange();
770               aStudy->setVisibilityState(theEntry, Qtx::ShownState);
771               break;
772             case eErase:
773                 //MESSAGE("--- erase " << anActor);
774               anActor->SetVisibility(false);
775               aStudy->setVisibilityState(theEntry, Qtx::HiddenState);
776               break;
777           }
778         } else {
779           switch (theAction) {
780           case eDisplay:
781           case eDisplayOnly:
782             {
783                 //MESSAGE("---");
784               SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(theWnd->getViewManager()->study());
785               _PTR(Study) aDocument = aStudy->studyDS();
786               // Pass non-visual objects (hypotheses, etc.), return true in this case
787               CORBA::Long anId = aDocument->StudyId();
788               TVisualObjPtr aVisualObj;
789               if ( (aVisualObj = GetVisualObj(anId,theEntry)) && aVisualObj->IsValid())
790               {
791                 if ((anActor = CreateActor(aDocument,theEntry,true))) {
792                   bool needFitAll = noSmeshActors(theWnd); // fit for the first object only
793                   DisplayActor(theWnd,anActor);
794                   aStudy->setVisibilityState(theEntry, Qtx::ShownState);
795                   // FitAll(); - PAL16770(Display of a group performs an automatic fit all)
796                   if (needFitAll) FitAll();
797                 } else {
798                   OK = false;
799                 }
800               }
801               break;
802             }
803           }
804         }
805       }
806       }
807     }
808     return OK;
809   }
810
811
812   bool UpdateView(EDisplaing theAction, const char* theEntry){
813         //MESSAGE("UpdateView");
814     SalomeApp_Study* aStudy = dynamic_cast< SalomeApp_Study* >( GetActiveStudy() );
815     SalomeApp_Application* app = dynamic_cast< SalomeApp_Application* >( aStudy->application() );
816     SUIT_ViewWindow *aWnd = app->activeViewManager()->getActiveView();
817     return UpdateView(aWnd,theAction,theEntry);
818   }
819
820   void UpdateView(){
821     if(SVTK_ViewWindow* aWnd = SMESH::GetCurrentVtkView()){
822       LightApp_SelectionMgr* mgr = SMESHGUI::selectionMgr();
823       SALOME_ListIO selected; mgr->selectedObjects( selected );
824
825       if( selected.Extent() == 0){
826         vtkRenderer* aRenderer = aWnd->getRenderer();
827         VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
828         vtkActorCollection *aCollection = aCopy.GetActors();
829         aCollection->InitTraversal();
830         while(vtkActor *anAct = aCollection->GetNextActor()){
831           if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)){
832             if(anActor->hasIO())
833               if (!Update(anActor->getIO(),anActor->GetVisibility()))
834                 break; // avoid multiple warinings if visu failed
835           }
836         }
837       }else{
838         SALOME_ListIteratorOfListIO anIter( selected );
839         for( ; anIter.More(); anIter.Next()){
840           Handle(SALOME_InteractiveObject) anIO = anIter.Value();
841           if ( !Update(anIO,true) )
842             break; // avoid multiple warinings if visu failed
843         }
844       }
845       RepaintCurrentView();
846     }
847   }
848
849
850   bool Update(const Handle(SALOME_InteractiveObject)& theIO, bool theDisplay)
851   {
852         MESSAGE("Update");
853     _PTR(Study) aStudy = GetActiveStudyDocument();
854     CORBA::Long anId = aStudy->StudyId();
855     if ( TVisualObjPtr aVisualObj = SMESH::GetVisualObj(anId,theIO->getEntry())) {
856       if ( theDisplay )
857         UpdateView(SMESH::eDisplay,theIO->getEntry());
858       return true;
859     }
860     return false;
861   }
862
863   bool UpdateNulData(const Handle(SALOME_InteractiveObject)& theIO, bool theDisplay)
864   {
865         MESSAGE("UpdateNulData");
866     _PTR(Study) aStudy = GetActiveStudyDocument();
867     CORBA::Long anId = aStudy->StudyId();
868     if ( TVisualObjPtr aVisualObj = SMESH::GetVisualObj(anId,theIO->getEntry(), true)) {
869       if ( theDisplay )
870         UpdateView(SMESH::eDisplay,theIO->getEntry());
871       return true;
872     }
873     return false;
874   }
875
876   void UpdateSelectionProp( SMESHGUI* theModule ) {
877     if( !theModule )
878       return;
879
880     SalomeApp_Application* app = dynamic_cast< SalomeApp_Application* >( theModule->application() );
881     if( !app )
882     {
883       MESSAGE( "UpdateSelectionProp: Application is null" );
884       return;
885     }
886
887     SUIT_ViewManager* vm = app->activeViewManager();
888     if( !vm )
889     {
890       MESSAGE( "UpdateSelectionProp: View manager is null" );
891       return;
892     }
893
894     QVector<SUIT_ViewWindow*> views = vm->getViews();
895
896     SUIT_ResourceMgr* mgr = SMESH::GetResourceMgr( theModule );
897     if( !mgr )
898     {
899       MESSAGE( "UpdateSelectionProp: Resource manager is null" );
900       return;
901     }
902
903     QColor aHiColor = mgr->colorValue( "SMESH", "selection_object_color", Qt::white ),
904            aSelColor = mgr->colorValue( "SMESH", "selection_element_color", Qt::yellow ),
905            aPreColor = mgr->colorValue( "SMESH", "highlight_color", Qt::cyan );
906
907     int aElem0DSize = mgr->integerValue("SMESH", "elem0d_size", 5);
908     int aBallSize   = mgr->integerValue("SMESH", "ball_elem_size", 5);
909     int aLineWidth  = mgr->integerValue("SMESH", "element_width", 1);
910     int maxSize = aElem0DSize;
911     if (aElem0DSize > maxSize) maxSize = aElem0DSize;
912     if (aLineWidth > maxSize) maxSize = aLineWidth;
913     if (aBallSize > maxSize) maxSize = aBallSize;
914
915     double SP1 = mgr->doubleValue( "SMESH", "selection_precision_node", 0.025 ),
916            SP2 = mgr->doubleValue( "SMESH", "selection_precision_element", 0.001 ),
917            SP3 = mgr->doubleValue( "SMESH", "selection_precision_object", 0.025 );
918
919     for ( int i=0, n=views.count(); i<n; i++ ){
920       // update VTK viewer properties
921       if(SVTK_ViewWindow* aVtkView = GetVtkViewWindow( views[i] )){
922         // mesh element selection
923         aVtkView->SetSelectionProp(aSelColor.red()/255.,
924                                    aSelColor.green()/255.,
925                                    aSelColor.blue()/255.);
926         // tolerances
927         aVtkView->SetSelectionTolerance(SP1, SP2, SP3);
928
929         // pre-selection
930         aVtkView->SetPreselectionProp(aPreColor.red()/255.,
931                                       aPreColor.green()/255.,
932                                       aPreColor.blue()/255.);
933         // update actors
934         vtkRenderer* aRenderer = aVtkView->getRenderer();
935         VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
936         vtkActorCollection *aCollection = aCopy.GetActors();
937         aCollection->InitTraversal();
938         while(vtkActor *anAct = aCollection->GetNextActor()){
939           if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)){
940             anActor->SetHighlightColor(aHiColor.red()/255.,
941                                        aHiColor.green()/255.,
942                                        aHiColor.blue()/255.);
943             anActor->SetPreHighlightColor(aPreColor.red()/255.,
944                                           aPreColor.green()/255.,
945                                           aPreColor.blue()/255.);
946           }
947         }
948       }
949     }
950   }
951
952
953   void UpdateFontProp( SMESHGUI* theModule )
954   {
955     if ( !theModule ) return;
956
957     SalomeApp_Application* app = dynamic_cast< SalomeApp_Application* >( theModule->application() );
958     if ( !app ) return;
959
960     SUIT_ResourceMgr* mgr = SMESH::GetResourceMgr( theModule );
961     if ( !mgr ) return;
962     //
963     double anRGBNd[3] = {1,1,1};
964     SMESH::GetColor( "SMESH", "numbering_node_color", anRGBNd[0], anRGBNd[1], anRGBNd[2], QColor( 255, 255, 255 ) );
965     int aSizeNd = 10;
966     SMESH::LabelFont aFamilyNd = SMESH::FntTimes;
967     bool aBoldNd    = true;
968     bool anItalicNd = false;
969     bool aShadowNd  = false;
970
971     if ( mgr->hasValue( "SMESH", "numbering_node_font" ) ) {
972       QFont f = mgr->fontValue( "SMESH", "numbering_node_font" );
973       if ( f.family()      == "Arial" )   aFamilyNd = SMESH::FntArial;
974       else if ( f.family() == "Courier" ) aFamilyNd = SMESH::FntCourier;
975       else if ( f.family() == "Times" )   aFamilyNd = SMESH::FntTimes;
976       aBoldNd    = f.bold();
977       anItalicNd = f.italic();
978       aShadowNd  = f.overline();
979       aSizeNd    = f.pointSize();
980     }
981     //
982     double anRGBEl[3] = {0,1,0};
983     SMESH::GetColor( "SMESH", "numbering_elem_color", anRGBEl[0], anRGBEl[1], anRGBEl[2], QColor( 0, 255, 0 ) );
984     int aSizeEl = 12;
985     SMESH::LabelFont aFamilyEl = SMESH::FntTimes;
986     bool aBoldEl    = true;
987     bool anItalicEl = false;
988     bool aShadowEl  = false;
989
990     if ( mgr->hasValue( "SMESH", "numbering_elem_font" ) ) {
991       QFont f = mgr->fontValue( "SMESH", "numbering_elem_font" );
992
993       if ( f.family()      == "Arial" )   aFamilyEl = SMESH::FntArial;
994       else if ( f.family() == "Courier" ) aFamilyEl = SMESH::FntCourier;
995       else if ( f.family() == "Times" )   aFamilyEl = SMESH::FntTimes;    
996       aBoldEl    = f.bold();
997       anItalicEl = f.italic();
998       aShadowEl  = f.overline();
999       aSizeEl    = f.pointSize();
1000     }
1001     //
1002     ViewManagerList vmList;
1003     app->viewManagers( SVTK_Viewer::Type(), vmList );
1004     foreach ( SUIT_ViewManager* vm, vmList ) {
1005       QVector<SUIT_ViewWindow*> views = vm->getViews();
1006       foreach ( SUIT_ViewWindow* vw, views ) {
1007         // update VTK viewer properties
1008         if ( SVTK_ViewWindow* aVtkView = GetVtkViewWindow( vw ) ) {
1009           // update actors
1010           vtkRenderer* aRenderer = aVtkView->getRenderer();
1011           VTK::ActorCollectionCopy aCopy( aRenderer->GetActors() );
1012           vtkActorCollection* aCollection = aCopy.GetActors();
1013           aCollection->InitTraversal();
1014           while ( vtkActor* anAct = aCollection->GetNextActor() ) {
1015             if ( SMESH_NodeLabelActor* anActor = dynamic_cast< SMESH_NodeLabelActor* >( anAct ) ) {
1016               anActor->SetFontProperties( aFamilyNd, aSizeNd, aBoldNd, anItalicNd, aShadowNd, anRGBNd[0], anRGBNd[1], anRGBNd[2] );
1017             }
1018             else if ( SMESH_CellLabelActor* anActor = dynamic_cast< SMESH_CellLabelActor* >( anAct ) ) {
1019               anActor->SetFontProperties( aFamilyEl, aSizeEl, aBoldEl, anItalicEl, aShadowEl, anRGBEl[0], anRGBEl[1], anRGBEl[2] );
1020             }
1021           }
1022           aVtkView->Repaint( false ); 
1023         }
1024       }
1025     }
1026   }
1027
1028   //----------------------------------------------------------------------------
1029   SVTK_Selector*
1030   GetSelector(SUIT_ViewWindow *theWindow)
1031   {
1032     if(SVTK_ViewWindow* aWnd = GetVtkViewWindow(theWindow))
1033       return aWnd->GetSelector();
1034
1035     return NULL;
1036   }
1037
1038   void SetFilter(const Handle(VTKViewer_Filter)& theFilter,
1039                  SVTK_Selector* theSelector)
1040   {
1041     if (theSelector)
1042       theSelector->SetFilter(theFilter);
1043   }
1044
1045   Handle(VTKViewer_Filter) GetFilter(int theId, SVTK_Selector* theSelector)
1046   {
1047     return theSelector->GetFilter(theId);
1048   }
1049
1050   bool IsFilterPresent(int theId, SVTK_Selector* theSelector)
1051   {
1052     return theSelector->IsFilterPresent(theId);
1053   }
1054
1055   void RemoveFilter(int theId, SVTK_Selector* theSelector)
1056   {
1057     theSelector->RemoveFilter(theId);
1058   }
1059
1060   void RemoveFilters(SVTK_Selector* theSelector)
1061   {
1062     for ( int id = SMESH::NodeFilter; theSelector && id < SMESH::LastFilter; id++ )
1063       theSelector->RemoveFilter( id );
1064   }
1065
1066   bool IsValid(SALOME_Actor* theActor, int theCellId,
1067                SVTK_Selector* theSelector)
1068   {
1069     return theSelector->IsValid(theActor,theCellId);
1070   }
1071
1072
1073   //----------------------------------------------------------------------------
1074   void SetPointRepresentation(bool theIsVisible){
1075     if(SVTK_ViewWindow* aViewWindow = GetCurrentVtkView()){
1076       vtkRenderer *aRenderer = aViewWindow->getRenderer();
1077       VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
1078       vtkActorCollection *aCollection = aCopy.GetActors();
1079       aCollection->InitTraversal();
1080       while(vtkActor *anAct = aCollection->GetNextActor()){
1081         if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)){
1082           if(anActor->GetVisibility()){
1083             anActor->SetPointRepresentation(theIsVisible);
1084           }
1085         }
1086       }
1087       RepaintCurrentView();
1088     }
1089   }
1090
1091
1092   void SetPickable(SMESH_Actor* theActor){
1093     if(SVTK_ViewWindow* aWnd = GetCurrentVtkView()){
1094       int anIsAllPickable = (theActor == NULL);
1095       vtkRenderer *aRenderer = aWnd->getRenderer();
1096       VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
1097       vtkActorCollection *aCollection = aCopy.GetActors();
1098       aCollection->InitTraversal();
1099       while(vtkActor *anAct = aCollection->GetNextActor()){
1100         if(SALOME_Actor *anActor = dynamic_cast<SALOME_Actor*>(anAct)){
1101           if(anActor->GetVisibility()){
1102             anActor->SetPickable(anIsAllPickable);
1103           }
1104         }
1105       }
1106       if(theActor)
1107         theActor->SetPickable(!anIsAllPickable);
1108       RepaintCurrentView();
1109     }
1110   }
1111
1112
1113   //----------------------------------------------------------------------------
1114   int GetNameOfSelectedNodes(SVTK_Selector* theSelector,
1115                              const Handle(SALOME_InteractiveObject)& theIO,
1116                              QString& theName)
1117   {
1118     theName = "";
1119     TColStd_IndexedMapOfInteger aMapIndex;
1120     theSelector->GetIndex(theIO,aMapIndex);
1121
1122     for(int i = 1; i <= aMapIndex.Extent(); i++)
1123       theName += QString(" %1").arg(aMapIndex(i));
1124
1125     return aMapIndex.Extent();
1126   }
1127
1128   int GetNameOfSelectedElements(SVTK_Selector* theSelector,
1129                                 const Handle(SALOME_InteractiveObject)& theIO,
1130                                 QString& theName)
1131   {
1132     theName = "";
1133     TColStd_IndexedMapOfInteger aMapIndex;
1134     theSelector->GetIndex(theIO,aMapIndex);
1135
1136     typedef std::set<int> TIdContainer;
1137     TIdContainer anIdContainer;
1138     for( int i = 1; i <= aMapIndex.Extent(); i++)
1139       anIdContainer.insert(aMapIndex(i));
1140
1141     TIdContainer::const_iterator anIter = anIdContainer.begin();
1142     for( ; anIter != anIdContainer.end(); anIter++)
1143       theName += QString(" %1").arg(*anIter);
1144
1145     return aMapIndex.Extent();
1146   }
1147
1148
1149   int GetEdgeNodes(SVTK_Selector* theSelector,
1150                    const TVisualObjPtr& theVisualObject,
1151                    int& theId1,
1152                    int& theId2)
1153   {
1154     const SALOME_ListIO& selected = theSelector->StoredIObjects();
1155
1156     if ( selected.Extent() != 1 )
1157       return -1;
1158
1159     Handle(SALOME_InteractiveObject) anIO = selected.First();
1160     if ( anIO.IsNull() || !anIO->hasEntry() )
1161       return -1;
1162
1163     TColStd_IndexedMapOfInteger aMapIndex;
1164     theSelector->GetIndex( anIO, aMapIndex );
1165     if ( aMapIndex.Extent() != 2 )
1166       return -1;
1167
1168     int anObjId = -1, anEdgeNum = -1;
1169     for ( int i = 1; i <= aMapIndex.Extent(); i++ ) {
1170       int aVal = aMapIndex( i );
1171       if ( aVal > 0 )
1172         anObjId = aVal;
1173       else
1174         anEdgeNum = abs( aVal ) - 1;
1175     }
1176
1177     if ( anObjId == -1 || anEdgeNum == -1 )
1178       return -1;
1179
1180     return theVisualObject->GetEdgeNodes( anObjId, anEdgeNum, theId1, theId2 ) ? 1 : -1;
1181   }
1182
1183   //----------------------------------------------------------------------------
1184   int GetNameOfSelectedNodes(LightApp_SelectionMgr *theMgr,
1185                              const Handle(SALOME_InteractiveObject)& theIO,
1186                              QString& theName)
1187   {
1188     theName = "";
1189     if(theIO->hasEntry()){
1190       if(FindActorByEntry(theIO->getEntry())){
1191         TColStd_IndexedMapOfInteger aMapIndex;
1192         theMgr->GetIndexes(theIO,aMapIndex);
1193         for(int i = 1; i <= aMapIndex.Extent(); i++){
1194           theName += QString(" %1").arg(aMapIndex(i));
1195         }
1196         return aMapIndex.Extent();
1197       }
1198     }
1199     return -1;
1200   }
1201
1202   int GetNameOfSelectedNodes(LightApp_SelectionMgr *theMgr, QString& theName){
1203     theName = "";
1204     SALOME_ListIO selected; theMgr->selectedObjects( selected );
1205     if(selected.Extent() == 1){
1206       Handle(SALOME_InteractiveObject) anIO = selected.First();
1207       return GetNameOfSelectedNodes(theMgr,anIO,theName);
1208     }
1209     return -1;
1210   }
1211
1212
1213   int GetNameOfSelectedElements(LightApp_SelectionMgr *theMgr,
1214                                 const Handle(SALOME_InteractiveObject)& theIO,
1215                                 QString& theName)
1216   {
1217     theName = "";
1218     if(theIO->hasEntry()){
1219       if(FindActorByEntry(theIO->getEntry())){
1220         TColStd_IndexedMapOfInteger aMapIndex;
1221         theMgr->GetIndexes(theIO,aMapIndex);
1222         typedef std::set<int> TIdContainer;
1223         TIdContainer anIdContainer;
1224         for( int i = 1; i <= aMapIndex.Extent(); i++)
1225           anIdContainer.insert(aMapIndex(i));
1226         TIdContainer::const_iterator anIter = anIdContainer.begin();
1227         for( ; anIter != anIdContainer.end(); anIter++){
1228           theName += QString(" %1").arg(*anIter);
1229         }
1230         return aMapIndex.Extent();
1231       }
1232     }
1233     return -1;
1234   }
1235
1236
1237   int GetNameOfSelectedElements(LightApp_SelectionMgr *theMgr, QString& theName)
1238   {
1239     theName = "";
1240     SALOME_ListIO selected; theMgr->selectedObjects( selected );
1241
1242     if( selected.Extent() == 1){
1243       Handle(SALOME_InteractiveObject) anIO = selected.First();
1244       return GetNameOfSelectedElements(theMgr,anIO,theName);
1245     }
1246     return -1;
1247   }
1248
1249   int GetSelected(LightApp_SelectionMgr*       theMgr,
1250                   TColStd_IndexedMapOfInteger& theMap,
1251                   const bool                   theIsElement)
1252   {
1253     theMap.Clear();
1254     SALOME_ListIO selected; theMgr->selectedObjects( selected );
1255
1256     if ( selected.Extent() == 1 )
1257     {
1258       Handle(SALOME_InteractiveObject) anIO = selected.First();
1259       if ( anIO->hasEntry() ) {
1260         theMgr->GetIndexes( anIO, theMap );
1261       }
1262     }
1263     return theMap.Extent();
1264   }
1265
1266
1267   int GetEdgeNodes( LightApp_SelectionMgr* theMgr, int& theId1, int& theId2 )
1268   {
1269     SALOME_ListIO selected; theMgr->selectedObjects( selected );
1270
1271     if ( selected.Extent() != 1 )
1272       return -1;
1273
1274     Handle(SALOME_InteractiveObject) anIO = selected.First();
1275     if ( anIO.IsNull() || !anIO->hasEntry() )
1276       return -1;
1277
1278     SMESH_Actor *anActor = SMESH::FindActorByEntry( anIO->getEntry() );
1279     if ( anActor == 0 )
1280       return -1;
1281
1282     TColStd_IndexedMapOfInteger aMapIndex;
1283     theMgr->GetIndexes( anIO, aMapIndex );
1284     if ( aMapIndex.Extent() != 2 )
1285       return -1;
1286
1287     int anObjId = -1, anEdgeNum = -1;
1288     for ( int i = 1; i <= aMapIndex.Extent(); i++ ) {
1289       int aVal = aMapIndex( i );
1290       if ( aVal > 0 )
1291         anObjId = aVal;
1292       else
1293         anEdgeNum = abs( aVal );
1294     }
1295
1296     if ( anObjId == -1 || anEdgeNum == -1 )
1297       return -1;
1298
1299     return anActor->GetObject()->GetEdgeNodes( anObjId, anEdgeNum, theId1, theId2 ) ? 1 : -1;
1300   }
1301
1302   void SetControlsPrecision( const long theVal )
1303   {
1304     if( SVTK_ViewWindow* aWnd = SMESH::GetCurrentVtkView() )
1305     {
1306       vtkRenderer *aRenderer = aWnd->getRenderer();
1307       VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
1308       vtkActorCollection *aCollection = aCopy.GetActors();
1309       aCollection->InitTraversal();
1310
1311       while ( vtkActor *anAct = aCollection->GetNextActor())
1312       {
1313         if ( SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>( anAct ) )
1314         {
1315           anActor->SetControlsPrecision( theVal );
1316           anActor->SetControlMode( anActor->GetControlMode() );
1317         }
1318       }
1319
1320     }
1321   }
1322
1323   //----------------------------------------------------------------------------
1324   // internal function
1325   void ComputeBoundsParam( double theBounds[6],
1326                            double theDirection[3],
1327                            double theMinPnt[3],
1328                            double& theMaxBoundPrj,
1329                            double& theMinBoundPrj )
1330   {
1331     //Enlarge bounds in order to avoid conflicts of precision
1332     for(int i = 0; i < 6; i += 2){
1333       static double EPS = 1.0E-3;
1334       double aDelta = (theBounds[i+1] - theBounds[i])*EPS;
1335       theBounds[i] -= aDelta;
1336       theBounds[i+1] += aDelta;
1337     }
1338
1339     double aBoundPoints[8][3] = { {theBounds[0],theBounds[2],theBounds[4]},
1340                                                 {theBounds[1],theBounds[2],theBounds[4]},
1341                                                 {theBounds[0],theBounds[3],theBounds[4]},
1342                                                 {theBounds[1],theBounds[3],theBounds[4]},
1343                                                 {theBounds[0],theBounds[2],theBounds[5]},
1344                                                 {theBounds[1],theBounds[2],theBounds[5]}, 
1345                                                 {theBounds[0],theBounds[3],theBounds[5]}, 
1346                                                 {theBounds[1],theBounds[3],theBounds[5]}};
1347
1348     int aMaxId = 0;
1349     theMaxBoundPrj = vtkMath::Dot(theDirection,aBoundPoints[aMaxId]);
1350     theMinBoundPrj = theMaxBoundPrj;
1351     for(int i = 1; i < 8; i++){
1352       double aTmp = vtkMath::Dot(theDirection,aBoundPoints[i]);
1353       if(theMaxBoundPrj < aTmp){
1354         theMaxBoundPrj = aTmp;
1355         aMaxId = i;
1356       }
1357       if(theMinBoundPrj > aTmp){
1358         theMinBoundPrj = aTmp;
1359       }
1360     }
1361     double *aMinPnt = aBoundPoints[aMaxId];
1362     theMinPnt[0] = aMinPnt[0];
1363     theMinPnt[1] = aMinPnt[1];
1364     theMinPnt[2] = aMinPnt[2];
1365   }
1366
1367   // internal function
1368   void DistanceToPosition( double theBounds[6],
1369                            double theDirection[3],
1370                            double theDist,
1371                            double thePos[3] )
1372   {
1373     double aMaxBoundPrj, aMinBoundPrj, aMinPnt[3];
1374     ComputeBoundsParam(theBounds,theDirection,aMinPnt,aMaxBoundPrj,aMinBoundPrj);
1375     double aLength = (aMaxBoundPrj-aMinBoundPrj)*theDist;
1376     thePos[0] = aMinPnt[0]-theDirection[0]*aLength;
1377     thePos[1] = aMinPnt[1]-theDirection[1]*aLength;
1378     thePos[2] = aMinPnt[2]-theDirection[2]*aLength;
1379   }
1380
1381   // internal function (currently unused, left just in case)
1382   void PositionToDistance( double theBounds[6],
1383                            double theDirection[3],
1384                            double thePos[3],
1385                            double& theDist )
1386   {
1387     double aMaxBoundPrj, aMinBoundPrj, aMinPnt[3];
1388     ComputeBoundsParam(theBounds,theDirection,aMinPnt,aMaxBoundPrj,aMinBoundPrj);
1389     double aPrj = vtkMath::Dot(theDirection,thePos);
1390     theDist = (aPrj-aMinBoundPrj)/(aMaxBoundPrj-aMinBoundPrj);
1391   }
1392
1393   bool ComputeClippingPlaneParameters( std::list<vtkActor*> theActorList,
1394                                        double theNormal[3],
1395                                        double theDist,
1396                                        double theBounds[6],
1397                                        double theOrigin[3] )
1398   {
1399     bool anIsOk = false;
1400     anIsOk = ComputeBounds( theActorList, theBounds );
1401
1402
1403     if( !anIsOk )
1404       return false;
1405
1406     DistanceToPosition( theBounds, theNormal, theDist, theOrigin );
1407     return true;
1408   }
1409
1410   bool ComputeBounds( std::list<vtkActor*> theActorList,
1411                       double theBounds[6])
1412   {
1413     bool anIsOk = false;
1414     theBounds[0] = theBounds[2] = theBounds[4] = VTK_DOUBLE_MAX;
1415     theBounds[1] = theBounds[3] = theBounds[5] = -VTK_DOUBLE_MAX;
1416     std::list<vtkActor*>::iterator anIter = theActorList.begin();
1417     for( ; anIter != theActorList.end(); anIter++ ) {
1418       if( vtkActor* aVTKActor = *anIter ) {
1419         if( SMESH_Actor* anActor = SMESH_Actor::SafeDownCast( aVTKActor ) ) {
1420           double aBounds[6];
1421           anActor->GetUnstructuredGrid()->GetBounds( aBounds );
1422           theBounds[0] = std::min( theBounds[0], aBounds[0] );
1423           theBounds[1] = std::max( theBounds[1], aBounds[1] );
1424           theBounds[2] = std::min( theBounds[2], aBounds[2] );
1425           theBounds[3] = std::max( theBounds[3], aBounds[3] );
1426           theBounds[4] = std::min( theBounds[4], aBounds[4] );
1427           theBounds[5] = std::max( theBounds[5], aBounds[5] );
1428           anIsOk = true;
1429         }
1430       }
1431     }
1432     return anIsOk;
1433   }
1434
1435 #ifndef DISABLE_PLOT2DVIEWER
1436   //================================================================================
1437   /*!
1438    * \brief Find all SMESH_Actor's in the View Window.
1439    * If actor constains Plot2d_Histogram object remove it from each Plot2d Viewer.
1440    */
1441   //================================================================================
1442
1443   void ClearPlot2Viewers( SUIT_ViewWindow* theWindow ) {
1444     if(SVTK_ViewWindow* aViewWindow = GetVtkViewWindow(theWindow)){
1445       vtkRenderer *aRenderer = aViewWindow->getRenderer();
1446       VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
1447       vtkActorCollection *aCollection = aCopy.GetActors();
1448       aCollection->InitTraversal();
1449       while(vtkActor *anAct = aCollection->GetNextActor()){
1450         if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)){
1451           if(anActor->hasIO() && anActor->GetPlot2Histogram() ){
1452             ProcessIn2DViewers(anActor,RemoveFrom2dViewer);
1453           }
1454         }
1455       }
1456     }
1457   }
1458   
1459 #endif
1460
1461 } // end of namespace SMESH