Salome HOME
Improvement of extrusion functionality
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_SelectionOp.cxx
1 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
3 // 
4 //  This library is free software; you can redistribute it and/or 
5 //  modify it under the terms of the GNU Lesser General Public 
6 //  License as published by the Free Software Foundation; either 
7 //  version 2.1 of the License. 
8 // 
9 //  This library is distributed in the hope that it will be useful, 
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 //  Lesser General Public License for more details. 
13 // 
14 //  You should have received a copy of the GNU Lesser General Public 
15 //  License along with this library; if not, write to the Free Software 
16 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
17 // 
18 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
19 //
20 //
21 //
22 //  File   : SMESHGUI_SelectionOp.cxx
23 //  Author : Alexander SOLOVYOV
24 //  Module : SMESH
25
26 #include <SMESHGUI_SelectionOp.h>
27 #include <SMESHGUI_VTKUtils.h>
28 #include <SMESHGUI_MeshUtils.h>
29 #include <SMESHGUI_Selection.h>
30 #include <SMESHGUI.h>
31 #include <SUIT_SelectionFilter.h>
32 #include <SalomeApp_SelectionMgr.h>
33 #include <SalomeApp_Study.h>
34 #include <SalomeApp_VTKSelector.h>
35 #include <SVTK_ViewWindow.h>
36 #include <SVTK_ViewModel.h>
37 #include <SVTK_Selector.h>
38 #include <SMESH_Actor.h>
39
40 #include <SMDS_Mesh.hxx>
41 #include <SMDS_MeshNode.hxx>
42
43 #include CORBA_SERVER_HEADER(GEOM_Gen)
44 #include <SALOMEDS_SObject.hxx>
45
46 /*
47   Class       : SMESHGUI_SelectionOp
48   Description : Base operation for all operations using object selection in viewer or objectbrowser
49                 through common widgets created by SalomeApp_Dialog::createObject
50 */
51
52 //=================================================================================
53 // name     : SMESHGUI_SelectionOp
54 // purpose  : 
55 //=================================================================================
56 SMESHGUI_SelectionOp::SMESHGUI_SelectionOp( const Selection_Mode mode )
57 : SMESHGUI_Operation(),
58   myDefSelectionMode( mode )
59 {
60 }
61
62 //=================================================================================
63 // name     : ~SMESHGUI_SelectionOp
64 // purpose  :
65 //=================================================================================
66 SMESHGUI_SelectionOp::~SMESHGUI_SelectionOp()
67 {
68   Filters::const_iterator anIt = myFilters.begin(),
69                           aLast = myFilters.end();
70   for( ; anIt!=aLast; anIt++ )
71     if( anIt.data() )
72       delete anIt.data();
73 }
74
75 //=================================================================================
76 // name     : startOperation
77 // purpose  :
78 //=================================================================================
79 void SMESHGUI_SelectionOp::startOperation()
80 {
81   SMESHGUI_Operation::startOperation();
82   if( dlg() )
83   {
84     disconnect( dlg(), SIGNAL( objectActivated( int ) ), this, SLOT( onActivateObject( int ) ) );
85     disconnect( dlg(), SIGNAL( objectDeactivated( int ) ), this, SLOT( onDeactivateObject( int ) ) );
86     disconnect( dlg(), SIGNAL( selectionChanged( int ) ), this, SLOT( onSelectionChanged( int ) ) );
87     connect( dlg(), SIGNAL( objectActivated( int ) ), this, SLOT( onActivateObject( int ) ) );
88     connect( dlg(), SIGNAL( objectDeactivated( int ) ), this, SLOT( onDeactivateObject( int ) ) );
89     connect( dlg(), SIGNAL( selectionChanged( int ) ), this, SLOT( onSelectionChanged( int ) ) );
90   }
91
92   myOldSelectionMode = selectionMode();
93   setSelectionMode( myDefSelectionMode );
94 }
95
96 //=================================================================================
97 // name     : removeCustomFilters
98 // purpose  :
99 //=================================================================================
100 void SMESHGUI_SelectionOp::removeCustomFilters() const
101 {
102   SalomeApp_SelectionMgr* mgr = selectionMgr();
103   if( !mgr )
104     return;
105     
106   Filters::const_iterator anIt = myFilters.begin(),
107                           aLast = myFilters.end();
108   for( ; anIt!=aLast; anIt++ )
109     if( anIt.data() )
110       mgr->removeFilter( anIt.data() );
111 }
112
113 //=================================================================================
114 // name     : commitOperation
115 // purpose  :
116 //=================================================================================
117 void SMESHGUI_SelectionOp::commitOperation()
118 {
119   removeCustomFilters();
120   setSelectionMode( myOldSelectionMode );
121   SMESHGUI_Operation::commitOperation();  
122 }
123
124 //=================================================================================
125 // name     : abortOperation
126 // purpose  :
127 //=================================================================================
128 void SMESHGUI_SelectionOp::abortOperation()
129 {
130   removeCustomFilters();
131   setSelectionMode( myOldSelectionMode );  
132   SMESHGUI_Operation::abortOperation();
133 }
134
135 //=================================================================================
136 // name     : selectionDone
137 // purpose  :
138 //=================================================================================
139 void SMESHGUI_SelectionOp::selectionDone()
140 {
141   if( !dlg() )
142     return;
143
144   if( selectionMode()!=ActorSelection )
145   {
146     SALOME_ListIO aList;
147     selectionMgr()->selectedObjects( aList, SVTK_Viewer::Type() );
148
149     if( aList.Extent() != 1 ) //we can select nodes or elements only within one mesh
150     {
151       dlg()->clearSelection();
152       return;
153     }    
154   }
155     
156   QStringList names, ids;
157   SalomeApp_Dialog::TypesList types;
158   selected( names, types, ids );
159   dlg()->selectObject( names, types, ids );
160 }
161
162 //=================================================================================
163 // name     : createFilter
164 // purpose  :
165 //=================================================================================
166 SUIT_SelectionFilter* SMESHGUI_SelectionOp::createFilter( const int ) const
167 {
168   return 0;
169 }
170
171 //=================================================================================
172 // name     : onActivateObject
173 // purpose  :
174 //=================================================================================
175 void SMESHGUI_SelectionOp::onActivateObject( int id )
176 {
177   SalomeApp_SelectionMgr* mgr = selectionMgr();
178   if( !mgr )
179     return;
180     
181   if( !myFilters.contains( id ) )
182     myFilters[ id ] = createFilter( id );
183
184   if( myFilters[ id ] )
185     mgr->installFilter( myFilters[ id ] );
186
187   selectionDone();
188 }
189
190 //=================================================================================
191 // name     : onDeactivateObject
192 // purpose  :
193 //=================================================================================
194 void SMESHGUI_SelectionOp::onDeactivateObject( int id )
195 {
196   SalomeApp_SelectionMgr* mgr = selectionMgr();
197   if( mgr && myFilters.contains( id ) && myFilters[ id ] )
198     mgr->removeFilter( myFilters[ id ] );
199 }
200
201 //=================================================================================
202 // name     : initDialog
203 // purpose  :
204 //=================================================================================
205 void SMESHGUI_SelectionOp::initDialog()
206 {
207   if( dlg() )
208   {
209     dlg()->clearSelection();
210     dlg()->deactivateAll();
211   }
212 }
213
214 //=================================================================================
215 // name     : initDialog
216 // purpose  :
217 //=================================================================================
218 void SMESHGUI_SelectionOp::onSelectionChanged( int )
219 {
220 }
221
222 //=======================================================================
223 // name    : selectionMode
224 // Purpose : Returns selection mode
225 //=======================================================================
226 Selection_Mode SMESHGUI_SelectionOp::selectionMode() const
227 {
228   SVTK_ViewWindow* wnd = viewWindow();
229   if( wnd )
230     return wnd->SelectionMode();
231   else
232     return ActorSelection;
233 }
234
235 //=======================================================================
236 // name    : setSelectionMode
237 // Purpose : Set selection mode
238 //=======================================================================
239 void SMESHGUI_SelectionOp::setSelectionMode( const Selection_Mode mode )
240 {
241   SVTK_ViewWindow* wnd = viewWindow();
242   if( wnd )
243     wnd->SetSelectionMode( mode );
244 }
245
246 //=======================================================================
247 // name    : highlight
248 // Purpose : Highlight object in 3d viewer
249 //=======================================================================
250 void SMESHGUI_SelectionOp::highlight( const Handle( SALOME_InteractiveObject )& obj,
251                                       const bool hilight, const bool immediately )
252 {
253   SVTK_ViewWindow* wnd = viewWindow();
254   if( wnd )
255     wnd->highlight( obj, hilight, immediately );
256 }
257
258 //=======================================================================
259 // name    : addOrRemoveIndex
260 // Purpose : Select/deselect cells of mesh
261 //=======================================================================
262 void SMESHGUI_SelectionOp::addOrRemoveIndex( const Handle( SALOME_InteractiveObject )& obj,
263                                              const TColStd_MapOfInteger& indices,
264                                              const bool isModeShift )
265 {
266   SVTK_Selector* sel = selector();
267   if( sel )
268     sel->AddOrRemoveIndex( obj, indices, isModeShift );
269 }
270
271 //=======================================================================
272 // name    : viewWindow
273 // Purpose : Get active view window
274 //=======================================================================
275 SVTK_ViewWindow* SMESHGUI_SelectionOp::viewWindow() const
276 {
277   return SMESH::GetViewWindow( getSMESHGUI() );
278 }
279
280 //=======================================================================
281 // name    : selector
282 // Purpose : Get selector
283 //=======================================================================
284 SVTK_Selector* SMESHGUI_SelectionOp::selector() const
285 {
286   SVTK_ViewWindow* wnd = viewWindow();
287   return wnd ? wnd->GetSelector() : 0;
288 }
289
290 //=======================================================================
291 // name    : typeById
292 // Purpose : Find type by id
293 //=======================================================================
294 int SMESHGUI_SelectionOp::typeById( const QString& str, const EntityType objtype ) const
295 {
296   SalomeApp_Study* _study = dynamic_cast<SalomeApp_Study*>( study() );
297   if( !_study )
298     return -1;
299
300   _PTR( Study ) st = _study->studyDS();
301
302   int res = -1;
303   if( objtype == Object )
304   {
305     SalomeApp_Study* _study = dynamic_cast<SalomeApp_Study*>( study() );
306     if( _study )
307     {
308       int t = SMESHGUI_Selection::type( str, _study->studyDS() );
309       if( t<0 )
310       {
311         //try to get GEOM type
312         _PTR( SObject ) sobj = st->FindObjectID( str.latin1() );
313         if( sobj )
314         {
315           GEOM::GEOM_Object_var obj = GEOM::GEOM_Object::_narrow(
316             dynamic_cast<SALOMEDS_SObject*>( sobj.get() )->GetObject() );
317           if( !CORBA::is_nil( obj ) )
318             res = SMESHGUI_Dialog::prefix( "GEOM" ) + obj->GetType();
319         }
320       }
321       else
322         res = SMESHGUI_Dialog::prefix( "SMESH" ) + t;
323     }
324   }
325   else
326   {
327     int pos = str.find( idChar() );
328     QString entry = str.left( pos ),
329             _id = str.mid( pos+1 );
330     bool ok;
331     int id = _id.toInt( &ok );
332     if( ok )
333     {
334       _PTR( SObject ) sobj = st->FindObjectID( entry.latin1() );
335       SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( 
336         dynamic_cast<SALOMEDS_SObject*>( sobj.get() )->GetObject() );
337       SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow( 
338         dynamic_cast<SALOMEDS_SObject*>( sobj.get() )->GetObject() );
339       if( !CORBA::is_nil( mesh ) )
340         res = SMESHGUI_Dialog::prefix( "SMESH element" ) + 
341           mesh->GetElementType( id, objtype==MeshElement );
342
343       else if( !CORBA::is_nil( submesh ) )
344         res = SMESHGUI_Dialog::prefix( "SMESH element" ) + 
345           submesh->GetElementType( id, objtype==MeshElement );
346     }
347   }
348
349   return res;
350 }
351
352 //=======================================================================
353 // name    : selected
354 // Purpose : Get names, types and ids of selected objects
355 //=======================================================================
356 void SMESHGUI_SelectionOp::selected( QStringList& names,
357                                      SalomeApp_Dialog::TypesList& types,
358                                      QStringList& ids ) const
359 {
360   SUIT_DataOwnerPtrList list; selectionMgr()->selected( list );
361   SUIT_DataOwnerPtrList::const_iterator anIt = list.begin(),
362                                         aLast = list.end();
363   for( ; anIt!=aLast; anIt++ )
364   {
365     SalomeApp_DataOwner* owner = dynamic_cast<SalomeApp_DataOwner*>( (*anIt).operator->() );
366     SalomeApp_SVTKDataOwner* vtkowner = dynamic_cast<SalomeApp_SVTKDataOwner*>( (*anIt).operator->() );
367
368     if( vtkowner )
369     {
370       QString id_str = QString( "%1%2%3" ).arg( vtkowner->entry() ).arg( idChar() ), current_id_str;
371       Selection_Mode mode = vtkowner->GetMode();
372       EntityType objtype = mode == NodeSelection ? MeshNode : MeshElement;
373       const TColStd_IndexedMapOfInteger& ownerids = vtkowner->GetIds();
374
375       for( int i=1, n=ownerids.Extent(); i<=n; i++ )
376       {
377         int curid = ownerids( i );
378         current_id_str = id_str.arg( curid );
379         ids.append( current_id_str );
380         types.append( typeById( current_id_str, objtype ) );
381         names.append( QString( "%1" ).arg( curid ) );
382       }
383     }
384
385     else if( owner )
386     {
387       QString id = owner->entry();
388       ids.append( id );
389       types.append( typeById( id, Object ) );
390       names.append( owner->IO()->getName() );
391     }
392   }
393 }
394
395 //=======================================================================
396 // name    : idChar
397 // Purpose : Char using to divide <entry> and <id> in string id representation. By default, '#'
398 //=======================================================================
399 QChar SMESHGUI_SelectionOp::idChar() const
400 {
401   return '#';
402 }
403
404 //=================================================================================
405 // name     : mesh
406 // purpose  :
407 //=================================================================================
408 SMESH::SMESH_Mesh_var SMESHGUI_SelectionOp::mesh() const
409 {
410   if( selectionMode()==ActorSelection )
411     return SMESH::SMESH_Mesh::_nil();
412     
413   SALOME_ListIO sel; selectionMgr()->selectedObjects( sel, SVTK_Viewer::Type() );
414   if( sel.Extent()==1 )
415     return SMESH::GetMeshByIO( sel.First() );
416   else
417     return SMESH::SMESH_Mesh::_nil();
418 }
419
420 //=================================================================================
421 // name     : actor
422 // purpose  :
423 //=================================================================================
424 SMESH_Actor* SMESHGUI_SelectionOp::actor() const
425 {
426   SMESH::SMESH_Mesh_var m = mesh();
427   if( !m->_is_nil() )
428     return SMESH::FindActorByObject( m.in() );
429   else
430     return 0;
431 }
432
433 //=================================================================================
434 // name     : onTextChanged
435 // purpose  :
436 //=================================================================================
437 void SMESHGUI_SelectionOp::onTextChanged( int, const QStringList& list )
438 {
439     if( !dlg() )
440       return;
441
442     TColStd_MapOfInteger newIndices;
443
444     SALOME_ListIO sel; selectionMgr()->selectedObjects( sel );
445     SMESH_Actor* anActor = actor();
446     if( sel.Extent()==0 || !anActor )
447       return;
448
449     SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();
450
451     IdList ids; extractIds( list, ids, '\0' );
452     IdList::const_iterator anIt = ids.begin(),
453                            aLast = ids.end();
454     for( ; anIt!=aLast; anIt++ )
455       if( const SMDS_MeshNode * n = aMesh->FindNode( *anIt ) )
456         newIndices.Add( n->GetID() );
457
458     selector()->AddOrRemoveIndex( sel.First(), newIndices, false );
459     highlight( sel.First(), true, true );
460
461     QStringList names, _ids; SalomeApp_Dialog::TypesList types;
462     selected( names, types, _ids );
463     dlg()->selectObject( names, types, _ids, false );
464 }
465
466 //=================================================================================
467 // name     : selectedIds
468 // purpose  :
469 //=================================================================================
470 void SMESHGUI_SelectionOp::selectedIds( const int id, IdList& list ) const
471 {
472   if( !dlg() )
473     return;
474
475   QStringList ids; dlg()->selectedObject( id, ids );
476   extractIds( ids, list );
477 }
478
479 //=================================================================================
480 // name     : extractIds
481 // purpose  :
482 //=================================================================================
483 void SMESHGUI_SelectionOp::extractIds( const QStringList& ids, IdList& list, const QChar idchar )
484 {
485   QStringList::const_iterator anIt = ids.begin(),
486                               aLast = ids.end();
487   QString id_str;
488   for( ; anIt!=aLast; anIt++ )
489   {
490     id_str = *anIt;
491     int pos = idchar=='\0' ? -1 : id_str.find( idchar );
492     int id = -1;
493     if( idchar=='\0' || pos>=0 )
494     {
495       id = id_str.mid( pos+1 ).toInt();
496       list.append( id );
497     }
498   }
499 }
500
501 //=================================================================================
502 // name     : extractIds
503 // purpose  :
504 //=================================================================================
505 void SMESHGUI_SelectionOp::extractIds( const QStringList& ids, IdList& list ) const
506 {
507   extractIds( ids, list, idChar() );
508 }