Salome HOME
write dbf with Hydro shapefiles, attribute string "PartName" with polyline name
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_OCCDisplayer.cxx
1 // Copyright (C) 2014-2015  EDF-R&D
2 // This library is free software; you can redistribute it and/or
3 // modify it under the terms of the GNU Lesser General Public
4 // License as published by the Free Software Foundation; either
5 // version 2.1 of the License, or (at your option) any later version.
6 //
7 // This library is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10 // Lesser General Public License for more details.
11 //
12 // You should have received a copy of the GNU Lesser General Public
13 // License along with this library; if not, write to the Free Software
14 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
15 //
16 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
17 //
18
19 #include "HYDROGUI_OCCDisplayer.h"
20
21 #include "HYDROGUI_DataModel.h"
22 #include "HYDROGUI_Module.h"
23 #include "HYDROGUI_Tool2.h"
24 #include <HYDROGUI_ShapeImage.h>
25 #include <HYDROGUI_ShapeBathymetry.h>
26 #include <HYDROGUI_ShapeLandCoverMap.h>
27 #include "HYDROGUI_Operation.h"
28 #include "HYDROGUI_DataObject.h"
29 #include "HYDROGUI_ZLayers.h"
30 #include "HYDROGUI_Polyline.h"
31
32 #include <HYDROData_Bathymetry.h>
33 #include <HYDROData_Image.h>
34 #include <HYDROData_LandCoverMap.h>
35 #include <HYDROData_StricklerTable.h>
36
37 #include <AIS_InteractiveContext.hxx>
38 #include <AIS_ListIteratorOfListOfInteractive.hxx>
39 #include <AIS_ListOfInteractive.hxx>
40 #include <AIS_ColorScale.hxx>
41
42 #include <TColStd_SequenceOfInteger.hxx>
43
44 #include <LightApp_Application.h>
45 #include <SUIT_Study.h>
46
47 #include <OCCViewer_ViewManager.h>
48 #include <OCCViewer_ViewModel.h>
49 #include <OCCViewer_ViewWindow.h>
50 #include <OCCViewer_ViewPort3d.h>
51
52 //#define _DEVDEBUG_
53 #include "HYDRO_trace.hxx"
54
55 HYDROGUI_OCCDisplayer::HYDROGUI_OCCDisplayer( HYDROGUI_Module* theModule )
56 : HYDROGUI_AbstractDisplayer( theModule )
57 {
58   myToUpdateColorScale = false;
59 }
60
61 HYDROGUI_OCCDisplayer::~HYDROGUI_OCCDisplayer()
62 {
63 }
64
65 void HYDROGUI_OCCDisplayer::SetToUpdate( const HYDROData_SequenceOfObjects& theObjs,
66                                          const size_t                       theViewerId )
67 {
68   OCCViewer_Viewer* aViewer = module()->getOCCViewer( theViewerId );
69   if( !aViewer )
70     return;
71
72   for ( int i = 1, n = theObjs.Length(); i <= n; i++ )
73   {
74     Handle(HYDROData_Entity) anObj = theObjs.Value( i );
75     if( anObj.IsNull() )
76       continue;
77
78     HYDROGUI_Shape* anObjShape = module()->getObjectShape( (size_t)aViewer, anObj );
79     if ( !anObjShape )
80       continue;
81     
82     anObjShape->setIsToUpdate( true );
83   }
84 }
85
86 int HYDROGUI_OCCDisplayer::AddPreviewZLayer( OCCViewer_ViewManager* theMgr )
87 {
88   int aLayer = -1;
89   OCCViewer_Viewer* aViewer = theMgr->getOCCViewer();
90   if ( !aViewer )
91     return aLayer;
92
93   aLayer = CreateTopZLayer( aViewer->getViewer3d() );
94   
95   // Hilight presentation should be on top
96   Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
97   if( !aCtx.IsNull() ) {
98     int aTopLayer = CreateTopZLayer( aViewer->getViewer3d() );
99     if ( aTopLayer > 0 ) {
100       UpdateZLayersOfHilightPresentationsOfDisplayedObjects( aCtx, aTopLayer );
101     }
102   }
103
104   return aLayer;
105 }
106
107 void HYDROGUI_OCCDisplayer::RemoveZLayer( OCCViewer_ViewManager* theMgr,
108                                           const int theLayer )
109 {
110   if ( theLayer < 0 )
111     return;
112
113   OCCViewer_Viewer* aViewer = theMgr->getOCCViewer();
114   if ( !aViewer )
115     return;
116
117   // Get existing Z layers
118   TColStd_SequenceOfInteger anExistingZLayers;
119   aViewer->getViewer3d()->GetAllZLayers( anExistingZLayers );
120   int aNbLayers = anExistingZLayers.Length();
121   
122   if ( theLayer < aNbLayers )
123     aViewer->getViewer3d()->RemoveZLayer( theLayer );
124 }
125
126 void HYDROGUI_OCCDisplayer::EraseAll( const size_t theViewerId )
127 {
128   OCCViewer_Viewer* aViewer = module()->getOCCViewer( theViewerId );
129   if( !aViewer )
130     return;
131
132   module()->removeViewShapes( (size_t)aViewer );
133   UpdateColorScale( aViewer );
134 }
135
136 void HYDROGUI_OCCDisplayer::Erase( const HYDROData_SequenceOfObjects& theObjs,
137                                    const size_t                       theViewerId )
138 {
139   OCCViewer_Viewer* aViewer = module()->getOCCViewer( theViewerId );
140   if( !aViewer )
141     return;
142
143   for ( int i = 1, n = theObjs.Length(); i <= n; i++ )
144   {
145     Handle(HYDROData_Entity) anObj = theObjs.Value( i );
146     if( anObj.IsNull() )
147       continue;
148
149     module()->removeObjectShape( (size_t)aViewer, anObj );
150   }
151   aViewer->update();
152   if ( !module()->isLandCoversScalarMapModeOn( (size_t)aViewer ) ) {
153     UpdateColorScale( aViewer );
154   }
155 }
156
157 HYDROGUI_Shape* HYDROGUI_OCCDisplayer::createShape( const size_t                          theViewerId,
158                                                     const Handle(AIS_InteractiveContext)& theContext,
159                                                     const Handle(HYDROData_Entity)&       theObject )
160 {
161   DEBTRACE("createShape " << theViewerId);
162   HYDROGUI_Shape* aResShape = NULL;
163   if ( theContext.IsNull() || theObject.IsNull() )
164     return aResShape;
165
166   if ( !HYDROGUI_Tool::IsObjectHasPresentation( theObject, OCCViewer_Viewer::Type() ) )
167     return aResShape;
168
169   if( theObject->IsKind( STANDARD_TYPE( HYDROData_Image ) ) )
170     aResShape = new HYDROGUI_ShapeImage( theContext, Handle(HYDROData_Image)::DownCast( theObject ) );
171   else if( theObject->IsKind( STANDARD_TYPE( HYDROData_Bathymetry ) ) )
172     aResShape = new HYDROGUI_ShapeBathymetry( this, theContext, Handle(HYDROData_Bathymetry)::DownCast( theObject ) );
173   else if( theObject->IsKind( STANDARD_TYPE( HYDROData_LandCoverMap ) ) ) {
174     bool isScalarMode = module()->isLandCoversScalarMapModeOn( theViewerId );
175     aResShape = new HYDROGUI_ShapeLandCoverMap( this, theContext, Handle(HYDROData_LandCoverMap)::DownCast( theObject ), -1, isScalarMode );
176   }
177   else
178     aResShape = new HYDROGUI_Shape( theContext, theObject );
179
180   module()->setObjectShape( theViewerId, theObject, aResShape );
181
182   return aResShape;
183 }
184
185 void HYDROGUI_OCCDisplayer::Display( const HYDROData_SequenceOfObjects& theObjs,
186                                      const size_t                       theViewerId,
187                                      const bool                         theIsForced,
188                                      const bool theDoFitAll )
189 {
190   // Get OCC viewer by id
191   OCCViewer_Viewer* aViewer = module()->getOCCViewer( theViewerId );
192   if( !aViewer )
193     return;
194
195   // Get interactive context
196   Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
197   if( aCtx.IsNull() )
198     return;
199
200   // Get the document
201   Handle(HYDROData_Document) aDoc = HYDROData_Document::Document();
202   if ( !aDoc )
203     return;
204   
205   // Assign Z layer indexes to the objects
206   aDoc->Show( theObjs );
207
208   // Sort objects by display order ( needed for Z layers assignment only )
209   HYDROData_SequenceOfObjects anUnorderedToDisplay = theObjs;
210   HYDROData_SequenceOfObjects anOrderedToDisplay;
211   HYDROData_SequenceOfObjects anAllOrderedObjects = aDoc->GetObjectsLayerOrder();
212
213   HYDROData_SequenceOfObjects::Iterator anAllOrderedIter( anAllOrderedObjects );
214   for ( ; anAllOrderedIter.More(); anAllOrderedIter.Next() ) {
215     QString anOrderedEntry = 
216       HYDROGUI_DataObject::dataObjectEntry( anAllOrderedIter.Value() );
217     
218     HYDROData_SequenceOfObjects::Iterator aToDisplayIter( anUnorderedToDisplay );
219     for ( ; aToDisplayIter.More(); aToDisplayIter.Next() ) {
220       Handle(HYDROData_Entity) anObjToDisplay = aToDisplayIter.Value();
221       QString anEntry = HYDROGUI_DataObject::dataObjectEntry( anObjToDisplay );
222       if ( anEntry == anOrderedEntry ) {
223         anOrderedToDisplay.Prepend( anObjToDisplay );
224         anUnorderedToDisplay.Remove( aToDisplayIter );
225         break;
226       }
227     }
228   }
229   
230   // Get 3d viewer
231   Handle(V3d_Viewer) aViewer3d = aViewer->getViewer3d();
232
233   // Display objects:
234   HYDROGUI_ZLayersIterator aZLayersIt( aViewer->getViewer3d() );
235   if ( !aZLayersIt.More() ) {
236     aZLayersIt.Next();
237   }
238
239   // 1. Display the ordered objects:
240   HYDROData_SequenceOfObjects::Iterator anOrderedIter( anOrderedToDisplay );
241   for ( ; anOrderedIter.More(); anOrderedIter.Next() ) {
242     Handle(HYDROData_Entity) anObj = anOrderedIter.Value();
243     if ( Display( anObj, aViewer, theIsForced ) ) {
244       // set Z layer ( one Z layer for each ordered object )
245       int aZLayerId = aZLayersIt.LayerId();
246       SetZLayer( aViewer, anObj, aZLayerId );
247       SetZLayerSettings( aViewer3d, aZLayerId, true );
248       aZLayersIt.Next();
249     }
250   }
251
252   // 2. Display the unordered objects:
253   bool isDisplayed = false;
254   int anUnorderedZLayerId = aZLayersIt.LayerId();
255   HYDROData_SequenceOfObjects::Iterator anUnorderedIter( anUnorderedToDisplay );
256   for ( ; anUnorderedIter.More(); anUnorderedIter.Next() ) {
257     Handle(HYDROData_Entity) anObj = anUnorderedIter.Value();
258     if ( Display( anObj, aViewer, theIsForced) ) {
259       // set Z layer ( one Z layer for all unordered objects )
260       SetZLayer( aViewer, anObj, anUnorderedZLayerId );
261       if ( !isDisplayed ) {
262         SetZLayerSettings( aViewer3d, anUnorderedZLayerId, false );
263       }
264       isDisplayed = true;
265     }
266   }
267   
268   // 3. Update the top Z layer index
269   if ( isDisplayed ) {
270     aZLayersIt.Next();
271   }
272
273   // Update Z layer of the active operation
274   int aPreviewZLayerId = aZLayersIt.LayerId();
275
276   HYDROGUI_Module* aModule = module();
277   SUIT_Operation* anOp = aModule->activeOperation();
278   HYDROGUI_Operation* aHOp = anOp ? dynamic_cast<HYDROGUI_Operation*>( anOp ) : 0;
279   if ( aHOp && aHOp->getPreviewZLayer() >= 0 ) {
280     aHOp->updatePreviewZLayer( aPreviewZLayerId );
281     aZLayersIt.Next();
282   }
283
284   // Update Z layer of hilight presentations
285   int aHilightLayer = aZLayersIt.TopLayer();
286   UpdateZLayersOfHilightPresentationsOfDisplayedObjects( aCtx, aHilightLayer );
287
288   // Fit all / update selection
289   if ( theDoFitAll ) {
290     OCCViewer_ViewManager* aViewManager
291       = ::qobject_cast<OCCViewer_ViewManager*>( aViewer->getViewManager() );
292     if ( aViewManager ) {
293       OCCViewer_ViewWindow* aViewWindow = 
294         ::qobject_cast<OCCViewer_ViewWindow*>( aViewManager->getActiveView() );
295       if ( aViewWindow ) {
296         aViewWindow->onFitAll();
297       }
298     }
299   } 
300   else if ( !aCtx.IsNull() ) { // TODO: determine if this code is necessary (added as a fix for issue# 359)
301     aCtx->UpdateSelected(true);
302   }
303
304   UpdateColorScale( aViewer );
305 }
306
307 void HYDROGUI_OCCDisplayer::purgeObjects( const size_t theViewerId )
308 {
309   OCCViewer_Viewer* aViewer = module()->getOCCViewer( theViewerId );
310   if( !aViewer )
311     return;
312
313   Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
314   if( aCtx.IsNull() )
315     return;
316
317   AIS_ListOfInteractive aDisplayedObjects;
318   aCtx->DisplayedObjects( aDisplayedObjects );
319
320   AIS_ListIteratorOfListOfInteractive aListIter( aDisplayedObjects );
321   for ( ; aListIter.More(); aListIter.Next() )
322   {
323     Handle(AIS_InteractiveObject) aPrsObj = aListIter.Value();
324     if ( aPrsObj.IsNull() )
325       continue;
326
327     Handle(HYDROData_Entity) anOwnerObj = 
328       Handle(HYDROData_Entity)::DownCast( aPrsObj->GetOwner() );
329     if ( !anOwnerObj.IsNull() && anOwnerObj->IsRemoved() )
330       module()->removeObjectShape( (size_t)aViewer, anOwnerObj );
331   }
332   UpdateColorScale( aViewer );
333 }
334
335 QString HYDROGUI_OCCDisplayer::GetType() const
336 {
337   return OCCViewer_Viewer::Type();
338 }
339
340 bool HYDROGUI_OCCDisplayer::Display( const Handle(HYDROData_Entity)& theObject,
341                                      const OCCViewer_Viewer* theViewer,
342                                      const bool theIsForced )
343 {
344   DEBTRACE("Display");
345   bool aRes = false;
346
347   if ( theObject.IsNull() || theObject->IsRemoved() || !theViewer ) {
348     return aRes;
349   }
350
351   // Get interactive context
352   Handle(AIS_InteractiveContext) aCtx = theViewer->getAISContext();
353   if( aCtx.IsNull() ) {
354     return aRes;
355   }
356
357   // Viewer id
358   size_t aViewerId = (size_t)theViewer;
359
360   // Object shape 
361   HYDROGUI_Shape* anObjShape = module()->getObjectShape( aViewerId, theObject );
362   // create if needed
363   if ( !anObjShape ) {
364     anObjShape = createShape( aViewerId, aCtx, theObject );
365     if ( anObjShape ) {
366       anObjShape->setIsToUpdate( true );
367     }
368   }
369   
370   // Process the shape
371   if ( anObjShape ) {
372     // update if needed
373     if ( anObjShape->getIsToUpdate() || theIsForced ) {
374       anObjShape->update( false, false );
375     }
376
377     // Set visibility
378     bool anIsVisible = module()->isObjectVisible( aViewerId, theObject );
379     anObjShape->setVisible( anIsVisible, false );
380
381     aRes = true;
382   }
383
384   return aRes;
385 }
386
387 void HYDROGUI_OCCDisplayer::SetZLayer( const OCCViewer_Viewer* theViewer,
388                                        const Handle(HYDROData_Entity)& theObject, 
389                                        const int theZLayerId )
390 {
391   if ( !theViewer /*|| ( theZLayerId < 0 )*/ ) {
392     return;
393   }
394   
395   // Get interactive context
396   Handle(AIS_InteractiveContext) aCtx = theViewer->getAISContext();
397   if( aCtx.IsNull() ) {
398     return;
399   }
400
401   // Get viewer id
402   size_t aViewerId = (size_t)theViewer;
403
404   // Get object shape 
405   HYDROGUI_Shape* anObjShape = module()->getObjectShape( aViewerId, theObject );
406
407   // Set Z layer
408   if ( anObjShape )
409   {
410     QList<Handle(AIS_InteractiveObject)> shapes = anObjShape->getAISObjects();
411     foreach( Handle(AIS_InteractiveObject) shape, shapes )
412       aCtx->SetZLayer( shape, theZLayerId );
413   }
414 }
415
416 void HYDROGUI_OCCDisplayer::SetToUpdateColorScale()
417 {
418   myToUpdateColorScale = true;
419 }
420
421 void HYDROGUI_OCCDisplayer::UpdateColorScale( const OCCViewer_Viewer* theViewer )
422 {
423   if( !myToUpdateColorScale || !theViewer )
424     return;
425   
426   OCCViewer_ViewWindow* aWnd = dynamic_cast<OCCViewer_ViewWindow*>( theViewer->getViewManager()->getActiveView() );
427   Handle(V3d_View) aView = aWnd->getViewPort()->getView();
428       
429
430   HYDROGUI_Module* aModule = module();
431   size_t aViewerId = (size_t)theViewer;//TODO: check if viewer id is correct
432   bool isLandCoverColoringOn = aModule->isLandCoversScalarMapModeOn( aViewerId );
433     
434   QList<HYDROGUI_Shape*> aLandCoverMapShapes = aModule->getObjectShapes( aViewerId, KIND_LAND_COVER_MAP );
435   QList<HYDROGUI_Shape*> aBathShapes = aModule->getObjectShapes( aViewerId, KIND_BATHYMETRY );
436
437   bool isDisplayColorScale = false;
438   foreach (HYDROGUI_Shape* shape, aLandCoverMapShapes)
439   {
440     if (aModule->isObjectVisible(aViewerId, shape->getObject()))
441     {
442       isDisplayColorScale = true;
443       break;
444     }
445   }
446   if (!isDisplayColorScale)
447     foreach (HYDROGUI_Shape* shape, aBathShapes)
448     {
449       if (aModule->isObjectVisible(aViewerId, shape->getObject()))
450       {
451         isDisplayColorScale = true;
452         break;
453       }
454     }
455   
456   Standard_Real aColorScaleMin = 0, aColorScaleMax = 1;
457
458   // Get range
459   Handle(HYDROData_StricklerTable) aTable;
460   QStringList aTableTypes;
461   if ( isLandCoverColoringOn ) {
462     aTable = module()->getLandCoverColoringTable( aViewerId );
463     if ( !aTable.IsNull() ) {
464       // TODO: non-empty title leads to buggy behaviour
465       // aColorScaleTitle = TCollection_ExtendedString( aTable->GetName().toLatin1().constData() );
466       aTable->GetCoefficientRange( aColorScaleMin, aColorScaleMax );
467       aTableTypes = aTable->GetTypes();
468     }
469   } else {
470     Standard_Real aMin, aMax;
471     bool isFirst = true;
472     foreach( HYDROGUI_Shape* aShape, aBathShapes )
473     {
474       HYDROGUI_ShapeBathymetry* aBathShape = dynamic_cast<HYDROGUI_ShapeBathymetry*>( aShape );
475       if( !aBathShape || !aBathShape->isVisible() )
476         continue;
477
478       aBathShape->GetRange( aMin, aMax );
479
480       if( isFirst || aMin < aColorScaleMin )
481         aColorScaleMin = aMin;
482       if( isFirst || aMax > aColorScaleMax )
483         aColorScaleMax = aMax;
484
485       isFirst = false;
486     }
487   }
488
489   Handle(AIS_ColorScale) aColorScale = GetColorScale( aViewerId );
490   Handle(AIS_InteractiveContext) aCtx = theViewer->getAISContext();
491   if( isDisplayColorScale )
492   {
493     if( !aColorScale.IsNull() )
494     {
495       // Set color scale title
496       TCollection_ExtendedString aColorScaleTitle = ""; //TODO
497       aColorScale->SetTitle( aColorScaleTitle );
498       
499       // Set color scale range
500       aColorScale->SetRange( aColorScaleMin, aColorScaleMax );
501       
502       aColorScale->SetToUpdate();
503
504       if ( !isLandCoverColoringOn ) {
505         foreach( HYDROGUI_Shape* aShape, aBathShapes ) {
506           HYDROGUI_ShapeBathymetry* aBathShape = dynamic_cast<HYDROGUI_ShapeBathymetry*>( aShape );
507           if( !aBathShape || !aBathShape->isVisible() )
508             continue;
509
510           aBathShape->UpdateWithColorScale( aColorScale );
511         }
512       }
513       
514       if ( !aCtx.IsNull()/* && !aCtx->IsDisplayed( aColorScale ) */) {
515         if ( !aCtx->IsDisplayed( aColorScale ) ) {
516           aCtx->Display( aColorScale, Standard_False );
517         }
518
519         aCtx->Update( aColorScale, true );
520       }
521     }
522   }
523   else
524   {
525     if ( !aCtx.IsNull() && aCtx->IsDisplayed( aColorScale ) ) {
526       aCtx->Erase( aColorScale, true );
527     }
528   }
529
530   foreach( HYDROGUI_Shape* aShape, aLandCoverMapShapes ) {
531     HYDROGUI_ShapeLandCoverMap* aLandCoverMapShape = 
532       dynamic_cast<HYDROGUI_ShapeLandCoverMap*>( aShape );
533
534     if ( !aLandCoverMapShape || !aLandCoverMapShape->isVisible() ) {
535       continue;
536     }
537     
538     Handle(HYDROData_LandCoverMap) aLandCoverMap = 
539       Handle(HYDROData_LandCoverMap)::DownCast( aLandCoverMapShape->getObject() );
540
541     if ( aLandCoverMap.IsNull() ) {
542       continue;
543     }
544     
545     bool isScalarMode = aLandCoverMapShape->isScalarMapModeEnabled();
546     if( isScalarMode != isLandCoverColoringOn )
547     {
548       aLandCoverMapShape->setScalarMapModeEnabled( isLandCoverColoringOn );
549       theViewer->getAISContext()->Redisplay( aLandCoverMapShape->getAISObjects()[0], Standard_False );
550     }
551   }
552   
553   myToUpdateColorScale = false;
554 }
555
556 Handle(AIS_ColorScale) HYDROGUI_OCCDisplayer::GetColorScale( const size_t theViewerId )
557 {
558   Handle(AIS_ColorScale) aColorScale;
559
560   aColorScale = myColorScales.value( theViewerId, aColorScale );
561   if ( aColorScale.IsNull() ) {
562     // Create color scale
563     aColorScale = new AIS_ColorScale();
564
565     // Set properties
566     Standard_Integer anXPos = 50; //TODO
567     Standard_Integer anYPos = 100; //TODO
568     Standard_Integer aWidth = 100; //TODO
569     Standard_Integer aHeight = 350; //TODO
570     
571     Standard_Integer aTextHeight = 14; //TODO
572     Standard_Integer aNbIntervals = 20; //TODO
573
574     aColorScale->SetTransformPersistence( Graphic3d_TMF_2d, gp_Pnt( -1, -1, 0 ) );
575     
576     aColorScale->SetXPosition( anXPos );
577     aColorScale->SetYPosition( anYPos );
578     aColorScale->SetSize( aWidth, aHeight );
579
580     aColorScale->SetTextHeight( aTextHeight );
581     aColorScale->SetNumberOfIntervals( aNbIntervals );
582
583     // Put into the map
584     myColorScales.insert( theViewerId, aColorScale );
585   }
586
587   return aColorScale;
588 }
589
590 void HYDROGUI_OCCDisplayer::UpdatePolylines( size_t theViewerId, int theType, int theSize )
591 {
592   OCCViewer_Viewer* aViewer = module()->getOCCViewer( theViewerId );
593   if( !aViewer )
594     return;
595
596   // Get interactive context
597   Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
598   if( aCtx.IsNull() )
599     return;
600
601   AIS_ListOfInteractive objs;
602   aCtx->DisplayedObjects( objs );
603   AIS_ListOfInteractive::const_iterator it = objs.begin(), last = objs.end();
604   for( ; it!=last; it++ )
605   {
606     Handle(HYDROGUI_Arrow) arr = Handle(HYDROGUI_Arrow)::DownCast( *it );
607     if( !arr.IsNull() )
608     {
609       if( theType>=0 )
610         arr->SetType( (HYDROGUI_Arrow::Type)theType );
611       if( theSize>=0 )
612         arr->SetSize( theSize );
613       aCtx->Redisplay( arr, Standard_False );
614     }
615   }
616   aCtx->UpdateCurrentViewer();
617 }