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