Salome HOME
9b04751b157bcd98236dd28b728c2b5150d185fd
[modules/gui.git] / src / OCCViewer / OCCViewer_ViewPort.cxx
1 /***************************************************************************
2 **  Class:   OCCViewer_ViewPort
3 **  Descr:   Visualisation canvas of SUIT-based application
4 **  Module:  SUIT
5 **  Created: UI team, 05.09.00
6 ****************************************************************************/
7 #if !defined WNT
8 #define QT_CLEAN_NAMESPACE         /* avoid definition of INT32 and INT8 */
9 #endif
10
11 #include "OCCViewer_ViewPort.h"
12
13 #include "SUIT_Session.h"
14
15 #include <qrect.h>
16 #include <qcursor.h>
17 #include <qpixmap.h>
18 #include <qpainter.h>
19 #include <qintdict.h>
20 #include <qpopupmenu.h>
21 #include <qcolordialog.h>
22
23 #include <stdlib.h>
24
25 #if !defined WNT
26 #include <GL/glx.h>
27 #include <X11/Xlib.h>
28 #include <X11/Xutil.h>
29 #include <X11/Xatom.h>
30 #include <X11/Xmu/StdCmap.h>
31 #undef QT_CLEAN_NAMESPACE
32 #include <Xw_Window.hxx>
33 #include <Graphic3d_GraphicDevice.hxx>
34
35 struct CMapEntry
36 {
37         CMapEntry();
38         ~CMapEntry();
39         Colormap          cmap;
40         bool              alloc;
41         XStandardColormap scmap;
42 };
43
44 CMapEntry::CMapEntry()
45 {
46         cmap = 0;
47         alloc = false;
48         scmap.colormap = 0;
49 }
50
51 CMapEntry::~CMapEntry()
52 {
53         if ( alloc )
54         XFreeColormap( QPaintDevice::x11AppDisplay(), cmap );
55 }
56
57 static QIntDict<CMapEntry> *cmap_dict = 0;
58 static bool mesa_gl = false;
59
60 static void cleanup_cmaps()
61 {
62         if ( !cmap_dict )
63                 return;
64         cmap_dict->setAutoDelete( true );
65         delete cmap_dict;
66         cmap_dict = 0;
67 }
68
69 static Colormap choose_cmap( Display *dpy, XVisualInfo *vi )
70 {
71         if ( !cmap_dict )
72         {
73                 cmap_dict = new QIntDict<CMapEntry>;
74                 const char *v = glXQueryServerString( dpy, vi->screen, GLX_VERSION );
75                 mesa_gl = strstr( v,"Mesa" ) != 0;
76                 qAddPostRoutine( cleanup_cmaps );
77         }
78
79         CMapEntry *x = cmap_dict->find( (long)vi->visualid );
80     if ( x )                                    // found colormap for visual
81         return x->cmap;
82
83     x = new CMapEntry();
84
85     XStandardColormap *c;
86     int n, i;
87
88 #ifdef DEBUG
89     cout << "Choosing cmap for vID = " << vi->visualid << endl;
90 #endif
91
92     if ( vi->visualid == XVisualIDFromVisual( (Visual*)QPaintDevice::x11AppVisual() ) )
93         {
94 #ifdef DEBUG
95                 cout << "Using x11AppColormap" << endl;
96 #endif
97                 return QPaintDevice::x11AppColormap();
98     }
99
100     if ( mesa_gl )
101         {
102                 Atom hp_cmaps = XInternAtom( dpy, "_HP_RGB_SMOOTH_MAP_LIST", true );
103                 if ( hp_cmaps && vi->visual->c_class == TrueColor && vi->depth == 8 )
104                 {
105                 if ( XGetRGBColormaps( dpy, RootWindow( dpy, vi->screen ), &c, &n, hp_cmaps ) )
106             {
107                         i = 0;
108                             while ( i < n && x->cmap == 0 )
109                 {
110                                 if ( c[i].visualid == vi->visual->visualid )
111                                     {
112                                         x->cmap = c[i].colormap;
113                                             x->scmap = c[i];
114                                 }
115                                     i++;
116                 }
117                             XFree( (char*)c );
118                 }
119         }
120         }
121 #if !defined( _OS_SOLARIS_ )
122     if ( !x->cmap )
123     {
124             if ( XmuLookupStandardColormap( dpy, vi->screen, vi->visualid, vi->depth, XA_RGB_DEFAULT_MAP, false, true ) )
125         {
126                     if ( XGetRGBColormaps( dpy, RootWindow( dpy, vi->screen ), &c, &n, XA_RGB_DEFAULT_MAP ) )
127             {
128                             i = 0;
129                                 while ( i < n && x->cmap == 0 )
130                                 {
131                                     if ( c[i].visualid == vi->visualid )
132                     {
133                                             x->cmap = c[i].colormap;
134                                                 x->scmap = c[i];
135                                     }
136                                         i++;
137                 }
138                                 XFree( (char *)c );
139             }
140         }
141     }
142 #endif
143         if ( !x->cmap )
144         {
145                 // no shared cmap found
146                 x->cmap = XCreateColormap( dpy, RootWindow( dpy, vi->screen ), vi->visual, AllocNone );
147                 x->alloc = true;
148         }
149
150         cmap_dict->insert( (long)vi->visualid, x ); // associate cmap with visualid
151         return x->cmap;
152 }
153 #endif
154
155
156 /*!
157     Constructor
158 */
159 OCCViewer_ViewPort::OCCViewer_ViewPort( QWidget* parent )
160 : QWidget( parent, 0, WRepaintNoErase | WResizeNoErase )
161 {
162         initialize();
163 }
164
165 /*!
166     Destructor
167 */
168 OCCViewer_ViewPort::~OCCViewer_ViewPort()
169 {
170         cleanup();
171 }
172
173 /*!
174     Initializes viewport. [ private ]
175 */
176 void OCCViewer_ViewPort::initialize()
177 {
178   myPopupActions.setAutoDelete( true );
179   myPaintersRedrawing = false;
180   myEnableSketching = false;
181   myEnableTransform = true;
182   
183   setMouseTracking( true );
184   setBackgroundMode( NoBackground );
185   // set focus policy to threat QContextMenuEvent from keyboard  
186   setFocusPolicy( StrongFocus );
187 }
188
189 /*!
190     Cleans up the viewport. [ private ]
191 */
192 void OCCViewer_ViewPort::cleanup()
193 {
194 }
195
196 /*!
197     Selects visual ID for OpenGL window ( X11 specific ). [ protected ]
198 */
199 void OCCViewer_ViewPort::selectVisualId()
200 {
201 #if !defined WNT
202         XVisualInfo* pVisualInfo;
203         if ( x11Display() )
204         {
205                 /* Initialization with the default VisualID */
206                 Visual *v = DefaultVisual( x11Display(), DefaultScreen( x11Display() ) );
207                 int visualID = XVisualIDFromVisual( v );
208
209                 /*  Here we use the settings from Optimizer_ViewInfo::TxglCreateWindow() */
210                 int visualAttr[] = { GLX_RGBA, GLX_DEPTH_SIZE, 1, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1,
211                                                          GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, None };
212
213                 pVisualInfo = ::glXChooseVisual( x11Display(), DefaultScreen( x11Display() ), visualAttr );
214
215                 if ( isVisible() )
216             hide();
217
218                 XSetWindowAttributes a;
219
220                 a.colormap = choose_cmap( x11Display(), pVisualInfo );      /* find best colormap */
221                 a.background_pixel = backgroundColor().pixel();
222                 a.border_pixel = black.pixel();
223                 Window p = RootWindow( x11Display(), DefaultScreen( x11Display() ) );
224                 if ( parentWidget() )
225             p = parentWidget()->winId();
226
227         Window w;
228         /*        if ( type == Type2D )  // creating simple X window for 2d
229         {
230             unsigned long xbackground =
231                 BlackPixel( x11Display(), DefaultScreen( x11Display() ) );
232             unsigned long xforeground =
233                 WhitePixel( x11Display(), DefaultScreen( x11Display() ) );
234
235             w = XCreateSimpleWindow ( x11Display(), p, x(), y(), width(),
236                                       height(), 0, xforeground, xbackground );
237         }
238         else if ( type == Type3D )
239         {
240                     w = XCreateWindow( x11Display(), p,  x(), y(), width(), height(),
241                                0, pVisualInfo->depth, InputOutput, pVisualInfo->visual,
242                                CWBackPixel | CWBorderPixel | CWColormap, &a );
243                 }
244                 else
245                 return;*/
246         w = XCreateWindow( x11Display(), p,  x(), y(), width(), height(),
247                            0, pVisualInfo->depth, InputOutput, pVisualInfo->visual,
248                            CWBackPixel | CWBorderPixel | CWColormap, &a );
249         
250                 Window *cmw;
251                 Window *cmwret;
252                 int count;
253                 if ( XGetWMColormapWindows( x11Display(), topLevelWidget()->winId(), &cmwret, &count ) )
254                 {
255                         cmw = new Window[count+1];
256                         memcpy( (char*)cmw, (char*)cmwret, sizeof(Window) * count );
257                         XFree( (char*)cmwret );
258             int i;
259
260                         for ( i = 0; i < count; i++ )
261                         {
262                                 if ( cmw[i] == winId() ) /* replace old window */
263                                 {
264                                         cmw[i] = w;
265                                         break;
266                                 }
267                         }
268
269                         if ( i >= count )                        /* append new window */
270                                 cmw[count++] = w;
271                 }
272                 else
273                 {
274                         count = 1;
275                         cmw = new Window[count];
276                         cmw[0] = w;
277                 }
278
279                 /* Creating new window (with good VisualID) for this widget */
280                 create(w);
281                 XSetWMColormapWindows( x11Display(), topLevelWidget()->winId(), cmw, count );
282                 delete[] cmw;
283
284                 if ( isVisible() )
285             show();
286
287                 if ( pVisualInfo )
288         {
289                         XFree( (char *)pVisualInfo );
290                 }
291                 XFlush( x11Display() );
292         }
293 #endif
294 }
295
296 /*!
297     Sets the background 'color'. [ virtual ]
298 */
299 void OCCViewer_ViewPort::setBackgroundColor( const QColor& color )
300 {
301     QPalette pal = palette();
302     pal.setColor( QColorGroup::Background, color );
303     setPalette( pal );
304     repaint();
305     emit vpChangeBGColor( color );
306 }
307
308 /*!
309     Returns the background color. [ virtual ]
310 */
311 QColor OCCViewer_ViewPort::backgroundColor() const
312 {
313     return palette().active().background();
314 }
315
316 /*!
317     Returns 'true' if sketching is enabled in  this viewport. [ public ]
318 */
319 bool OCCViewer_ViewPort::isSketchingEnabled() const
320 {
321     return myEnableSketching;
322 }
323
324 /*!
325     Enables / disables sketching  [ public ]
326 */
327 void OCCViewer_ViewPort::setSketchingEnabled( bool enable )
328 {
329         myEnableSketching = enable;
330 }
331
332 /*!
333     Returns 'true' if transformations ( rotation, zoom etc. )
334     are enabled in this viewport. [ public ]
335 */
336 bool OCCViewer_ViewPort::isTransformEnabled() const
337 {
338     return myEnableTransform;
339 }
340
341 /*!
342     Enables / disables transformations. [ public ]
343 */
344 void OCCViewer_ViewPort::setTransformEnabled( bool enable )
345 {
346         myEnableTransform = enable;
347 }
348
349 /*!
350     Emits 'mouseEvent' signal. [ virtual protected ]
351 */
352 void OCCViewer_ViewPort::mousePressEvent( QMouseEvent *e )
353 {
354     emit vpMouseEvent( e );
355 }
356
357 /*!
358     Emits 'mouseEvent' signal. [ virtual protected ]
359 */
360 void OCCViewer_ViewPort::mouseMoveEvent( QMouseEvent* e )
361 {
362     emit vpMouseEvent( e );
363 }
364
365 /*!
366     Emits 'mouseEvent' signal. [ virtual protected ]
367 */
368 void OCCViewer_ViewPort::mouseReleaseEvent( QMouseEvent *e )
369 {
370     emit vpMouseEvent( e );
371 }
372
373 /*!
374     Emits 'mouseEvent' signal. [ virtual protected ]
375 */
376 void OCCViewer_ViewPort::mouseDoubleClickEvent( QMouseEvent *e )
377 {
378     emit vpMouseEvent( e );
379 }
380
381 /*!
382     Emits 'keyEvent' signal. [ virtual protected ]
383 */
384 void OCCViewer_ViewPort::keyPressEvent( QKeyEvent *e )
385 {
386     emit vpKeyEvent( e );
387 }
388
389 /*!
390     Emits 'keyEvent' signal. [ virtual protected ]
391 */
392 void OCCViewer_ViewPort::keyReleaseEvent( QKeyEvent *e )
393 {
394     emit vpKeyEvent( e );
395 }
396
397 /*!
398     Repaints the viewport. [ virtual protected ]
399 */
400 void OCCViewer_ViewPort::paintEvent( QPaintEvent* )
401 {
402         if ( myPaintersRedrawing )
403         {
404                 QPainter p( this );
405                 emit vpDrawExternal( &p );
406                 myPaintersRedrawing = false;
407         }
408 }
409
410 /*!
411     Forces to redraw the viewport by an external painter. [ public ]
412 */
413 void OCCViewer_ViewPort::redrawPainters()
414 {
415         myPaintersRedrawing = true;
416         repaint();
417 }
418
419 /*!
420     Updates this view. Does nothing by default. [ virtual public ]
421 */
422 void OCCViewer_ViewPort::onUpdate()
423 {
424 }
425
426 /*!
427     Creates the popup. [ virtual protected ]
428 */
429 /*void OCCViewer_ViewPort::onCreatePopup( QPopupMenu* popup )
430 {
431         if ( popup )
432         {
433                 QtxAction* a = new QtxAction( "", tr( "MEN_VP_CHANGEBGR" ), 0, this );
434         a->setStatusTip( tr( "PRP_VP_CHANGEBGR" ) );
435                 connect( a, SIGNAL( activated() ), SLOT( onChangeBgColor()));
436                 myPopupActions.append( a );
437                 a->addTo( popup );
438         }
439 }*/
440
441 /*!
442     Destroys the popup. [ virtual protected ]
443 */
444 /*void OCCViewer_ViewPort::onDestroyPopup( QPopupMenu* popup )
445 {
446         if ( popup )
447         {
448                 for ( QtxAction* a = myPopupActions.first(); a; a = myPopupActions.next() )
449                         a->removeFrom( popup );
450                 myPopupActions.clear();
451         }
452 }*/
453
454 /*!
455     Sets the background color with color selection dialog. [ virtual protected slot ]
456 */
457 void OCCViewer_ViewPort::onChangeBgColor()
458 {
459     QColor selColor = QColorDialog::getColor ( backgroundColor(), this );
460     if ( selColor.isValid() )
461         setBackgroundColor( selColor );
462 }