0027860: Visualization - clean up Transformation Persistence API
[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 #include <AIS_ColorScale.hxx>
19 #include <AIS_Manipulator.hxx>
20 #include <AIS_RubberBand.hxx>
21 #include <AIS_Shape.hxx>
22 #include <AIS_InteractiveObject.hxx>
23 #include <AIS_ListOfInteractive.hxx>
24 #include <AIS_ListIteratorOfListOfInteractive.hxx>
25 #include <DBRep.hxx>
26 #include <Graphic3d_ArrayOfPolylines.hxx>
27 #include <Graphic3d_AspectMarker3d.hxx>
28 #include <Graphic3d_ExportFormat.hxx>
29 #include <Graphic3d_NameOfTextureEnv.hxx>
30 #include <Graphic3d_GraduatedTrihedron.hxx>
31 #include <Graphic3d_TextureEnv.hxx>
32 #include <Graphic3d_TextureParams.hxx>
33 #include <Graphic3d_TypeOfTextureFilter.hxx>
34 #include <Graphic3d_AspectFillArea3d.hxx>
35 #include <ViewerTest.hxx>
36 #include <ViewerTest_AutoUpdater.hxx>
37 #include <ViewerTest_EventManager.hxx>
38 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
39 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
40 #include <ViewerTest_CmdParser.hxx>
41 #include <V3d_AmbientLight.hxx>
42 #include <V3d_DirectionalLight.hxx>
43 #include <V3d_PositionalLight.hxx>
44 #include <V3d_SpotLight.hxx>
45 #include <NCollection_DoubleMap.hxx>
46 #include <NCollection_List.hxx>
47 #include <NCollection_Vector.hxx>
48 #include <AIS_InteractiveContext.hxx>
49 #include <Draw_Interpretor.hxx>
50 #include <Draw.hxx>
51 #include <Draw_Appli.hxx>
52 #include <Image_AlienPixMap.hxx>
53 #include <OpenGl_GraphicDriver.hxx>
54 #include <OSD_Timer.hxx>
55 #include <TColStd_HSequenceOfAsciiString.hxx>
56 #include <TColStd_SequenceOfInteger.hxx>
57 #include <TColStd_HSequenceOfReal.hxx>
58 #include <TColgp_Array1OfPnt2d.hxx>
59 #include <TColStd_MapOfAsciiString.hxx>
60 #include <Aspect_TypeOfLine.hxx>
61 #include <Image_Diff.hxx>
62 #include <Aspect_DisplayConnection.hxx>
63 #include <gp_Pnt.hxx>
64 #include <gp_Dir.hxx>
65 #include <gp_Pln.hxx>
66 #include <PrsMgr_PresentableObject.hxx>
67 #include <Graphic3d_ClipPlane.hxx>
68 #include <NCollection_DataMap.hxx>
69 #include <Graphic3d_Texture2Dmanual.hxx>
70 #include <Prs3d_ShadingAspect.hxx>
71 #include <Prs3d_Drawer.hxx>
72 #include <Prs3d_LineAspect.hxx>
73 #include <Prs3d_Root.hxx>
74
75 #ifdef _WIN32
76 #undef DrawText
77 #endif
78
79 #include <cstdlib>
80
81 #if defined(_WIN32)
82   #include <WNT_WClass.hxx>
83   #include <WNT_Window.hxx>
84 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
85   #include <Cocoa_Window.hxx>
86 #else
87   #include <Xw_Window.hxx>
88   #include <X11/Xlib.h> /* contains some dangerous #defines such as Status, True etc. */
89   #include <X11/Xutil.h>
90   #include <tk.h>
91 #endif
92
93 // Auxiliary definitions
94 static const char THE_KEY_DELETE = 127;
95
96 //==============================================================================
97 //  VIEWER GLOBAL VARIABLES
98 //==============================================================================
99
100 Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
101 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
102
103 Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
104 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
105
106 extern int VErase (Draw_Interpretor& theDI,
107                    Standard_Integer  theArgNb,
108                    const char**      theArgVec);
109
110 #if defined(_WIN32)
111 static Handle(WNT_Window)& VT_GetWindow() {
112   static Handle(WNT_Window) WNTWin;
113   return WNTWin;
114 }
115 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
116 static Handle(Cocoa_Window)& VT_GetWindow()
117 {
118   static Handle(Cocoa_Window) aWindow;
119   return aWindow;
120 }
121 extern void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow);
122 extern void SetCocoaWindowTitle (const Handle(Cocoa_Window)& theWindow, Standard_CString theTitle);
123 extern void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight);
124
125 #else
126 static Handle(Xw_Window)& VT_GetWindow(){
127   static Handle(Xw_Window) XWWin;
128   return XWWin;
129 }
130
131 static void VProcessEvents(ClientData,int);
132 #endif
133
134 static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
135 {
136   static Handle(Aspect_DisplayConnection) aDisplayConnection;
137   return aDisplayConnection;
138 }
139
140 static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
141 {
142   GetDisplayConnection() = theDisplayConnection;
143 }
144
145 #if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
146 Aspect_Handle GetWindowHandle(const Handle(Aspect_Window)& theWindow)
147 {
148   Aspect_Handle aWindowHandle = (Aspect_Handle)NULL;
149 #if defined(_WIN32)
150   const Handle (WNT_Window) aWindow = Handle(WNT_Window)::DownCast (theWindow);
151   if (!aWindow.IsNull())
152     return aWindow->HWindow();
153 #elif (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
154   const Handle (Xw_Window) aWindow = Handle(Xw_Window)::DownCast (theWindow);
155   if (!aWindow.IsNull())
156   return aWindow->XWindow();
157 #endif
158   return aWindowHandle;
159 }
160 #endif
161
162 static Standard_Boolean MyHLRIsOn = Standard_False;
163
164 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
165 static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>  ViewerTest_myContexts;
166 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
167 static OpenGl_Caps ViewerTest_myDefaultCaps;
168
169 static void OSWindowSetup();
170
171 static struct
172 {
173   Quantity_Color FlatColor;
174   Quantity_Color GradientColor1;
175   Quantity_Color GradientColor2;
176   Aspect_GradientFillMethod FillMethod;
177 } ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
178
179 //==============================================================================
180 //  EVENT GLOBAL VARIABLES
181 //==============================================================================
182
183 static int Start_Rot = 0;
184 int X_Motion = 0; // Current cursor position
185 int Y_Motion = 0;
186 int X_ButtonPress = 0; // Last ButtonPress position
187 int Y_ButtonPress = 0;
188 Standard_Boolean IsDragged = Standard_False;
189 Standard_Boolean DragFirst = Standard_False;
190
191
192 Standard_EXPORT const Handle(AIS_RubberBand)& GetRubberBand()
193 {
194   static Handle(AIS_RubberBand) aBand;
195   if (aBand.IsNull())
196   {
197     aBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
198     aBand->SetDisplayMode (0);
199   }
200   return aBand;
201 }
202
203 typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
204
205 Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
206 {
207   static ViewerTest_MapOfAISManipulators aMap;
208   return aMap;
209 }
210
211 Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
212 {
213   ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
214   for (; anIt.More(); anIt.Next())
215   {
216     if (anIt.Value()->HasActiveMode())
217     {
218       return anIt.Value();
219     }
220   }
221   return NULL;
222 }
223
224 //==============================================================================
225
226 #ifdef _WIN32
227 static LRESULT WINAPI ViewerWindowProc(
228                                        HWND hwnd,
229                                        UINT uMsg,
230                                        WPARAM wParam,
231                                        LPARAM lParam );
232 static LRESULT WINAPI AdvViewerWindowProc(
233   HWND hwnd,
234   UINT uMsg,
235   WPARAM wParam,
236   LPARAM lParam );
237 #endif
238
239
240 //==============================================================================
241 //function : WClass
242 //purpose  :
243 //==============================================================================
244
245 const Handle(MMgt_TShared)& ViewerTest::WClass()
246 {
247   static Handle(MMgt_TShared) theWClass;
248 #if defined(_WIN32)
249   if (theWClass.IsNull())
250   {
251     theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
252       CS_VREDRAW | CS_HREDRAW, 0, 0,
253       ::LoadCursor (NULL, IDC_ARROW));
254   }
255 #endif
256   return theWClass;
257 }
258
259 //==============================================================================
260 //function : CreateName
261 //purpose  : Create numerical name for new object in theMap
262 //==============================================================================
263 template <typename ObjectType>
264 TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
265                                     const TCollection_AsciiString& theDefaultString)
266 {
267   if (theObjectMap.IsEmpty())
268     return theDefaultString + TCollection_AsciiString(1);
269
270   Standard_Integer aNextKey = 1;
271   Standard_Boolean isFound = Standard_False;
272   while (!isFound)
273   {
274     TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
275     // Look for objects with default names
276     if (theObjectMap.IsBound1(aStringKey))
277     {
278       aNextKey++;
279     }
280     else
281       isFound = Standard_True;
282   }
283
284   return theDefaultString + TCollection_AsciiString(aNextKey);
285 }
286
287 //==============================================================================
288 //structure : ViewerTest_Names
289 //purpose   : Allow to operate with full view name: driverName/viewerName/viewName
290 //==============================================================================
291 struct ViewerTest_Names
292 {
293 private:
294   TCollection_AsciiString myDriverName;
295   TCollection_AsciiString myViewerName;
296   TCollection_AsciiString myViewName;
297
298 public:
299
300   const TCollection_AsciiString& GetDriverName () const
301   {
302     return myDriverName;
303   }
304   void SetDriverName (const TCollection_AsciiString& theDriverName)
305   {
306     myDriverName = theDriverName;
307   }
308   const TCollection_AsciiString& GetViewerName () const
309   {
310     return myViewerName;
311   }
312   void SetViewerName (const TCollection_AsciiString& theViewerName)
313   {
314     myViewerName = theViewerName;
315   }
316   const TCollection_AsciiString& GetViewName () const
317   {
318     return myViewName;
319   }
320   void SetViewName (const TCollection_AsciiString& theViewName)
321   {
322     myViewName = theViewName;
323   }
324
325   //===========================================================================
326   //function : Constructor for ViewerTest_Names
327   //purpose  : Get view, viewer, driver names from custom string
328   //===========================================================================
329
330   ViewerTest_Names (const TCollection_AsciiString& theInputString)
331   {
332     TCollection_AsciiString aName(theInputString);
333     if (theInputString.IsEmpty())
334     {
335       // Get current configuration
336       if (ViewerTest_myDrivers.IsEmpty())
337         myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
338           (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
339       else
340         myDriverName = ViewerTest_myDrivers.Find2
341         (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
342
343       if(ViewerTest_myContexts.IsEmpty())
344       {
345         myViewerName = CreateName <Handle(AIS_InteractiveContext)>
346           (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
347       }
348       else
349         myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
350
351         myViewName = CreateName <Handle(V3d_View)>
352           (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
353     }
354     else
355     {
356       // There is at least view name
357       Standard_Integer aParserNumber = 0;
358       for (Standard_Integer i = 0; i < 3; ++i)
359       {
360         Standard_Integer aParserPos = aName.SearchFromEnd("/");
361         if(aParserPos != -1)
362         {
363           aParserNumber++;
364           aName.Split(aParserPos-1);
365         }
366         else
367           break;
368       }
369       if (aParserNumber == 0)
370       {
371         // Only view name
372         if (!ViewerTest::GetAISContext().IsNull())
373         {
374           myDriverName = ViewerTest_myDrivers.Find2
375           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
376           myViewerName = ViewerTest_myContexts.Find2
377           (ViewerTest::GetAISContext());
378         }
379         else
380         {
381           // There is no opened contexts here, need to create names for viewer and driver
382           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
383             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
384
385           myViewerName = CreateName <Handle(AIS_InteractiveContext)>
386             (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
387         }
388         myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
389       }
390       else if (aParserNumber == 1)
391       {
392         // Here is viewerName/viewName
393         if (!ViewerTest::GetAISContext().IsNull())
394           myDriverName = ViewerTest_myDrivers.Find2
395           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
396         else
397         {
398           // There is no opened contexts here, need to create name for driver
399           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
400             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
401         }
402         myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
403
404         myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
405       }
406       else
407       {
408         //Here is driverName/viewerName/viewName
409         myDriverName = TCollection_AsciiString(aName);
410
411         TCollection_AsciiString aViewerName(theInputString);
412         aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
413         myViewerName = TCollection_AsciiString(aViewerName);
414
415         myViewName = TCollection_AsciiString(theInputString);
416       }
417     }
418   }
419 };
420
421 //==============================================================================
422 //function : FindContextByView
423 //purpose  : Find AIS_InteractiveContext by View
424 //==============================================================================
425
426 Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
427 {
428   Handle(AIS_InteractiveContext) anAISContext;
429
430   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
431        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
432   {
433     if (anIter.Value()->CurrentViewer() == theView->Viewer())
434        return anIter.Key2();
435   }
436   return anAISContext;
437 }
438
439
440 //==============================================================================
441 //function : SetWindowTitle
442 //purpose  : Set window title
443 //==============================================================================
444
445 void SetWindowTitle (const Handle(Aspect_Window)& theWindow,
446                      Standard_CString theTitle)
447 {
448 #if defined(_WIN32)
449   SetWindowText ((HWND)Handle(WNT_Window)::DownCast(theWindow)->HWindow(),
450     theTitle);
451 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
452   SetCocoaWindowTitle (Handle(Cocoa_Window)::DownCast(theWindow), theTitle);
453 #else
454   if(GetDisplayConnection()->GetDisplay())
455   {
456     Window aWindow =
457       Handle(Xw_Window)::DownCast(theWindow)->XWindow();
458     XStoreName (GetDisplayConnection()->GetDisplay(), aWindow , theTitle);
459   }
460 #endif
461 }
462
463 //==============================================================================
464 //function : IsWindowOverlapped
465 //purpose  : Check if theWindow overlapp another view
466 //==============================================================================
467
468 Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
469                                      const Standard_Integer thePxTop,
470                                      const Standard_Integer thePxRight,
471                                      const Standard_Integer thePxBottom,
472                                      TCollection_AsciiString& theViewId)
473 {
474   for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
475       anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
476   {
477     Standard_Integer aTop = 0,
478       aLeft = 0,
479       aRight = 0,
480       aBottom = 0;
481     anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
482     if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
483         (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
484         (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
485         (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
486     {
487       theViewId = anIter.Key1();
488       return Standard_True;
489     }
490   }
491   return Standard_False;
492 }
493
494 // Workaround: to create and delete non-orthographic views outside ViewerTest
495 void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
496 {
497   ViewerTest_myViews.UnBind1 (theName);
498 }
499
500 void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
501                                const Handle(V3d_View)& theView)
502 {
503   ViewerTest_myViews.Bind (theName, theView);
504 }
505
506 TCollection_AsciiString ViewerTest::GetCurrentViewName ()
507 {
508   return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
509 }
510 //==============================================================================
511 //function : ViewerInit
512 //purpose  : Create the window viewer and initialize all the global variable
513 //==============================================================================
514
515 TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
516                                                 const Standard_Integer thePxTop,
517                                                 const Standard_Integer thePxWidth,
518                                                 const Standard_Integer thePxHeight,
519                                                 Standard_CString theViewName,
520                                                 Standard_CString theDisplayName)
521 {
522   // Default position and dimension of the viewer window.
523   // Note that left top corner is set to be sufficiently small to have
524   // window fit in the small screens (actual for remote desktops, see #23003).
525   // The position corresponds to the window's client area, thus some
526   // gap is added for window frame to be visible.
527   Standard_Integer aPxLeft   = 20;
528   Standard_Integer aPxTop    = 40;
529   Standard_Integer aPxWidth  = 409;
530   Standard_Integer aPxHeight = 409;
531   Standard_Boolean toCreateViewer = Standard_False;
532
533   Handle(OpenGl_GraphicDriver) aGraphicDriver;
534   ViewerTest_Names aViewNames(theViewName);
535   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
536     aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
537
538   if (thePxLeft != 0)
539     aPxLeft = thePxLeft;
540   if (thePxTop != 0)
541     aPxTop = thePxTop;
542   if (thePxWidth != 0)
543     aPxWidth = thePxWidth;
544   if (thePxHeight != 0)
545     aPxHeight = thePxHeight;
546
547   // Get graphic driver (create it or get from another view)
548   if (!ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName()))
549   {
550     // Get connection string
551   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
552     TCollection_AsciiString aDisplayName(theDisplayName);
553     if (!aDisplayName.IsEmpty())
554       SetDisplayConnection (new Aspect_DisplayConnection ());
555     else
556       SetDisplayConnection (new Aspect_DisplayConnection (aDisplayName));
557   #else
558     (void)theDisplayName; // avoid warning on unused argument
559     SetDisplayConnection (new Aspect_DisplayConnection ());
560   #endif
561
562     if (Draw_VirtualWindows)
563     {
564       // don't waste the time waiting for VSync when window is not displayed on the screen
565       ViewerTest_myDefaultCaps.swapInterval = 0;
566       // alternatively we can disable buffer swap at all, but this might be inappropriate for testing
567       //ViewerTest_myDefaultCaps.buffersNoSwap = true;
568     }
569     aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection());
570     aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
571
572     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
573     toCreateViewer = Standard_True;
574   }
575   else
576   {
577     aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
578   }
579
580   //Dispose the window if input parameters are default
581   if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
582   {
583     Standard_Integer aTop = 0,
584                      aLeft = 0,
585                      aRight = 0,
586                      aBottom = 0,
587                      aScreenWidth = 0,
588                      aScreenHeight = 0;
589
590     // Get screen resolution
591 #if defined(_WIN32) || defined(__WIN32__)
592     RECT aWindowSize;
593     GetClientRect(GetDesktopWindow(), &aWindowSize);
594     aScreenHeight = aWindowSize.bottom;
595     aScreenWidth = aWindowSize.right;
596 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
597     GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
598 #else
599     Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
600     aScreenWidth = WidthOfScreen(aScreen);
601     aScreenHeight = HeightOfScreen(aScreen);
602 #endif
603
604     TCollection_AsciiString anOverlappedViewId("");
605
606     while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
607     {
608       ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
609
610       if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
611         && aRight + 2*aPxWidth + 40 > aScreenWidth)
612       {
613         if (aBottom + aPxHeight + 40 > aScreenHeight)
614         {
615           aPxLeft = 20;
616           aPxTop = 40;
617           break;
618         }
619         aPxLeft = 20;
620         aPxTop = aBottom + 40;
621       }
622       else
623         aPxLeft = aRight + 20;
624     }
625   }
626
627   // Get viewer name
628   TCollection_AsciiString aTitle("3D View - ");
629   aTitle = aTitle + aViewNames.GetViewName() + "(*)";
630
631   // Change name of current active window
632   if (!ViewerTest::CurrentView().IsNull())
633   {
634     TCollection_AsciiString anActiveWindowTitle("3D View - ");
635     anActiveWindowTitle = anActiveWindowTitle
636       + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
637     SetWindowTitle (ViewerTest::CurrentView()->Window(), anActiveWindowTitle.ToCString());
638   }
639
640   // Create viewer
641   Handle(V3d_Viewer) a3DViewer;
642   // If it's the single view, we first look for empty context
643   if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
644   {
645     NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
646       anIter(ViewerTest_myContexts);
647     if (anIter.More())
648       ViewerTest::SetAISContext (anIter.Value());
649     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
650   }
651   else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
652   {
653     ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
654     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
655   }
656   else if (a3DViewer.IsNull())
657   {
658     toCreateViewer = Standard_True;
659     TCollection_ExtendedString NameOfWindow("Viewer3D");
660     a3DViewer = new V3d_Viewer(aGraphicDriver, NameOfWindow.ToExtString());
661     a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
662     a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
663                                            ViewerTest_DefaultBackground.GradientColor2,
664                                            ViewerTest_DefaultBackground.FillMethod);
665   }
666
667   // AIS context setup
668   if (ViewerTest::GetAISContext().IsNull() ||
669       !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
670   {
671     Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
672     ViewerTest::SetAISContext (aContext);
673     ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
674   }
675   else
676   {
677     ViewerTest::ResetEventManager();
678   }
679
680   // Create window
681 #if defined(_WIN32)
682   VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
683                                     Handle(WNT_WClass)::DownCast (WClass()),
684                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
685                                     aPxLeft, aPxTop,
686                                     aPxWidth, aPxHeight,
687                                     Quantity_NOC_BLACK);
688 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
689   VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
690                                      aPxLeft, aPxTop,
691                                      aPxWidth, aPxHeight);
692   ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
693 #else
694   VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
695                                   aTitle.ToCString(),
696                                   aPxLeft, aPxTop,
697                                   aPxWidth, aPxHeight);
698 #endif
699   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
700
701   // View setup
702   Handle(V3d_View) aView = a3DViewer->CreateView();
703   aView->SetWindow (VT_GetWindow());
704   ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
705
706   ViewerTest::CurrentView(aView);
707   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
708
709   // Setup for X11 or NT
710   OSWindowSetup();
711
712   // Set parameters for V3d_View and V3d_Viewer
713   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
714   aV3dView->SetComputedMode(Standard_False);
715   MyHLRIsOn = aV3dView->ComputedMode();
716
717   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
718   if (toCreateViewer)
719   {
720     a3DViewer->SetDefaultLights();
721     a3DViewer->SetLightOn();
722   }
723
724   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
725   #if TCL_MAJOR_VERSION  < 8
726   Tk_CreateFileHandler((void*)XConnectionNumber(GetDisplayConnection()->GetDisplay()),
727       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
728   #else
729   Tk_CreateFileHandler(XConnectionNumber(GetDisplayConnection()->GetDisplay()),
730       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
731   #endif
732   #endif
733
734   VT_GetWindow()->Map();
735
736   // Set the handle of created view in the event manager
737   ViewerTest::ResetEventManager();
738
739   ViewerTest::CurrentView()->Redraw();
740
741   aView.Nullify();
742   a3DViewer.Nullify();
743
744   return aViewNames.GetViewName();
745 }
746
747 //==============================================================================
748 //function : RedrawAllViews
749 //purpose  : Redraw all created views
750 //==============================================================================
751 void ViewerTest::RedrawAllViews()
752 {
753   NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
754   for (; aViewIt.More(); aViewIt.Next())
755   {
756     const Handle(V3d_View)& aView = aViewIt.Key2();
757     aView->Redraw();
758   }
759 }
760
761 //==============================================================================
762 //function : Vinit
763 //purpose  : Create the window viewer and initialize all the global variable
764 //    Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
765 //==============================================================================
766
767 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
768 {
769   if (theArgsNb > 9)
770   {
771     std::cerr << theArgVec[0] << ": incorrect number of command arguments.\n"
772               << "Type help for more information.\n";
773     return 1;
774   }
775
776   TCollection_AsciiString aViewName, aDisplayName;
777   Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
778   TCollection_AsciiString aName, aValue;
779   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
780   {
781     const TCollection_AsciiString anArg = theArgVec[anArgIt];
782     TCollection_AsciiString anArgCase = anArg;
783     anArgCase.UpperCase();
784     if (ViewerTest::SplitParameter (anArg, aName, aValue))
785     {
786       aName.UpperCase();
787       if (aName.IsEqual ("NAME"))
788       {
789         aViewName = aValue;
790       }
791       else if (aName.IsEqual ("L")
792             || aName.IsEqual ("LEFT"))
793       {
794         aPxLeft = aValue.IntegerValue();
795       }
796       else if (aName.IsEqual ("T")
797             || aName.IsEqual ("TOP"))
798       {
799         aPxTop = aValue.IntegerValue();
800       }
801     #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
802       else if (aName.IsEqual ("DISP")
803             || aName.IsEqual ("DISPLAY"))
804       {
805         aDisplayName = aValue;
806       }
807     #endif
808       else if (aName.IsEqual ("W")
809             || aName.IsEqual ("WIDTH"))
810       {
811         aPxWidth = aValue.IntegerValue();
812       }
813       else if (aName.IsEqual ("H")
814             || aName.IsEqual ("HEIGHT"))
815       {
816         aPxHeight = aValue.IntegerValue();
817       }
818       else
819       {
820         std::cerr << theArgVec[0] << ": Warning: unknown argument " << anArg << ".\n";
821       }
822     }
823     else if (aViewName.IsEmpty())
824     {
825       aViewName = anArg;
826     }
827     else
828     {
829       std::cerr << theArgVec[0] << ": Warning: unknown argument " << anArg << ".\n";
830     }
831   }
832
833   ViewerTest_Names aViewNames (aViewName);
834   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
835   {
836     TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
837     theDi.Eval (aCommand.ToCString());
838     return 0;
839   }
840
841   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
842                                                             aViewName.ToCString(),
843                                                             aDisplayName.ToCString());
844   theDi << aViewId;
845   return 0;
846 }
847
848 //==============================================================================
849 //function : VHLR
850 //purpose  : hidden lines removal algorithm
851 //draw args: vhlr is_enabled={on|off} [show_hidden={1|0}]
852 //==============================================================================
853
854 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
855 {
856   if (ViewerTest::CurrentView().IsNull())
857   {
858     di << argv[0] << ": Call vinit before this command, please.\n";
859     return 1;
860   }
861
862   if (argc < 2)
863   {
864     di << argv[0] << ": Wrong number of command arguments.\n"
865       << "Type help " << argv[0] << " for more information.\n";
866     return 1;
867   }
868
869   // Enable or disable HLR mode.
870   Standard_Boolean isHLROn =
871     (!strcasecmp (argv[1], "on")) ? Standard_True : Standard_False;
872
873   if (isHLROn != MyHLRIsOn)
874   {
875     MyHLRIsOn = isHLROn;
876     ViewerTest::CurrentView()->SetComputedMode (MyHLRIsOn);
877   }
878
879   // Show or hide hidden lines in HLR mode.
880   Standard_Boolean isCurrentShowHidden
881     = ViewerTest::GetAISContext()->DefaultDrawer()->DrawHiddenLine();
882
883   Standard_Boolean isShowHidden =
884     (argc == 3) ? (atoi(argv[2]) == 1 ? Standard_True : Standard_False)
885                 : isCurrentShowHidden;
886
887
888   if (isShowHidden != isCurrentShowHidden)
889   {
890     if (isShowHidden)
891     {
892       ViewerTest::GetAISContext()->DefaultDrawer()->EnableDrawHiddenLine();
893     }
894     else
895     {
896       ViewerTest::GetAISContext()->DefaultDrawer()->DisableDrawHiddenLine();
897     }
898
899     // Redisplay shapes.
900     if (MyHLRIsOn)
901     {
902       AIS_ListOfInteractive aListOfShapes;
903       ViewerTest::GetAISContext()->DisplayedObjects (aListOfShapes);
904
905       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
906       {
907         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (anIter.Value());
908         if (aShape.IsNull())
909         {
910           continue;
911         }
912         ViewerTest::GetAISContext()->Redisplay (aShape, Standard_False);
913       }
914     }
915   }
916
917   ViewerTest::CurrentView()->Update();
918   return 0;
919 }
920
921 //==============================================================================
922 //function : VHLRType
923 //purpose  : change type of using HLR algorithm
924 //==============================================================================
925
926 static int VHLRType (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
927 {
928   if (ViewerTest::CurrentView().IsNull())
929   {
930     di << argv[0] << ": Call vinit before this command, please.\n";
931     return 1;
932   }
933
934   if (argc < 2)
935   {
936     di << argv[0] << ": Wrong number of command arguments.\n"
937       << "Type help " << argv[0] << " for more information.\n";
938     return 1;
939   }
940
941   Prs3d_TypeOfHLR aTypeOfHLR =
942     (!strcasecmp (argv[1], "algo")) ? Prs3d_TOH_Algo : Prs3d_TOH_PolyAlgo;
943
944   if (argc == 2)
945   {
946     AIS_ListOfInteractive aListOfShapes;
947     ViewerTest::GetAISContext()->DisplayedObjects (aListOfShapes);
948     ViewerTest::GetAISContext()->DefaultDrawer()->SetTypeOfHLR(aTypeOfHLR);
949     for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
950       anIter.More(); anIter.Next())
951     {
952       Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
953       if (aShape.IsNull())
954         continue;
955       if (aShape->TypeOfHLR() != aTypeOfHLR)
956         aShape->SetTypeOfHLR (aTypeOfHLR);
957       if (MyHLRIsOn)
958         ViewerTest::GetAISContext()->Redisplay (aShape, Standard_False);
959     }
960     ViewerTest::CurrentView()->Update();
961     return 0;
962   }
963   else
964   {
965     for (Standard_Integer i = 2; i < argc; ++i)
966     {
967       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
968       TCollection_AsciiString aName (argv[i]);
969
970       if (!aMap.IsBound2 (aName))
971       {
972         di << argv[0] << ": Wrong shape name:" << aName.ToCString() << ".\n";
973         continue;
974       }
975       Handle(AIS_Shape) anAISObject =
976         Handle(AIS_Shape)::DownCast (aMap.Find2(aName));
977       if (anAISObject.IsNull())
978         continue;
979       anAISObject->SetTypeOfHLR (aTypeOfHLR);
980       if (MyHLRIsOn)
981         ViewerTest::GetAISContext()->Redisplay (anAISObject, Standard_False);
982     }
983     ViewerTest::CurrentView()->Update();
984   }
985
986   return 0;
987 }
988
989 //==============================================================================
990 //function : FindViewIdByWindowHandle
991 //purpose  : Find theView Id in the map of views by window handle
992 //==============================================================================
993 #if defined(_WIN32) || defined(__WIN32__) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
994 TCollection_AsciiString FindViewIdByWindowHandle(const Aspect_Handle theWindowHandle)
995 {
996   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
997        anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
998   {
999     Aspect_Handle aWindowHandle = GetWindowHandle(anIter.Value()->Window());
1000     if (aWindowHandle == theWindowHandle)
1001       return anIter.Key1();
1002   }
1003   return TCollection_AsciiString("");
1004 }
1005 #endif
1006
1007 //==============================================================================
1008 //function : ActivateView
1009 //purpose  : Make the view active
1010 //==============================================================================
1011
1012 void ActivateView (const TCollection_AsciiString& theViewName)
1013 {
1014   const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1015   if (!aView.IsNull())
1016   {
1017     Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
1018     if (!anAISContext.IsNull())
1019     {
1020       if (!ViewerTest::CurrentView().IsNull())
1021       {
1022         TCollection_AsciiString aTitle("3D View - ");
1023         aTitle = aTitle + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
1024         SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1025       }
1026
1027       ViewerTest::CurrentView (aView);
1028       // Update degenerate mode
1029       MyHLRIsOn = ViewerTest::CurrentView()->ComputedMode();
1030       ViewerTest::SetAISContext (anAISContext);
1031       TCollection_AsciiString aTitle = TCollection_AsciiString("3D View - ");
1032       aTitle = aTitle + theViewName + "(*)";
1033       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1034 #if defined(_WIN32) || defined(__WIN32__)
1035       VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
1036 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1037       VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
1038 #else
1039       VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
1040 #endif
1041       SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
1042       ViewerTest::CurrentView()->Redraw();
1043     }
1044   }
1045 }
1046
1047 //==============================================================================
1048 //function : RemoveView
1049 //purpose  :
1050 //==============================================================================
1051 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
1052                              const Standard_Boolean  theToRemoveContext)
1053 {
1054   if (!ViewerTest_myViews.IsBound2 (theView))
1055   {
1056     return;
1057   }
1058
1059   const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
1060   RemoveView (aViewName, theToRemoveContext);
1061 }
1062
1063 //==============================================================================
1064 //function : RemoveView
1065 //purpose  : Close and remove view from display, clear maps if neccessary
1066 //==============================================================================
1067 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
1068 {
1069   if (!ViewerTest_myViews.IsBound1(theViewName))
1070   {
1071     cout << "Wrong view name\n";
1072     return;
1073   }
1074
1075   // Activate another view if it's active now
1076   if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
1077   {
1078     if (ViewerTest_myViews.Extent() > 1)
1079     {
1080       TCollection_AsciiString aNewViewName;
1081       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> :: Iterator
1082            anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1083         if (anIter.Key1() != theViewName)
1084         {
1085           aNewViewName = anIter.Key1();
1086           break;
1087         }
1088         ActivateView (aNewViewName);
1089     }
1090     else
1091     {
1092       Handle(V3d_View) anEmptyView;
1093 #if defined(_WIN32) || defined(__WIN32__)
1094       Handle(WNT_Window) anEmptyWindow;
1095 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1096       Handle(Cocoa_Window) anEmptyWindow;
1097 #else
1098       Handle(Xw_Window) anEmptyWindow;
1099 #endif
1100       VT_GetWindow() = anEmptyWindow;
1101       ViewerTest::CurrentView (anEmptyView);
1102       if (isContextRemoved)
1103       {
1104         Handle(AIS_InteractiveContext) anEmptyContext;
1105         ViewerTest::SetAISContext(anEmptyContext);
1106       }
1107     }
1108   }
1109
1110   // Delete view
1111   Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1112   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
1113
1114   // Remove view resources
1115   ViewerTest_myViews.UnBind1(theViewName);
1116   aView->Remove();
1117
1118 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1119   XFlush (GetDisplayConnection()->GetDisplay());
1120 #endif
1121
1122   // Keep context opened only if the closed view is last to avoid
1123   // unused empty contexts
1124   if (!aCurrentContext.IsNull())
1125   {
1126     // Check if there are more difined views in the viewer
1127     aCurrentContext->CurrentViewer()->InitDefinedViews();
1128     if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
1129     {
1130       // Remove driver if there is no viewers that use it
1131       Standard_Boolean isRemoveDriver = Standard_True;
1132       for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1133           anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
1134       {
1135         if (aCurrentContext != anIter.Key2() &&
1136           aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
1137         {
1138           isRemoveDriver = Standard_False;
1139           break;
1140         }
1141       }
1142       if(isRemoveDriver)
1143       {
1144         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
1145       #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1146         #if TCL_MAJOR_VERSION  < 8
1147         Tk_DeleteFileHandler((void*)XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1148         #else
1149         Tk_DeleteFileHandler(XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1150         #endif
1151       #endif
1152       }
1153
1154       ViewerTest_myContexts.UnBind2(aCurrentContext);
1155     }
1156   }
1157   cout << "3D View - " << theViewName << " was deleted.\n";
1158
1159 }
1160
1161 //==============================================================================
1162 //function : VClose
1163 //purpose  : Remove the view defined by its name
1164 //==============================================================================
1165
1166 static int VClose (Draw_Interpretor& /*theDi*/,
1167                    Standard_Integer  theArgsNb,
1168                    const char**      theArgVec)
1169 {
1170   NCollection_List<TCollection_AsciiString> aViewList;
1171   if (theArgsNb > 1)
1172   {
1173     TCollection_AsciiString anArg (theArgVec[1]);
1174     anArg.UpperCase();
1175     if (anArg.IsEqual ("ALL")
1176      || anArg.IsEqual ("*"))
1177     {
1178       for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1179            anIter.More(); anIter.Next())
1180       {
1181         aViewList.Append (anIter.Key1());
1182       }
1183       if (aViewList.IsEmpty())
1184       {
1185         std::cout << "No view to close\n";
1186         return 0;
1187       }
1188     }
1189     else
1190     {
1191       ViewerTest_Names aViewName (theArgVec[1]);
1192       if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
1193       {
1194         std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
1195         return 1;
1196       }
1197       aViewList.Append (aViewName.GetViewName());
1198     }
1199   }
1200   else
1201   {
1202     // close active view
1203     if (ViewerTest::CurrentView().IsNull())
1204     {
1205       std::cerr << "No active view!\n";
1206       return 1;
1207     }
1208     aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
1209   }
1210
1211   Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
1212   for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
1213        anIter.More(); anIter.Next())
1214   {
1215     ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
1216   }
1217
1218   return 0;
1219 }
1220
1221 //==============================================================================
1222 //function : VActivate
1223 //purpose  : Activate the view defined by its ID
1224 //==============================================================================
1225
1226 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1227 {
1228   if (theArgsNb > 2)
1229   {
1230     theDi << theArgVec[0] << ": wrong number of command arguments.\n"
1231     << "Usage: " << theArgVec[0] << " ViewID\n";
1232     return 1;
1233   }
1234   if(theArgsNb == 1)
1235   {
1236     theDi.Eval("vviewlist");
1237     return 0;
1238   }
1239
1240   TCollection_AsciiString aNameString(theArgVec[1]);
1241   if ( strcasecmp( aNameString.ToCString(), "NONE" ) == 0 )
1242   {
1243     TCollection_AsciiString aTitle("3D View - ");
1244     aTitle = aTitle + ViewerTest_myViews.Find2(ViewerTest::CurrentView());
1245     SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1246     Handle(V3d_View) anEmptyView;
1247 #if defined(_WIN32) || defined(__WIN32__)
1248     Handle(WNT_Window) anEmptyWindow;
1249 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1250     Handle(Cocoa_Window) anEmptyWindow;
1251 #else
1252     Handle(Xw_Window) anEmptyWindow;
1253 #endif
1254     VT_GetWindow() = anEmptyWindow;
1255     ViewerTest::CurrentView (anEmptyView);
1256     ViewerTest::ResetEventManager();
1257     theDi << theArgVec[0] << ": all views are inactive\n";
1258     return 0;
1259   }
1260
1261   ViewerTest_Names aViewNames(aNameString);
1262
1263   // Check if this view exists in the viewer with the driver
1264   if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
1265   {
1266     theDi << "Wrong view name\n";
1267     return 1;
1268   }
1269
1270   // Check if it is active already
1271   if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
1272   {
1273     theDi << theArgVec[0] << ": the view is active already\n";
1274     return 0;
1275   }
1276
1277   ActivateView (aViewNames.GetViewName());
1278   return 0;
1279 }
1280
1281 //==============================================================================
1282 //function : VViewList
1283 //purpose  : Print current list of views per viewer and graphic driver ID
1284 //           shared between viewers
1285 //==============================================================================
1286
1287 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1288 {
1289   if (theArgsNb > 2)
1290   {
1291     theDi << theArgVec[0] << ": Wrong number of command arguments\n"
1292           << "Usage: " << theArgVec[0] << " name";
1293     return 1;
1294   }
1295   if (ViewerTest_myContexts.Size() < 1)
1296     return 0;
1297
1298   Standard_Boolean isTreeView =
1299     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
1300
1301   if (isTreeView)
1302     theDi << theArgVec[0] <<":\n";
1303
1304     for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
1305       aDriverIter(ViewerTest_myDrivers); aDriverIter.More(); aDriverIter.Next())
1306     {
1307       if (isTreeView)
1308         theDi << aDriverIter.Key1() << ":\n";
1309
1310       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1311         aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
1312       {
1313         if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
1314         {
1315           if (isTreeView)
1316           {
1317             TCollection_AsciiString aContextName(aContextIter.Key1());
1318             theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
1319           }
1320
1321           for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
1322             aViewIter(ViewerTest_myViews); aViewIter.More(); aViewIter.Next())
1323           {
1324             if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
1325             {
1326               TCollection_AsciiString aViewName(aViewIter.Key1());
1327               if (isTreeView)
1328               {
1329                 if (aViewIter.Value() == ViewerTest::CurrentView())
1330                   theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
1331                 else
1332                   theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
1333               }
1334               else
1335               {
1336                 theDi << aViewName << " ";
1337               }
1338             }
1339           }
1340         }
1341       }
1342     }
1343   return 0;
1344 }
1345
1346 //==============================================================================
1347 //function : VT_ProcessKeyPress
1348 //purpose  : Handle KeyPress event from a CString
1349 //==============================================================================
1350 void VT_ProcessKeyPress (const char* buf_ret)
1351 {
1352   //cout << "KeyPress" << endl;
1353   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1354   // Letter in alphabetic order
1355
1356   if (!strcasecmp (buf_ret, "A"))
1357   {
1358     // AXO
1359     aView->SetProj(V3d_XposYnegZpos);
1360   }
1361   else if (!strcasecmp (buf_ret, "D"))
1362   {
1363     // Reset
1364     aView->Reset();
1365   }
1366   else if (!strcasecmp (buf_ret, "F"))
1367   {
1368     if (ViewerTest::GetAISContext()->NbSelected() > 0)
1369     {
1370       ViewerTest::GetAISContext()->FitSelected (aView);
1371     }
1372     else
1373     {
1374       // FitAll
1375       aView->FitAll();
1376     }
1377   }
1378   else if (!strcasecmp (buf_ret, "H"))
1379   {
1380     // HLR
1381     cout << "HLR" << endl;
1382     aView->SetComputedMode (!aView->ComputedMode());
1383     MyHLRIsOn = aView->ComputedMode();
1384   }
1385   else if (!strcasecmp (buf_ret, "P"))
1386   {
1387     // Type of HLR
1388     Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
1389     if (aContext->DefaultDrawer()->TypeOfHLR() == Prs3d_TOH_Algo)
1390       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_PolyAlgo);
1391     else
1392       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_Algo);
1393     if (aContext->NbSelected()==0)
1394     {
1395       AIS_ListOfInteractive aListOfShapes;
1396       aContext->DisplayedObjects(aListOfShapes);
1397       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
1398         anIter.More(); anIter.Next())
1399       {
1400         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1401         if (aShape.IsNull())
1402           continue;
1403         if (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1404           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1405         else
1406           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1407         aContext->Redisplay (aShape, Standard_False);
1408       }
1409     }
1410     else
1411     {
1412       for (aContext->InitSelected();aContext->MoreSelected();aContext->NextSelected())
1413       {
1414         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aContext->SelectedInteractive());
1415         if (aShape.IsNull())
1416           continue;
1417         if(aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1418           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1419         else
1420           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1421         aContext->Redisplay (aShape, Standard_False);
1422       }
1423     }
1424
1425     aContext->UpdateCurrentViewer();
1426
1427   }
1428   else if (!strcasecmp (buf_ret, "S"))
1429   {
1430     std::cout << "setup Shaded display mode" << std::endl;
1431
1432     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1433     if(Ctx->NbSelected()==0)
1434       Ctx->SetDisplayMode(AIS_Shaded);
1435     else{
1436       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1437         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),1,Standard_False);
1438       Ctx->UpdateCurrentViewer();
1439     }
1440   }
1441   else if (!strcasecmp (buf_ret, "U"))
1442   {
1443     // Unset display mode
1444     std::cout << "reset display mode to defaults" << std::endl;
1445
1446     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1447     if(Ctx->NbSelected()==0)
1448       Ctx->SetDisplayMode(AIS_WireFrame);
1449     else{
1450       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1451         Ctx->UnsetDisplayMode(Ctx->SelectedInteractive(),Standard_False);
1452       Ctx->UpdateCurrentViewer();
1453     }
1454
1455   }
1456   else if (!strcasecmp (buf_ret, "T"))
1457   {
1458     // Top
1459     aView->SetProj(V3d_Zpos);
1460   }
1461   else if (!strcasecmp (buf_ret, "B"))
1462   {
1463     // Bottom
1464     aView->SetProj(V3d_Zneg);
1465   }
1466   else if (!strcasecmp (buf_ret, "L"))
1467   {
1468     // Left
1469     aView->SetProj(V3d_Xneg);
1470   }
1471   else if (!strcasecmp (buf_ret, "R"))
1472   {
1473     // Right
1474     aView->SetProj(V3d_Xpos);
1475   }
1476   else if (!strcasecmp (buf_ret, "W"))
1477   {
1478     std::cout << "setup WireFrame display mode" << std::endl;
1479     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1480     if(Ctx->NbSelected()==0)
1481       Ctx->SetDisplayMode(AIS_WireFrame);
1482     else{
1483       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1484         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),0,Standard_False);
1485       Ctx->UpdateCurrentViewer();
1486     }
1487   }
1488   else if (!strcasecmp (buf_ret, ","))
1489   {
1490     ViewerTest::GetAISContext()->HilightNextDetected(ViewerTest::CurrentView());
1491   }
1492   else if (!strcasecmp (buf_ret, "."))
1493   {
1494     ViewerTest::GetAISContext()->HilightPreviousDetected(ViewerTest::CurrentView());
1495   }
1496   else if (!strcasecmp (buf_ret, "/"))
1497   {
1498     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1499     if (aCamera->IsStereo())
1500     {
1501       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01);
1502       aView->Redraw();
1503     }
1504   }
1505   else if (!strcasecmp (buf_ret, "*"))
1506   {
1507     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1508     if (aCamera->IsStereo())
1509     {
1510       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01);
1511       aView->Redraw();
1512     }
1513   }
1514   else if (*buf_ret == THE_KEY_DELETE)
1515   {
1516     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1517     if (!aCtx.IsNull()
1518      && aCtx->NbSelected() > 0)
1519     {
1520       Draw_Interprete ("verase");
1521     }
1522   }
1523   else
1524   {
1525     // Number
1526     Standard_Integer Num = Draw::Atoi(buf_ret);
1527     if(Num>=0 && Num<=7)
1528       ViewerTest::StandardModeActivation(Num);
1529   }
1530 }
1531
1532 //==============================================================================
1533 //function : VT_ProcessExpose
1534 //purpose  : Redraw the View on an Expose Event
1535 //==============================================================================
1536 void VT_ProcessExpose()
1537 {
1538   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1539   if (!aView3d.IsNull())
1540   {
1541     aView3d->Redraw();
1542   }
1543 }
1544
1545 //==============================================================================
1546 //function : VT_ProcessConfigure
1547 //purpose  : Resize the View on an Configure Event
1548 //==============================================================================
1549 void VT_ProcessConfigure()
1550 {
1551   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1552   if (aView3d.IsNull())
1553   {
1554     return;
1555   }
1556
1557   aView3d->MustBeResized();
1558   aView3d->Update();
1559   aView3d->Redraw();
1560 }
1561
1562 //==============================================================================
1563 //function : VT_ProcessButton1Press
1564 //purpose  : Picking
1565 //==============================================================================
1566 Standard_Boolean VT_ProcessButton1Press (Standard_Integer ,
1567                                          const char**     theArgVec,
1568                                          Standard_Boolean theToPick,
1569                                          Standard_Boolean theIsShift)
1570 {
1571   if (theToPick)
1572   {
1573     Standard_Real X, Y, Z;
1574     ViewerTest::CurrentView()->Convert (X_Motion, Y_Motion, X, Y, Z);
1575
1576     Draw::Set (theArgVec[1], X);
1577     Draw::Set (theArgVec[2], Y);
1578     Draw::Set (theArgVec[3], Z);
1579   }
1580
1581   if (theIsShift)
1582   {
1583     ViewerTest::CurrentEventManager()->ShiftSelect();
1584   }
1585   else
1586   {
1587     ViewerTest::CurrentEventManager()->Select();
1588   }
1589
1590   return Standard_False;
1591 }
1592
1593 //==============================================================================
1594 //function : VT_ProcessButton1Release
1595 //purpose  : End selecting
1596 //==============================================================================
1597 void VT_ProcessButton1Release (Standard_Boolean theIsShift)
1598 {
1599   if (IsDragged)
1600   {
1601     IsDragged = Standard_False;
1602     Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1603     if (theIsShift)
1604     {
1605       EM->ShiftSelect (X_ButtonPress, Y_ButtonPress,
1606                        X_Motion, Y_Motion);
1607     }
1608     else
1609     {
1610       EM->Select (X_ButtonPress, Y_ButtonPress,
1611                   X_Motion, Y_Motion);
1612     }
1613   }
1614 }
1615
1616 //==============================================================================
1617 //function : VT_ProcessButton3Press
1618 //purpose  : Start Rotation
1619 //==============================================================================
1620 void VT_ProcessButton3Press()
1621 {
1622   Start_Rot = 1;
1623   if (MyHLRIsOn)
1624   {
1625     ViewerTest::CurrentView()->SetComputedMode (Standard_False);
1626   }
1627   ViewerTest::CurrentView()->StartRotation( X_ButtonPress, Y_ButtonPress );
1628 }
1629
1630 //==============================================================================
1631 //function : VT_ProcessButton3Release
1632 //purpose  : End rotation
1633 //==============================================================================
1634 void VT_ProcessButton3Release()
1635 {
1636   if (Start_Rot)
1637   {
1638     Start_Rot = 0;
1639     if (MyHLRIsOn)
1640     {
1641       ViewerTest::CurrentView()->SetComputedMode (Standard_True);
1642     }
1643   }
1644 }
1645
1646 //==============================================================================
1647 //function : ProcessControlButton1Motion
1648 //purpose  : Zoom
1649 //==============================================================================
1650
1651 #if defined(_WIN32) || ! defined(__APPLE__) || defined(MACOSX_USE_GLX)
1652 static void ProcessControlButton1Motion()
1653 {
1654   ViewerTest::CurrentView()->Zoom( X_ButtonPress, Y_ButtonPress, X_Motion, Y_Motion);
1655
1656   X_ButtonPress = X_Motion;
1657   Y_ButtonPress = Y_Motion;
1658 }
1659 #endif
1660
1661 //==============================================================================
1662 //function : VT_ProcessControlButton2Motion
1663 //purpose  : Panning
1664 //==============================================================================
1665 void VT_ProcessControlButton2Motion()
1666 {
1667   Standard_Integer aDx = X_Motion - X_ButtonPress;
1668   Standard_Integer aDy = Y_Motion - Y_ButtonPress;
1669
1670   aDy = -aDy; // Xwindow Y axis is from top to Bottom
1671
1672   ViewerTest::CurrentView()->Pan (aDx, aDy);
1673
1674   X_ButtonPress = X_Motion;
1675   Y_ButtonPress = Y_Motion;
1676 }
1677
1678 //==============================================================================
1679 //function : VT_ProcessControlButton3Motion
1680 //purpose  : Rotation
1681 //==============================================================================
1682 void VT_ProcessControlButton3Motion()
1683 {
1684   if (Start_Rot)
1685   {
1686     ViewerTest::CurrentView()->Rotation (X_Motion, Y_Motion);
1687   }
1688 }
1689
1690 //==============================================================================
1691 //function : VT_ProcessMotion
1692 //purpose  :
1693 //==============================================================================
1694 void VT_ProcessMotion()
1695 {
1696   //pre-hilights detected objects at mouse position
1697
1698   Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1699   EM->MoveTo(X_Motion, Y_Motion);
1700 }
1701
1702
1703 void ViewerTest::GetMousePosition(Standard_Integer& Xpix,Standard_Integer& Ypix)
1704 {
1705   Xpix = X_Motion;Ypix=Y_Motion;
1706 }
1707
1708 //==============================================================================
1709 //function : ViewProject: implements VAxo, VTop, VLeft, ...
1710 //purpose  : Switches to an axonometric, top, left and other views
1711 //==============================================================================
1712
1713 static int ViewProject(Draw_Interpretor& di, const V3d_TypeOfOrientation ori)
1714 {
1715   if ( ViewerTest::CurrentView().IsNull() )
1716   {
1717     di<<"Call vinit before this command, please\n";
1718     return 1;
1719   }
1720
1721   ViewerTest::CurrentView()->SetProj(ori);
1722   return 0;
1723 }
1724
1725 //==============================================================================
1726 //function : VAxo
1727 //purpose  : Switch to an Axonometric view
1728 //Draw arg : No args
1729 //==============================================================================
1730
1731 static int VAxo(Draw_Interpretor& di, Standard_Integer , const char** )
1732 {
1733   return ViewProject(di, V3d_XposYnegZpos);
1734 }
1735
1736 //==============================================================================
1737 //function : VTop
1738 //purpose  : Switch to a Top View
1739 //Draw arg : No args
1740 //==============================================================================
1741
1742 static int VTop(Draw_Interpretor& di, Standard_Integer , const char** )
1743 {
1744   return ViewProject(di, V3d_Zpos);
1745 }
1746
1747 //==============================================================================
1748 //function : VBottom
1749 //purpose  : Switch to a Bottom View
1750 //Draw arg : No args
1751 //==============================================================================
1752
1753 static int VBottom(Draw_Interpretor& di, Standard_Integer , const char** )
1754 {
1755   return ViewProject(di, V3d_Zneg);
1756 }
1757
1758 //==============================================================================
1759 //function : VLeft
1760 //purpose  : Switch to a Left View
1761 //Draw arg : No args
1762 //==============================================================================
1763
1764 static int VLeft(Draw_Interpretor& di, Standard_Integer , const char** )
1765 {
1766   return ViewProject(di, V3d_Xneg);
1767 }
1768
1769 //==============================================================================
1770 //function : VRight
1771 //purpose  : Switch to a Right View
1772 //Draw arg : No args
1773 //==============================================================================
1774
1775 static int VRight(Draw_Interpretor& di, Standard_Integer , const char** )
1776 {
1777   return ViewProject(di, V3d_Xpos);
1778 }
1779
1780 //==============================================================================
1781 //function : VFront
1782 //purpose  : Switch to a Front View
1783 //Draw arg : No args
1784 //==============================================================================
1785
1786 static int VFront(Draw_Interpretor& di, Standard_Integer , const char** )
1787 {
1788   return ViewProject(di, V3d_Yneg);
1789 }
1790
1791 //==============================================================================
1792 //function : VBack
1793 //purpose  : Switch to a Back View
1794 //Draw arg : No args
1795 //==============================================================================
1796
1797 static int VBack(Draw_Interpretor& di, Standard_Integer , const char** )
1798 {
1799   return ViewProject(di, V3d_Ypos);
1800 }
1801
1802 //==============================================================================
1803 //function : VHelp
1804 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
1805 //Draw arg : No args
1806 //==============================================================================
1807
1808 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
1809 {
1810
1811   di << "Q : Quit the application\n";
1812
1813   di << "=========================\n";
1814   di << "F : FitAll\n";
1815   di << "T : TopView\n";
1816   di << "B : BottomView\n";
1817   di << "R : RightView\n";
1818   di << "L : LeftView\n";
1819   di << "A : AxonometricView\n";
1820   di << "D : ResetView\n";
1821
1822   di << "=========================\n";
1823   di << "S : Shading\n";
1824   di << "W : Wireframe\n";
1825   di << "H : HidelLineRemoval\n";
1826   di << "U : Unset display mode\n";
1827   di << "Delete : Remove selection from viewer\n";
1828
1829   di << "=========================\n";
1830   di << "Selection mode \n";
1831   di << "0 : Shape\n";
1832   di << "1 : Vertex\n";
1833   di << "2 : Edge\n";
1834   di << "3 : Wire\n";
1835   di << "4 : Face\n";
1836   di << "5 : Shell\n";
1837   di << "6 : Solid\n";
1838   di << "7 : Compound\n";
1839
1840   di << "=========================\n";
1841   di << "Z : Switch Z clipping On/Off\n";
1842   di << ", : Hilight next detected\n";
1843   di << ". : Hilight previous detected\n";
1844
1845   return 0;
1846 }
1847
1848 #ifdef _WIN32
1849
1850 static Standard_Boolean Ppick = 0;
1851 static Standard_Integer Pargc = 0;
1852 static const char**           Pargv = NULL;
1853
1854
1855 static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
1856                                           UINT Msg,
1857                                           WPARAM wParam,
1858                                           LPARAM lParam )
1859 {
1860   if (!ViewerTest_myViews.IsEmpty()) {
1861
1862     WPARAM fwKeys = wParam;
1863
1864     switch( Msg ) {
1865     case WM_CLOSE:
1866        {
1867          // Delete view from map of views
1868          ViewerTest::RemoveView(FindViewIdByWindowHandle(hwnd));
1869          return 0;
1870        }
1871        break;
1872     case WM_ACTIVATE:
1873       if(LOWORD(wParam) == WA_CLICKACTIVE || LOWORD(wParam) == WA_ACTIVE
1874         || ViewerTest::CurrentView().IsNull())
1875       {
1876         // Activate inactive window
1877         if(GetWindowHandle(VT_GetWindow()) != hwnd)
1878         {
1879           ActivateView (FindViewIdByWindowHandle(hwnd));
1880         }
1881       }
1882       break;
1883
1884     case WM_LBUTTONUP:
1885       if (IsDragged && !DragFirst)
1886       {
1887         if (!GetActiveAISManipulator().IsNull())
1888         {
1889           GetActiveAISManipulator()->StopTransform();
1890           ViewerTest::GetAISContext()->ClearSelected();
1891         }
1892
1893         if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
1894         {
1895           ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
1896           ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
1897         }
1898
1899         VT_ProcessButton1Release ((fwKeys & MK_SHIFT) != 0);
1900       }
1901       IsDragged = Standard_False;
1902       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1903
1904     case WM_RBUTTONUP:
1905       if (IsDragged && !DragFirst)
1906       {
1907         if (!GetActiveAISManipulator().IsNull())
1908         {
1909           GetActiveAISManipulator()->StopTransform (Standard_False);
1910           ViewerTest::GetAISContext()->ClearSelected();
1911         }
1912         IsDragged = Standard_False;
1913       }
1914       return ViewerWindowProc (hwnd, Msg, wParam, lParam);
1915
1916     case WM_LBUTTONDOWN:
1917       if (!GetActiveAISManipulator().IsNull())
1918       {
1919         IsDragged = ( fwKeys == MK_LBUTTON );
1920       }
1921       else
1922       {
1923         IsDragged = ( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) );
1924       }
1925
1926       if (IsDragged)
1927       {
1928         DragFirst = Standard_True;
1929         X_ButtonPress = LOWORD(lParam);
1930         Y_ButtonPress = HIWORD(lParam);
1931       }
1932       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1933
1934     case WM_MOUSEMOVE:
1935       if (IsDragged)
1936       {
1937         X_Motion = LOWORD (lParam);
1938         Y_Motion = HIWORD (lParam);
1939         if (!GetActiveAISManipulator().IsNull())
1940         {
1941           if (DragFirst)
1942           {
1943             GetActiveAISManipulator()->StartTransform (X_ButtonPress, Y_ButtonPress, ViewerTest::CurrentView());
1944           }
1945           else
1946           {
1947             GetActiveAISManipulator()->Transform (X_Motion, Y_Motion, ViewerTest::CurrentView());
1948             ViewerTest::GetAISContext()->CurrentViewer()->Redraw();
1949           }
1950         }
1951         else
1952         {
1953           bool toRedraw = false;
1954           if (!DragFirst && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
1955           {
1956             ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
1957             toRedraw = true;
1958           }
1959
1960           RECT aRect;
1961           if (GetClientRect (hwnd, &aRect))
1962           {
1963             int aHeight = aRect.bottom - aRect.top;
1964             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
1965             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
1966             toRedraw = true;
1967           }
1968           if (toRedraw)
1969           {
1970             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
1971           }
1972         }
1973
1974         DragFirst = Standard_False;
1975       }
1976       else
1977         return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1978       break;
1979
1980     default:
1981       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1982     }
1983     return 0;
1984   }
1985   return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1986 }
1987
1988
1989 static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
1990                                        UINT Msg,
1991                                        WPARAM wParam,
1992                                        LPARAM lParam )
1993 {
1994   static int Up = 1;
1995   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
1996   if (aView.IsNull())
1997   {
1998     return DefWindowProc( hwnd, Msg, wParam, lParam );
1999   }
2000
2001     PAINTSTRUCT    ps;
2002
2003     switch( Msg ) {
2004     case WM_PAINT:
2005       BeginPaint(hwnd, &ps);
2006       EndPaint(hwnd, &ps);
2007       VT_ProcessExpose();
2008       break;
2009
2010     case WM_SIZE:
2011       VT_ProcessConfigure();
2012       break;
2013     case WM_MOVE:
2014     case WM_MOVING:
2015     case WM_SIZING:
2016       switch (aView->RenderingParams().StereoMode)
2017       {
2018         case Graphic3d_StereoMode_RowInterlaced:
2019         case Graphic3d_StereoMode_ColumnInterlaced:
2020         case Graphic3d_StereoMode_ChessBoard:
2021           VT_ProcessConfigure(); // track window moves to reverse stereo pair
2022           break;
2023         default:
2024           break;
2025       }
2026       break;
2027
2028     case WM_KEYDOWN:
2029       if ((wParam != VK_SHIFT) && (wParam != VK_CONTROL))
2030       {
2031         char c[2];
2032         c[0] = (char) wParam;
2033         c[1] = '\0';
2034         if (wParam == VK_DELETE)
2035         {
2036           c[0] = THE_KEY_DELETE;
2037         }
2038         // comma
2039         else if (wParam == VK_OEM_COMMA)
2040         {
2041           c[0] = ',';
2042         }
2043         // dot
2044         else if (wParam == VK_OEM_PERIOD)
2045         {
2046           c[0] = '.';
2047         }
2048         else if (wParam == VK_DIVIDE)
2049         {
2050           c[0] = '/';
2051         }
2052         // dot
2053         else if (wParam == VK_MULTIPLY)
2054         {
2055           c[0] = '*';
2056         }
2057         VT_ProcessKeyPress (c);
2058       }
2059       break;
2060
2061     case WM_LBUTTONUP:
2062     case WM_MBUTTONUP:
2063     case WM_RBUTTONUP:
2064       Up = 1;
2065       VT_ProcessButton3Release();
2066       break;
2067
2068     case WM_LBUTTONDOWN:
2069     case WM_MBUTTONDOWN:
2070     case WM_RBUTTONDOWN:
2071       {
2072         WPARAM fwKeys = wParam;
2073
2074         Up = 0;
2075
2076         X_ButtonPress = LOWORD(lParam);
2077         Y_ButtonPress = HIWORD(lParam);
2078
2079         if (Msg == WM_LBUTTONDOWN)
2080         {
2081           if ((fwKeys & MK_CONTROL) != 0)
2082           {
2083             Ppick = VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2084           }
2085           else
2086           {
2087             VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2088           }
2089         }
2090         else if (Msg == WM_RBUTTONDOWN)
2091         {
2092           // Start rotation
2093           VT_ProcessButton3Press();
2094         }
2095       }
2096       break;
2097
2098     case WM_MOUSEWHEEL:
2099     {
2100       int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
2101       if (wParam & MK_CONTROL)
2102       {
2103         if (aView->Camera()->IsStereo())
2104         {
2105           Standard_Real aFocus = aView->Camera()->ZFocus() + (aDelta > 0 ? 0.05 : -0.05);
2106           if (aFocus > 0.2
2107            && aFocus < 2.0)
2108           {
2109             aView->Camera()->SetZFocus (aView->Camera()->ZFocusType(), aFocus);
2110             aView->Redraw();
2111           }
2112         }
2113       }
2114       else
2115       {
2116         aView->Zoom (0, 0, aDelta / 40, aDelta / 40);
2117       }
2118       break;
2119     }
2120
2121     case WM_MOUSEMOVE:
2122       {
2123         //cout << "\t WM_MOUSEMOVE" << endl;
2124         WPARAM fwKeys = wParam;
2125         X_Motion = LOWORD(lParam);
2126         Y_Motion = HIWORD(lParam);
2127
2128         if ( Up &&
2129           (fwKeys & ( MK_LBUTTON|MK_MBUTTON|MK_RBUTTON )) != 0 )
2130           {
2131             Up = 0;
2132             X_ButtonPress = LOWORD(lParam);
2133             Y_ButtonPress = HIWORD(lParam);
2134
2135             if ((fwKeys & MK_RBUTTON) != 0) {
2136               // Start rotation
2137               VT_ProcessButton3Press();
2138             }
2139           }
2140
2141           if ((fwKeys & MK_CONTROL) != 0)
2142           {
2143             if ((fwKeys & MK_LBUTTON) != 0)
2144             {
2145               ProcessControlButton1Motion();
2146             }
2147             else if ((fwKeys & MK_MBUTTON) != 0
2148                  || ((fwKeys & MK_LBUTTON) != 0
2149                   && (fwKeys & MK_RBUTTON) != 0))
2150             {
2151               VT_ProcessControlButton2Motion();
2152             }
2153             else if ((fwKeys & MK_RBUTTON) != 0)
2154             {
2155               VT_ProcessControlButton3Motion();
2156             }
2157           }
2158           else if (GetWindowHandle (VT_GetWindow()) == hwnd)
2159           {
2160             VT_ProcessMotion();
2161           }
2162       }
2163       break;
2164
2165     default:
2166       return( DefWindowProc( hwnd, Msg, wParam, lParam ));
2167     }
2168     return 0L;
2169 }
2170
2171
2172
2173
2174 //==============================================================================
2175 //function : ViewerMainLoop
2176 //purpose  : Get a Event on the view and dispatch it
2177 //==============================================================================
2178
2179
2180 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2181 {
2182   Ppick = (argc > 0)? 1 : 0;
2183   Pargc = argc;
2184   Pargv = argv;
2185
2186   if ( Ppick ) {
2187     MSG msg;
2188     msg.wParam = 1;
2189
2190     cout << "Start picking" << endl;
2191
2192     while ( Ppick == 1 ) {
2193       // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
2194       if (GetMessage(&msg, NULL, 0, 0) ) {
2195         TranslateMessage(&msg);
2196         DispatchMessage(&msg);
2197       }
2198     }
2199
2200     cout << "Picking done" << endl;
2201   }
2202
2203   return Ppick;
2204 }
2205
2206 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
2207
2208 int min( int a, int b )
2209 {
2210   if( a<b )
2211     return a;
2212   else
2213     return b;
2214 }
2215
2216 int max( int a, int b )
2217 {
2218   if( a>b )
2219     return a;
2220   else
2221     return b;
2222 }
2223
2224 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2225
2226 {
2227   static XEvent aReport;
2228   Standard_Boolean pick = argc > 0;
2229   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2230   XNextEvent (aDisplay, &aReport);
2231
2232   // Handle event for the chosen display connection
2233   switch (aReport.type) {
2234       case ClientMessage:
2235         {
2236           if((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
2237           {
2238             // Close the window
2239             ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
2240           }
2241         }
2242         return 0;
2243      case FocusIn:
2244       {
2245          // Activate inactive view
2246          Window aWindow = GetWindowHandle(VT_GetWindow());
2247          if(aWindow != aReport.xfocus.window)
2248          {
2249            ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
2250          }
2251       }
2252       break;
2253       case Expose:
2254         {
2255           VT_ProcessExpose();
2256         }
2257         break;
2258       case ConfigureNotify:
2259         {
2260           VT_ProcessConfigure();
2261         }
2262         break;
2263       case KeyPress:
2264         {
2265
2266           KeySym ks_ret ;
2267           char buf_ret[11] ;
2268           int ret_len ;
2269           XComposeStatus status_in_out;
2270
2271           ret_len = XLookupString( ( XKeyEvent *)&aReport ,
2272             (char *) buf_ret , 10 ,
2273             &ks_ret , &status_in_out ) ;
2274
2275
2276           buf_ret[ret_len] = '\0' ;
2277
2278           if (ret_len)
2279           {
2280             VT_ProcessKeyPress (buf_ret);
2281           }
2282         }
2283         break;
2284       case ButtonPress:
2285         {
2286           X_ButtonPress = aReport.xbutton.x;
2287           Y_ButtonPress = aReport.xbutton.y;
2288
2289           if (aReport.xbutton.button == Button1)
2290           {
2291             if (aReport.xbutton.state & ControlMask)
2292             {
2293               pick = VT_ProcessButton1Press (argc, argv, pick, (aReport.xbutton.state & ShiftMask));
2294             }
2295             else
2296             {
2297               IsDragged = Standard_True;
2298               DragFirst = Standard_True;
2299             }
2300           }
2301           else if (aReport.xbutton.button == Button3)
2302           {
2303             // Start rotation
2304             VT_ProcessButton3Press();
2305           }
2306         }
2307         break;
2308       case ButtonRelease:
2309         {
2310           if( IsDragged )
2311           {
2312             if( !DragFirst )
2313             {
2314               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2315               {
2316                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2317                 ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2318               }
2319             }
2320
2321             Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
2322             if( aContext.IsNull() )
2323             {
2324               cout << "The context is null. Please use vinit before createmesh" << endl;
2325               return 0;
2326             }
2327
2328             Standard_Boolean ShiftPressed = ( aReport.xbutton.state & ShiftMask );
2329             if( aReport.xbutton.button==1 )
2330               if( DragFirst )
2331                 if( ShiftPressed )
2332                 {
2333                   aContext->ShiftSelect();
2334                 }
2335                 else
2336                 {
2337                   aContext->Select();
2338                 }
2339               else
2340                 if( ShiftPressed )
2341                 {
2342                   aContext->ShiftSelect( min( X_ButtonPress, X_Motion ), min( Y_ButtonPress, Y_Motion ),
2343                     max( X_ButtonPress, X_Motion ), max( Y_ButtonPress, Y_Motion ),
2344                     ViewerTest::CurrentView());
2345                 }
2346                 else
2347                 {
2348                   aContext->Select( min( X_ButtonPress, X_Motion ), min( Y_ButtonPress, Y_Motion ),
2349                     max( X_ButtonPress, X_Motion ), max( Y_ButtonPress, Y_Motion ),
2350                     ViewerTest::CurrentView() );
2351                 }
2352             else
2353               VT_ProcessButton3Release();
2354
2355             IsDragged = Standard_False;
2356           }
2357           else
2358             VT_ProcessButton3Release();
2359         }
2360         break;
2361       case MotionNotify:
2362         {
2363           if (GetWindowHandle (VT_GetWindow()) != aReport.xmotion.window)
2364           {
2365             break;
2366           }
2367           if( IsDragged )
2368           {
2369             if( !DragFirst )
2370             {
2371               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2372               {
2373                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2374               }
2375             }
2376
2377             X_Motion = aReport.xmotion.x;
2378             Y_Motion = aReport.xmotion.y;
2379             DragFirst = Standard_False;
2380
2381             Window aWindow = GetWindowHandle(VT_GetWindow());
2382             Window aRoot;
2383             int anX, anY;
2384             unsigned int aWidth, aHeight, aBorderWidth, aDepth;
2385             XGetGeometry (aDisplay, aWindow, &aRoot, &anX, &anY, &aWidth, &aHeight, &aBorderWidth, &aDepth);
2386             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2387             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
2388             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2389           }
2390           else
2391           {
2392             X_Motion = aReport.xmotion.x;
2393             Y_Motion = aReport.xmotion.y;
2394
2395             // remove all the ButtonMotionMaskr
2396             while( XCheckMaskEvent( aDisplay, ButtonMotionMask, &aReport) ) ;
2397
2398             if ( aReport.xmotion.state & ControlMask ) {
2399               if ( aReport.xmotion.state & Button1Mask ) {
2400                 ProcessControlButton1Motion();
2401               }
2402               else if ( aReport.xmotion.state & Button2Mask ) {
2403                 VT_ProcessControlButton2Motion();
2404               }
2405               else if ( aReport.xmotion.state & Button3Mask ) {
2406                 VT_ProcessControlButton3Motion();
2407               }
2408             }
2409             else
2410             {
2411               VT_ProcessMotion();
2412             }
2413           }
2414         }
2415         break;
2416 }
2417 return pick;
2418 }
2419
2420 //==============================================================================
2421 //function : VProcessEvents
2422 //purpose  : call by Tk_CreateFileHandler() to be able to manage the
2423 //       event in the Viewer window
2424 //==============================================================================
2425
2426 static void VProcessEvents(ClientData,int)
2427 {
2428   NCollection_Vector<int> anEventNumbers;
2429   // Get number of messages from every display
2430   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2431        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next())
2432   {
2433     anEventNumbers.Append(XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()));
2434   }
2435     // Handle events for every display
2436   int anEventIter = 0;
2437   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2438        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next(), anEventIter++)
2439   {
2440     for (int i = 0; i < anEventNumbers.Value(anEventIter) &&
2441          XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()) > 0; ++i)
2442     {
2443       SetDisplayConnection (anIter.Key2()->GetDisplayConnection());
2444       int anEventResult = ViewerMainLoop( 0, NULL);
2445       // If window is closed or context was not found finish current event processing loop
2446       if (!anEventResult)
2447         return;
2448     }
2449   }
2450
2451   SetDisplayConnection (ViewerTest::GetAISContext()->CurrentViewer()->Driver()->GetDisplayConnection());
2452
2453 }
2454 #endif
2455
2456 //==============================================================================
2457 //function : OSWindowSetup
2458 //purpose  : Setup for the X11 window to be able to cath the event
2459 //==============================================================================
2460
2461
2462 static void OSWindowSetup()
2463 {
2464 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2465   // X11
2466
2467   Window  window   = VT_GetWindow()->XWindow();
2468   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2469   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2470   XSynchronize(aDisplay, 1);
2471
2472   // X11 : For keyboard on SUN
2473   XWMHints wmhints;
2474   wmhints.flags = InputHint;
2475   wmhints.input = 1;
2476
2477   XSetWMHints( aDisplay, window, &wmhints);
2478
2479   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask |
2480     ButtonPressMask | ButtonReleaseMask |
2481     StructureNotifyMask |
2482     PointerMotionMask |
2483     Button1MotionMask | Button2MotionMask |
2484     Button3MotionMask | FocusChangeMask
2485     );
2486   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
2487   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
2488
2489   XSynchronize(aDisplay, 0);
2490
2491 #else
2492   // _WIN32
2493 #endif
2494
2495 }
2496
2497 //==============================================================================
2498 //function : VFit
2499
2500 //purpose  : Fitall, no DRAW arguments
2501 //Draw arg : No args
2502 //==============================================================================
2503
2504 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgc, const char** theArgv)
2505 {
2506   if (theArgc > 2)
2507   {
2508     std::cout << "Wrong number of arguments! Use: vfit [-selected]" << std::endl;
2509   }
2510
2511   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2512
2513   if (theArgc == 2)
2514   {
2515     TCollection_AsciiString anArg (theArgv[1]);
2516     anArg.LowerCase();
2517     if (anArg == "-selected")
2518     {
2519       ViewerTest::GetAISContext()->FitSelected (aView);
2520       return 0;
2521     }
2522   }
2523   if (aView.IsNull() == Standard_False) {
2524
2525     aView->FitAll();
2526   }
2527   return 0;
2528 }
2529
2530 //=======================================================================
2531 //function : VFitArea
2532 //purpose  : Fit view to show area located between two points
2533 //         : given in world 2D or 3D coordinates.
2534 //=======================================================================
2535 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
2536 {
2537   Handle(V3d_View) aView = ViewerTest::CurrentView();
2538   if (aView.IsNull())
2539   {
2540     std::cerr << theArgVec[0] << "Error: No active view.\n";
2541     return 1;
2542   }
2543
2544   // Parse arguments.
2545   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
2546   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
2547
2548   if (theArgNb == 5)
2549   {
2550     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2551     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2552     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
2553     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
2554   }
2555   else if (theArgNb == 7)
2556   {
2557     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2558     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2559     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
2560     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
2561     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
2562     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
2563   }
2564   else
2565   {
2566     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
2567     theDI.PrintHelp(theArgVec[0]);
2568     return 1;
2569   }
2570
2571   // Convert model coordinates to view space
2572   Handle(Graphic3d_Camera) aCamera = aView->Camera();
2573   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
2574   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
2575
2576   // Determine fit area
2577   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
2578   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
2579
2580   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
2581
2582   if (aDiagonal < Precision::Confusion())
2583   {
2584     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
2585     return 1;
2586   }
2587
2588   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
2589   return 0;
2590 }
2591
2592 //==============================================================================
2593 //function : VZFit
2594 //purpose  : ZFitall, no DRAW arguments
2595 //Draw arg : No args
2596 //==============================================================================
2597 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
2598 {
2599   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
2600
2601   if (aCurrentView.IsNull())
2602   {
2603     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
2604     return 1;
2605   }
2606
2607   if (theArgsNb == 1)
2608   {
2609     aCurrentView->ZFitAll();
2610     aCurrentView->Redraw();
2611     return 0;
2612   }
2613
2614   Standard_Real aScale = 1.0;
2615
2616   if (theArgsNb >= 2)
2617   {
2618     aScale = Draw::Atoi (theArgVec[1]);
2619   }
2620
2621   aCurrentView->ZFitAll (aScale);
2622   aCurrentView->Redraw();
2623
2624   return 0;
2625 }
2626
2627 //==============================================================================
2628 //function : VRepaint
2629 //purpose  :
2630 //==============================================================================
2631 static int VRepaint (Draw_Interpretor& , Standard_Integer , const char** )
2632 {
2633   Handle(V3d_View) V = ViewerTest::CurrentView();
2634   if ( !V.IsNull() ) V->Redraw(); return 0;
2635 }
2636
2637 //==============================================================================
2638 //function : VClear
2639 //purpose  : Remove all the object from the viewer
2640 //Draw arg : No args
2641 //==============================================================================
2642
2643 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
2644 {
2645   Handle(V3d_View) V = ViewerTest::CurrentView();
2646   if(!V.IsNull())
2647     ViewerTest::Clear();
2648   return 0;
2649 }
2650
2651 //==============================================================================
2652 //function : VPick
2653 //purpose  :
2654 //==============================================================================
2655
2656 static int VPick(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2657 { if (ViewerTest::CurrentView().IsNull() ) return 1;
2658
2659 if ( argc < 4 ) {
2660   di << argv[0] << "Invalid number of arguments\n";
2661   return 1;
2662 }
2663
2664 while (ViewerMainLoop( argc, argv)) {
2665 }
2666
2667 return 0;
2668 }
2669
2670 //==============================================================================
2671 //function : VSetBg
2672 //purpose  : Load image as background
2673 //==============================================================================
2674
2675 static int VSetBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2676 {
2677   if (argc < 2 || argc > 3)
2678   {
2679     di << "Usage : " << argv[0] << " imagefile [filltype] : Load image as background\n";
2680     di << "filltype can be one of CENTERED, TILED, STRETCH, NONE\n";
2681     return 1;
2682   }
2683
2684   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2685   if(AISContext.IsNull())
2686   {
2687     di << "use 'vinit' command before " << argv[0] << "\n";
2688     return 1;
2689   }
2690
2691   Aspect_FillMethod aFillType = Aspect_FM_CENTERED;
2692   if (argc == 3)
2693   {
2694     const char* szType = argv[2];
2695     if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2696     else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2697     else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2698     else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2699     else
2700     {
2701       di << "Wrong fill type : " << szType << "\n";
2702       di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2703       return 1;
2704     }
2705   }
2706
2707   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2708   V3dView->SetBackgroundImage(argv[1], aFillType, Standard_True);
2709
2710   return 0;
2711 }
2712
2713 //==============================================================================
2714 //function : VSetBgMode
2715 //purpose  : Change background image fill type
2716 //==============================================================================
2717
2718 static int VSetBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2719 {
2720   if (argc != 2)
2721   {
2722     di << "Usage : " << argv[0] << " filltype : Change background image mode\n";
2723     di << "filltype must be one of CENTERED, TILED, STRETCH, NONE\n";
2724     return 1;
2725   }
2726
2727   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2728   if(AISContext.IsNull())
2729   {
2730     di << "use 'vinit' command before " << argv[0] << "\n";
2731     return 1;
2732   }
2733   Aspect_FillMethod aFillType = Aspect_FM_NONE;
2734   const char* szType = argv[1];
2735   if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2736   else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2737   else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2738   else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2739   else
2740   {
2741     di << "Wrong fill type : " << szType << "\n";
2742     di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2743     return 1;
2744   }
2745   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2746   V3dView->SetBgImageStyle(aFillType, Standard_True);
2747   return 0;
2748 }
2749
2750 //==============================================================================
2751 //function : VSetGradientBg
2752 //purpose  : Mount gradient background
2753 //==============================================================================
2754 static int VSetGradientBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2755 {
2756   if (argc != 8 )
2757   {
2758     di << "Usage : " << argv[0] << " R1 G1 B1 R2 G2 B2 Type : Mount gradient background\n";
2759     di << "R1,G1,B1,R2,G2,B2 = [0..255]\n";
2760     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2761     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2762     return 1;
2763   }
2764
2765   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2766   if(AISContext.IsNull())
2767   {
2768     di << "use 'vinit' command before " << argv[0] << "\n";
2769     return 1;
2770   }
2771   if (argc == 8)
2772   {
2773
2774     Standard_Real R1 = Draw::Atof(argv[1])/255.;
2775     Standard_Real G1 = Draw::Atof(argv[2])/255.;
2776     Standard_Real B1 = Draw::Atof(argv[3])/255.;
2777     Quantity_Color aColor1(R1,G1,B1,Quantity_TOC_RGB);
2778
2779     Standard_Real R2 = Draw::Atof(argv[4])/255.;
2780     Standard_Real G2 = Draw::Atof(argv[5])/255.;
2781     Standard_Real B2 = Draw::Atof(argv[6])/255.;
2782
2783     Quantity_Color aColor2(R2,G2,B2,Quantity_TOC_RGB);
2784     int aType = Draw::Atoi(argv[7]);
2785     if( aType < 0 || aType > 8 )
2786     {
2787       di << "Wrong fill type \n";
2788       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2789       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2790       return 1;
2791     }
2792
2793     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
2794
2795     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2796     V3dView->SetBgGradientColors( aColor1, aColor2, aMethod, 1);
2797   }
2798
2799   return 0;
2800 }
2801
2802 //==============================================================================
2803 //function : VSetGradientBgMode
2804 //purpose  : Change gradient background fill style
2805 //==============================================================================
2806 static int VSetGradientBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2807 {
2808   if (argc != 2 )
2809   {
2810     di << "Usage : " << argv[0] << " Type : Change gradient background fill type\n";
2811     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2812     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2813     return 1;
2814   }
2815
2816   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2817   if(AISContext.IsNull())
2818   {
2819     di << "use 'vinit' command before " << argv[0] << "\n";
2820     return 1;
2821   }
2822   if (argc == 2)
2823   {
2824     int aType = Draw::Atoi(argv[1]);
2825     if( aType < 0 || aType > 8 )
2826     {
2827       di << "Wrong fill type \n";
2828       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2829       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2830       return 1;
2831     }
2832
2833     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
2834
2835     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2836     V3dView->SetBgGradientStyle( aMethod, 1 );
2837   }
2838
2839   return 0;
2840 }
2841
2842 //==============================================================================
2843 //function : VSetColorBg
2844 //purpose  : Set color background
2845 //==============================================================================
2846 static int VSetColorBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2847 {
2848   if (argc != 4 )
2849   {
2850     di << "Usage : " << argv[0] << " R G B : Set color background\n";
2851     di << "R,G,B = [0..255]\n";
2852     return 1;
2853   }
2854
2855   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2856   if(AISContext.IsNull())
2857   {
2858     di << "use 'vinit' command before " << argv[0] << "\n";
2859     return 1;
2860   }
2861   if (argc == 4)
2862   {
2863
2864     Standard_Real R = Draw::Atof(argv[1])/255.;
2865     Standard_Real G = Draw::Atof(argv[2])/255.;
2866     Standard_Real B = Draw::Atof(argv[3])/255.;
2867     Quantity_Color aColor(R,G,B,Quantity_TOC_RGB);
2868
2869     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2870     V3dView->SetBackgroundColor( aColor );
2871     V3dView->Update();
2872   }
2873
2874   return 0;
2875 }
2876
2877 //==============================================================================
2878 //function : VSetDefaultBg
2879 //purpose  : Set default viewer background fill color
2880 //==============================================================================
2881 static int VSetDefaultBg (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
2882 {
2883   if (theArgNb != 4
2884    && theArgNb != 8)
2885   {
2886     std::cout << "Error: wrong syntax! See usage:\n";
2887     theDI.PrintHelp (theArgVec[0]);
2888     return 1;
2889   }
2890
2891   ViewerTest_DefaultBackground.FillMethod =
2892     theArgNb == 4 ? Aspect_GFM_NONE
2893                   : (Aspect_GradientFillMethod) Draw::Atoi (theArgVec[7]);
2894
2895   if (theArgNb == 4)
2896   {
2897     Standard_Real R = Draw::Atof (theArgVec[1]) / 255.;
2898     Standard_Real G = Draw::Atof (theArgVec[2]) / 255.;
2899     Standard_Real B = Draw::Atof (theArgVec[3]) / 255.;
2900     ViewerTest_DefaultBackground.FlatColor.SetValues (R, G, B, Quantity_TOC_RGB);
2901   }
2902   else
2903   {
2904     Standard_Real R1 = Draw::Atof (theArgVec[1]) / 255.;
2905     Standard_Real G1 = Draw::Atof (theArgVec[2]) / 255.;
2906     Standard_Real B1 = Draw::Atof (theArgVec[3]) / 255.;
2907     ViewerTest_DefaultBackground.GradientColor1.SetValues (R1, G1, B1, Quantity_TOC_RGB);
2908
2909     Standard_Real R2 = Draw::Atof (theArgVec[4]) / 255.;
2910     Standard_Real G2 = Draw::Atof (theArgVec[5]) / 255.;
2911     Standard_Real B2 = Draw::Atof (theArgVec[6]) / 255.;
2912     ViewerTest_DefaultBackground.GradientColor2.SetValues (R2, G2, B2, Quantity_TOC_RGB);
2913   }
2914
2915   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2916        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
2917   {
2918     const Handle(V3d_Viewer)& aViewer = anIter.Value()->CurrentViewer();
2919     aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
2920     aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
2921                                          ViewerTest_DefaultBackground.GradientColor2,
2922                                          ViewerTest_DefaultBackground.FillMethod);
2923   }
2924
2925   return 0;
2926 }
2927
2928 //==============================================================================
2929 //function : VScale
2930 //purpose  : View Scaling
2931 //==============================================================================
2932
2933 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2934 {
2935   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2936   if ( V3dView.IsNull() ) return 1;
2937
2938   if ( argc != 4 ) {
2939     di << argv[0] << "Invalid number of arguments\n";
2940     return 1;
2941   }
2942   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
2943   return 0;
2944 }
2945 //==============================================================================
2946 //function : VZBuffTrihedron
2947 //purpose  :
2948 //==============================================================================
2949
2950 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
2951                             Standard_Integer  theArgNb,
2952                             const char**      theArgVec)
2953 {
2954   Handle(V3d_View) aView = ViewerTest::CurrentView();
2955   if (aView.IsNull())
2956   {
2957     std::cout << "Error: no active viewer!\n";
2958     return 1;
2959   }
2960
2961   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
2962
2963   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
2964   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
2965   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
2966   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
2967   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
2968   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
2969   Standard_Real                 aScale        = 0.1;
2970   Standard_Real                 aSizeRatio    = 0.8;
2971   Standard_Real                 anArrowDiam   = 0.05;
2972   Standard_Integer              aNbFacets     = 12;
2973   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2974   {
2975     Standard_CString        anArg = theArgVec[anArgIter];
2976     TCollection_AsciiString aFlag (anArg);
2977     aFlag.LowerCase();
2978     if (anUpdateTool.parseRedrawMode (aFlag))
2979     {
2980       continue;
2981     }
2982     else if (aFlag == "-on")
2983     {
2984       continue;
2985     }
2986     else if (aFlag == "-off")
2987     {
2988       aView->TriedronErase();
2989       return 0;
2990     }
2991     else if (aFlag == "-pos"
2992           || aFlag == "-position"
2993           || aFlag == "-corner")
2994     {
2995       if (++anArgIter >= theArgNb)
2996       {
2997         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
2998         return 1;
2999       }
3000
3001       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
3002       aPosName.LowerCase();
3003       if (aPosName == "center")
3004       {
3005         aPosition = Aspect_TOTP_CENTER;
3006       }
3007       else if (aPosName == "left_lower"
3008             || aPosName == "lower_left"
3009             || aPosName == "leftlower"
3010             || aPosName == "lowerleft")
3011       {
3012         aPosition = Aspect_TOTP_LEFT_LOWER;
3013       }
3014       else if (aPosName == "left_upper"
3015             || aPosName == "upper_left"
3016             || aPosName == "leftupper"
3017             || aPosName == "upperleft")
3018       {
3019         aPosition = Aspect_TOTP_LEFT_UPPER;
3020       }
3021       else if (aPosName == "right_lower"
3022             || aPosName == "lower_right"
3023             || aPosName == "rightlower"
3024             || aPosName == "lowerright")
3025       {
3026         aPosition = Aspect_TOTP_RIGHT_LOWER;
3027       }
3028       else if (aPosName == "right_upper"
3029             || aPosName == "upper_right"
3030             || aPosName == "rightupper"
3031             || aPosName == "upperright")
3032       {
3033         aPosition = Aspect_TOTP_RIGHT_UPPER;
3034       }
3035       else
3036       {
3037         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
3038         return 1;
3039       }
3040     }
3041     else if (aFlag == "-type")
3042     {
3043       if (++anArgIter >= theArgNb)
3044       {
3045         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3046         return 1;
3047       }
3048
3049       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
3050       aTypeName.LowerCase();
3051       if (aTypeName == "wireframe"
3052        || aTypeName == "wire")
3053       {
3054         aVisType = V3d_WIREFRAME;
3055       }
3056       else if (aTypeName == "zbuffer"
3057             || aTypeName == "shaded")
3058       {
3059         aVisType = V3d_ZBUFFER;
3060       }
3061       else
3062       {
3063         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
3064       }
3065     }
3066     else if (aFlag == "-scale")
3067     {
3068       if (++anArgIter >= theArgNb)
3069       {
3070         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3071         return 1;
3072       }
3073
3074       aScale = Draw::Atof (theArgVec[anArgIter]);
3075     }
3076     else if (aFlag == "-size"
3077           || aFlag == "-sizeratio")
3078     {
3079       if (++anArgIter >= theArgNb)
3080       {
3081         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3082         return 1;
3083       }
3084
3085       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
3086     }
3087     else if (aFlag == "-arrowdiam"
3088           || aFlag == "-arrowdiameter")
3089     {
3090       if (++anArgIter >= theArgNb)
3091       {
3092         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3093         return 1;
3094       }
3095
3096       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
3097     }
3098     else if (aFlag == "-nbfacets")
3099     {
3100       if (++anArgIter >= theArgNb)
3101       {
3102         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3103         return 1;
3104       }
3105
3106       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
3107     }
3108     else if (aFlag == "-colorlabel"
3109           || aFlag == "-colorlabels")
3110     {
3111       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3112                                                            theArgVec + anArgIter + 1,
3113                                                            aLabelsColor);
3114       if (aNbParsed == 0)
3115       {
3116         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3117         return 1;
3118       }
3119       anArgIter += aNbParsed;
3120     }
3121     else if (aFlag == "-colorarrowx")
3122     {
3123       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3124                                                            theArgVec + anArgIter + 1,
3125                                                            anArrowColorX);
3126       if (aNbParsed == 0)
3127       {
3128         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3129         return 1;
3130       }
3131       anArgIter += aNbParsed;
3132     }
3133     else if (aFlag == "-colorarrowy")
3134     {
3135       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3136                                                            theArgVec + anArgIter + 1,
3137                                                            anArrowColorY);
3138       if (aNbParsed == 0)
3139       {
3140         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3141         return 1;
3142       }
3143       anArgIter += aNbParsed;
3144     }
3145     else if (aFlag == "-colorarrowz")
3146     {
3147       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3148                                                            theArgVec + anArgIter + 1,
3149                                                            anArrowColorZ);
3150       if (aNbParsed == 0)
3151       {
3152         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3153         return 1;
3154       }
3155       anArgIter += aNbParsed;
3156     }
3157     else
3158     {
3159       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3160       return 1;
3161     }
3162   }
3163
3164   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
3165                                aSizeRatio, anArrowDiam, aNbFacets);
3166   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
3167   aView->ZFitAll();
3168   return 0;
3169 }
3170
3171 //==============================================================================
3172 //function : VRotate
3173 //purpose  : Camera Rotating
3174 //==============================================================================
3175
3176 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
3177 {
3178   Handle(V3d_View) aView = ViewerTest::CurrentView();
3179   if (aView.IsNull())
3180   {
3181     std::cout << "No active view!\n";
3182     return 1;
3183   }
3184
3185   Standard_Boolean hasFlags = Standard_False;
3186   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3187   {
3188     Standard_CString        anArg (theArgVec[anArgIter]);
3189     TCollection_AsciiString aFlag (anArg);
3190     aFlag.LowerCase();
3191     if (aFlag == "-mousestart"
3192      || aFlag == "-mousefrom")
3193     {
3194       hasFlags = Standard_True;
3195       if (anArgIter + 2 >= theArgNb)
3196       {
3197         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3198         return 1;
3199       }
3200
3201       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3202       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3203       aView->StartRotation (anX, anY);
3204     }
3205     else if (aFlag == "-mousemove")
3206     {
3207       hasFlags = Standard_True;
3208       if (anArgIter + 2 >= theArgNb)
3209       {
3210         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3211         return 1;
3212       }
3213
3214       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3215       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3216       aView->Rotation (anX, anY);
3217     }
3218     else if (theArgNb != 4
3219           && theArgNb != 7)
3220     {
3221       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3222       return 1;
3223     }
3224   }
3225
3226   if (hasFlags)
3227   {
3228     return 0;
3229   }
3230   else if (theArgNb == 4)
3231   {
3232     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3233     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3234     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3235     aView->Rotate (anAX, anAY, anAZ);
3236     return 0;
3237   }
3238   else if (theArgNb == 7)
3239   {
3240     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3241     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3242     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3243
3244     Standard_Real anX = Draw::Atof (theArgVec[4]);
3245     Standard_Real anY = Draw::Atof (theArgVec[5]);
3246     Standard_Real anZ = Draw::Atof (theArgVec[6]);
3247
3248     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
3249     return 0;
3250   }
3251
3252   std::cout << "Error: Invalid number of arguments\n";
3253   return 1;
3254 }
3255
3256 //==============================================================================
3257 //function : VZoom
3258 //purpose  : View zoom in / out (relative to current zoom)
3259 //==============================================================================
3260
3261 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3262   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3263   if ( V3dView.IsNull() ) {
3264     return 1;
3265   }
3266
3267   if ( argc == 2 ) {
3268     Standard_Real coef = Draw::Atof(argv[1]);
3269     if ( coef <= 0.0 ) {
3270       di << argv[1] << "Invalid value\n";
3271       return 1;
3272     }
3273     V3dView->SetZoom( Draw::Atof(argv[1]) );
3274     return 0;
3275   } else {
3276     di << argv[0] << " Invalid number of arguments\n";
3277     return 1;
3278   }
3279 }
3280
3281 //==============================================================================
3282 //function : VPan
3283 //purpose  : View panning (in pixels)
3284 //==============================================================================
3285
3286 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3287   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3288   if ( V3dView.IsNull() ) return 1;
3289
3290   if ( argc == 3 ) {
3291     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
3292     return 0;
3293   } else {
3294     di << argv[0] << " Invalid number of arguments\n";
3295     return 1;
3296   }
3297 }
3298
3299 //==============================================================================
3300 //function : VPlace
3301 //purpose  : Place the point (in pixels) at the center of the window
3302 //==============================================================================
3303 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
3304 {
3305   Handle(V3d_View) aView = ViewerTest::CurrentView();
3306   if (aView.IsNull())
3307   {
3308     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
3309     return 1;
3310   }
3311
3312   if (theArgNb != 3)
3313   {
3314     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
3315     return 1;
3316   }
3317
3318   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
3319
3320   return 0;
3321 }
3322
3323 //==============================================================================
3324 //function : VExport
3325 //purpose  : Export the view to a vector graphic format (PS, EMF, PDF)
3326 //==============================================================================
3327
3328 static int VExport(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3329 {
3330   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3331   if (V3dView.IsNull())
3332     return 1;
3333
3334   if (argc == 1)
3335   {
3336     std::cout << "Usage: " << argv[0] << " Filename [Format]\n";
3337     return 1;
3338   }
3339
3340   Graphic3d_ExportFormat anExpFormat = Graphic3d_EF_PDF;
3341   TCollection_AsciiString aFormatStr;
3342
3343   TCollection_AsciiString aFileName (argv[1]);
3344   Standard_Integer aLen = aFileName.Length();
3345
3346   if (argc > 2)
3347   {
3348     aFormatStr = TCollection_AsciiString (argv[2]);
3349   }
3350   else if (aLen >= 4)
3351   {
3352     if (aFileName.Value (aLen - 2) == '.')
3353     {
3354       aFormatStr = aFileName.ToCString() + aLen - 2;
3355     }
3356     else if (aFileName.Value (aLen - 3) == '.')
3357     {
3358       aFormatStr = aFileName.ToCString() + aLen - 3;
3359     }
3360     else
3361     {
3362       std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3363       return 1;
3364     }
3365   }
3366   else
3367   {
3368     std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3369     return 1;
3370   }
3371
3372   aFormatStr.UpperCase();
3373   if (aFormatStr == "PS")
3374     anExpFormat = Graphic3d_EF_PostScript;
3375   else if (aFormatStr == "EPS")
3376     anExpFormat = Graphic3d_EF_EnhPostScript;
3377   else if (aFormatStr == "TEX")
3378     anExpFormat = Graphic3d_EF_TEX;
3379   else if (aFormatStr == "PDF")
3380     anExpFormat = Graphic3d_EF_PDF;
3381   else if (aFormatStr == "SVG")
3382     anExpFormat = Graphic3d_EF_SVG;
3383   else if (aFormatStr == "PGF")
3384     anExpFormat = Graphic3d_EF_PGF;
3385   else if (aFormatStr == "EMF")
3386     anExpFormat = Graphic3d_EF_EMF;
3387   else
3388   {
3389     std::cout << "Invalid export format '" << aFormatStr << "'\n";
3390     return 1;
3391   }
3392
3393   try
3394   {
3395   Standard_DISABLE_DEPRECATION_WARNINGS
3396     if (!V3dView->Export (argv[1], anExpFormat))
3397   Standard_ENABLE_DEPRECATION_WARNINGS
3398     {
3399       di << "Error: export of image to " << aFormatStr << " failed!\n";
3400     }
3401   }
3402   catch (Standard_Failure)
3403   {
3404     di << "Error: export of image to " << aFormatStr << " failed";
3405     di << " (exception: " << Standard_Failure::Caught()->GetMessageString() << ")";
3406   }
3407   return 0;
3408 }
3409
3410 //==============================================================================
3411 //function : VColorScale
3412 //purpose  : representation color scale
3413 //==============================================================================
3414
3415 static Standard_Boolean checkColor (const TCollection_AsciiString& theRed,
3416                                     const TCollection_AsciiString& theGreen,
3417                                     const TCollection_AsciiString& theBlue,
3418                                                     Standard_Real& theRedValue,
3419                                                     Standard_Real& theGreenValue,
3420                                                     Standard_Real& theBlueValue)
3421 {
3422   if (!theRed.IsRealValue()
3423    || !theGreen.IsRealValue()
3424    || !theBlue.IsRealValue())
3425   {
3426     std::cout << "Error: RGB color values should be real!\n";
3427     return Standard_True;
3428   }
3429   theRedValue = theRed    .RealValue();
3430   theGreenValue = theGreen.RealValue();
3431   theBlueValue = theBlue  .RealValue();
3432   if (theRedValue < 0.0 || theRedValue > 1.0
3433    || theGreenValue < 0.0 || theGreenValue > 1.0
3434    || theBlueValue < 0.0 || theBlueValue > 1.0)
3435   {
3436     std::cout << "Error: RGB color values should be within range 0..1!\n";
3437     return Standard_True;
3438   }
3439   return Standard_False;
3440 }
3441
3442 static int VColorScale (Draw_Interpretor& theDI,
3443                         Standard_Integer  theArgNb,
3444                         const char**      theArgVec)
3445 {
3446   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
3447   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
3448   if (aContext.IsNull())
3449   {
3450     std::cout << "Error: no active view!\n";
3451     return 1;
3452   }
3453   if (theArgNb <= 1)
3454   {
3455     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
3456     return 1;
3457   }
3458
3459   Handle(AIS_ColorScale) aCS;
3460   // find object
3461   Handle(AIS_InteractiveObject) anIObj;
3462   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
3463   {
3464     aCS = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
3465     if (aCS.IsNull())
3466     {
3467       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
3468       return 1;
3469     }
3470   }
3471   else
3472   {
3473     aCS = new AIS_ColorScale();
3474     GetMapOfAIS().Bind (aCS,theArgVec[1]);
3475   }
3476
3477   if (aCS->ZLayer() != Graphic3d_ZLayerId_TopOSD)
3478   {
3479     aCS->SetZLayer (Graphic3d_ZLayerId_TopOSD);
3480   }
3481   if (aCS->TransformPersistence().IsNull()
3482    || aCS->TransformPersistence()->Mode() != Graphic3d_TMF_2d)
3483   {
3484     aContext->SetTransformPersistence (aCS, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
3485   }
3486