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