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