]> SALOME platform Git repositories - modules/gui.git/blob - src/OCCViewer/OCCViewer_ViewPort.cxx
Salome HOME
4c6dd5d2d56c2f46b464ebb383c76a0eec31f7d7
[modules/gui.git] / src / OCCViewer / OCCViewer_ViewPort.cxx
1 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #if !defined WNT
24 #define QT_CLEAN_NAMESPACE         /* avoid definition of INT32 and INT8 */
25 #endif
26
27 #include "OCCViewer_ViewPort.h"
28
29 #include "SUIT_Session.h"
30
31 #include <QColor>
32 #include <QRect>
33 #include <QPixmap>
34 #include <QPainter>
35 #include <QMultiHash>
36 #include <QMenu>
37 #include <QColorDialog>
38 #include <QColormap>
39 #include <QCoreApplication>
40
41 #include <stdlib.h>
42
43 #if !defined WNT
44 #include <QX11Info>
45 #include <GL/glx.h>
46 #include <X11/Xlib.h>
47 #include <X11/Xutil.h>
48 #include <X11/Xatom.h>
49 #include <X11/Xmu/StdCmap.h>
50 #undef QT_CLEAN_NAMESPACE
51 #include <Xw_Window.hxx>
52 #include <Graphic3d_GraphicDevice.hxx>
53
54 struct CMapEntry
55 {
56   CMapEntry();
57   ~CMapEntry();
58   Colormap          cmap;
59   bool              alloc;
60   XStandardColormap scmap;
61 };
62
63 /*!
64   Constructor
65 */
66 CMapEntry::CMapEntry()
67 {
68   cmap = 0;
69   alloc = false;
70   scmap.colormap = 0;
71 }
72
73 /*!
74   Destructor
75 */
76 CMapEntry::~CMapEntry()
77 {
78   if ( alloc )
79     XFreeColormap( QX11Info::display(), cmap );
80 }
81
82 static QMultiHash<int,CMapEntry> *cmap_dict = 0;
83 static bool mesa_gl = false;
84
85 static void cleanup_cmaps()
86 {
87   if ( !cmap_dict )
88     return;
89   //while (!cmap_dict->isEmpty())
90   //  cmap_dict->erase(cmap_dict->begin());
91   cmap_dict->clear();
92   delete cmap_dict;
93   cmap_dict = 0;
94 }
95
96 static Colormap choose_cmap( Display *dpy, XVisualInfo *vi )
97 {
98   if ( !cmap_dict )
99   {
100     cmap_dict = new QMultiHash<int,CMapEntry>;
101     const char *v = glXQueryServerString( dpy, vi->screen, GLX_VERSION );
102     mesa_gl = strstr( v,"Mesa" ) != 0;
103     qAddPostRoutine( cleanup_cmaps );
104   }
105
106   QHash<int,CMapEntry>::iterator itH = cmap_dict->find( (long)vi->visualid );
107   if ( itH != cmap_dict->end() )  // found colormap for visual
108     return itH.value().cmap;
109   
110   CMapEntry x;
111   
112   XStandardColormap *c;
113   int n, i;
114
115   //#ifdef DEBUG
116   //cout << "Choosing cmap for vID = " << vi->visualid << endl;
117   //#endif
118
119   if ( vi->visualid == XVisualIDFromVisual( (Visual*)QX11Info::appVisual() ) )
120   {
121 #ifdef DEBUG
122 //    cout << "Using x11AppColormap" << endl;
123 #endif
124     return QX11Info::appColormap();
125   }
126
127   if ( mesa_gl )
128   {
129     Atom hp_cmaps = XInternAtom( dpy, "_HP_RGB_SMOOTH_MAP_LIST", true );
130     if ( hp_cmaps && vi->visual->c_class == TrueColor && vi->depth == 8 )
131     {
132       if ( XGetRGBColormaps( dpy, RootWindow( dpy, vi->screen ), &c, &n, hp_cmaps ) )
133       {
134         i = 0;
135         while ( i < n && x.cmap == 0 )
136         {
137           if ( c[i].visualid == vi->visual->visualid )
138           {
139             x.cmap = c[i].colormap;
140             x.scmap = c[i];
141           }
142           i++;
143         }
144         XFree( (char*)c );
145       }
146     }
147   }
148 #if !defined( _OS_SOLARIS_ )
149   if ( !x.cmap )
150   {
151     if ( XmuLookupStandardColormap( dpy, vi->screen, vi->visualid, vi->depth, XA_RGB_DEFAULT_MAP, false, true ) )
152     {
153       if ( XGetRGBColormaps( dpy, RootWindow( dpy, vi->screen ), &c, &n, XA_RGB_DEFAULT_MAP ) )
154       {
155         i = 0;
156         while ( i < n && x.cmap == 0 )
157         {
158           if ( c[i].visualid == vi->visualid )
159           {
160             x.cmap = c[i].colormap;
161             x.scmap = c[i];
162           }
163           i++;
164         }
165         XFree( (char *)c );
166       }
167     }
168   }
169 #endif
170   if ( !x.cmap )
171   {
172     // no shared cmap found
173     x.cmap = XCreateColormap( dpy, RootWindow( dpy, vi->screen ), vi->visual, AllocNone );
174     x.alloc = true;
175   }
176
177   cmap_dict->insert( (long)vi->visualid, x ); // associate cmap with visualid
178   return x.cmap;
179 }
180 #endif
181
182
183 /*!
184     Constructor
185 */
186 OCCViewer_ViewPort::OCCViewer_ViewPort( QWidget* parent )
187 : QWidget( parent )
188 {
189   initialize();
190 }
191
192 /*!
193     Destructor
194 */
195 OCCViewer_ViewPort::~OCCViewer_ViewPort()
196 {
197   cleanup();
198 }
199
200 /*!
201     Initializes viewport. [ private ]
202 */
203 void OCCViewer_ViewPort::initialize()
204 {
205   myPaintersRedrawing = false;
206   myEnableSketching = true;
207   myEnableTransform = true;
208   
209   setMouseTracking( true );
210   setBackgroundRole( QPalette::NoRole );//NoBackground );
211   // set focus policy to threat QContextMenuEvent from keyboard  
212   setFocusPolicy( Qt::StrongFocus );
213   setAttribute( Qt::WA_PaintOnScreen );
214   setAttribute( Qt::WA_NoSystemBackground );
215 }
216
217 /*!
218     Cleans up the viewport. [ private ]
219 */
220 void OCCViewer_ViewPort::cleanup()
221 {
222 }
223
224 /*!
225     Selects visual ID for OpenGL window ( X11 specific ). [ protected ]
226 */
227 void OCCViewer_ViewPort::selectVisualId()
228 {
229 #if !defined WNT
230   XVisualInfo* pVisualInfo;
231   if ( QX11Info::display() )
232   {
233     /* Initialization with the default VisualID */
234     Visual *v = DefaultVisual( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
235     /*int visualID = */XVisualIDFromVisual( v );
236     
237     /*  Here we use the settings from Optimizer_ViewInfo::TxglCreateWindow() */
238     int visualAttr[] = { GLX_RGBA, GLX_DEPTH_SIZE, 1, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1,
239                           GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, None };
240     
241     pVisualInfo = ::glXChooseVisual( QX11Info::display(), DefaultScreen( QX11Info::display() ), visualAttr );
242     
243     if ( isVisible() )
244       hide();
245     
246     XSetWindowAttributes a;
247     
248     a.colormap = choose_cmap( QX11Info::display(), pVisualInfo );       /* find best colormap */
249     a.background_pixel = QColormap::instance().pixel( backgroundColor() );
250     a.border_pixel = QColormap::instance().pixel( Qt::black );
251     Window p = RootWindow( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
252     if ( parentWidget() )
253       p = parentWidget()->winId();
254     
255     Window w;
256     /*
257     if ( type == Type2D )  // creating simple X window for 2d
258     {
259       unsigned long xbackground =
260           BlackPixel( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
261       unsigned long xforeground =
262           WhitePixel( QX11Info::display(), DefaultScreen( QX11Info::display() ) );
263
264       w = XCreateSimpleWindow ( QX11Info::display(), p, x(), y(), width(),
265                                 height(), 0, xforeground, xbackground );
266     }
267     else if ( type == Type3D )
268     {
269       w = XCreateWindow( QX11Info::display(), p,  x(), y(), width(), height(),
270                           0, pVisualInfo->depth, InputOutput, pVisualInfo->visual,
271                           CWBackPixel | CWBorderPixel | CWColormap, &a );
272     }
273     else
274       return;
275     */
276     w = XCreateWindow( QX11Info::display(), p,  x(), y(), width(), height(),
277                       0, pVisualInfo->depth, InputOutput, pVisualInfo->visual,
278                       CWBackPixel | CWBorderPixel | CWColormap, &a );
279   
280     Window *cmw;
281     Window *cmwret;
282     int count;
283     if ( XGetWMColormapWindows( QX11Info::display(), topLevelWidget()->winId(), &cmwret, &count ) )
284     {
285       cmw = new Window[count+1];
286       memcpy( (char*)cmw, (char*)cmwret, sizeof(Window) * count );
287       XFree( (char*)cmwret );
288       int i;
289
290       for ( i = 0; i < count; i++ )
291       {
292         if ( cmw[i] == winId() ) /* replace old window */
293         {
294           cmw[i] = w;
295           break;
296         }
297       }
298
299       if ( i >= count )                        /* append new window */
300         cmw[count++] = w;
301     }
302     else
303     {
304       count = 1;
305       cmw = new Window[count];
306       cmw[0] = w;
307     }
308
309     /* Creating new window (with good VisualID) for this widget */
310     create(w);
311     XSetWMColormapWindows( QX11Info::display(), topLevelWidget()->winId(), cmw, count );
312     delete[] cmw;
313
314     if ( isVisible() )
315       show();
316
317     if ( pVisualInfo )
318       XFree( (char *)pVisualInfo );
319
320     XFlush( QX11Info::display() );
321   }
322 #endif
323 }
324
325 /*!
326     Sets the background 'color'. [ virtual ]
327 */
328 void OCCViewer_ViewPort::setBackgroundColor( const QColor& color )
329 {
330   QPalette pal = palette();
331   pal.setColor( QPalette::Background, color );
332   setPalette( pal );
333   repaint();
334   emit vpChangeBGColor( color );
335 }
336
337 /*!
338     Returns the background color. [ virtual ]
339 */
340 QColor OCCViewer_ViewPort::backgroundColor() const
341 {
342   return palette().color( QPalette::Active, QPalette::Background );
343 }
344
345 /*!
346     Returns 'true' if sketching is enabled in  this viewport. [ public ]
347 */
348 bool OCCViewer_ViewPort::isSketchingEnabled() const
349 {
350   return myEnableSketching;
351 }
352
353 /*!
354     Enables / disables sketching  [ public ]
355 */
356 void OCCViewer_ViewPort::setSketchingEnabled( bool enable )
357 {
358   myEnableSketching = enable;
359 }
360
361 /*!
362     Returns 'true' if transformations ( rotation, zoom etc. )
363     are enabled in this viewport. [ public ]
364 */
365 bool OCCViewer_ViewPort::isTransformEnabled() const
366 {
367   return myEnableTransform;
368 }
369
370 /*!
371     Enables / disables transformations. [ public ]
372 */
373 void OCCViewer_ViewPort::setTransformEnabled( bool enable )
374 {
375   myEnableTransform = enable;
376 }
377
378 /*!
379     Emits 'mouseEvent' signal. [ virtual protected ]
380 */
381 void OCCViewer_ViewPort::mousePressEvent( QMouseEvent *e )
382 {
383     emit vpMouseEvent( e );
384 }
385
386 /*!
387     Emits 'mouseEvent' signal. [ virtual protected ]
388 */
389 void OCCViewer_ViewPort::mouseMoveEvent( QMouseEvent* e )
390 {
391   emit vpMouseEvent( e );
392 }
393
394 /*!
395     Emits 'mouseEvent' signal. [ virtual protected ]
396 */
397 void OCCViewer_ViewPort::mouseReleaseEvent( QMouseEvent *e )
398 {
399   emit vpMouseEvent( e );
400 }
401
402 /*!
403     Emits 'mouseEvent' signal. [ virtual protected ]
404 */
405 void OCCViewer_ViewPort::mouseDoubleClickEvent( QMouseEvent *e )
406 {
407   emit vpMouseEvent( e );
408 }
409
410 /*!
411     Emits 'keyEvent' signal. [ virtual protected ]
412 */
413 void OCCViewer_ViewPort::keyPressEvent( QKeyEvent *e )
414 {
415   emit vpKeyEvent( e );
416 }
417
418 /*!
419     Emits 'keyEvent' signal. [ virtual protected ]
420 */
421 void OCCViewer_ViewPort::keyReleaseEvent( QKeyEvent *e )
422 {
423   emit vpKeyEvent( e );
424 }
425
426 /*!
427     Repaints the viewport. [ virtual protected ]
428 */
429 void OCCViewer_ViewPort::paintEvent( QPaintEvent* )
430 {
431   if ( myPaintersRedrawing )
432   {
433     QPainter p( this );
434     emit vpDrawExternal( &p );
435     myPaintersRedrawing = false;
436   }
437 }
438
439 /*!
440     Forces to redraw the viewport by an external painter. [ public ]
441 */
442 void OCCViewer_ViewPort::redrawPainters()
443 {
444   myPaintersRedrawing = true;
445   repaint();
446 }
447
448 /*!
449     Updates this view. Does nothing by default. [ virtual public ]
450 */
451 void OCCViewer_ViewPort::onUpdate()
452 {
453 }
454
455 /*!
456   Get paint engine for the OpenGL viewer. [ virtual public ]
457 */
458 QPaintEngine* OCCViewer_ViewPort::paintEngine() const
459 {
460   return 0;
461 }
462
463 /*!
464     Creates the popup. [ virtual protected ]
465 */
466 /*void OCCViewer_ViewPort::onCreatePopup( QPopupMenu* popup )
467 {
468   if ( popup )
469   {
470     QtxAction* a = new QtxAction( "", tr( "MEN_VP_CHANGEBGR" ), 0, this );
471     a->setStatusTip( tr( "PRP_VP_CHANGEBGR" ) );
472     connect( a, SIGNAL( activated() ), SLOT( onChangeBgColor()));
473     myPopupActions.append( a );
474     a->addTo( popup );
475   }
476 }*/
477
478 /*!
479     Destroys the popup. [ virtual protected ]
480 */
481 /*void OCCViewer_ViewPort::onDestroyPopup( QPopupMenu* popup )
482 {
483   if ( popup )
484   {
485     for ( QtxAction* a = myPopupActions.first(); a; a = myPopupActions.next() )
486       a->removeFrom( popup );
487     //while (!myPopupActions.isEmpty())
488     //  delete myPopupActions.takeFirst();
489     myPopupActions.clear();
490   }
491 }*/
492
493 /*!
494   Performs synchronization of view parameters with the specified view.
495   Returns \c true if synchronization is done successfully or \c false otherwise.
496   Default implementation does nothing (return \c false)
497 */
498 bool OCCViewer_ViewPort::synchronize( OCCViewer_ViewPort* )
499 {
500   return false;
501 }
502
503 /*!
504     Sets the background color with color selection dialog. [ virtual protected slot ]
505 */
506 void OCCViewer_ViewPort::onChangeBackground()
507 {
508   QColor selColor = QColorDialog::getColor ( backgroundColor(), this );
509   if ( selColor.isValid() )
510     setBackgroundColor( selColor );
511 }