0030692: Data Exchange - introduce base framework RWMesh for importing mesh data...
[occt.git] / src / ViewerTest / ViewerTest_ViewerCommands.cxx
1 // Created on: 1998-09-01
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <OpenGl_GlCore20.hxx>
18
19 #include <AIS_Animation.hxx>
20 #include <AIS_AnimationCamera.hxx>
21 #include <AIS_AnimationObject.hxx>
22 #include <AIS_CameraFrustum.hxx>
23 #include <AIS_ColorScale.hxx>
24 #include <AIS_Manipulator.hxx>
25 #include <AIS_RubberBand.hxx>
26 #include <AIS_Shape.hxx>
27 #include <AIS_InteractiveObject.hxx>
28 #include <AIS_ListOfInteractive.hxx>
29 #include <AIS_ListIteratorOfListOfInteractive.hxx>
30 #include <Aspect_Grid.hxx>
31 #include <DBRep.hxx>
32 #include <Draw_ProgressIndicator.hxx>
33 #include <Graphic3d_ArrayOfPolylines.hxx>
34 #include <Graphic3d_AspectMarker3d.hxx>
35 #include <Graphic3d_NameOfTextureEnv.hxx>
36 #include <Graphic3d_GraduatedTrihedron.hxx>
37 #include <Graphic3d_TextureEnv.hxx>
38 #include <Graphic3d_TextureParams.hxx>
39 #include <Graphic3d_TypeOfTextureFilter.hxx>
40 #include <Graphic3d_AspectFillArea3d.hxx>
41 #include <ViewerTest.hxx>
42 #include <ViewerTest_AutoUpdater.hxx>
43 #include <ViewerTest_EventManager.hxx>
44 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
45 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
46 #include <ViewerTest_CmdParser.hxx>
47 #include <V3d_AmbientLight.hxx>
48 #include <V3d_DirectionalLight.hxx>
49 #include <V3d_PositionalLight.hxx>
50 #include <V3d_SpotLight.hxx>
51 #include <Message_ProgressSentry.hxx>
52 #include <NCollection_DoubleMap.hxx>
53 #include <NCollection_List.hxx>
54 #include <NCollection_Vector.hxx>
55 #include <AIS_InteractiveContext.hxx>
56 #include <Draw_Interpretor.hxx>
57 #include <Draw.hxx>
58 #include <Draw_Appli.hxx>
59 #include <Image_AlienPixMap.hxx>
60 #include <Image_VideoRecorder.hxx>
61 #include <OpenGl_GraphicDriver.hxx>
62 #include <OSD.hxx>
63 #include <OSD_Timer.hxx>
64 #include <TColStd_HSequenceOfAsciiString.hxx>
65 #include <TColStd_SequenceOfInteger.hxx>
66 #include <TColStd_HSequenceOfReal.hxx>
67 #include <TColgp_Array1OfPnt2d.hxx>
68 #include <TColStd_MapOfAsciiString.hxx>
69 #include <Aspect_TypeOfLine.hxx>
70 #include <Image_Diff.hxx>
71 #include <Aspect_DisplayConnection.hxx>
72 #include <gp_Pnt.hxx>
73 #include <gp_Dir.hxx>
74 #include <gp_Pln.hxx>
75 #include <PrsMgr_PresentableObject.hxx>
76 #include <Graphic3d_ClipPlane.hxx>
77 #include <NCollection_DataMap.hxx>
78 #include <Graphic3d_Texture2Dmanual.hxx>
79 #include <Prs3d_ShadingAspect.hxx>
80 #include <Prs3d_Drawer.hxx>
81 #include <Prs3d_LineAspect.hxx>
82 #include <Prs3d_Root.hxx>
83 #include <Prs3d_Text.hxx>
84 #include <Select3D_SensitivePrimitiveArray.hxx>
85
86 #include <tcl.h>
87
88 #ifdef _WIN32
89 #undef DrawText
90 #endif
91
92 #include <cstdlib>
93
94 #if defined(_WIN32)
95   #include <WNT_WClass.hxx>
96   #include <WNT_Window.hxx>
97 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
98   #include <Cocoa_Window.hxx>
99 #else
100   #include <Xw_Window.hxx>
101   #include <X11/Xlib.h> /* contains some dangerous #defines such as Status, True etc. */
102   #include <X11/Xutil.h>
103   #include <tk.h>
104 #endif
105
106 // Auxiliary definitions
107 static const char THE_KEY_DELETE = 127;
108 static const char THE_KEY_ESCAPE = 27;
109
110 //==============================================================================
111 //  VIEWER GLOBAL VARIABLES
112 //==============================================================================
113
114 Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
115 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
116
117 Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
118 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
119
120 extern int VErase (Draw_Interpretor& theDI,
121                    Standard_Integer  theArgNb,
122                    const char**      theArgVec);
123
124 #if defined(_WIN32)
125 static Handle(WNT_Window)& VT_GetWindow() {
126   static Handle(WNT_Window) WNTWin;
127   return WNTWin;
128 }
129 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
130 static Handle(Cocoa_Window)& VT_GetWindow()
131 {
132   static Handle(Cocoa_Window) aWindow;
133   return aWindow;
134 }
135 extern void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow);
136 extern void SetCocoaWindowTitle (const Handle(Cocoa_Window)& theWindow, Standard_CString theTitle);
137 extern void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight);
138
139 #else
140 static Handle(Xw_Window)& VT_GetWindow(){
141   static Handle(Xw_Window) XWWin;
142   return XWWin;
143 }
144
145 static void VProcessEvents(ClientData,int);
146 #endif
147
148 static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
149 {
150   static Handle(Aspect_DisplayConnection) aDisplayConnection;
151   return aDisplayConnection;
152 }
153
154 static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
155 {
156   GetDisplayConnection() = theDisplayConnection;
157 }
158
159 #if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
160 Aspect_Handle GetWindowHandle(const Handle(Aspect_Window)& theWindow)
161 {
162   Aspect_Handle aWindowHandle = (Aspect_Handle)NULL;
163 #if defined(_WIN32)
164   const Handle (WNT_Window) aWindow = Handle(WNT_Window)::DownCast (theWindow);
165   if (!aWindow.IsNull())
166     return aWindow->HWindow();
167 #elif (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
168   const Handle (Xw_Window) aWindow = Handle(Xw_Window)::DownCast (theWindow);
169   if (!aWindow.IsNull())
170   return aWindow->XWindow();
171 #endif
172   return aWindowHandle;
173 }
174 #endif
175
176 //! Setting additional flag to store 2D mode of the View to avoid scene rotation by mouse/key events
177 class ViewerTest_V3dView : public V3d_View
178 {
179   DEFINE_STANDARD_RTTI_INLINE(ViewerTest_V3dView, V3d_View)
180 public:
181   //! Initializes the view.
182   ViewerTest_V3dView (const Handle(V3d_Viewer)& theViewer, const V3d_TypeOfView theType = V3d_ORTHOGRAPHIC,
183                       bool theIs2dMode = false)
184   : V3d_View (theViewer, theType), myIs2dMode (theIs2dMode) {}
185
186   //! Initializes the view by copying.
187   ViewerTest_V3dView (const Handle(V3d_Viewer)& theViewer, const Handle(V3d_View)& theView)
188   : V3d_View (theViewer, theView), myIs2dMode (false)
189   {
190     if (Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (theView))
191     {
192       myIs2dMode = aV3dView->IsViewIn2DMode();
193     }
194   }
195
196   //! Returns true if 2D mode is set for the view
197   bool IsViewIn2DMode() const { return myIs2dMode; }
198
199   //! Sets 2D mode for the view
200   void SetView2DMode (bool the2dMode) { myIs2dMode = the2dMode; }
201
202 public:
203
204   //! Returns true if active view in 2D mode.
205   static bool IsCurrentViewIn2DMode()
206   {
207     if (Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView()))
208     {
209       return aV3dView->IsViewIn2DMode();
210     }
211     return false;
212   }
213
214   //! Set if active view in 2D mode.
215   static void SetCurrentView2DMode (bool theIs2d)
216   {
217     if (Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView()))
218     {
219       aV3dView->SetView2DMode (theIs2d);
220     }
221   }
222
223 private:
224
225   Standard_Boolean myIs2dMode; //!< 2D mode flag
226
227 };
228
229 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
230 static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>  ViewerTest_myContexts;
231 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
232 static OpenGl_Caps ViewerTest_myDefaultCaps;
233
234 static void OSWindowSetup();
235
236 static struct
237 {
238   Quantity_Color FlatColor;
239   Quantity_Color GradientColor1;
240   Quantity_Color GradientColor2;
241   Aspect_GradientFillMethod FillMethod;
242 } ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
243
244 //==============================================================================
245 //  EVENT GLOBAL VARIABLES
246 //==============================================================================
247
248 static int Start_Rot = 0;
249 Standard_Boolean HasHlrOnBeforeRotation = Standard_False;
250 int X_Motion = 0; // Current cursor position
251 int Y_Motion = 0;
252 int X_ButtonPress = 0; // Last ButtonPress position
253 int Y_ButtonPress = 0;
254 Standard_Boolean IsDragged = Standard_False;
255 Standard_Boolean DragFirst = Standard_False;
256 Standard_Boolean TheIsAnimating = Standard_False;
257 Standard_Boolean Draw_ToExitOnCloseView = Standard_False;
258 Standard_Boolean Draw_ToCloseViewOnEsc  = Standard_False;
259
260 namespace
261 {
262
263   //! Checks if some set is a subset of other set
264   //! @tparam TheSuperSet the type of the superset
265   //! @tparam TheSubSet the type of the subset
266   //! @param theSuperSet the superset
267   //! @param theSubSet the subset to be checked
268   //! @return true if the superset includes subset, or false otherwise
269   template <typename TheSuperSet, typename TheSubSet>
270   static bool includes (const TheSuperSet& theSuperSet, const TheSubSet& theSubSet)
271   {
272     return std::includes (theSuperSet.begin(), theSuperSet.end(), theSubSet.begin(), theSubSet.end());
273   }
274
275   //! A variable set of keys for command-line options.
276   //! It includes a set of mandatory keys and a set of all possible keys.
277   class CommandOptionKeyVariableSet
278   {
279   public:
280     //! Default constructor
281     CommandOptionKeyVariableSet()
282     {
283     }
284
285     //! Constructor
286     //! @param theMandatoryKeySet the set of the mandatory option keys
287     //! @param theAdditionalKeySet the set of additional options that could be omitted
288     CommandOptionKeyVariableSet (
289       const ViewerTest_CommandOptionKeySet& theMandatoryKeySet,
290       const ViewerTest_CommandOptionKeySet& theAdditionalKeySet = ViewerTest_CommandOptionKeySet())
291     : myMandatoryKeySet (theMandatoryKeySet)
292     {
293       std::set_union (theMandatoryKeySet.begin(),
294                       theMandatoryKeySet.end(),
295                       theAdditionalKeySet.begin(),
296                       theAdditionalKeySet.end(),
297                       std::inserter (myFullKeySet, myFullKeySet.begin()));
298     }
299
300     //! Checks if the set of option keys fits to the current variable set (it must contain all mandatory keys
301     //! and be contained in the full key set)
302     //! @param theCheckedKeySet the set of option keys to be checked
303     bool IsInSet (const ViewerTest_CommandOptionKeySet& theCheckedKeySet) const
304     {
305       return includes (theCheckedKeySet, myMandatoryKeySet) && includes (myFullKeySet, theCheckedKeySet);
306     }
307
308   private:
309     //! A set of mandatory command-line option keys
310     ViewerTest_CommandOptionKeySet myMandatoryKeySet;
311
312     //! A full set of command-line option keys (includes mandatory and additional option keys)
313     ViewerTest_CommandOptionKeySet myFullKeySet;
314   };
315
316   //! Gets some code by its name
317   //! @tparam TheCode the type of a code to be found
318   //! @param theCodeNameMap the map from code names to codes
319   //! @param theCodeName the name of a code to be found
320   //! @param theCode the code to be found
321   //! @return true if a code is found, or false otherwise
322   template <typename TheCode>
323   static bool getSomeCodeByName (const std::map<TCollection_AsciiString, TheCode>& theCodeNameMap,
324                                  TCollection_AsciiString                           theCodeName,
325                                  TheCode&                                          theCode)
326   {
327     theCodeName.LowerCase();
328     const typename std::map<TCollection_AsciiString, TheCode>::const_iterator aCodeIterator = theCodeNameMap.find (
329       theCodeName);
330     if (aCodeIterator == theCodeNameMap.end())
331     {
332       return false;
333     }
334     theCode = aCodeIterator->second;
335     return true;
336   }
337
338   // Defines possible commands related to background changing
339   enum BackgroundCommand
340   {
341     BackgroundCommand_Main,         //!< The main command that manages other commands through options
342     BackgroundCommand_Image,        //!< Sets an image as a background
343     BackgroundCommand_ImageMode,    //!< Changes a background image mode
344     BackgroundCommand_Gradient,     //!< Sets a gradient as a background
345     BackgroundCommand_GradientMode, //!< Changes a background gradient mode
346     BackgroundCommand_Color,        //!< Fills background with a specified color
347     BackgroundCommand_Default       //!< Sets the background default color or gradient
348   };
349
350   //! Map from background command names to its codes
351   typedef std::map<TCollection_AsciiString, BackgroundCommand> BackgroundCommandNameMap;
352
353   //! Creates a map from background command names to its codes
354   //! @return a map from background command names to its codes
355   static BackgroundCommandNameMap createBackgroundCommandNameMap()
356   {
357     BackgroundCommandNameMap aBackgroundCommandNameMap;
358     aBackgroundCommandNameMap["vbackground"]    = BackgroundCommand_Main;
359     aBackgroundCommandNameMap["vsetbg"]         = BackgroundCommand_Image;
360     aBackgroundCommandNameMap["vsetbgmode"]     = BackgroundCommand_ImageMode;
361     aBackgroundCommandNameMap["vsetgradientbg"] = BackgroundCommand_Gradient;
362     aBackgroundCommandNameMap["vsetgrbgmode"]   = BackgroundCommand_GradientMode;
363     aBackgroundCommandNameMap["vsetcolorbg"]    = BackgroundCommand_Color;
364     aBackgroundCommandNameMap["vsetdefaultbg"]  = BackgroundCommand_Default;
365     return aBackgroundCommandNameMap;
366   }
367
368   //! Gets a background command by its name
369   //! @param theBackgroundCommandName the name of the background command
370   //! @param theBackgroundCommand the background command to be found
371   //! @return true if a background command is found, or false otherwise
372   static bool getBackgroundCommandByName (const TCollection_AsciiString& theBackgroundCommandName,
373                                           BackgroundCommand&             theBackgroundCommand)
374   {
375     static const BackgroundCommandNameMap THE_BACKGROUND_COMMAND_NAME_MAP = createBackgroundCommandNameMap();
376     return getSomeCodeByName (THE_BACKGROUND_COMMAND_NAME_MAP, theBackgroundCommandName, theBackgroundCommand);
377   }
378
379   //! Map from background image fill method names to its codes
380   typedef std::map<TCollection_AsciiString, Aspect_FillMethod> BackgroundImageFillMethodNameMap;
381
382   //! Creates a map from background image fill method names to its codes
383   //! @return a map from background image fill method names to its codes
384   static BackgroundImageFillMethodNameMap createBackgroundImageFillMethodNameMap()
385   {
386     BackgroundImageFillMethodNameMap aBackgroundImageFillMethodNameMap;
387     aBackgroundImageFillMethodNameMap["none"]     = Aspect_FM_NONE;
388     aBackgroundImageFillMethodNameMap["centered"] = Aspect_FM_CENTERED;
389     aBackgroundImageFillMethodNameMap["tiled"]    = Aspect_FM_TILED;
390     aBackgroundImageFillMethodNameMap["stretch"]  = Aspect_FM_STRETCH;
391     return aBackgroundImageFillMethodNameMap;
392   }
393
394   //! Gets a background image fill method by its name
395   //! @param theBackgroundImageFillMethodName the name of the background image fill method
396   //! @param theBackgroundImageFillMethod the background image fill method to be found
397   //! @return true if a background image fill method is found, or false otherwise
398   static bool getBackgroundImageFillMethodByName (const TCollection_AsciiString& theBackgroundImageFillMethodName,
399                                                   Aspect_FillMethod&             theBackgroundImageFillMethod)
400   {
401     static const BackgroundImageFillMethodNameMap THE_BACKGROUND_IMAGE_FILL_METHOD_NAME_MAP =
402       createBackgroundImageFillMethodNameMap();
403     return getSomeCodeByName (THE_BACKGROUND_IMAGE_FILL_METHOD_NAME_MAP,
404                               theBackgroundImageFillMethodName,
405                               theBackgroundImageFillMethod);
406   }
407
408   //! Map from background gradient fill method names to its codes
409   typedef std::map<TCollection_AsciiString, Aspect_GradientFillMethod> BackgroundGradientFillMethodNameMap;
410
411   //! Creates a map from background gradient fill method names to its codes
412   //! @return a map from background gradient fill method names to its codes
413   static BackgroundGradientFillMethodNameMap createBackgroundGradientFillMethodNameMap()
414   {
415     BackgroundGradientFillMethodNameMap aBackgroundGradientFillMethodNameMap;
416     aBackgroundGradientFillMethodNameMap["none"]       = Aspect_GFM_NONE;
417     aBackgroundGradientFillMethodNameMap["hor"]        = Aspect_GFM_HOR;
418     aBackgroundGradientFillMethodNameMap["horizontal"] = Aspect_GFM_HOR;
419     aBackgroundGradientFillMethodNameMap["ver"]        = Aspect_GFM_VER;
420     aBackgroundGradientFillMethodNameMap["vertical"]   = Aspect_GFM_VER;
421     aBackgroundGradientFillMethodNameMap["diag1"]      = Aspect_GFM_DIAG1;
422     aBackgroundGradientFillMethodNameMap["diagonal1"]  = Aspect_GFM_DIAG1;
423     aBackgroundGradientFillMethodNameMap["diag2"]      = Aspect_GFM_DIAG2;
424     aBackgroundGradientFillMethodNameMap["diagonal2"]  = Aspect_GFM_DIAG2;
425     aBackgroundGradientFillMethodNameMap["corner1"]    = Aspect_GFM_CORNER1;
426     aBackgroundGradientFillMethodNameMap["corner2"]    = Aspect_GFM_CORNER2;
427     aBackgroundGradientFillMethodNameMap["corner3"]    = Aspect_GFM_CORNER3;
428     aBackgroundGradientFillMethodNameMap["corner4"]    = Aspect_GFM_CORNER4;
429     return aBackgroundGradientFillMethodNameMap;
430   }
431
432   //! Gets a gradient fill method by its name
433   //! @param theBackgroundGradientFillMethodName the name of the gradient fill method
434   //! @param theBackgroundGradientFillMethod the gradient fill method to be found
435   //! @return true if a gradient fill method is found, or false otherwise
436   static bool getBackgroundGradientFillMethodByName (const TCollection_AsciiString& theBackgroundGradientFillMethodName,
437                                                      Aspect_GradientFillMethod&     theBackgroundGradientFillMethod)
438   {
439     static const BackgroundGradientFillMethodNameMap THE_BACKGROUND_GRADIENT_FILL_METHOD_NAME_MAP =
440       createBackgroundGradientFillMethodNameMap();
441     return getSomeCodeByName (THE_BACKGROUND_GRADIENT_FILL_METHOD_NAME_MAP,
442                               theBackgroundGradientFillMethodName,
443                               theBackgroundGradientFillMethod);
444   }
445
446   //! Changes the background in accordance with passed command line options
447   class BackgroundChanger
448   {
449   public:
450     //! Constructor. Prepares the command parser
451     BackgroundChanger()
452     {
453       prepareCommandParser();
454     }
455
456     //! Processes the command line and changes the background
457     //! @param theDrawInterpretor the interpreter of the Draw Harness application
458     //! @param theNumberOfCommandLineArguments the number of passed command line arguments
459     //! @param theCommandLineArguments the array of command line arguments
460     bool ProcessCommandLine (Draw_Interpretor&        theDrawInterpretor,
461                              const Standard_Integer   theNumberOfCommandLineArguments,
462                              const char* const* const theCommandLineArguments)
463     {
464       const char* const aBackgroundCommandName = theCommandLineArguments[0];
465       BackgroundCommand aBackgroundCommand = BackgroundCommand_Main;
466       if (!getBackgroundCommandByName (aBackgroundCommandName, aBackgroundCommand))
467       {
468         return false;
469       }
470       addCommandDescription (aBackgroundCommand);
471       myCommandParser.Parse (theNumberOfCommandLineArguments, theCommandLineArguments);
472       return processCommandOptions (aBackgroundCommandName, aBackgroundCommand, theDrawInterpretor);
473     }
474
475   private:
476     //! The type of functions that are able to set gradient background filling
477     typedef void SetGradientFunction (const Quantity_Color& /* theColor1 */,
478                                       const Quantity_Color& /* theColor2 */,
479                                       const Aspect_GradientFillMethod /* theGradientMode */);
480
481     //! The type of functions that are able to fill a background with a specific color
482     typedef void SetColorFunction (const Quantity_Color& /* theColor */);
483
484     //! the command parser used to parse command line options and its arguments
485     ViewerTest_CmdParser myCommandParser;
486
487     //! the option key for the command that sets an image as a background
488     ViewerTest_CommandOptionKey myImageOptionKey;
489
490     //! the option key for the command that sets a background image fill type
491     ViewerTest_CommandOptionKey myImageModeOptionKey;
492
493     //! the option key for the command that sets a gradient filling for the background
494     ViewerTest_CommandOptionKey myGradientOptionKey;
495
496     //! the option key for the command that sets a background gradient filling method
497     ViewerTest_CommandOptionKey myGradientModeOptionKey;
498
499     //! the option key for the command that fills background with a specific color
500     ViewerTest_CommandOptionKey myColorOptionKey;
501
502     //! the option key for the command that sets default background gradient or color
503     ViewerTest_CommandOptionKey myDefaultOptionKey;
504
505     //! the variable set of options that are allowed for the old scenario (without any option passed)
506     CommandOptionKeyVariableSet myUnnamedOptionVariableSet;
507
508     //! the variable set of options that are allowed for setting an image as a background
509     CommandOptionKeyVariableSet myImageOptionVariableSet;
510
511     //! the variable set of options that are allowed for setting a background image fill type
512     CommandOptionKeyVariableSet myImageModeOptionVariableSet;
513
514     //! the variable set of options that are allowed for setting a gradient filling for the background
515     CommandOptionKeyVariableSet myGradientOptionVariableSet;
516
517     //! the variable set of options that are allowed for setting a background gradient filling method
518     CommandOptionKeyVariableSet myGradientModeOptionVariableSet;
519
520     //! the variable set of options that are allowed for filling a background with a specific color
521     CommandOptionKeyVariableSet myColorOptionVariableSet;
522
523     //! the variable set of options that are allowed for setting a default background gradient
524     CommandOptionKeyVariableSet myDefaultGradientOptionVariableSet;
525
526     //! the variable set of options that are allowed for setting a default background color
527     CommandOptionKeyVariableSet myDefaultColorOptionVariableSet;
528
529     //! the variable set of options that are allowed for printing help
530     CommandOptionKeyVariableSet myHelpOptionVariableSet;
531
532     //! Adds options to command parser
533     void addOptionsToCommandParser()
534     {
535       myImageOptionKey     = myCommandParser.AddOption ("imageFile|image|imgFile|img",
536                                                     "filename of image used as background");
537       myImageModeOptionKey = myCommandParser.AddOption (
538         "imageMode|imgMode", "image fill type, should be one of CENTERED, TILED, STRETCH, NONE");
539       myGradientOptionKey = myCommandParser.AddOption ("gradient|grad|gr",
540                                                        "sets background gradient starting and ending colors");
541       myGradientModeOptionKey =
542         myCommandParser.AddOption ("gradientMode|gradMode|gradMd|grMode|grMd",
543                                    "gradient fill method, should be one of NONE, HOR[IZONTAL], VER[TICAL], "
544                                    "DIAG[ONAL]1, DIAG[ONAL]2, CORNER1, CORNER2, CORNER3, CORNER4");
545       myColorOptionKey   = myCommandParser.AddOption ("color|col", "background color");
546       myDefaultOptionKey = myCommandParser.AddOption ("default|def", "sets background default gradient or color");
547     }
548
549     //! Creates option sets used to determine if a passed option set is valid or not
550     void createOptionSets()
551     {
552       ViewerTest_CommandOptionKeySet anUnnamedOptionSet;
553       anUnnamedOptionSet.insert (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
554       myUnnamedOptionVariableSet = CommandOptionKeyVariableSet (anUnnamedOptionSet);
555
556       ViewerTest_CommandOptionKeySet anImageOptionSet;
557       anImageOptionSet.insert (myImageOptionKey);
558       ViewerTest_CommandOptionKeySet anImageModeOptionSet;
559       anImageModeOptionSet.insert (myImageModeOptionKey);
560       myImageOptionVariableSet     = CommandOptionKeyVariableSet (anImageOptionSet, anImageModeOptionSet);
561       myImageModeOptionVariableSet = CommandOptionKeyVariableSet (anImageModeOptionSet);
562
563       ViewerTest_CommandOptionKeySet aGradientOptionSet;
564       aGradientOptionSet.insert (myGradientOptionKey);
565       ViewerTest_CommandOptionKeySet aGradientModeOptionSet;
566       aGradientModeOptionSet.insert (myGradientModeOptionKey);
567       myGradientOptionVariableSet     = CommandOptionKeyVariableSet (aGradientOptionSet, aGradientModeOptionSet);
568       myGradientModeOptionVariableSet = CommandOptionKeyVariableSet (aGradientModeOptionSet);
569
570       ViewerTest_CommandOptionKeySet aColorOptionSet;
571       aColorOptionSet.insert (myColorOptionKey);
572       myColorOptionVariableSet = CommandOptionKeyVariableSet (aColorOptionSet);
573
574       aGradientOptionSet.insert (myDefaultOptionKey);
575       myDefaultGradientOptionVariableSet = CommandOptionKeyVariableSet (aGradientOptionSet, aGradientModeOptionSet);
576       aColorOptionSet.insert (myDefaultOptionKey);
577       myDefaultColorOptionVariableSet = CommandOptionKeyVariableSet (aColorOptionSet);
578
579       ViewerTest_CommandOptionKeySet aHelpOptionSet;
580       aHelpOptionSet.insert (ViewerTest_CmdParser::THE_HELP_COMMAND_OPTION_KEY);
581       myHelpOptionVariableSet = CommandOptionKeyVariableSet (aHelpOptionSet);
582     }
583
584     //! Prepares the command parser. Adds options and creates option sets used to determine
585     //! if a passed option set is valid or not
586     void prepareCommandParser()
587     {
588       addOptionsToCommandParser();
589       createOptionSets();
590     }
591
592     //! Adds a command description to the command parser
593     //! @param theBackgroundCommand the key of the command which description is added to the command parser
594     void addCommandDescription (const BackgroundCommand theBackgroundCommand)
595     {
596       std::string aDescription;
597       bool        isMainCommand = false;
598       switch (theBackgroundCommand)
599       {
600         case BackgroundCommand_Main:
601           aDescription  = "Command: vbackground (changes background or some background settings)";
602           isMainCommand = true;
603           break;
604         case BackgroundCommand_Image:
605           aDescription = "Command: vsetbg (loads image as a background)";
606           break;
607         case BackgroundCommand_ImageMode:
608           aDescription = "Command: vsetbgmode (changes background fill type)";
609           break;
610         case BackgroundCommand_Gradient:
611           aDescription = "Command: vsetgradientbg (mounts gradient background)";
612           break;
613         case BackgroundCommand_GradientMode:
614           aDescription = "Command: vsetgradientbgmode (changes gradient background fill method)";
615           break;
616         case BackgroundCommand_Color:
617           aDescription = "Command: vsetcolorbg (sets color background)";
618           break;
619         case BackgroundCommand_Default:
620           aDescription = "Command: vsetdefaultbg (sets default viewer background gradient or fill color)";
621           break;
622         default:
623           return;
624       }
625       if (!isMainCommand)
626       {
627         aDescription += "\nThis command is obsolete. Use vbackground instead.";
628       }
629       myCommandParser.SetDescription (aDescription);
630     }
631
632     //! Check if a viewer is needed to be initialized
633     //! @param theBackgroundCommand the key of the command that changes the background
634     //! @return true if processing was successful, or false otherwise
635     bool checkViewerIsNeeded (const BackgroundCommand theBackgroundCommand) const
636     {
637       const bool                           isMain             = (theBackgroundCommand == BackgroundCommand_Main);
638       const ViewerTest_CommandOptionKeySet aUsedOptions       = myCommandParser.GetUsedOptions();
639       const bool                           aViewerIsNotNeeded =
640         (theBackgroundCommand == BackgroundCommand_Default)
641         || (myDefaultGradientOptionVariableSet.IsInSet (aUsedOptions) && isMain)
642         || (myDefaultColorOptionVariableSet.IsInSet (aUsedOptions) && isMain)
643         || myHelpOptionVariableSet.IsInSet (aUsedOptions);
644       return !aViewerIsNotNeeded;
645     }
646
647     //! Check if a viewer is initialized
648     //! @param theBackgroundCommandName the name of the command that changes the background
649     //! @param theDrawInterpretor the interpreter of the Draw Harness application
650     //! @return true if a viewer is initialized, or false otherwise
651     static bool checkViewerIsInitialized (const char* const theBackgroundCommandName,
652                                           Draw_Interpretor& theDrawInterpretor)
653     {
654       const Handle (AIS_InteractiveContext)& anAISContext = ViewerTest::GetAISContext();
655       if (anAISContext.IsNull())
656       {
657         theDrawInterpretor << "Use 'vinit' command before executing '" << theBackgroundCommandName << "' command.\n";
658         return false;
659       }
660       return true;
661     }
662
663     //! Processes command options
664     //! @param theBackgroundCommandName the name of the command that changes the background
665     //! @param theBackgroundCommand the key of the command that changes the background
666     //! @param theDrawInterpretor the interpreter of the Draw Harness application
667     //! @return true if processing was successful, or false otherwise
668     bool processCommandOptions (const char* const       theBackgroundCommandName,
669                                 const BackgroundCommand theBackgroundCommand,
670                                 Draw_Interpretor&       theDrawInterpretor) const
671     {
672       if (myCommandParser.HasNoOption())
673       {
674         return printHelp (theBackgroundCommandName, theDrawInterpretor);
675       }
676       if (checkViewerIsNeeded (theBackgroundCommand)
677           && !checkViewerIsInitialized (theBackgroundCommandName, theDrawInterpretor))
678       {
679         return false;
680       }
681       if (myCommandParser.HasOnlyUnnamedOption())
682       {
683         return processUnnamedOption (theBackgroundCommand);
684       }
685       return processNamedOptions (theBackgroundCommandName, theBackgroundCommand, theDrawInterpretor);
686     }
687
688     //! Processes the unnamed option
689     //! @param theBackgroundCommand the key of the command that changes the background
690     //! @return true if processing was successful, or false otherwise
691     bool processUnnamedOption (const BackgroundCommand theBackgroundCommand) const
692     {
693       switch (theBackgroundCommand)
694       {
695         case BackgroundCommand_Main:
696           return false;
697         case BackgroundCommand_Image:
698           return processImageUnnamedOption();
699         case BackgroundCommand_ImageMode:
700           return processImageModeUnnamedOption();
701         case BackgroundCommand_Gradient:
702           return processGradientUnnamedOption();
703         case BackgroundCommand_GradientMode:
704           return processGradientModeUnnamedOption();
705         case BackgroundCommand_Color:
706           return processColorUnnamedOption();
707         case BackgroundCommand_Default:
708           return processDefaultUnnamedOption();
709         default:
710           return false;
711       }
712     }
713
714     //! Processes the image unnamed option
715     //! @return true if processing was successful, or false otherwise
716     bool processImageUnnamedOption() const
717     {
718       const std::size_t aNumberOfImageUnnamedOptionArguments = myCommandParser.GetNumberOfOptionArguments (
719         ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
720       if ((aNumberOfImageUnnamedOptionArguments != 1) && (aNumberOfImageUnnamedOptionArguments != 2))
721       {
722         return false;
723       }
724       std::string anImageFileName;
725       if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 0, anImageFileName))
726       {
727         return false;
728       }
729       Aspect_FillMethod anImageMode = Aspect_FM_CENTERED;
730       if (aNumberOfImageUnnamedOptionArguments == 2)
731       {
732         std::string anImageModeString;
733         if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 1, anImageModeString))
734         {
735           return false;
736         }
737         if (!getBackgroundImageFillMethodByName (anImageModeString.c_str(), anImageMode))
738         {
739           return false;
740         }
741       }
742       setImage (anImageFileName.c_str(), anImageMode);
743       return true;
744     }
745
746     //! Processes the image mode unnamed option
747     //! @return true if processing was successful, or false otherwise
748     bool processImageModeUnnamedOption() const
749     {
750       return processImageModeOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
751     }
752
753     //! Processes the gradient unnamed option
754     //! @param theSetGradient the function used to set a background gradient filling
755     //! @return true if processing was successful, or false otherwise
756     bool processGradientUnnamedOption (SetGradientFunction* const theSetGradient = setGradient) const
757     {
758       const Standard_Integer aNumberOfGradientUnnamedOptionArguments = myCommandParser.GetNumberOfOptionArguments (
759         ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
760       if (aNumberOfGradientUnnamedOptionArguments < 2)
761       {
762         return false;
763       }
764
765       Standard_Integer anArgumentIndex = 0;
766       Quantity_Color   aColor1;
767       if (!myCommandParser.ArgColor (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, anArgumentIndex, aColor1))
768       {
769         return false;
770       }
771       if (anArgumentIndex >= aNumberOfGradientUnnamedOptionArguments)
772       {
773         return false;
774       }
775
776       Quantity_Color aColor2;
777       if (!myCommandParser.ArgColor (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, anArgumentIndex, aColor2))
778       {
779         return false;
780       }
781       if (anArgumentIndex > aNumberOfGradientUnnamedOptionArguments)
782       {
783         return false;
784       }
785
786       Aspect_GradientFillMethod aGradientMode = Aspect_GFM_HOR;
787       if (anArgumentIndex == aNumberOfGradientUnnamedOptionArguments - 1)
788       {
789         std::string anGradientModeString;
790
791         if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY,
792                                   anArgumentIndex,
793                                   anGradientModeString))
794         {
795           return false;
796         }
797         if (!getBackgroundGradientFillMethodByName (anGradientModeString.c_str(), aGradientMode))
798         {
799           return false;
800         }
801         ++anArgumentIndex;
802       }
803       if (anArgumentIndex != aNumberOfGradientUnnamedOptionArguments)
804       {
805         return false;
806       }
807       theSetGradient (aColor1, aColor2, aGradientMode);
808       return true;
809     }
810
811     //! Processes the gradient mode unnamed option
812     //! @return true if processing was successful, or false otherwise
813     bool processGradientModeUnnamedOption() const
814     {
815       return processGradientModeOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
816     }
817
818     //! Processes the color unnamed option
819     //! @param theSetColor the function used to set a background color
820     //! @return true if processing was successful, or false otherwise
821     bool processColorUnnamedOption (SetColorFunction* const theSetColor = setColor) const
822     {
823       return processColorOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, theSetColor);
824     }
825
826     //! Processes the default back unnamed option
827     //! @return true if processing was successful, or false otherwise
828     bool processDefaultUnnamedOption() const
829     {
830       if (processGradientUnnamedOption (setDefaultGradient))
831       {
832         return true;
833       }
834       return processColorUnnamedOption (setDefaultColor);
835     }
836
837     //! Processes named options
838     //! @param theBackgroundCommandName the name of the command that changes the background
839     //! @param theBackgroundCommand the key of the command that changes the background
840     //! @param theDrawInterpretor the interpreter of the Draw Harness application
841     //! @return true if processing was successful, or false otherwise
842     bool processNamedOptions (const char* const       theBackgroundCommandName,
843                               const BackgroundCommand theBackgroundCommand,
844                               Draw_Interpretor&       theDrawInterpretor) const
845     {
846       const bool                           isMain       = (theBackgroundCommand == BackgroundCommand_Main);
847       const ViewerTest_CommandOptionKeySet aUsedOptions = myCommandParser.GetUsedOptions();
848       if (myImageOptionVariableSet.IsInSet (aUsedOptions)
849           && (isMain || (theBackgroundCommand == BackgroundCommand_Image)))
850       {
851         return processImageOptionSet();
852       }
853       if (myImageModeOptionVariableSet.IsInSet (aUsedOptions)
854           && (isMain || (theBackgroundCommand == BackgroundCommand_ImageMode)))
855       {
856         return processImageModeOptionSet();
857       }
858       if (myGradientOptionVariableSet.IsInSet (aUsedOptions)
859           && (isMain || (theBackgroundCommand == BackgroundCommand_Gradient)))
860       {
861         return processGradientOptionSet();
862       }
863       if (myGradientModeOptionVariableSet.IsInSet (aUsedOptions)
864           && (isMain || (theBackgroundCommand == BackgroundCommand_GradientMode)))
865       {
866         return processGradientModeOptionSet();
867       }
868       if (myColorOptionVariableSet.IsInSet (aUsedOptions)
869           && (isMain || (theBackgroundCommand == BackgroundCommand_Color)))
870       {
871         return processColorOptionSet();
872       }
873       if ((myDefaultGradientOptionVariableSet.IsInSet (aUsedOptions) && isMain)
874           || (myGradientOptionVariableSet.IsInSet (aUsedOptions)
875               && (theBackgroundCommand == BackgroundCommand_Default)))
876       {
877         return processDefaultGradientOptionSet();
878       }
879       if ((myDefaultColorOptionVariableSet.IsInSet (aUsedOptions) && isMain)
880           || (myColorOptionVariableSet.IsInSet (aUsedOptions) && (theBackgroundCommand == BackgroundCommand_Default)))
881       {
882         return processDefaultColorOptionSet();
883       }
884       if (myHelpOptionVariableSet.IsInSet (aUsedOptions))
885       {
886         return processHelpOptionSet (theBackgroundCommandName, theDrawInterpretor);
887       }
888       return false;
889     }
890
891     //! Processes the image option set
892     //! @return true if processing was successful, or false otherwise
893     bool processImageOptionSet() const
894     {
895       std::string anImageFileName;
896       if (!processImageOption (anImageFileName))
897       {
898         return false;
899       }
900       Aspect_FillMethod anImageMode = Aspect_FM_CENTERED;
901       if (myCommandParser.HasOption (myImageModeOptionKey) && !processImageModeOption (anImageMode))
902       {
903         return false;
904       }
905       setImage (anImageFileName.c_str(), anImageMode);
906       return true;
907     }
908
909     //! Processes the image mode option set
910     //! @return true if processing was successful, or false otherwise
911     bool processImageModeOptionSet() const
912     {
913       return processImageModeOptionSet (myImageModeOptionKey);
914     }
915
916     //! Processes the image mode option set
917     //! @param theImageModeOptionKey the key of the option that is interpreted as an image mode option
918     //! @return true if processing was successful, or false otherwise
919     bool processImageModeOptionSet (const ViewerTest_CommandOptionKey theImageModeOptionKey) const
920     {
921       Aspect_FillMethod anImageMode = Aspect_FM_NONE;
922       if (!processImageModeOption (theImageModeOptionKey, anImageMode))
923       {
924         return false;
925       }
926       setImageMode (anImageMode);
927       return true;
928     }
929
930     //! Processes the gradient option set
931     //! @param theSetGradient the function used to set a background gradient filling
932     //! @return true if processing was successful, or false otherwise
933     bool processGradientOptionSet (SetGradientFunction* const theSetGradient = setGradient) const
934     {
935       Quantity_Color aColor1;
936       Quantity_Color aColor2;
937       if (!processGradientOption (aColor1, aColor2))
938       {
939         return false;
940       }
941       Aspect_GradientFillMethod aGradientMode = Aspect_GFM_HOR;
942       if (myCommandParser.HasOption (myGradientModeOptionKey) && !processGradientModeOption (aGradientMode))
943       {
944         return false;
945       }
946       theSetGradient (aColor1, aColor2, aGradientMode);
947       return true;
948     }
949
950     //! Processes the gradient mode option set
951     //! @return true if processing was successful, or false otherwise
952     bool processGradientModeOptionSet() const
953     {
954       return processGradientModeOptionSet (myGradientModeOptionKey);
955     }
956
957     //! Processes the gradient mode option set
958     //! @param theGradientModeOptionKey the key of the option that is interpreted as a gradient mode option
959     //! @return true if processing was successful, or false otherwise
960     bool processGradientModeOptionSet (const ViewerTest_CommandOptionKey theGradientModeOptionKey) const
961     {
962       Aspect_GradientFillMethod aGradientMode = Aspect_GFM_NONE;
963       if (!processGradientModeOption (theGradientModeOptionKey, aGradientMode))
964       {
965         return false;
966       }
967       setGradientMode (aGradientMode);
968       return true;
969     }
970
971     //! Processes the color option set
972     //! @param theSetColor the function used to set a background color
973     //! @return true if processing was successful, or false otherwise
974     bool processColorOptionSet (SetColorFunction* const theSetColor = setColor) const
975     {
976       return processColorOptionSet (myColorOptionKey, theSetColor);
977     }
978
979     //! Processes the default color option set
980     //! @return true if processing was successful, or false otherwise
981     bool processDefaultGradientOptionSet() const
982     {
983       return processGradientOptionSet (setDefaultGradient);
984     }
985
986     //! Processes the default gradient option set
987     //! @return true if processing was successful, or false otherwise
988     bool processDefaultColorOptionSet() const
989     {
990       return processColorOptionSet (setDefaultColor);
991     }
992
993     //! Processes the color option set
994     //! @param theColorOptionKey the key of the option that is interpreted as a color option
995     //! @param theSetColor the function used to set a background color
996     //! @return true if processing was successful, or false otherwise
997     bool processColorOptionSet (const ViewerTest_CommandOptionKey theColorOptionKey,
998                                 SetColorFunction* const           theSetColor = setColor) const
999     {
1000       Quantity_Color aColor;
1001       if (!processColorOption (theColorOptionKey, aColor))
1002       {
1003         return false;
1004       }
1005       theSetColor (aColor);
1006       return true;
1007     }
1008
1009     //! Processes the help option set
1010     //! @param theBackgroundCommandName the name of the command that changes the background
1011     //! @param theDrawInterpretor the interpreter of the Draw Harness application
1012     //! @return true if processing was successful, or false otherwise
1013     bool processHelpOptionSet (const char* const theBackgroundCommandName, Draw_Interpretor& theDrawInterpretor) const
1014     {
1015       const Standard_Integer aNumberOfHelpOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1016         ViewerTest_CmdParser::THE_HELP_COMMAND_OPTION_KEY);
1017       if (aNumberOfHelpOptionArguments != 0)
1018       {
1019         return false;
1020       }
1021       return printHelp (theBackgroundCommandName, theDrawInterpretor);
1022     }
1023
1024     //! Processes the image option
1025     //! @param theImageFileName the filename of the image to be used as a background
1026     //! @return true if processing was successful, or false otherwise
1027     bool processImageOption (std::string& theImageFileName) const
1028     {
1029       const Standard_Integer aNumberOfImageOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1030         myImageOptionKey);
1031       if (aNumberOfImageOptionArguments != 1)
1032       {
1033         return false;
1034       }
1035       std::string anImageFileName;
1036       if (!myCommandParser.Arg (myImageOptionKey, 0, anImageFileName))
1037       {
1038         return false;
1039       }
1040       theImageFileName = anImageFileName;
1041       return true;
1042     }
1043
1044     //! Processes the image mode option
1045     //! @param theImageMode the fill type used for a background image
1046     //! @return true if processing was successful, or false otherwise
1047     bool processImageModeOption (Aspect_FillMethod& theImageMode) const
1048     {
1049       return processImageModeOption (myImageModeOptionKey, theImageMode);
1050     }
1051
1052     //! Processes the image mode option
1053     //! @param theImageModeOptionKey the key of the option that is interpreted as an image mode option
1054     //! @param theImageMode the fill type used for a background image
1055     //! @return true if processing was successful, or false otherwise
1056     bool processImageModeOption (const ViewerTest_CommandOptionKey theImageModeOptionKey,
1057                                  Aspect_FillMethod&                theImageMode) const
1058     {
1059       return processModeOption (theImageModeOptionKey, getBackgroundImageFillMethodByName, theImageMode);
1060     }
1061
1062     //! Processes the gradient option
1063     //! @param theColor1 the gradient starting color
1064     //! @param theColor2 the gradient ending color
1065     //! @return true if processing was successful, or false otherwise
1066     bool processGradientOption (Quantity_Color& theColor1, Quantity_Color& theColor2) const
1067     {
1068       Standard_Integer anArgumentIndex = 0;
1069       Quantity_Color   aColor1;
1070       if (!myCommandParser.ArgColor (myGradientOptionKey, anArgumentIndex, aColor1))
1071       {
1072         return false;
1073       }
1074       Quantity_Color aColor2;
1075       if (!myCommandParser.ArgColor (myGradientOptionKey, anArgumentIndex, aColor2))
1076       {
1077         return false;
1078       }
1079       const Standard_Integer aNumberOfGradientOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1080         myGradientOptionKey);
1081       if (anArgumentIndex != aNumberOfGradientOptionArguments)
1082       {
1083         return false;
1084       }
1085       theColor1 = aColor1;
1086       theColor2 = aColor2;
1087       return true;
1088     }
1089
1090     //! Processes the gradient mode option
1091     //! @param theGradientMode the fill method used for a background gradient filling
1092     //! @return true if processing was successful, or false otherwise
1093     bool processGradientModeOption (Aspect_GradientFillMethod& theGradientMode) const
1094     {
1095       return processGradientModeOption (myGradientModeOptionKey, theGradientMode);
1096     }
1097
1098     //! Processes the gradient mode option
1099     //! @param theGradientModeOptionKey the key of the option that is interpreted as a gradient mode option
1100     //! @param theGradientMode the fill method used for a background gradient filling
1101     //! @return true if processing was successful, or false otherwise
1102     bool processGradientModeOption (const ViewerTest_CommandOptionKey theGradientModeOptionKey,
1103                                     Aspect_GradientFillMethod&        theGradientMode) const
1104     {
1105       return processModeOption (theGradientModeOptionKey, getBackgroundGradientFillMethodByName, theGradientMode);
1106     }
1107
1108     //! Processes some mode option
1109     //! @tparam TheMode the type of a mode to be processed
1110     //! @param theModeOptionKey the key of the option that is interpreted as a mode option
1111     //! @param theMode a mode to be processed
1112     //! @return true if processing was successful, or false otherwise
1113     template <typename TheMode>
1114     bool processModeOption (const ViewerTest_CommandOptionKey theModeOptionKey,
1115                             bool (*const theGetModeByName) (const TCollection_AsciiString& /* theModeName */,
1116                                                             TheMode& /* theMode */),
1117                             TheMode& theMode) const
1118     {
1119       const Standard_Integer aNumberOfModeOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1120         theModeOptionKey);
1121       if (aNumberOfModeOptionArguments != 1)
1122       {
1123         return false;
1124       }
1125       std::string aModeString;
1126       if (!myCommandParser.Arg (theModeOptionKey, 0, aModeString))
1127       {
1128         return false;
1129       }
1130       TheMode aMode = TheMode();
1131       if (!theGetModeByName (aModeString.c_str(), aMode))
1132       {
1133         return false;
1134       }
1135       theMode = aMode;
1136       return true;
1137     }
1138
1139     //! Processes the color option
1140     //! @param theColor a color used for filling a background
1141     //! @return true if processing was successful, or false otherwise
1142     bool processColorOption (Quantity_Color& theColor) const
1143     {
1144       return processColorOption (myColorOptionKey, theColor);
1145     }
1146
1147     //! Processes the color option
1148     //! @param theColorOptionKey the key of the option that is interpreted as a color option
1149     //! @param theColor a color used for filling a background
1150     //! @return true if processing was successful, or false otherwise
1151     bool processColorOption (const ViewerTest_CommandOptionKey theColorOptionKey, Quantity_Color& theColor) const
1152     {
1153       Standard_Integer anArgumentIndex = 0;
1154       Quantity_Color   aColor;
1155       if (!myCommandParser.ArgColor (theColorOptionKey, anArgumentIndex, aColor))
1156       {
1157         return false;
1158       }
1159       const Standard_Integer aNumberOfColorOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1160         theColorOptionKey);
1161       if (anArgumentIndex != aNumberOfColorOptionArguments)
1162       {
1163         return false;
1164       }
1165       theColor = aColor;
1166       return true;
1167     }
1168
1169     //! Prints helping message
1170     //! @param theBackgroundCommandName the name of the command that changes the background
1171     //! @param theDrawInterpretor the interpreter of the Draw Harness application
1172     //! @return true if printing was successful, or false otherwise
1173     static bool printHelp (const char* const theBackgroundCommandName, Draw_Interpretor& theDrawInterpretor)
1174     {
1175       return theDrawInterpretor.PrintHelp (theBackgroundCommandName) == TCL_OK;
1176     }
1177
1178     //! Sets the image as a background
1179     //! @param theImageFileName the filename of the image to be used as a background
1180     //! @param theImageMode the fill type used for a background image
1181     static void setImage (const Standard_CString theImageFileName, const Aspect_FillMethod theImageMode)
1182     {
1183       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1184       aCurrentView->SetBackgroundImage (theImageFileName, theImageMode, Standard_True);
1185     }
1186
1187     //! Sets the fill type used for a background image
1188     //! @param theImageMode the fill type used for a background image
1189     static void setImageMode (const Aspect_FillMethod theImageMode)
1190     {
1191       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1192       aCurrentView->SetBgImageStyle (theImageMode, Standard_True);
1193     }
1194
1195     //! Sets the gradient filling for a background
1196     //! @param theColor1 the gradient starting color
1197     //! @param theColor2 the gradient ending color
1198     //! @param theGradientMode the fill method used for a background gradient filling
1199     static void setGradient (const Quantity_Color&           theColor1,
1200                              const Quantity_Color&           theColor2,
1201                              const Aspect_GradientFillMethod theGradientMode)
1202     {
1203       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1204       aCurrentView->SetBgGradientColors (theColor1, theColor2, theGradientMode, Standard_True);
1205     }
1206
1207     //! Sets the fill method used for a background gradient filling
1208     //! @param theGradientMode the fill method used for a background gradient filling
1209     static void setGradientMode (const Aspect_GradientFillMethod theGradientMode)
1210     {
1211       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1212       aCurrentView->SetBgGradientStyle (theGradientMode, Standard_True);
1213     }
1214
1215     //! Sets the color used for filling a background
1216     //! @param theColor the color used for filling a background
1217     static void setColor (const Quantity_Color& theColor)
1218     {
1219       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1220       aCurrentView->SetBgGradientStyle (Aspect_GFM_NONE);
1221       aCurrentView->SetBackgroundColor (theColor);
1222       aCurrentView->Update();
1223     }
1224
1225     //! Sets the gradient filling for a background in a default viewer
1226     //! @param theColor1 the gradient starting color
1227     //! @param theColor2 the gradient ending color
1228     //! @param theGradientMode the fill method used for a background gradient filling
1229     static void setDefaultGradient (const Quantity_Color&           theColor1,
1230                                     const Quantity_Color&           theColor2,
1231                                     const Aspect_GradientFillMethod theGradientMode)
1232     {
1233       ViewerTest_DefaultBackground.GradientColor1 = theColor1;
1234       ViewerTest_DefaultBackground.GradientColor2 = theColor2;
1235       ViewerTest_DefaultBackground.FillMethod     = theGradientMode;
1236       setDefaultGradient();
1237     }
1238
1239     //! Sets the color used for filling a background in a default viewer
1240     //! @param theColor the color used for filling a background
1241     static void setDefaultColor (const Quantity_Color& theColor)
1242     {
1243       ViewerTest_DefaultBackground.GradientColor1 = Quantity_Color();
1244       ViewerTest_DefaultBackground.GradientColor2 = Quantity_Color();
1245       ViewerTest_DefaultBackground.FillMethod     = Aspect_GFM_NONE;
1246       ViewerTest_DefaultBackground.FlatColor      = theColor;
1247       setDefaultGradient();
1248       setDefaultColor();
1249     }
1250
1251     //! Sets the gradient filling for a background in a default viewer.
1252     //! Gradient settings are taken from ViewerTest_DefaultBackground structure
1253     static void setDefaultGradient()
1254     {
1255       for (NCollection_DoubleMap<TCollection_AsciiString, Handle (AIS_InteractiveContext)>::Iterator
1256              anInteractiveContextIterator (ViewerTest_myContexts);
1257            anInteractiveContextIterator.More();
1258            anInteractiveContextIterator.Next())
1259       {
1260         const Handle (V3d_Viewer)& aViewer = anInteractiveContextIterator.Value()->CurrentViewer();
1261         aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
1262                                              ViewerTest_DefaultBackground.GradientColor2,
1263                                              ViewerTest_DefaultBackground.FillMethod);
1264       }
1265     }
1266
1267     //! Sets the color used for filling a background in a default viewer.
1268     //! The color value is taken from ViewerTest_DefaultBackground structure
1269     static void setDefaultColor()
1270     {
1271       for (NCollection_DoubleMap<TCollection_AsciiString, Handle (AIS_InteractiveContext)>::Iterator
1272              anInteractiveContextIterator (ViewerTest_myContexts);
1273            anInteractiveContextIterator.More();
1274            anInteractiveContextIterator.Next())
1275       {
1276         const Handle (V3d_Viewer)& aViewer = anInteractiveContextIterator.Value()->CurrentViewer();
1277         aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
1278       }
1279     }
1280   };
1281
1282 } // namespace
1283
1284 Standard_EXPORT const Handle(AIS_RubberBand)& GetRubberBand()
1285 {
1286   static Handle(AIS_RubberBand) aBand;
1287   if (aBand.IsNull())
1288   {
1289     aBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
1290     aBand->SetDisplayMode (0);
1291   }
1292   return aBand;
1293 }
1294
1295 typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
1296
1297 Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
1298 {
1299   static ViewerTest_MapOfAISManipulators aMap;
1300   return aMap;
1301 }
1302
1303 Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
1304 {
1305   ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
1306   for (; anIt.More(); anIt.Next())
1307   {
1308     if (anIt.Value()->HasActiveMode())
1309     {
1310       return anIt.Value();
1311     }
1312   }
1313   return NULL;
1314 }
1315
1316 //==============================================================================
1317
1318 #ifdef _WIN32
1319 static LRESULT WINAPI ViewerWindowProc(
1320                                        HWND hwnd,
1321                                        UINT uMsg,
1322                                        WPARAM wParam,
1323                                        LPARAM lParam );
1324 static LRESULT WINAPI AdvViewerWindowProc(
1325   HWND hwnd,
1326   UINT uMsg,
1327   WPARAM wParam,
1328   LPARAM lParam );
1329 #endif
1330
1331
1332 //==============================================================================
1333 //function : WClass
1334 //purpose  :
1335 //==============================================================================
1336
1337 const Handle(Standard_Transient)& ViewerTest::WClass()
1338 {
1339   static Handle(Standard_Transient) theWClass;
1340 #if defined(_WIN32)
1341   if (theWClass.IsNull())
1342   {
1343     theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
1344                                 CS_VREDRAW | CS_HREDRAW, 0, 0,
1345                                 ::LoadCursor (NULL, IDC_ARROW));
1346   }
1347 #endif
1348   return theWClass;
1349 }
1350
1351 //==============================================================================
1352 //function : CreateName
1353 //purpose  : Create numerical name for new object in theMap
1354 //==============================================================================
1355 template <typename ObjectType>
1356 TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
1357                                     const TCollection_AsciiString& theDefaultString)
1358 {
1359   if (theObjectMap.IsEmpty())
1360     return theDefaultString + TCollection_AsciiString(1);
1361
1362   Standard_Integer aNextKey = 1;
1363   Standard_Boolean isFound = Standard_False;
1364   while (!isFound)
1365   {
1366     TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
1367     // Look for objects with default names
1368     if (theObjectMap.IsBound1(aStringKey))
1369     {
1370       aNextKey++;
1371     }
1372     else
1373       isFound = Standard_True;
1374   }
1375
1376   return theDefaultString + TCollection_AsciiString(aNextKey);
1377 }
1378
1379 //==============================================================================
1380 //structure : ViewerTest_Names
1381 //purpose   : Allow to operate with full view name: driverName/viewerName/viewName
1382 //==============================================================================
1383 struct ViewerTest_Names
1384 {
1385 private:
1386   TCollection_AsciiString myDriverName;
1387   TCollection_AsciiString myViewerName;
1388   TCollection_AsciiString myViewName;
1389
1390 public:
1391
1392   const TCollection_AsciiString& GetDriverName () const
1393   {
1394     return myDriverName;
1395   }
1396   void SetDriverName (const TCollection_AsciiString& theDriverName)
1397   {
1398     myDriverName = theDriverName;
1399   }
1400   const TCollection_AsciiString& GetViewerName () const
1401   {
1402     return myViewerName;
1403   }
1404   void SetViewerName (const TCollection_AsciiString& theViewerName)
1405   {
1406     myViewerName = theViewerName;
1407   }
1408   const TCollection_AsciiString& GetViewName () const
1409   {
1410     return myViewName;
1411   }
1412   void SetViewName (const TCollection_AsciiString& theViewName)
1413   {
1414     myViewName = theViewName;
1415   }
1416
1417   //===========================================================================
1418   //function : Constructor for ViewerTest_Names
1419   //purpose  : Get view, viewer, driver names from custom string
1420   //===========================================================================
1421
1422   ViewerTest_Names (const TCollection_AsciiString& theInputString)
1423   {
1424     TCollection_AsciiString aName(theInputString);
1425     if (theInputString.IsEmpty())
1426     {
1427       // Get current configuration
1428       if (ViewerTest_myDrivers.IsEmpty())
1429         myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
1430           (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
1431       else
1432         myDriverName = ViewerTest_myDrivers.Find2
1433         (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1434
1435       if(ViewerTest_myContexts.IsEmpty())
1436       {
1437         myViewerName = CreateName <Handle(AIS_InteractiveContext)>
1438           (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
1439       }
1440       else
1441       {
1442         myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
1443       }
1444
1445       myViewName = CreateName <Handle(V3d_View)> (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
1446     }
1447     else
1448     {
1449       // There is at least view name
1450       Standard_Integer aParserNumber = 0;
1451       for (Standard_Integer i = 0; i < 3; ++i)
1452       {
1453         Standard_Integer aParserPos = aName.SearchFromEnd("/");
1454         if(aParserPos != -1)
1455         {
1456           aParserNumber++;
1457           aName.Split(aParserPos-1);
1458         }
1459         else
1460           break;
1461       }
1462       if (aParserNumber == 0)
1463       {
1464         // Only view name
1465         if (!ViewerTest::GetAISContext().IsNull())
1466         {
1467           myDriverName = ViewerTest_myDrivers.Find2
1468           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1469           myViewerName = ViewerTest_myContexts.Find2
1470           (ViewerTest::GetAISContext());
1471         }
1472         else
1473         {
1474           // There is no opened contexts here, need to create names for viewer and driver
1475           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
1476             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
1477
1478           myViewerName = CreateName <Handle(AIS_InteractiveContext)>
1479             (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
1480         }
1481         myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
1482       }
1483       else if (aParserNumber == 1)
1484       {
1485         // Here is viewerName/viewName
1486         if (!ViewerTest::GetAISContext().IsNull())
1487           myDriverName = ViewerTest_myDrivers.Find2
1488           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1489         else
1490         {
1491           // There is no opened contexts here, need to create name for driver
1492           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
1493             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
1494         }
1495         myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
1496
1497         myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
1498       }
1499       else
1500       {
1501         //Here is driverName/viewerName/viewName
1502         myDriverName = TCollection_AsciiString(aName);
1503
1504         TCollection_AsciiString aViewerName(theInputString);
1505         aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
1506         myViewerName = TCollection_AsciiString(aViewerName);
1507
1508         myViewName = TCollection_AsciiString(theInputString);
1509       }
1510     }
1511   }
1512 };
1513
1514 //==============================================================================
1515 //function : FindContextByView
1516 //purpose  : Find AIS_InteractiveContext by View
1517 //==============================================================================
1518
1519 Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
1520 {
1521   Handle(AIS_InteractiveContext) anAISContext;
1522
1523   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1524        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
1525   {
1526     if (anIter.Value()->CurrentViewer() == theView->Viewer())
1527        return anIter.Key2();
1528   }
1529   return anAISContext;
1530 }
1531
1532
1533 //==============================================================================
1534 //function : SetWindowTitle
1535 //purpose  : Set window title
1536 //==============================================================================
1537
1538 void SetWindowTitle (const Handle(Aspect_Window)& theWindow,
1539                      Standard_CString theTitle)
1540 {
1541 #if defined(_WIN32)
1542   const TCollection_ExtendedString theTitleW (theTitle);
1543   SetWindowTextW ((HWND )Handle(WNT_Window)::DownCast(theWindow)->HWindow(), theTitleW.ToWideString());
1544 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1545   SetCocoaWindowTitle (Handle(Cocoa_Window)::DownCast(theWindow), theTitle);
1546 #else
1547   if(GetDisplayConnection()->GetDisplay())
1548   {
1549     Window aWindow =
1550       Handle(Xw_Window)::DownCast(theWindow)->XWindow();
1551     XStoreName (GetDisplayConnection()->GetDisplay(), aWindow , theTitle);
1552   }
1553 #endif
1554 }
1555
1556 //==============================================================================
1557 //function : IsWindowOverlapped
1558 //purpose  : Check if theWindow overlapp another view
1559 //==============================================================================
1560
1561 Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
1562                                      const Standard_Integer thePxTop,
1563                                      const Standard_Integer thePxRight,
1564                                      const Standard_Integer thePxBottom,
1565                                      TCollection_AsciiString& theViewId)
1566 {
1567   for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
1568       anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1569   {
1570     Standard_Integer aTop = 0,
1571       aLeft = 0,
1572       aRight = 0,
1573       aBottom = 0;
1574     anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
1575     if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
1576         (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
1577         (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
1578         (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
1579     {
1580       theViewId = anIter.Key1();
1581       return Standard_True;
1582     }
1583   }
1584   return Standard_False;
1585 }
1586
1587 // Workaround: to create and delete non-orthographic views outside ViewerTest
1588 void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
1589 {
1590   ViewerTest_myViews.UnBind1 (theName);
1591 }
1592
1593 void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
1594                                const Handle(V3d_View)& theView)
1595 {
1596   ViewerTest_myViews.Bind (theName, theView);
1597 }
1598
1599 TCollection_AsciiString ViewerTest::GetCurrentViewName ()
1600 {
1601   return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
1602 }
1603
1604 //! Auxiliary tool performing continuous redraws of specified window.
1605 class ViewerTest_ContinuousRedrawer
1606 {
1607 public:
1608   //! Return global instance.
1609   static ViewerTest_ContinuousRedrawer& Instance()
1610   {
1611     static ViewerTest_ContinuousRedrawer aRedrawer;
1612     return aRedrawer;
1613   }
1614 public:
1615
1616   //! Destructor.
1617   ~ViewerTest_ContinuousRedrawer()
1618   {
1619     Stop();
1620   }
1621
1622   //! Start thread.
1623   void Start (const Handle(Aspect_Window)& theWindow,
1624               Standard_Real theTargetFps)
1625   {
1626     if (myWindow != theWindow
1627      || myTargetFps != theTargetFps)
1628     {
1629       Stop();
1630       myWindow = theWindow;
1631       myTargetFps = theTargetFps;
1632     }
1633     if (myThread.GetId() == 0)
1634     {
1635       myToStop = false;
1636       myThread.Run (this);
1637     }
1638   }
1639
1640   //! Stop thread.
1641   void Stop (const Handle(Aspect_Window)& theWindow = NULL)
1642   {
1643     if (!theWindow.IsNull()
1644       && myWindow != theWindow)
1645     {
1646       return;
1647     }
1648
1649     {
1650       Standard_Mutex::Sentry aLock (myMutex);
1651       myToStop = true;
1652     }
1653     myThread.Wait();
1654     myToStop = false;
1655     myWindow.Nullify();
1656   }
1657
1658 private:
1659
1660   //! Thread loop.
1661   void doThreadLoop()
1662   {
1663     Handle(Aspect_DisplayConnection) aDisp = new Aspect_DisplayConnection();
1664     OSD_Timer aTimer;
1665     aTimer.Start();
1666     Standard_Real aTimeOld = 0.0;
1667     const Standard_Real aTargetDur = myTargetFps > 0.0 ? 1.0 / myTargetFps : -1.0;
1668     for (;;)
1669     {
1670       {
1671         Standard_Mutex::Sentry aLock (myMutex);
1672         if (myToStop)
1673         {
1674           return;
1675         }
1676       }
1677       if (myTargetFps > 0.0)
1678       {
1679         const Standard_Real aTimeNew  = aTimer.ElapsedTime();
1680         const Standard_Real aDuration = aTimeNew - aTimeOld;
1681         if (aDuration >= aTargetDur)
1682         {
1683           myWindow->InvalidateContent (aDisp);
1684           aTimeOld = aTimeNew;
1685         }
1686       }
1687       else
1688       {
1689         myWindow->InvalidateContent (aDisp);
1690       }
1691
1692       OSD::MilliSecSleep (1);
1693     }
1694   }
1695
1696   //! Thread creation callback.
1697   static Standard_Address doThreadWrapper (Standard_Address theData)
1698   {
1699     ViewerTest_ContinuousRedrawer* aThis = (ViewerTest_ContinuousRedrawer* )theData;
1700     aThis->doThreadLoop();
1701     return 0;
1702   }
1703
1704   //! Empty constructor.
1705   ViewerTest_ContinuousRedrawer()
1706   : myThread (doThreadWrapper),
1707     myTargetFps (0.0),
1708     myToStop (false) {}
1709
1710 private:
1711   Handle(Aspect_Window) myWindow;
1712   OSD_Thread      myThread;
1713   Standard_Mutex  myMutex;
1714   Standard_Real   myTargetFps;
1715   volatile bool   myToStop;
1716 };
1717
1718 //==============================================================================
1719 //function : ViewerInit
1720 //purpose  : Create the window viewer and initialize all the global variable
1721 //==============================================================================
1722
1723 TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
1724                                                 const Standard_Integer thePxTop,
1725                                                 const Standard_Integer thePxWidth,
1726                                                 const Standard_Integer thePxHeight,
1727                                                 const TCollection_AsciiString& theViewName,
1728                                                 const TCollection_AsciiString& theDisplayName,
1729                                                 const Handle(V3d_View)& theViewToClone)
1730 {
1731   // Default position and dimension of the viewer window.
1732   // Note that left top corner is set to be sufficiently small to have
1733   // window fit in the small screens (actual for remote desktops, see #23003).
1734   // The position corresponds to the window's client area, thus some
1735   // gap is added for window frame to be visible.
1736   Standard_Integer aPxLeft   = 20;
1737   Standard_Integer aPxTop    = 40;
1738   Standard_Integer aPxWidth  = 409;
1739   Standard_Integer aPxHeight = 409;
1740   Standard_Boolean toCreateViewer = Standard_False;
1741   if (!theViewToClone.IsNull())
1742   {
1743     theViewToClone->Window()->Size (aPxWidth, aPxHeight);
1744   }
1745
1746   Handle(OpenGl_GraphicDriver) aGraphicDriver;
1747   ViewerTest_Names aViewNames(theViewName);
1748   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
1749     aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
1750
1751   if (thePxLeft != 0)
1752     aPxLeft = thePxLeft;
1753   if (thePxTop != 0)
1754     aPxTop = thePxTop;
1755   if (thePxWidth != 0)
1756     aPxWidth = thePxWidth;
1757   if (thePxHeight != 0)
1758     aPxHeight = thePxHeight;
1759
1760   // Get graphic driver (create it or get from another view)
1761   const bool isNewDriver = !ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName());
1762   if (isNewDriver)
1763   {
1764     // Get connection string
1765   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1766     if (!theDisplayName.IsEmpty())
1767     {
1768       SetDisplayConnection (new Aspect_DisplayConnection (theDisplayName));
1769     }
1770     else
1771     {
1772       ::Display* aDispX = NULL;
1773       // create dedicated display connection instead of reusing Tk connection
1774       // so that to procede events independently through VProcessEvents()/ViewerMainLoop() callbacks
1775       /*Draw_Interpretor& aCommands = Draw::GetInterpretor();
1776       Tcl_Interp* aTclInterp = aCommands.Interp();
1777       Tk_Window aMainWindow = Tk_MainWindow (aTclInterp);
1778       aDispX = aMainWindow != NULL ? Tk_Display (aMainWindow) : NULL;*/
1779       SetDisplayConnection (new Aspect_DisplayConnection (aDispX));
1780     }
1781   #else
1782     (void)theDisplayName; // avoid warning on unused argument
1783     SetDisplayConnection (new Aspect_DisplayConnection ());
1784   #endif
1785
1786     if (Draw_VirtualWindows)
1787     {
1788       // don't waste the time waiting for VSync when window is not displayed on the screen
1789       ViewerTest_myDefaultCaps.swapInterval = 0;
1790       // alternatively we can disable buffer swap at all, but this might be inappropriate for testing
1791       //ViewerTest_myDefaultCaps.buffersNoSwap = true;
1792     }
1793     aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection());
1794     aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
1795
1796     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
1797     toCreateViewer = Standard_True;
1798   }
1799   else
1800   {
1801     aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
1802   }
1803
1804   //Dispose the window if input parameters are default
1805   if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
1806   {
1807     Standard_Integer aTop = 0,
1808                      aLeft = 0,
1809                      aRight = 0,
1810                      aBottom = 0,
1811                      aScreenWidth = 0,
1812                      aScreenHeight = 0;
1813
1814     // Get screen resolution
1815 #if defined(_WIN32) || defined(__WIN32__)
1816     RECT aWindowSize;
1817     GetClientRect(GetDesktopWindow(), &aWindowSize);
1818     aScreenHeight = aWindowSize.bottom;
1819     aScreenWidth = aWindowSize.right;
1820 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1821     GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
1822 #else
1823     Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
1824     aScreenWidth = WidthOfScreen(aScreen);
1825     aScreenHeight = HeightOfScreen(aScreen);
1826 #endif
1827
1828     TCollection_AsciiString anOverlappedViewId("");
1829
1830     while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
1831     {
1832       ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
1833
1834       if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
1835         && aRight + 2*aPxWidth + 40 > aScreenWidth)
1836       {
1837         if (aBottom + aPxHeight + 40 > aScreenHeight)
1838         {
1839           aPxLeft = 20;
1840           aPxTop = 40;
1841           break;
1842         }
1843         aPxLeft = 20;
1844         aPxTop = aBottom + 40;
1845       }
1846       else
1847         aPxLeft = aRight + 20;
1848     }
1849   }
1850
1851   // Get viewer name
1852   TCollection_AsciiString aTitle("3D View - ");
1853   aTitle = aTitle + aViewNames.GetViewName() + "(*)";
1854
1855   // Change name of current active window
1856   if (!ViewerTest::CurrentView().IsNull())
1857   {
1858     TCollection_AsciiString anActiveWindowTitle("3D View - ");
1859     anActiveWindowTitle = anActiveWindowTitle
1860       + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
1861     SetWindowTitle (ViewerTest::CurrentView()->Window(), anActiveWindowTitle.ToCString());
1862   }
1863
1864   // Create viewer
1865   Handle(V3d_Viewer) a3DViewer;
1866   // If it's the single view, we first look for empty context
1867   if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
1868   {
1869     NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1870       anIter(ViewerTest_myContexts);
1871     if (anIter.More())
1872       ViewerTest::SetAISContext (anIter.Value());
1873     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
1874   }
1875   else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
1876   {
1877     ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
1878     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
1879   }
1880   else if (a3DViewer.IsNull())
1881   {
1882     toCreateViewer = Standard_True;
1883     a3DViewer = new V3d_Viewer(aGraphicDriver);
1884     a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
1885     a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
1886                                            ViewerTest_DefaultBackground.GradientColor2,
1887                                            ViewerTest_DefaultBackground.FillMethod);
1888   }
1889
1890   // AIS context setup
1891   if (ViewerTest::GetAISContext().IsNull() ||
1892       !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
1893   {
1894     Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
1895     ViewerTest::SetAISContext (aContext);
1896     ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
1897   }
1898   else
1899   {
1900     ViewerTest::ResetEventManager();
1901   }
1902
1903   // Create window
1904 #if defined(_WIN32)
1905   VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
1906                                     Handle(WNT_WClass)::DownCast (WClass()),
1907                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
1908                                     aPxLeft, aPxTop,
1909                                     aPxWidth, aPxHeight,
1910                                     Quantity_NOC_BLACK);
1911 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1912   VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
1913                                      aPxLeft, aPxTop,
1914                                      aPxWidth, aPxHeight);
1915   ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
1916 #else
1917   VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
1918                                   aTitle.ToCString(),
1919                                   aPxLeft, aPxTop,
1920                                   aPxWidth, aPxHeight);
1921 #endif
1922   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
1923
1924   // View setup
1925   Handle(V3d_View) aView;
1926   if (!theViewToClone.IsNull())
1927   {
1928     aView = new ViewerTest_V3dView (a3DViewer, theViewToClone);
1929   }
1930   else
1931   {
1932     aView = new ViewerTest_V3dView (a3DViewer, a3DViewer->DefaultTypeOfView());
1933   }
1934
1935   aView->SetWindow (VT_GetWindow());
1936   ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
1937
1938   ViewerTest::CurrentView(aView);
1939   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
1940
1941   // Setup for X11 or NT
1942   OSWindowSetup();
1943
1944   // Set parameters for V3d_View and V3d_Viewer
1945   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
1946   aV3dView->SetComputedMode(Standard_False);
1947
1948   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
1949   if (toCreateViewer)
1950   {
1951     a3DViewer->SetDefaultLights();
1952     a3DViewer->SetLightOn();
1953   }
1954
1955 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1956   if (isNewDriver)
1957   {
1958     ::Display* aDispX = GetDisplayConnection()->GetDisplay();
1959     Tcl_CreateFileHandler (XConnectionNumber (aDispX), TCL_READABLE, VProcessEvents, (ClientData )aDispX);
1960   }
1961 #endif
1962
1963   VT_GetWindow()->Map();
1964
1965   // Set the handle of created view in the event manager
1966   ViewerTest::ResetEventManager();
1967
1968   ViewerTest::CurrentView()->Redraw();
1969
1970   aView.Nullify();
1971   a3DViewer.Nullify();
1972
1973   return aViewNames.GetViewName();
1974 }
1975
1976 //==============================================================================
1977 //function : RedrawAllViews
1978 //purpose  : Redraw all created views
1979 //==============================================================================
1980 void ViewerTest::RedrawAllViews()
1981 {
1982   NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
1983   for (; aViewIt.More(); aViewIt.Next())
1984   {
1985     const Handle(V3d_View)& aView = aViewIt.Key2();
1986     aView->Redraw();
1987   }
1988 }
1989
1990 //==============================================================================
1991 //function : Vinit
1992 //purpose  : Create the window viewer and initialize all the global variable
1993 //    Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
1994 //==============================================================================
1995
1996 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1997 {
1998   TCollection_AsciiString aViewName, aDisplayName;
1999   Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
2000   Handle(V3d_View) aCopyFrom;
2001   TCollection_AsciiString aName, aValue;
2002   int is2dMode = -1;
2003   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
2004   {
2005     const TCollection_AsciiString anArg = theArgVec[anArgIt];
2006     TCollection_AsciiString anArgCase = anArg;
2007     anArgCase.LowerCase();
2008     if (anArgIt + 1 < theArgsNb
2009      && anArgCase == "-name")
2010     {
2011       aViewName = theArgVec[++anArgIt];
2012     }
2013     else if (anArgIt + 1 < theArgsNb
2014           && (anArgCase == "-left"
2015            || anArgCase == "-l"))
2016     {
2017       aPxLeft = Draw::Atoi (theArgVec[++anArgIt]);
2018     }
2019     else if (anArgIt + 1 < theArgsNb
2020           && (anArgCase == "-top"
2021            || anArgCase == "-t"))
2022     {
2023       aPxTop = Draw::Atoi (theArgVec[++anArgIt]);
2024     }
2025     else if (anArgIt + 1 < theArgsNb
2026           && (anArgCase == "-width"
2027            || anArgCase == "-w"))
2028     {
2029       aPxWidth = Draw::Atoi (theArgVec[++anArgIt]);
2030     }
2031     else if (anArgIt + 1 < theArgsNb
2032           && (anArgCase == "-height"
2033            || anArgCase == "-h"))
2034     {
2035       aPxHeight = Draw::Atoi (theArgVec[++anArgIt]);
2036     }
2037     else if (anArgCase == "-exitonclose")
2038     {
2039       Draw_ToExitOnCloseView = true;
2040       if (anArgIt + 1 < theArgsNb
2041        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], Draw_ToExitOnCloseView))
2042       {
2043         ++anArgIt;
2044       }
2045     }
2046     else if (anArgCase == "-closeonescape"
2047           || anArgCase == "-closeonesc")
2048     {
2049       Draw_ToCloseViewOnEsc = true;
2050       if (anArgIt + 1 < theArgsNb
2051        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], Draw_ToCloseViewOnEsc))
2052       {
2053         ++anArgIt;
2054       }
2055     }
2056     else if (anArgCase == "-2d_mode"
2057           || anArgCase == "-2dmode"
2058           || anArgCase == "-2d")
2059     {
2060       bool toEnable = true;
2061       if (anArgIt + 1 < theArgsNb
2062        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], toEnable))
2063       {
2064         ++anArgIt;
2065       }
2066       is2dMode = toEnable ? 1 : 0;
2067     }
2068     else if (anArgIt + 1 < theArgsNb
2069           && (anArgCase == "-disp"
2070            || anArgCase == "-display"))
2071     {
2072       aDisplayName = theArgVec[++anArgIt];
2073     }
2074     else if (!ViewerTest::CurrentView().IsNull()
2075           &&  aCopyFrom.IsNull()
2076           && (anArgCase == "-copy"
2077            || anArgCase == "-clone"
2078            || anArgCase == "-cloneactive"
2079            || anArgCase == "-cloneactiveview"))
2080     {
2081       aCopyFrom = ViewerTest::CurrentView();
2082     }
2083     // old syntax
2084     else if (ViewerTest::SplitParameter (anArg, aName, aValue))
2085     {
2086       aName.LowerCase();
2087       if (aName == "name")
2088       {
2089         aViewName = aValue;
2090       }
2091       else if (aName == "l"
2092             || aName == "left")
2093       {
2094         aPxLeft = aValue.IntegerValue();
2095       }
2096       else if (aName == "t"
2097             || aName == "top")
2098       {
2099         aPxTop = aValue.IntegerValue();
2100       }
2101       else if (aName == "disp"
2102             || aName == "display")
2103       {
2104         aDisplayName = aValue;
2105       }
2106       else if (aName == "w"
2107             || aName == "width")
2108       {
2109         aPxWidth = aValue.IntegerValue();
2110       }
2111       else if (aName == "h"
2112             || aName == "height")
2113       {
2114         aPxHeight = aValue.IntegerValue();
2115       }
2116       else
2117       {
2118         std::cout << "Syntax error: unknown argument " << anArg << ".\n";
2119         return 1;
2120       }
2121     }
2122     else if (aViewName.IsEmpty())
2123     {
2124       aViewName = anArg;
2125     }
2126     else
2127     {
2128       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
2129       return 1;
2130     }
2131   }
2132
2133 #if defined(_WIN32) || (defined(__APPLE__) && !defined(MACOSX_USE_GLX))
2134   if (!aDisplayName.IsEmpty())
2135   {
2136     aDisplayName.Clear();
2137     std::cout << "Warning: display parameter will be ignored.\n";
2138   }
2139 #endif
2140
2141   ViewerTest_Names aViewNames (aViewName);
2142   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
2143   {
2144     TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
2145     theDi.Eval (aCommand.ToCString());
2146     if (is2dMode != -1)
2147     {
2148       ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
2149     }
2150     return 0;
2151   }
2152
2153   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
2154                                                             aViewName, aDisplayName, aCopyFrom);
2155   if (is2dMode != -1)
2156   {
2157     ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
2158   }
2159   theDi << aViewId;
2160   return 0;
2161 }
2162
2163 //! Parse HLR algo type.
2164 static Standard_Boolean parseHlrAlgoType (const char* theName,
2165                                           Prs3d_TypeOfHLR& theType)
2166 {
2167   TCollection_AsciiString aName (theName);
2168   aName.LowerCase();
2169   if (aName == "polyalgo")
2170   {
2171     theType = Prs3d_TOH_PolyAlgo;
2172   }
2173   else if (aName == "algo")
2174   {
2175     theType = Prs3d_TOH_Algo;
2176   }
2177   else
2178   {
2179     return Standard_False;
2180   }
2181   return Standard_True;
2182 }
2183
2184 //==============================================================================
2185 //function : VHLR
2186 //purpose  : hidden lines removal algorithm
2187 //==============================================================================
2188
2189 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2190 {
2191   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2192   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2193   if (aView.IsNull())
2194   {
2195     std::cerr << "Error: No opened viewer!\n";
2196     return 1;
2197   }
2198
2199   Standard_Boolean hasHlrOnArg = Standard_False;
2200   Standard_Boolean hasShowHiddenArg = Standard_False;
2201   Standard_Boolean isHLROn = Standard_False;
2202   Standard_Boolean toShowHidden = aCtx->DefaultDrawer()->DrawHiddenLine();
2203   Prs3d_TypeOfHLR  aTypeOfHLR = Prs3d_TOH_NotSet;
2204   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2205   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
2206   {
2207     TCollection_AsciiString anArg (argv[anArgIter]);
2208     anArg.LowerCase();
2209     if (anUpdateTool.parseRedrawMode (anArg))
2210     {
2211       continue;
2212     }
2213     else if (anArg == "-showhidden"
2214           && anArgIter + 1 < argc
2215           && ViewerTest::ParseOnOff (argv[anArgIter + 1], toShowHidden))
2216     {
2217       ++anArgIter;
2218       hasShowHiddenArg = Standard_True;
2219       continue;
2220     }
2221     else if ((anArg == "-type"
2222            || anArg == "-algo"
2223            || anArg == "-algotype")
2224           && anArgIter + 1 < argc
2225           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
2226     {
2227       ++anArgIter;
2228       continue;
2229     }
2230     else if (!hasHlrOnArg
2231           && ViewerTest::ParseOnOff (argv[anArgIter], isHLROn))
2232     {
2233       hasHlrOnArg = Standard_True;
2234       continue;
2235     }
2236     // old syntax
2237     else if (!hasShowHiddenArg
2238           && ViewerTest::ParseOnOff(argv[anArgIter], toShowHidden))
2239     {
2240       hasShowHiddenArg = Standard_True;
2241       continue;
2242     }
2243     else
2244     {
2245       std::cout << "Syntax error at '" << argv[anArgIter] << "'\n";
2246       return 1;
2247     }
2248   }
2249   if (!hasHlrOnArg)
2250   {
2251     di << "HLR:        " << aView->ComputedMode() << "\n";
2252     di << "HiddenLine: " << aCtx->DefaultDrawer()->DrawHiddenLine() << "\n";
2253     di << "HlrAlgo:    ";
2254     switch (aCtx->DefaultDrawer()->TypeOfHLR())
2255     {
2256       case Prs3d_TOH_NotSet:   di << "NotSet\n";   break;
2257       case Prs3d_TOH_PolyAlgo: di << "PolyAlgo\n"; break;
2258       case Prs3d_TOH_Algo:     di << "Algo\n";     break;
2259     }
2260     anUpdateTool.Invalidate();
2261     return 0;
2262   }
2263
2264   Standard_Boolean toRecompute = Standard_False;
2265   if (aTypeOfHLR != Prs3d_TOH_NotSet
2266    && aTypeOfHLR != aCtx->DefaultDrawer()->TypeOfHLR())
2267   {
2268     toRecompute = Standard_True;
2269     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
2270   }
2271   if (toShowHidden != aCtx->DefaultDrawer()->DrawHiddenLine())
2272   {
2273     toRecompute = Standard_True;
2274     if (toShowHidden)
2275     {
2276       aCtx->DefaultDrawer()->EnableDrawHiddenLine();
2277     }
2278     else
2279     {
2280       aCtx->DefaultDrawer()->DisableDrawHiddenLine();
2281     }
2282   }
2283
2284   // redisplay shapes
2285   if (aView->ComputedMode() && isHLROn && toRecompute)
2286   {
2287     AIS_ListOfInteractive aListOfShapes;
2288     aCtx->DisplayedObjects (aListOfShapes);
2289     for (AIS_ListIteratorOfListOfInteractive anIter (aListOfShapes); anIter.More(); anIter.Next())
2290     {
2291       if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value()))
2292       {
2293         aCtx->Redisplay (aShape, Standard_False);
2294       }
2295     }
2296   }
2297
2298   aView->SetComputedMode (isHLROn);
2299   return 0;
2300 }
2301
2302 //==============================================================================
2303 //function : VHLRType
2304 //purpose  : change type of using HLR algorithm
2305 //==============================================================================
2306
2307 static int VHLRType (Draw_Interpretor& , Standard_Integer argc, const char** argv)
2308 {
2309   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2310   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2311   if (aView.IsNull())
2312   {
2313     std::cerr << "Error: No opened viewer!\n";
2314     return 1;
2315   }
2316
2317   Prs3d_TypeOfHLR aTypeOfHLR = Prs3d_TOH_NotSet;
2318   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2319   AIS_ListOfInteractive aListOfShapes;
2320   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
2321   {
2322     TCollection_AsciiString anArg (argv[anArgIter]);
2323     anArg.LowerCase();
2324     if (anUpdateTool.parseRedrawMode (anArg))
2325     {
2326       continue;
2327     }
2328     else if ((anArg == "-type"
2329            || anArg == "-algo"
2330            || anArg == "-algotype")
2331           && anArgIter + 1 < argc
2332           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
2333     {
2334       ++anArgIter;
2335       continue;
2336     }
2337     // old syntax
2338     else if (aTypeOfHLR == Prs3d_TOH_NotSet
2339           && parseHlrAlgoType (argv[anArgIter], aTypeOfHLR))
2340     {
2341       continue;
2342     }
2343     else
2344     {
2345       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
2346       TCollection_AsciiString aName (argv[anArgIter]);
2347       if (!aMap.IsBound2 (aName))
2348       {
2349         std::cout << "Syntax error: Wrong shape name '" << aName << "'.\n";
2350         return 1;
2351       }
2352
2353       Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (aMap.Find2 (aName));
2354       if (aShape.IsNull())
2355       {
2356         std::cout << "Syntax error: '" << aName << "' is not a shape presentation.\n";
2357         return 1;
2358       }
2359       aListOfShapes.Append (aShape);
2360       continue;
2361     }
2362   }
2363   if (aTypeOfHLR == Prs3d_TOH_NotSet)
2364   {
2365     std::cout << "Syntax error: wrong number of arguments!\n";
2366     return 1;
2367   }
2368
2369   const Standard_Boolean isGlobal = aListOfShapes.IsEmpty();
2370   if (isGlobal)
2371   {
2372     aCtx->DisplayedObjects (aListOfShapes);
2373     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
2374   }
2375
2376   for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
2377   {
2378     Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
2379     if (aShape.IsNull())
2380     {
2381       continue;
2382     }
2383
2384     const bool toUpdateShape = aShape->TypeOfHLR() != aTypeOfHLR
2385                             && aView->ComputedMode();
2386     if (!isGlobal
2387      || aShape->TypeOfHLR() != aTypeOfHLR)
2388     {
2389       aShape->SetTypeOfHLR (aTypeOfHLR);
2390     }
2391     if (toUpdateShape)
2392     {
2393       aCtx->Redisplay (aShape, Standard_False);
2394     }
2395   }
2396   return 0;
2397 }
2398
2399 //==============================================================================
2400 //function : FindViewIdByWindowHandle
2401 //purpose  : Find theView Id in the map of views by window handle
2402 //==============================================================================
2403 #if defined(_WIN32) || defined(__WIN32__) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2404 TCollection_AsciiString FindViewIdByWindowHandle(const Aspect_Handle theWindowHandle)
2405 {
2406   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
2407        anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
2408   {
2409     Aspect_Handle aWindowHandle = GetWindowHandle(anIter.Value()->Window());
2410     if (aWindowHandle == theWindowHandle)
2411       return anIter.Key1();
2412   }
2413   return TCollection_AsciiString("");
2414 }
2415 #endif
2416
2417 //! Make the view active
2418 void ActivateView (const TCollection_AsciiString& theViewName,
2419                    Standard_Boolean theToUpdate = Standard_True)
2420 {
2421   const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
2422   if (aView.IsNull())
2423   {
2424     return;
2425   }
2426
2427   Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
2428   if (!anAISContext.IsNull())
2429   {
2430     if (!ViewerTest::CurrentView().IsNull())
2431     {
2432       TCollection_AsciiString aTitle("3D View - ");
2433       aTitle = aTitle + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
2434       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
2435     }
2436
2437     ViewerTest::CurrentView (aView);
2438     ViewerTest::SetAISContext (anAISContext);
2439     TCollection_AsciiString aTitle = TCollection_AsciiString("3D View - ") + theViewName + "(*)";
2440     SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
2441 #if defined(_WIN32)
2442     VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
2443 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
2444     VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
2445 #else
2446     VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
2447 #endif
2448     SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2449     if (theToUpdate)
2450     {
2451       ViewerTest::CurrentView()->Redraw();
2452     }
2453   }
2454 }
2455
2456 //==============================================================================
2457 //function : RemoveView
2458 //purpose  :
2459 //==============================================================================
2460 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
2461                              const Standard_Boolean  theToRemoveContext)
2462 {
2463   if (!ViewerTest_myViews.IsBound2 (theView))
2464   {
2465     return;
2466   }
2467
2468   const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
2469   RemoveView (aViewName, theToRemoveContext);
2470 }
2471
2472 //==============================================================================
2473 //function : RemoveView
2474 //purpose  : Close and remove view from display, clear maps if neccessary
2475 //==============================================================================
2476 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
2477 {
2478   if (!ViewerTest_myViews.IsBound1(theViewName))
2479   {
2480     cout << "Wrong view name\n";
2481     return;
2482   }
2483
2484   // Activate another view if it's active now
2485   if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
2486   {
2487     if (ViewerTest_myViews.Extent() > 1)
2488     {
2489       TCollection_AsciiString aNewViewName;
2490       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
2491            anIter.More(); anIter.Next())
2492       {
2493         if (anIter.Key1() != theViewName)
2494         {
2495           aNewViewName = anIter.Key1();
2496           break;
2497         }
2498       }
2499       ActivateView (aNewViewName);
2500     }
2501     else
2502     {
2503       VT_GetWindow().Nullify();
2504       ViewerTest::CurrentView (Handle(V3d_View)());
2505       if (isContextRemoved)
2506       {
2507         Handle(AIS_InteractiveContext) anEmptyContext;
2508         ViewerTest::SetAISContext(anEmptyContext);
2509       }
2510     }
2511   }
2512
2513   // Delete view
2514   Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
2515   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
2516   ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
2517   aRedrawer.Stop (aView->Window());
2518
2519   // Remove view resources
2520   ViewerTest_myViews.UnBind1(theViewName);
2521   aView->Window()->Unmap();
2522   aView->Remove();
2523
2524 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2525   XFlush (GetDisplayConnection()->GetDisplay());
2526 #endif
2527
2528   // Keep context opened only if the closed view is last to avoid
2529   // unused empty contexts
2530   if (!aCurrentContext.IsNull())
2531   {
2532     // Check if there are more difined views in the viewer
2533     aCurrentContext->CurrentViewer()->InitDefinedViews();
2534     if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
2535     {
2536       // Remove driver if there is no viewers that use it
2537       Standard_Boolean isRemoveDriver = Standard_True;
2538       for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2539           anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
2540       {
2541         if (aCurrentContext != anIter.Key2() &&
2542           aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
2543         {
2544           isRemoveDriver = Standard_False;
2545           break;
2546         }
2547       }
2548
2549       aCurrentContext->RemoveAll (Standard_False);
2550       if(isRemoveDriver)
2551       {
2552         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
2553       #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2554         Tcl_DeleteFileHandler (XConnectionNumber (aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
2555       #endif
2556       }
2557
2558       ViewerTest_myContexts.UnBind2(aCurrentContext);
2559     }
2560   }
2561   cout << "3D View - " << theViewName << " was deleted.\n";
2562   if (Draw_ToExitOnCloseView)
2563   {
2564     Draw_Interprete ("exit");
2565   }
2566 }
2567
2568 //==============================================================================
2569 //function : VClose
2570 //purpose  : Remove the view defined by its name
2571 //==============================================================================
2572
2573 static int VClose (Draw_Interpretor& /*theDi*/,
2574                    Standard_Integer  theArgsNb,
2575                    const char**      theArgVec)
2576 {
2577   NCollection_List<TCollection_AsciiString> aViewList;
2578   if (theArgsNb > 1)
2579   {
2580     TCollection_AsciiString anArg (theArgVec[1]);
2581     anArg.UpperCase();
2582     if (anArg.IsEqual ("ALL")
2583      || anArg.IsEqual ("*"))
2584     {
2585       for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
2586            anIter.More(); anIter.Next())
2587       {
2588         aViewList.Append (anIter.Key1());
2589       }
2590       if (aViewList.IsEmpty())
2591       {
2592         std::cout << "No view to close\n";
2593         return 0;
2594       }
2595     }
2596     else
2597     {
2598       ViewerTest_Names aViewName (theArgVec[1]);
2599       if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
2600       {
2601         std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
2602         return 1;
2603       }
2604       aViewList.Append (aViewName.GetViewName());
2605     }
2606   }
2607   else
2608   {
2609     // close active view
2610     if (ViewerTest::CurrentView().IsNull())
2611     {
2612       std::cerr << "No active view!\n";
2613       return 1;
2614     }
2615     aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
2616   }
2617
2618   Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
2619   for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
2620        anIter.More(); anIter.Next())
2621   {
2622     ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
2623   }
2624
2625   return 0;
2626 }
2627
2628 //==============================================================================
2629 //function : VActivate
2630 //purpose  : Activate the view defined by its ID
2631 //==============================================================================
2632
2633 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
2634 {
2635   if (theArgsNb == 1)
2636   {
2637     theDi.Eval("vviewlist");
2638     return 0;
2639   }
2640
2641   TCollection_AsciiString aNameString;
2642   Standard_Boolean toUpdate = Standard_True;
2643   Standard_Boolean toActivate = Standard_True;
2644   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
2645   {
2646     TCollection_AsciiString anArg (theArgVec[anArgIter]);
2647     anArg.LowerCase();
2648     if (toUpdate
2649      && anArg == "-noupdate")
2650     {
2651       toUpdate = Standard_False;
2652     }
2653     else if (toActivate
2654           && aNameString.IsEmpty()
2655           && anArg == "none")
2656     {
2657       TCollection_AsciiString aTitle("3D View - ");
2658       aTitle = aTitle + ViewerTest_myViews.Find2(ViewerTest::CurrentView());
2659       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
2660       VT_GetWindow().Nullify();
2661       ViewerTest::CurrentView (Handle(V3d_View)());
2662       ViewerTest::ResetEventManager();
2663       theDi << theArgVec[0] << ": all views are inactive\n";
2664       toActivate = Standard_False;
2665     }
2666     else if (toActivate
2667           && aNameString.IsEmpty())
2668     {
2669       aNameString = theArgVec[anArgIter];
2670     }
2671     else
2672     {
2673       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
2674       return 1;
2675     }
2676   }
2677
2678   if (!toActivate)
2679   {
2680     return 0;
2681   }
2682   else if (aNameString.IsEmpty())
2683   {
2684     std::cout << "Syntax error: wrong number of arguments\n";
2685     return 1;
2686   }
2687
2688   // Check if this view exists in the viewer with the driver
2689   ViewerTest_Names aViewNames (aNameString);
2690   if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
2691   {
2692     theDi << "Syntax error: wrong view name '" << aNameString << "'\n";
2693     return 1;
2694   }
2695
2696   // Check if it is active already
2697   if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
2698   {
2699     theDi << theArgVec[0] << ": the view is active already\n";
2700     return 0;
2701   }
2702
2703   ActivateView (aViewNames.GetViewName(), toUpdate);
2704   return 0;
2705 }
2706
2707 //==============================================================================
2708 //function : VViewList
2709 //purpose  : Print current list of views per viewer and graphic driver ID
2710 //           shared between viewers
2711 //==============================================================================
2712
2713 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
2714 {
2715   if (theArgsNb > 2)
2716   {
2717     theDi << theArgVec[0] << ": Wrong number of command arguments\n"
2718           << "Usage: " << theArgVec[0] << " name";
2719     return 1;
2720   }
2721   if (ViewerTest_myContexts.Size() < 1)
2722     return 0;
2723
2724   Standard_Boolean isTreeView =
2725     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
2726
2727   if (isTreeView)
2728   {
2729     theDi << theArgVec[0] <<":\n";
2730   }
2731
2732   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator aDriverIter (ViewerTest_myDrivers);
2733        aDriverIter.More(); aDriverIter.Next())
2734   {
2735     if (isTreeView)
2736       theDi << aDriverIter.Key1() << ":\n";
2737
2738     for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2739       aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
2740     {
2741       if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
2742       {
2743         if (isTreeView)
2744         {
2745           TCollection_AsciiString aContextName(aContextIter.Key1());
2746           theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
2747         }
2748
2749         for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIter (ViewerTest_myViews);
2750              aViewIter.More(); aViewIter.Next())
2751         {
2752           if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
2753           {
2754             TCollection_AsciiString aViewName(aViewIter.Key1());
2755             if (isTreeView)
2756             {
2757               if (aViewIter.Value() == ViewerTest::CurrentView())
2758                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
2759               else
2760                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
2761             }
2762             else
2763             {
2764               theDi << aViewName << " ";
2765             }
2766           }
2767         }
2768       }
2769     }
2770   }
2771   return 0;
2772 }
2773
2774 //==============================================================================
2775 //function : VT_ProcessKeyPress
2776 //purpose  : Handle KeyPress event from a CString
2777 //==============================================================================
2778 void VT_ProcessKeyPress (const char* buf_ret)
2779 {
2780   //cout << "KeyPress" << endl;
2781   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2782   // Letter in alphabetic order
2783
2784   if (!strcasecmp (buf_ret, "A")
2785    && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
2786   {
2787     // AXO
2788     aView->SetProj(V3d_XposYnegZpos);
2789   }
2790   else if (!strcasecmp (buf_ret, "D")
2791         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
2792   {
2793     // Reset
2794     aView->Reset();
2795   }
2796   else if (!strcasecmp (buf_ret, "F"))
2797   {
2798     if (ViewerTest::GetAISContext()->NbSelected() > 0)
2799     {
2800       ViewerTest::GetAISContext()->FitSelected (aView);
2801     }
2802     else
2803     {
2804       // FitAll
2805       aView->FitAll();
2806     }
2807   }
2808   else if (!strcasecmp (buf_ret, "H"))
2809   {
2810     // HLR
2811     std::cout << "HLR" << std::endl;
2812     aView->SetComputedMode (!aView->ComputedMode());
2813     aView->Redraw();
2814   }
2815   else if (!strcasecmp (buf_ret, "P"))
2816   {
2817     // Type of HLR
2818     Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
2819     if (aContext->DefaultDrawer()->TypeOfHLR() == Prs3d_TOH_Algo)
2820       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_PolyAlgo);
2821     else
2822       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_Algo);
2823     if (aContext->NbSelected()==0)
2824     {
2825       AIS_ListOfInteractive aListOfShapes;
2826       aContext->DisplayedObjects(aListOfShapes);
2827       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
2828         anIter.More(); anIter.Next())
2829       {
2830         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
2831         if (aShape.IsNull())
2832           continue;
2833         if (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
2834           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
2835         else
2836           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
2837         aContext->Redisplay (aShape, Standard_False);
2838       }
2839     }
2840     else
2841     {
2842       for (aContext->InitSelected();aContext->MoreSelected();aContext->NextSelected())
2843       {
2844         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aContext->SelectedInteractive());
2845         if (aShape.IsNull())
2846           continue;
2847         if(aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
2848           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
2849         else
2850           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
2851         aContext->Redisplay (aShape, Standard_False);
2852       }
2853     }
2854
2855     aContext->UpdateCurrentViewer();
2856
2857   }
2858   else if (!strcasecmp (buf_ret, "S"))
2859   {
2860     std::cout << "setup Shaded display mode" << std::endl;
2861
2862     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
2863     if(Ctx->NbSelected()==0)
2864       Ctx->SetDisplayMode (AIS_Shaded, Standard_True);
2865     else{
2866       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
2867         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),1,Standard_False);
2868       Ctx->UpdateCurrentViewer();
2869     }
2870   }
2871   else if (!strcasecmp (buf_ret, "U"))
2872   {
2873     // Unset display mode
2874     std::cout << "reset display mode to defaults" << std::endl;
2875
2876     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
2877     if(Ctx->NbSelected()==0)
2878       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
2879     else{
2880       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
2881         Ctx->UnsetDisplayMode(Ctx->SelectedInteractive(),Standard_False);
2882       Ctx->UpdateCurrentViewer();
2883     }
2884
2885   }
2886   else if (!strcasecmp (buf_ret, "T")
2887         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
2888   {
2889     // Top
2890     aView->SetProj(V3d_Zpos);
2891   }
2892   else if (!strcasecmp (buf_ret, "B")
2893         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
2894   {
2895     // Bottom
2896     aView->SetProj(V3d_Zneg);
2897   }
2898   else if (!strcasecmp (buf_ret, "L")
2899         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
2900   {
2901     // Left
2902     aView->SetProj(V3d_Xneg);
2903   }
2904   else if (!strcasecmp (buf_ret, "R")
2905         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
2906   {
2907     // Right
2908     aView->SetProj(V3d_Xpos);
2909   }
2910   else if (!strcasecmp (buf_ret, "W"))
2911   {
2912     std::cout << "setup WireFrame display mode" << std::endl;
2913     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
2914     if(Ctx->NbSelected()==0)
2915       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
2916     else{
2917       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
2918         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),0,Standard_False);
2919       Ctx->UpdateCurrentViewer();
2920     }
2921   }
2922   else if (!strcasecmp (buf_ret, ","))
2923   {
2924     ViewerTest::GetAISContext()->HilightNextDetected(ViewerTest::CurrentView());
2925   }
2926   else if (!strcasecmp (buf_ret, "."))
2927   {
2928     ViewerTest::GetAISContext()->HilightPreviousDetected(ViewerTest::CurrentView());
2929   }
2930   else if (!strcasecmp (buf_ret, "/"))
2931   {
2932     Handle(Graphic3d_Camera) aCamera = aView->Camera();
2933     if (aCamera->IsStereo())
2934     {
2935       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01);
2936       aView->Redraw();
2937     }
2938   }
2939   else if (!strcasecmp (buf_ret, "*"))
2940   {
2941     Handle(Graphic3d_Camera) aCamera = aView->Camera();
2942     if (aCamera->IsStereo())
2943     {
2944       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01);
2945       aView->Redraw();
2946     }
2947   }
2948   else if (*buf_ret == THE_KEY_DELETE)
2949   {
2950     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2951     if (!aCtx.IsNull()
2952      && aCtx->NbSelected() > 0)
2953     {
2954       Draw_Interprete ("verase");
2955     }
2956   }
2957   else if (*buf_ret == THE_KEY_ESCAPE)
2958   {
2959     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2960     if (!aCtx.IsNull()
2961      && Draw_ToCloseViewOnEsc)
2962     {
2963       Draw_Interprete (Draw_ToExitOnCloseView ? "exit" : "vclose");
2964     }
2965   }
2966   else if (*buf_ret >= '0' && *buf_ret <= '7') // Number
2967   {
2968     const Standard_Integer aSelMode = Draw::Atoi (buf_ret);
2969     bool toEnable = true;
2970     if (const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext())
2971     {
2972       AIS_ListOfInteractive aPrsList;
2973       aCtx->DisplayedObjects (aPrsList);
2974       for (AIS_ListOfInteractive::Iterator aPrsIter (aPrsList); aPrsIter.More() && toEnable; aPrsIter.Next())
2975       {
2976         TColStd_ListOfInteger aModes;
2977         aCtx->ActivatedModes (aPrsIter.Value(), aModes);
2978         for (TColStd_ListOfInteger::Iterator aModeIter (aModes); aModeIter.More() && toEnable; aModeIter.Next())
2979         {
2980           if (aModeIter.Value() == aSelMode)
2981           {
2982             toEnable = false;
2983           }
2984         }
2985       }
2986     }
2987     TCollection_AsciiString aCmd = TCollection_AsciiString ("vselmode ") + aSelMode + (toEnable ? " 1" : " 0");
2988     Draw_Interprete (aCmd.ToCString());
2989   }
2990 }
2991
2992 //==============================================================================
2993 //function : VT_ProcessExpose
2994 //purpose  : Redraw the View on an Expose Event
2995 //==============================================================================
2996 void VT_ProcessExpose()
2997 {
2998   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
2999   if (!aView3d.IsNull())
3000   {
3001     aView3d->Redraw();
3002   }
3003 }
3004
3005 //==============================================================================
3006 //function : VT_ProcessConfigure
3007 //purpose  : Resize the View on an Configure Event
3008 //==============================================================================
3009 void VT_ProcessConfigure()
3010 {
3011   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
3012   if (aView3d.IsNull())
3013   {
3014     return;
3015   }
3016
3017   aView3d->MustBeResized();
3018   aView3d->Update();
3019   aView3d->Redraw();
3020 }
3021
3022 //==============================================================================
3023 //function : VT_ProcessButton1Press
3024 //purpose  : Picking
3025 //==============================================================================
3026 Standard_Boolean VT_ProcessButton1Press (Standard_Integer ,
3027                                          const char**     theArgVec,
3028                                          Standard_Boolean theToPick,
3029                                          Standard_Boolean theIsShift)
3030 {
3031   if (TheIsAnimating)
3032   {
3033     TheIsAnimating = Standard_False;
3034     return Standard_False;
3035   }
3036
3037   if (theToPick)
3038   {
3039     Standard_Real X, Y, Z;
3040     ViewerTest::CurrentView()->Convert (X_Motion, Y_Motion, X, Y, Z);
3041
3042     Draw::Set (theArgVec[1], X);
3043     Draw::Set (theArgVec[2], Y);
3044     Draw::Set (theArgVec[3], Z);
3045   }
3046
3047   if (theIsShift)
3048   {
3049     ViewerTest::CurrentEventManager()->ShiftSelect();
3050   }
3051   else
3052   {
3053     ViewerTest::CurrentEventManager()->Select();
3054   }
3055
3056   return Standard_False;
3057 }
3058
3059 //==============================================================================
3060 //function : VT_ProcessButton1Release
3061 //purpose  : End selecting
3062 //==============================================================================
3063 void VT_ProcessButton1Release (Standard_Boolean theIsShift)
3064 {
3065   if (IsDragged)
3066   {
3067     IsDragged = Standard_False;
3068     Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
3069     if (theIsShift)
3070     {
3071       EM->ShiftSelect (X_ButtonPress, Y_ButtonPress,
3072                        X_Motion, Y_Motion);
3073     }
3074     else
3075     {
3076       EM->Select (X_ButtonPress, Y_ButtonPress,
3077                   X_Motion, Y_Motion);
3078     }
3079   }
3080 }
3081
3082 //==============================================================================
3083 //function : VT_ProcessButton3Press
3084 //purpose  : Start Rotation
3085 //==============================================================================
3086 void VT_ProcessButton3Press()
3087 {
3088   if (ViewerTest_V3dView::IsCurrentViewIn2DMode())
3089   {
3090     return;
3091   }
3092
3093   Start_Rot = 1;
3094   HasHlrOnBeforeRotation = ViewerTest::CurrentView()->ComputedMode();
3095   if (HasHlrOnBeforeRotation)
3096   {
3097     ViewerTest::CurrentView()->SetComputedMode (Standard_False);
3098   }
3099   ViewerTest::CurrentView()->StartRotation( X_ButtonPress, Y_ButtonPress );
3100 }
3101
3102 //==============================================================================
3103 //function : VT_ProcessButton3Release
3104 //purpose  : End rotation
3105 //==============================================================================
3106 void VT_ProcessButton3Release()
3107 {
3108   if (Start_Rot)
3109   {
3110     Start_Rot = 0;
3111     if (HasHlrOnBeforeRotation)
3112     {
3113       HasHlrOnBeforeRotation = Standard_False;
3114       ViewerTest::CurrentView()->SetComputedMode (Standard_True);
3115       ViewerTest::CurrentView()->Redraw();
3116     }
3117   }
3118 }
3119
3120 //==============================================================================
3121 //function : ProcessControlButton1Motion
3122 //purpose  : Zoom
3123 //==============================================================================
3124
3125 #if defined(_WIN32) || ! defined(__APPLE__) || defined(MACOSX_USE_GLX)
3126 static void ProcessControlButton1Motion()
3127 {
3128   ViewerTest::CurrentView()->Zoom( X_ButtonPress, Y_ButtonPress, X_Motion, Y_Motion);
3129
3130   X_ButtonPress = X_Motion;
3131   Y_ButtonPress = Y_Motion;
3132 }
3133 #endif
3134
3135 //==============================================================================
3136 //function : VT_ProcessControlButton2Motion
3137 //purpose  : Panning
3138 //==============================================================================
3139 void VT_ProcessControlButton2Motion()
3140 {
3141   Standard_Integer aDx = X_Motion - X_ButtonPress;
3142   Standard_Integer aDy = Y_Motion - Y_ButtonPress;
3143
3144   aDy = -aDy; // Xwindow Y axis is from top to Bottom
3145
3146   ViewerTest::CurrentView()->Pan (aDx, aDy);
3147
3148   X_ButtonPress = X_Motion;
3149   Y_ButtonPress = Y_Motion;
3150 }
3151
3152 //==============================================================================
3153 //function : VT_ProcessControlButton3Motion
3154 //purpose  : Rotation
3155 //==============================================================================
3156 void VT_ProcessControlButton3Motion()
3157 {
3158   if (Start_Rot)
3159   {
3160     ViewerTest::CurrentView()->Rotation (X_Motion, Y_Motion);
3161   }
3162 }
3163
3164 //==============================================================================
3165 //function : VT_ProcessMotion
3166 //purpose  :
3167 //==============================================================================
3168 void VT_ProcessMotion()
3169 {
3170   //pre-hilights detected objects at mouse position
3171
3172   Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
3173   EM->MoveTo(X_Motion, Y_Motion);
3174 }
3175
3176
3177 void ViewerTest::GetMousePosition(Standard_Integer& Xpix,Standard_Integer& Ypix)
3178 {
3179   Xpix = X_Motion;Ypix=Y_Motion;
3180 }
3181
3182 //==============================================================================
3183 //function : VViewProj
3184 //purpose  : Switch view projection
3185 //==============================================================================
3186 static int VViewProj (Draw_Interpretor& ,
3187                       Standard_Integer theNbArgs,
3188                       const char** theArgVec)
3189 {
3190   static Standard_Boolean isYup = Standard_False;
3191   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
3192   if (aView.IsNull())
3193   {
3194     std::cout << "Error: no active view\n";
3195     return 1;
3196   }
3197
3198   TCollection_AsciiString aCmdName (theArgVec[0]);
3199   Standard_Boolean isGeneralCmd = Standard_False;
3200   if (aCmdName == "vfront")
3201   {
3202     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Front : V3d_TypeOfOrientation_Zup_Front, isYup);
3203   }
3204   else if (aCmdName == "vback")
3205   {
3206     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Back : V3d_TypeOfOrientation_Zup_Back, isYup);
3207   }
3208   else if (aCmdName == "vtop")
3209   {
3210     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Top : V3d_TypeOfOrientation_Zup_Top, isYup);
3211   }
3212   else if (aCmdName == "vbottom")
3213   {
3214     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Bottom : V3d_TypeOfOrientation_Zup_Bottom, isYup);
3215   }
3216   else if (aCmdName == "vleft")
3217   {
3218     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Left : V3d_TypeOfOrientation_Zup_Left, isYup);
3219   }
3220   else if (aCmdName == "vright")
3221   {
3222     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Right : V3d_TypeOfOrientation_Zup_Right, isYup);
3223   }
3224   else if (aCmdName == "vaxo")
3225   {
3226     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoRight : V3d_TypeOfOrientation_Zup_AxoRight, isYup);
3227   }
3228   else
3229   {
3230     isGeneralCmd = Standard_True;
3231     for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
3232     {
3233       TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
3234       anArgCase.LowerCase();
3235       if (anArgCase == "-zup")
3236       {
3237         isYup = Standard_False;
3238       }
3239       else if (anArgCase == "-yup")
3240       {
3241         isYup = Standard_True;
3242       }
3243       else if (anArgCase == "-front"
3244             || anArgCase == "front"
3245             || anArgCase == "-f"
3246             || anArgCase == "f")
3247       {
3248         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Front : V3d_TypeOfOrientation_Zup_Front, isYup);
3249       }
3250       else if (anArgCase == "-back"
3251             || anArgCase == "back"
3252             || anArgCase == "-b"
3253             || anArgCase == "b")
3254       {
3255         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Back : V3d_TypeOfOrientation_Zup_Back, isYup);
3256       }
3257       else if (anArgCase == "-top"
3258             || anArgCase == "top"
3259             || anArgCase == "-t"
3260             || anArgCase == "t")
3261       {
3262         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Top : V3d_TypeOfOrientation_Zup_Top, isYup);
3263       }
3264       else if (anArgCase == "-bottom"
3265             || anArgCase == "bottom"
3266             || anArgCase == "-bot"
3267             || anArgCase == "bot"
3268             || anArgCase == "-b"
3269             || anArgCase == "b")
3270       {
3271         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Bottom : V3d_TypeOfOrientation_Zup_Bottom, isYup);
3272       }
3273       else if (anArgCase == "-left"
3274             || anArgCase == "left"
3275             || anArgCase == "-l"
3276             || anArgCase == "l")
3277       {
3278         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Left : V3d_TypeOfOrientation_Zup_Left, isYup);
3279       }
3280       else if (anArgCase == "-right"
3281             || anArgCase == "right"
3282             || anArgCase == "-r"
3283             || anArgCase == "r")
3284       {
3285         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Right : V3d_TypeOfOrientation_Zup_Right, isYup);
3286       }
3287       else if (anArgCase == "-axoleft"
3288             || anArgCase == "-leftaxo"
3289             || anArgCase == "axoleft"
3290             || anArgCase == "leftaxo")
3291       {
3292         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoLeft : V3d_TypeOfOrientation_Zup_AxoLeft, isYup);
3293       }
3294       else if (anArgCase == "-axo"
3295             || anArgCase == "axo"
3296             || anArgCase == "-a"
3297             || anArgCase == "a"
3298             || anArgCase == "-axoright"
3299             || anArgCase == "-rightaxo"
3300             || anArgCase == "axoright"
3301             || anArgCase == "rightaxo")
3302       {
3303         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoRight : V3d_TypeOfOrientation_Zup_AxoRight, isYup);
3304       }
3305       else if (anArgCase == "+x")
3306       {
3307         aView->SetProj (V3d_Xpos, isYup);
3308       }
3309       else if (anArgCase == "-x")
3310       {
3311         aView->SetProj (V3d_Xneg, isYup);
3312       }
3313       else if (anArgCase == "+y")
3314       {
3315         aView->SetProj (V3d_Ypos, isYup);
3316       }
3317       else if (anArgCase == "-y")
3318       {
3319         aView->SetProj (V3d_Yneg, isYup);
3320       }
3321       else if (anArgCase == "+z")
3322       {
3323         aView->SetProj (V3d_Zpos, isYup);
3324       }
3325       else if (anArgCase == "-z")
3326       {
3327         aView->SetProj (V3d_Zneg, isYup);
3328       }
3329       else if (anArgCase == "+x+y+z")
3330       {
3331         aView->SetProj (V3d_XposYposZpos, isYup);
3332       }
3333       else if (anArgCase == "+x+y-z")
3334       {
3335         aView->SetProj (V3d_XposYposZneg, isYup);
3336       }
3337       else if (anArgCase == "+x-y+z")
3338       {
3339         aView->SetProj (V3d_XposYnegZpos, isYup);
3340       }
3341       else if (anArgCase == "+x-y-z")
3342       {
3343         aView->SetProj (V3d_XposYnegZneg, isYup);
3344       }
3345       else if (anArgCase == "-x+y+z")
3346       {
3347         aView->SetProj (V3d_XnegYposZpos, isYup);
3348       }
3349       else if (anArgCase == "-x+y-z")
3350       {
3351         aView->SetProj (V3d_XnegYposZneg, isYup);
3352       }
3353       else if (anArgCase == "-x-y+z")
3354       {
3355         aView->SetProj (V3d_XnegYnegZpos, isYup);
3356       }
3357       else if (anArgCase == "-x-y-z")
3358       {
3359         aView->SetProj (V3d_XnegYnegZneg, isYup);
3360       }
3361       else if (anArgCase == "+x+y")
3362       {
3363         aView->SetProj (V3d_XposYpos, isYup);
3364       }
3365       else if (anArgCase == "+x-y")
3366       {
3367         aView->SetProj (V3d_XposYneg, isYup);
3368       }
3369       else if (anArgCase == "-x+y")
3370       {
3371         aView->SetProj (V3d_XnegYpos, isYup);
3372       }
3373       else if (anArgCase == "-x-y")
3374       {
3375         aView->SetProj (V3d_XnegYneg, isYup);
3376       }
3377       else if (anArgCase == "+x+z")
3378       {
3379         aView->SetProj (V3d_XposZpos, isYup);
3380       }
3381       else if (anArgCase == "+x-z")
3382       {
3383         aView->SetProj (V3d_XposZneg, isYup);
3384       }
3385       else if (anArgCase == "-x+z")
3386       {
3387         aView->SetProj (V3d_XnegZpos, isYup);
3388       }
3389       else if (anArgCase == "-x-z")
3390       {
3391         aView->SetProj (V3d_XnegZneg, isYup);
3392       }
3393       else if (anArgCase == "+y+z")
3394       {
3395         aView->SetProj (V3d_YposZpos, isYup);
3396       }
3397       else if (anArgCase == "+y-z")
3398       {
3399         aView->SetProj (V3d_YposZneg, isYup);
3400       }
3401       else if (anArgCase == "-y+z")
3402       {
3403         aView->SetProj (V3d_YnegZpos, isYup);
3404       }
3405       else if (anArgCase == "-y-z")
3406       {
3407         aView->SetProj (V3d_YnegZneg, isYup);
3408       }