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