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