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