Salome HOME
NRI : KERNEL is now defined in KERNELCatalog.
[modules/kernel.git] / src / OCCViewer / OCCViewer_ViewPort.cxx
1 using namespace std;
2 //  File      : OCCViewer_ViewPort.cxx
3 //  Created   : Wed Mar 20 10:44:24 2002
4 //  Author    : Nicolas REJNERI
5 //  Project   : SALOME
6 //  Module    : OCCViewer
7 //  Copyright : Open CASCADE 2002
8 //  $Header$
9
10
11 #include <stdlib.h>
12
13 #if !defined WNT
14 #define QT_CLEAN_NAMESPACE         /* avoid definition of INT32 and INT8 */
15 #endif
16
17 #include "OCCViewer_ViewPort.h"
18
19 #include "QAD.h"
20 #include "QAD_Tools.h"
21 #include "QAD_Desktop.h"
22 #include "QAD_MessageBox.h"
23
24 #if !defined WNT
25 #include <GL/glx.h>
26 #include <X11/Xlib.h>
27 #include <X11/Xutil.h>
28 #include <X11/Xatom.h>
29 #include <X11/Xmu/StdCmap.h>
30 #undef QT_CLEAN_NAMESPACE
31 #include <Xw_Window.hxx>
32 #include <Graphic3d_GraphicDevice.hxx>
33
34 #include <qpixmap.h>
35 #include <qintdict.h>
36
37 /* XPM */
38 const char* imageZoomCursor[] = { 
39 "32 32 3 1",
40 ". c None",
41 "a c #000000",
42 "# c #ffffff",
43 "................................",
44 "................................",
45 ".#######........................",
46 "..aaaaaaa.......................",
47 "................................",
48 ".............#####..............",
49 "...........##.aaaa##............",
50 "..........#.aa.....a#...........",
51 ".........#.a.........#..........",
52 ".........#a..........#a.........",
53 "........#.a...........#.........",
54 "........#a............#a........",
55 "........#a............#a........",
56 "........#a............#a........",
57 "........#a............#a........",
58 ".........#...........#.a........",
59 ".........#a..........#a.........",
60 ".........##.........#.a.........",
61 "........#####.....##.a..........",
62 ".......###aaa#####.aa...........",
63 "......###aa...aaaaa.......#.....",
64 ".....###aa................#a....",
65 "....###aa.................#a....",
66 "...###aa...............#######..",
67 "....#aa.................aa#aaaa.",
68 ".....a....................#a....",
69 "..........................#a....",
70 "...........................a....",
71 "................................",
72 "................................",
73 "................................",
74 "................................"};
75
76 const char* imageRotateCursor[] = { 
77 "32 32 3 1",
78 ". c None",
79 "a c #000000",
80 "# c #ffffff",
81 "................................",
82 "................................",
83 "................................",
84 "................................",
85 "........#.......................",
86 ".......#.a......................",
87 "......#######...................",
88 ".......#aaaaa#####..............",
89 "........#..##.a#aa##........##..",
90 ".........a#.aa..#..a#.....##.aa.",
91 ".........#.a.....#...#..##.aa...",
92 ".........#a.......#..###.aa.....",
93 "........#.a.......#a..#aa.......",
94 "........#a.........#..#a........",
95 "........#a.........#a.#a........",
96 "........#a.........#a.#a........",
97 "........#a.........#a.#a........",
98 ".........#.........#a#.a........",
99 "........##a........#a#a.........",
100 "......##.a#.......#.#.a.........",
101 "....##.aa..##.....##.a..........",
102 "..##.aa.....a#####.aa...........",
103 "...aa.........aaa#a.............",
104 "................#.a.............",
105 "...............#.a..............",
106 "..............#.a...............",
107 "...............a................",
108 "................................",
109 "................................",
110 "................................",
111 "................................",
112 "................................"};
113
114 struct CMapEntry {
115   CMapEntry();
116   ~CMapEntry();
117   Colormap cmap;
118   bool alloc;
119   XStandardColormap     scmap;
120 };
121
122 CMapEntry::CMapEntry()
123 {
124   cmap = 0;
125   alloc = false;
126   scmap.colormap = 0;
127 }
128
129 CMapEntry::~CMapEntry()
130 {
131   if ( alloc )
132     XFreeColormap( QPaintDevice::x11AppDisplay(), cmap );
133 }
134
135 static QIntDict<CMapEntry> *cmap_dict = 0;
136 static bool mesa_gl = false;
137
138 static void cleanup_cmaps()
139 {
140   if ( !cmap_dict )
141     return;
142   cmap_dict->setAutoDelete(true);
143   delete cmap_dict;
144   cmap_dict = 0;
145 }
146
147 static Colormap choose_cmap(Display *dpy, XVisualInfo *vi)
148 {
149   if ( !cmap_dict ) 
150     {
151       cmap_dict = new QIntDict<CMapEntry>;
152       const char *v = glXQueryServerString( dpy, vi->screen, GLX_VERSION );
153       mesa_gl = strstr(v,"Mesa") != 0;
154       qAddPostRoutine( cleanup_cmaps );
155     }
156   
157   CMapEntry *x = cmap_dict->find( (long)vi->visualid );
158   if ( x )                                      // found colormap for visual
159     return x->cmap;
160   
161   x = new CMapEntry();
162   
163   XStandardColormap *c;
164   int n, i;
165   
166 #ifdef DEBUG
167   MESSAGE( "Choosing cmap for vID = " << vi->visualid );
168 #endif
169   
170   if ( vi->visualid == XVisualIDFromVisual( (Visual*)QPaintDevice::x11AppVisual() ) ) 
171     {
172 #ifdef DEBUG
173       MESSAGE( "Using x11AppColormap" );
174 #endif
175       return QPaintDevice::x11AppColormap();
176     }
177   
178   if ( mesa_gl ) 
179     {   
180       Atom hp_cmaps = XInternAtom( dpy, "_HP_RGB_SMOOTH_MAP_LIST", true );
181       if ( hp_cmaps && vi->visual->c_class == TrueColor && vi->depth == 8 ) 
182         {
183           if ( XGetRGBColormaps(dpy, RootWindow(dpy,vi->screen), &c, &n, hp_cmaps) ) 
184             {
185               i = 0;
186               while ( i < n && x->cmap == 0 ) 
187                 {
188                   if ( c[i].visualid == vi->visual->visualid ) 
189                     {
190                       x->cmap = c[i].colormap;
191                       x->scmap = c[i];
192                       // Using HP_RGB scmap
193                     }
194                   i++;
195                 }
196               XFree( (char *)c );
197             }
198         }
199     }
200   
201 #if !defined(_OS_SOLARIS_)
202   if ( !x->cmap ) 
203     {
204       if ( XmuLookupStandardColormap(dpy,vi->screen,vi->visualid,vi->depth,
205                                      XA_RGB_DEFAULT_MAP,false,true) ) 
206         {
207           if ( XGetRGBColormaps(dpy,RootWindow(dpy,vi->screen),&c,&n,
208                                 XA_RGB_DEFAULT_MAP) ) 
209             {
210               i = 0;
211               while ( i < n && x->cmap == 0 ) 
212                 {
213                   if ( c[i].visualid == vi->visualid ) 
214                     {
215                       x->cmap = c[i].colormap;
216                       x->scmap = c[i];
217                       // Using RGB_DEFAULT scmap
218                     }
219                   i++;
220                 }
221               XFree( (char *)c );
222             }
223         }
224     }
225 #endif
226   if ( !x->cmap ) 
227     {                           
228       // no shared cmap found
229       x->cmap = XCreateColormap( dpy, RootWindow(dpy,vi->screen), vi->visual,
230                                  AllocNone );
231       x->alloc = true;
232       // Allocating cmap
233     }
234   
235   cmap_dict->insert( (long)vi->visualid, x ); // associate cmap with visualid
236   return x->cmap;
237 }       
238 #endif
239
240 /* statics */
241 int             OCCViewer_ViewPort::nCounter    = 0;
242 QCursor*        OCCViewer_ViewPort::defCursor   = NULL;
243 QCursor*        OCCViewer_ViewPort::handCursor  = NULL;
244 QCursor*        OCCViewer_ViewPort::panCursor   = NULL;
245 QCursor*        OCCViewer_ViewPort::zoomCursor  = NULL;
246 QCursor*        OCCViewer_ViewPort::rotCursor   = NULL;
247 QCursor*        OCCViewer_ViewPort::glPanCursor = NULL;
248
249 /*!
250     Creates the necessary viewport cursors [ static ]
251 */
252 void OCCViewer_ViewPort::createCursors ()
253 {
254   defCursor    = new QCursor ( ArrowCursor );
255   handCursor   = new QCursor ( PointingHandCursor );
256   panCursor    = new QCursor ( SizeAllCursor  );
257   zoomCursor   = new QCursor (QPixmap(imageZoomCursor));
258   rotCursor    = new QCursor (QPixmap(imageRotateCursor));
259   glPanCursor  = new QCursor (CrossCursor);
260 //  QAD_ResourceMgr* rmgr = QAD_Desktop::getResourceManager();
261 //  zoomCursor = new QCursor ( rmgr->loadPixmap( "QAD", tr("ICON_CURSOR_ZOOM") ));
262 //  rotCursor = new QCursor ( rmgr->loadPixmap( "QAD", tr("ICON_CURSOR_ROTATE") ));
263 }
264
265 /*!
266     Destroys the viewport cursors [ static ]
267 */
268 void OCCViewer_ViewPort::destroyCursors ()
269 {
270   if ( defCursor ) delete defCursor;
271   defCursor = 0;
272   if ( handCursor ) delete handCursor;
273   handCursor = 0;
274   if ( panCursor ) delete panCursor;
275   panCursor = 0;
276   if ( zoomCursor ) delete zoomCursor;
277   zoomCursor = 0;
278   if ( rotCursor ) delete rotCursor;
279   rotCursor = 0;
280   if ( glPanCursor ) delete glPanCursor;
281   glPanCursor = 0;
282 }
283
284 /*!
285     Sets new default cursor [ static ]
286 */
287 void OCCViewer_ViewPort::setDefaultCursor(const QCursor& newCursor) 
288 {
289   if ( !defCursor ) defCursor = new QCursor; 
290   *defCursor = newCursor; 
291 }
292
293 /*!
294     Sets new cursor for drawing rectangle in the viewport [ static ]
295 */
296 void OCCViewer_ViewPort::setHandCursor(const QCursor& newCursor) 
297
298   if ( !handCursor ) handCursor = new QCursor;
299   *handCursor = newCursor; 
300 }
301
302 /*!
303     Sets new cursor for panning [ static ]
304 */
305 void OCCViewer_ViewPort::setPanCursor(const QCursor& newCursor) 
306
307   if ( !panCursor ) panCursor = new QCursor;
308   *panCursor = newCursor; 
309 }
310
311 /*!
312     Sets new cursor for zooming [ static ]
313 */
314 void OCCViewer_ViewPort::setZoomCursor(const QCursor& newCursor) 
315
316   if ( !zoomCursor ) zoomCursor = new QCursor;
317   *zoomCursor = newCursor; 
318 }
319
320 /*!
321     Sets new cursor for rotating [ static ]
322 */
323 void OCCViewer_ViewPort::setRotCursor(const QCursor& newCursor) 
324
325   if ( !rotCursor ) rotCursor = new QCursor;
326   *rotCursor = newCursor; 
327 }
328
329 /*!
330     Sets new cursor for global panning [ static ]
331 */
332 void OCCViewer_ViewPort::setGlPanCursor(const QCursor& newCursor) 
333
334   if ( !glPanCursor ) glPanCursor = new QCursor;
335   *glPanCursor = newCursor; 
336 }
337
338 /*!
339     Constructor
340 */
341 OCCViewer_ViewPort::OCCViewer_ViewPort(QWidget* parent) : 
342   QWidget( parent, 0, WRepaintNoErase | WResizeNoErase)
343 {
344   initialize();
345 }
346
347 /*!
348     Destructor
349 */
350 OCCViewer_ViewPort::~OCCViewer_ViewPort()
351 {
352   cleanup();
353 }
354
355 /*!
356     Initializes viewport
357 */
358 void OCCViewer_ViewPort::initialize()
359 {
360   /* initialize cursors */
361   if ( nCounter++ == 0 ) createCursors();
362
363 #if !defined WNT
364
365   XVisualInfo* pVisualInfo;
366   if ( x11Display() ) 
367     {
368       /* Initialization with the default VisualID
369        */
370       //NRI Visual *v = DefaultVisual(x11Display(), DefaultScreen(x11Display()));
371       //NRI int visualID = XVisualIDFromVisual(v);
372
373           /*  Here we use the settings from 
374               Optimizer_ViewInfo::TxglCreateWindow()
375           */
376       int visualAttr[] = { GLX_RGBA, GLX_DEPTH_SIZE, 1, 
377                            GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1,
378                            GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER,
379                            None };
380
381       pVisualInfo = ::glXChooseVisual (x11Display(), DefaultScreen(x11Display()), visualAttr);
382           
383       if ( isVisible() ) hide();
384           
385       XSetWindowAttributes a;
386           
387       a.colormap = choose_cmap( x11Display(), pVisualInfo );        /* find best colormap */
388       a.background_pixel = backgroundColor().pixel();
389       a.border_pixel = black.pixel();
390       Window p = RootWindow( x11Display(), DefaultScreen(x11Display()) ); 
391       if ( parentWidget() ) p = parentWidget()->winId();
392           
393       Window w = XCreateWindow( x11Display(), p,  x(), y(), width(), height(),
394                                 0, pVisualInfo->depth, InputOutput,  pVisualInfo->visual,
395                                 CWBackPixel | CWBorderPixel | CWColormap, &a );
396       Window *cmw;
397       Window *cmwret;
398       int count;
399       if ( XGetWMColormapWindows( x11Display(), topLevelWidget()->winId(), &cmwret, &count ) )
400         {
401           cmw = new Window[count+1];
402           memcpy( (char *)cmw, (char *)cmwret, sizeof(Window)*count );
403           XFree( (char *)cmwret );
404           int i;
405               
406           for (i = 0; i < count; i++) 
407             {
408               if ( cmw[i] == winId() ) /* replace old window */
409                 {               
410                   cmw[i] = w;
411                   break;
412                 }
413             }
414               
415           if ( i >= count )                      /* append new window */
416             cmw[count++] = w;
417         } 
418       else 
419         {
420           count = 1;
421           cmw = new Window[count];
422           cmw[0] = w;
423         }
424           
425       /* Creating new window (with good VisualID) for this widget
426            */
427       create(w);
428       XSetWMColormapWindows( x11Display(), topLevelWidget()->winId(), cmw, count );
429       delete [] cmw;
430           
431       if ( isVisible() ) show();
432           
433       if ( pVisualInfo ) {
434         XFree( (char *)pVisualInfo );
435       }
436           
437       XFlush(x11Display());
438       //                XSync(x11Display(), false);
439       //                XSynchronize(x11Display(), true);
440     } 
441 #endif  // !defined WNT
442   
443   myOriginalViewport = NULL;    
444   myCursorIsHand = false;
445   myCursor = *defCursor;
446   myHasWindow = false;
447   myDrawRect = false;
448   myStartX = myStartY = myCurrX = myCurrY =0;
449   myPaintersRedrawing = false;
450   myEnableDrawMode = true;
451   
452   setTransformRequested ( NOTHING );
453   setTransformInProcess ( false );
454   
455   setMouseTracking( true );
456   setBackgroundMode(NoBackground);
457
458   setFocus();
459 }
460
461 /*!
462     Cleans up the viewport
463 */
464 void OCCViewer_ViewPort::cleanup()
465 {
466   if ( --nCounter == 0 ) 
467     destroyCursors();
468 }
469
470 /*!
471     Sets the original view for the viewport   
472 */
473 void OCCViewer_ViewPort::setOriginalView( OCCViewer_ViewPort* viewport, 
474                                           const QRect& magnify )
475 {
476   myOriginalViewport = viewport;
477   myMagnifyRect = magnify;
478 }
479
480 /*!
481     Returns the original view or null
482 */
483 OCCViewer_ViewPort* OCCViewer_ViewPort::getOriginalView() const
484 {
485   return myOriginalViewport;
486 }
487
488 /*!
489     Returns the 'magnify' rect ( used for 'magnify' operation )
490 */
491 const QRect& OCCViewer_ViewPort::getMagnifyRect() const
492 {
493   return myMagnifyRect;
494 }
495
496 /*!
497     Returns the sketched rect ( used for multiple selection )
498 */
499 const QRect& OCCViewer_ViewPort::getSelectionRect() const
500 {
501   return myRect;
502 }
503
504 /*!
505     Returns 'true' if the viewport has a native window
506 */
507 bool OCCViewer_ViewPort::hasWindow() const
508 {
509   return myHasWindow;
510 }
511
512 /*!
513     Must be called if native window was changed 
514 */
515 void OCCViewer_ViewPort::windowChanged() 
516 {
517   myHasWindow = false;
518 }
519
520 /*!
521     Sets the default cursor active    
522 */
523 void OCCViewer_ViewPort::setDefaultCursorOn()
524 {
525   setCursor ( *OCCViewer_ViewPort::defCursor );
526 }
527
528 /*!
529     Sets the 'hand' cursor active    
530 */
531 void OCCViewer_ViewPort::setHandCursorOn()
532 {
533   setCursor ( *OCCViewer_ViewPort::handCursor );
534 }
535
536 /*!
537     Sets the panning cursor active    
538 */
539 void OCCViewer_ViewPort::setPanCursorOn()
540 {
541   setCursor( *OCCViewer_ViewPort::panCursor );
542 }
543
544 /*!
545     Sets the zooming cursor active    
546 */
547 void OCCViewer_ViewPort::setZoomCursorOn()
548 {
549   setCursor( *OCCViewer_ViewPort::zoomCursor );
550 }
551
552 /*!
553     Sets the rotating cursor active    
554 */
555 void OCCViewer_ViewPort::setRotCursorOn()
556 {
557   setCursor( *OCCViewer_ViewPort::rotCursor );
558 }
559
560 /*!
561     Sets the global panning cursor active    
562 */
563 void OCCViewer_ViewPort::setGlPanCursorOn()
564 {
565   setCursor( *OCCViewer_ViewPort::glPanCursor );
566 }
567
568 /*!
569     Returns the default background color
570 */
571 QColor OCCViewer_ViewPort::backgroundColor() const
572 {
573   return Qt::white;
574 }
575
576 /*!
577     Activates 'zoom' transformation
578 */
579 void OCCViewer_ViewPort::activateZoom()
580 {
581   if ( !transformRequested() && !myCursorIsHand )
582     myCursor = cursor();                /* save old cursor */
583   
584   if ( myOperation != ZOOMVIEW ) {
585     setTransformRequested ( ZOOMVIEW );         
586     setCursor( *zoomCursor );
587   }
588 }
589
590 /*!
591     Activates 'panning' transformation
592 */
593 void OCCViewer_ViewPort::activatePanning()
594 {
595   if ( !transformRequested() && !myCursorIsHand )
596     myCursor = cursor();                /* save old cursor */
597   
598   if ( myOperation != PANVIEW ) {
599     setTransformRequested ( PANVIEW );
600     setCursor( *panCursor );
601   }
602 }
603
604 /*!
605     Activates 'rotation' transformation
606 */
607 void OCCViewer_ViewPort::activateRotation()
608 {
609   if ( !transformRequested() && !myCursorIsHand )
610     myCursor = cursor();                /* save old cursor */
611   
612   if ( myOperation != ROTATE ) {
613     setTransformRequested ( ROTATE );
614     setCursor( *rotCursor );    
615   }
616 }
617
618 /*!
619     Activates 'fit' transformation
620 */
621 void OCCViewer_ViewPort::activateWindowFit()
622 {
623   if ( !transformRequested() && !myCursorIsHand )
624     myCursor = cursor();                /* save old cursor */
625
626   if ( myOperation != WINDOWFIT ) {
627     setTransformRequested ( WINDOWFIT );                
628     setCursor ( *handCursor );
629     myCursorIsHand = true;
630   }
631 //  setTransformInProcess( true );              
632 //  emit vpTransformationStarted ( WINDOWFIT );
633 }
634
635 /*!
636     Activates 'global panning' transformation
637 */
638 void OCCViewer_ViewPort::activateGlobalPanning()
639 {
640   if ( !transformRequested() && !myCursorIsHand )
641     myCursor = cursor();                /* save old cursor */
642   
643   if ( myOperation != PANGLOBAL ) 
644     {
645       fitAll(); /* fits view before selecting a new scene center */
646       setTransformRequested ( PANGLOBAL );
647       setCursor( *glPanCursor );
648     }
649 //  setTransformInProcess( true );              
650 //  emit vpTransformationStarted ( PANGLOBAL );
651 }
652
653 /*!
654     Sets the viewport to its initial state
655     ( no transformations in process etc. )
656 */
657 void OCCViewer_ViewPort::resetState()
658 {
659   myDrawRect = false;
660   
661   /* make rectangle empty (left > right) */
662   myRect.setLeft(2);
663   myRect.setRight(0);
664   
665   if ( transformRequested() || myCursorIsHand ) 
666     setCursor( myCursor );
667   myCursorIsHand = false;
668   
669   if ( transformRequested() ) 
670     emit vpTransformationFinished (myOperation);
671   
672   setTransformInProcess( false );               
673   setTransformRequested ( NOTHING );    
674   QAD_Application::getDesktop()->putInfo( tr("INF_READY") );
675 }
676
677 /*!
678     Enable/disable user's ability to sketch a rect in the viewport
679 */
680 void OCCViewer_ViewPort::enableDrawMode(bool bEnable )
681 {
682   myEnableDrawMode = bEnable;
683 }
684
685 /*!
686     Returns 'true' if user can sketch a rect in the viewport
687 */
688 bool OCCViewer_ViewPort::enableDrawMode() const
689 {
690   return myEnableDrawMode;
691 }
692
693 /*!
694     Sets the active operation 'op'
695 */
696 void OCCViewer_ViewPort::setTransformRequested ( OperationType op )
697 {    
698   myOperation = op;
699   setMouseTracking ( myOperation == NOTHING );  
700 }
701
702 /*!
703     Mouse event handler
704 */
705 void OCCViewer_ViewPort::mousePressEvent (QMouseEvent* event)
706 {
707   myStartX = event->x();
708   myStartY = event->y();
709   switch ( myOperation )
710     {
711     case WINDOWFIT:
712       if ( event->button() == Qt::LeftButton )
713         emit vpTransformationStarted ( WINDOWFIT );
714       break;    
715 //      return;
716     case PANGLOBAL:
717       if ( event->button() == Qt::LeftButton )
718         emit vpTransformationStarted ( PANGLOBAL );
719       break;    
720 //      return;
721       
722     case ZOOMVIEW:
723       if ( event->button() == Qt::LeftButton )
724         emit vpTransformationStarted ( ZOOMVIEW );
725       break;
726       
727     case PANVIEW:
728       if ( event->button() == Qt::LeftButton )
729         emit vpTransformationStarted ( PANVIEW );
730       break;
731
732     case ROTATE:
733       if ( event->button() == Qt::LeftButton )
734         {
735           startRotation(myStartX, myStartY);
736           emit vpTransformationStarted ( ROTATE );
737         }
738       break;
739       
740     default:
741       
742       /*        Try to activate a transformation
743        */
744       if ( (event->state() == Qt::ControlButton) &&
745            (event->button() == Qt::LeftButton) )
746         {
747                                 /* MB1 + CTRL = Zooming */
748           activateZoom();
749         }
750       else if ( (event->state() == Qt::ControlButton) &&
751                 (event->button() == Qt::MidButton) )
752         {
753                                 /* MB2 + CTRL = Panning */
754           activatePanning();
755         }
756       else if ( (event->state() == Qt::ControlButton) &&
757                 (event->button() == Qt::RightButton) )
758         {
759                                 /* MB3 + CTRL = Rotation */
760           activateRotation();
761           startRotation(myStartX, myStartY);
762         }
763       
764       /* notify that we start a transformation */
765       if ( transformRequested() ) 
766         emit vpTransformationStarted ( myOperation );
767     }
768   
769   if ( transformRequested() ) 
770     setTransformInProcess( true );              
771   
772   /*  NOTE: this signal must be emitted at the end 
773       because we must to detect a transformation first
774   */
775   emit vpMousePress (event);
776 }
777
778 /*!
779     Mouse event handler 
780 */
781 void OCCViewer_ViewPort::mouseMoveEvent (QMouseEvent* event)
782 {
783   myCurrX = event->x();
784   myCurrY = event->y();
785   switch (myOperation)
786     {
787     case ROTATE:
788       rotate(myCurrX, myCurrY);
789       break;
790       
791     case ZOOMVIEW:
792       zoom(myStartX, myStartY, myCurrX, myCurrY);
793       myStartX = myCurrX;
794       myStartY = myCurrY;
795       break;
796       
797     case PANVIEW:
798       pan(myCurrX - myStartX, myStartY - myCurrY);
799       myStartX = myCurrX;
800       myStartY = myCurrY;
801       break;
802       
803 /*    case WINDOWFIT:
804       myDrawRect = true;
805       repaint();
806       break;
807 */      
808     case PANGLOBAL:
809       break;
810       
811     default:
812       if ( event->state() == Qt::LeftButton ||
813            event->state() == ( Qt::LeftButton | Qt::ShiftButton) )
814         {
815           myDrawRect = myEnableDrawMode;
816           if ( myDrawRect ) 
817             {
818               repaint( visibleRect(), false);
819               if ( !myCursorIsHand )
820                 {   /* we are going to sketch a rectangle */                                        
821                   myCursorIsHand = true;                
822                   myCursor = cursor();
823                   setCursor ( *handCursor );
824                 }
825             }
826         }
827     }
828   emit vpMouseMove( event );                    
829 }
830
831 /*!
832     Mouse event handler 
833 */
834 void OCCViewer_ViewPort::mouseReleaseEvent (QMouseEvent* event)
835 {
836   if ( !transformRequested() && (event->button() == Qt::RightButton) )
837     {
838       QPopupMenu* popup = createPopup();
839       if ( popup ) {
840         QAD_Tools::checkPopup( popup );
841         if ( popup->count()>0 ) {
842           popup->exec( QCursor::pos() );
843         }
844         destroyPopup();
845       }
846       return;
847     }
848   
849   switch ( myOperation )
850     {
851     case NOTHING:
852       break;
853     case ROTATE:
854       endRotation();
855       resetState();
856       break;
857       
858     case PANVIEW:
859     case ZOOMVIEW:
860       resetState();
861       break;
862       
863     case PANGLOBAL:
864       if ( event->button() == Qt::LeftButton )
865         {
866           setCenter( event->x(), event->y() );
867           resetState();
868         }
869       break;
870       
871     case WINDOWFIT:
872       if ( event->state() == Qt::LeftButton )
873         {
874           myCurrX = event->x();
875           myCurrY = event->y();
876           QRect rect = QAD_Tools::makeRect(myStartX, myStartY, myCurrX, myCurrY);
877           if ( !rect.isEmpty() ) fitWindow(rect);
878           resetState();
879         }
880       break;
881     }
882   
883   // NOTE: viewer 3D detects a rectangle of selection using this event
884   // so we must emit it BEFORE resetting the selection rectangle
885   emit vpMouseRelease  (event);         
886   
887   if ( event->button() == Qt::LeftButton && myDrawRect )
888     {
889       myDrawRect = false;
890       repaint(visibleRect(), false);
891       resetState(); 
892     }
893 }
894
895 /*!
896     Mouse event handler 
897 */
898 void OCCViewer_ViewPort::mouseDoubleClickEvent(QMouseEvent *event)
899 {
900   emit vpMouseDoubleClick (event);
901 }
902
903 /*!
904     Key event handler 
905 */
906 void OCCViewer_ViewPort::keyPressEvent(QKeyEvent *event)
907 {
908   emit vpKeyPress (event);
909 }
910
911 /*!
912     Key event handler 
913 */
914 void OCCViewer_ViewPort::keyReleaseEvent(QKeyEvent *event)
915 {
916   emit vpKeyRelease (event);
917 }
918
919 /*!
920     Called when the viewport gets the focus
921 */
922 void OCCViewer_ViewPort::focusInEvent(QFocusEvent *event)
923 {
924   emit vpFocusIn (event);
925 }
926
927 /*!
928     Called when the viewport loses the focus
929 */
930 void OCCViewer_ViewPort::focusOutEvent(QFocusEvent *event)
931 {
932   emit vpFocusOut (event);
933 }
934         
935 /*!
936     Resizes the viewport
937 */
938 void OCCViewer_ViewPort::resizeEvent (QResizeEvent* event)
939 {
940   windowResize();
941 }
942
943 /*!
944     Updates the viewport
945 */
946 void OCCViewer_ViewPort::update(int x, int y, int w, int h)
947 {
948   if ( !myHasWindow )
949     myHasWindow = setWindow();
950   if ( myHasWindow) 
951     repaint(x, y, w, h, true);
952 }
953
954 /*!
955     Repaints the viewport    
956 */
957 void OCCViewer_ViewPort::paintEvent (QPaintEvent *ev)
958 {
959   emit vpPaint (ev);
960   if ( myDrawRect )     
961     {
962       QPainter thePainter(this);
963       thePainter.setRasterOp(Qt::XorROP);
964       thePainter.setPen(Qt::white);
965       QRect aRect = QAD_Tools::makeRect(myStartX, myStartY, myCurrX, myCurrY);
966       if ( !myRect.isEmpty() )
967         thePainter.drawRect( myRect );
968       thePainter.drawRect(aRect);
969       myRect = aRect;
970     }
971
972   if ( myPaintersRedrawing )
973     {
974       QPainter thePainter(this);
975       emit vpDrawExternal  (&thePainter);
976       myPaintersRedrawing = false;
977     }
978 }
979
980 /*!
981   Forces to redraw the viewport by an external painter     
982 */
983 void OCCViewer_ViewPort::redrawPainters()
984 {
985   myPaintersRedrawing = true;
986   repaint();
987 }