Salome HOME
Implement generic "Dump view" method to be used by all views (toolbar & context menu)
[modules/gui.git] / src / GLViewer / GLViewer_ViewFrame.cxx
1 // File:      GLViewer_ViewFrame.cxx
2 // Created:   November, 2004
3 // Author:    OCC team
4 // Copyright (C) CEA 2004
5
6 /***************************************************************************
7 **  Class:   GLViewer_ViewFrame
8 **  Descr:   Frame window for viewport in QAD-based application
9 **  Module:  QAD
10 **  Created: UI team, 05.09.00
11 ****************************************************************************/
12
13 #include "GLViewer_ViewFrame.h"
14
15 #include "GLViewer_Viewer.h"
16 #include "GLViewer_Viewer2d.h"
17 #include "GLViewer_ViewPort2d.h"
18
19 #include <SUIT_Desktop.h>
20 #include <SUIT_Application.h>
21 #include <SUIT_Session.h>
22 #include <SUIT_ToolButton.h>
23 #include <SUIT_ResourceMgr.h>
24 #include <SUIT_Tools.h>
25 #include <QtxAction.h>
26 #include <SUIT_MessageBox.h>
27
28 #include <qcolor.h>
29 #include <qimage.h>
30 #include <qlayout.h>
31 #include <qstring.h>
32
33 /*!
34     Constructor
35 */
36 GLViewer_ViewFrame::GLViewer_ViewFrame( SUIT_Desktop* d, GLViewer_Viewer* vw )
37 : SUIT_ViewWindow( d ),
38 myViewer( vw ),
39 myVP( 0 )
40 {
41     QFrame* client = new QFrame( this );    
42     setCentralWidget( client );
43
44     QBoxLayout* layout = new QHBoxLayout( client, 1, 1 );
45     layout->setAutoAdd( true );
46
47     GLViewer_ViewPort2d* vp = new GLViewer_ViewPort2d( client, this );
48     //vp->turnGrid( true );
49     //vp->turnCompass( true );
50     //vp->enablePopup( false );
51     setViewPort( vp );
52     setBackgroundColor( Qt::white );
53
54     myToolBar = new QToolBar(this);
55     myToolBar->setCloseMode(QDockWindow::Undocked);
56     myToolBar->setLabel(tr("LBL_TOOLBAR_LABEL"));
57     createActions();
58     createToolBar();
59 }
60
61 /*!
62     Destructor
63 */
64 GLViewer_ViewFrame::~GLViewer_ViewFrame()
65 {
66 }
67
68 //================================================================
69 // Function : createActions
70 // Purpose  : 
71 //================================================================
72 void GLViewer_ViewFrame::createActions()
73 {
74   if ( !myActionsMap.isEmpty() )
75     return;
76
77   QtxAction* aAction;
78   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
79
80   // Dump view
81   aAction = new QtxAction(tr("MNU_DUMP_VIEW"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_DUMP" ) ),
82                            tr( "MNU_DUMP_VIEW" ), 0, this);
83   aAction->setStatusTip(tr("DSC_DUMP_VIEW"));
84   connect(aAction, SIGNAL(activated()), this, SLOT(onDumpView()));
85   myActionsMap[ DumpId ] = aAction;
86
87   // FitAll
88   aAction = new QtxAction(tr("MNU_FITALL"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_FITALL" ) ),
89                            tr( "MNU_FITALL" ), 0, this);
90   aAction->setStatusTip(tr("DSC_FITALL"));
91   connect(aAction, SIGNAL(activated()), this, SLOT(onViewFitAll()));
92   myActionsMap[ FitAllId ] = aAction;
93
94   // FitRect
95   aAction = new QtxAction(tr("MNU_FITRECT"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_FITAREA" ) ),
96                            tr( "MNU_FITRECT" ), 0, this);
97   aAction->setStatusTip(tr("DSC_FITRECT"));
98   connect(aAction, SIGNAL(activated()), this, SLOT(onViewFitArea()));
99   myActionsMap[ FitRectId ] = aAction;
100
101   // FitSelect
102   aAction = new QtxAction(tr("MNU_FITSELECT"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_FITSELECT" ) ),
103                           tr( "MNU_FITSELECT" ), 0, this);
104   aAction->setStatusTip(tr("DSC_FITSELECT"));
105   connect(aAction, SIGNAL(activated()), this, SLOT(onViewFitSelect()));
106   myActionsMap[ FitSelectId ] = aAction;
107
108   // Zoom
109   aAction = new QtxAction(tr("MNU_ZOOM_VIEW"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_ZOOM" ) ),
110                            tr( "MNU_ZOOM_VIEW" ), 0, this);
111   aAction->setStatusTip(tr("DSC_ZOOM_VIEW"));
112   connect(aAction, SIGNAL(activated()), this, SLOT(onViewZoom()));
113   myActionsMap[ ZoomId ] = aAction;
114
115   // Panning
116   aAction = new QtxAction(tr("MNU_PAN_VIEW"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_PAN" ) ),
117                            tr( "MNU_PAN_VIEW" ), 0, this);
118   aAction->setStatusTip(tr("DSC_PAN_VIEW"));
119   connect(aAction, SIGNAL(activated()), this, SLOT(onViewPan()));
120   myActionsMap[ PanId ] = aAction;
121
122   // Global Panning
123   aAction = new QtxAction(tr("MNU_GLOBALPAN_VIEW"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_GLOBALPAN" ) ),
124                            tr( "MNU_GLOBALPAN_VIEW" ), 0, this);
125   aAction->setStatusTip(tr("DSC_GLOBALPAN_VIEW"));
126   connect(aAction, SIGNAL(activated()), this, SLOT(onViewGlobalPan()));
127   myActionsMap[ GlobalPanId ] = aAction;
128
129   aAction = new QtxAction(tr("MNU_RESET_VIEW"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_RESET" ) ),
130                            tr( "MNU_RESET_VIEW" ), 0, this);
131   aAction->setStatusTip(tr("DSC_RESET_VIEW"));
132   connect(aAction, SIGNAL(activated()), this, SLOT(onViewReset()));
133   myActionsMap[ ResetId ] = aAction;
134 }
135
136 //================================================================
137 // Function : createToolBar
138 // Purpose  : 
139 //================================================================
140 void GLViewer_ViewFrame::createToolBar()
141 {
142   myActionsMap[DumpId]->addTo(myToolBar);
143
144   SUIT_ToolButton* aScaleBtn = new SUIT_ToolButton(myToolBar);
145   aScaleBtn->AddAction(myActionsMap[FitAllId]);
146   aScaleBtn->AddAction(myActionsMap[FitRectId]);
147   aScaleBtn->AddAction(myActionsMap[FitSelectId]);
148   aScaleBtn->AddAction(myActionsMap[ZoomId]);
149
150   SUIT_ToolButton* aPanBtn = new SUIT_ToolButton(myToolBar);
151   aPanBtn->AddAction(myActionsMap[PanId]);
152   aPanBtn->AddAction(myActionsMap[GlobalPanId]);
153
154   myActionsMap[ResetId]->addTo(myToolBar);
155 }
156
157 /*!
158     Sets the viewport for this frame
159 */
160 void GLViewer_ViewFrame::setViewPort( GLViewer_ViewPort* vp )
161 {
162     if ( myVP == vp )
163         return;
164
165     if ( myVP )
166     {
167         disconnect( myVP, SIGNAL( vpDrawExternal( QPainter* ) ), this, SIGNAL( vfDrawExternal( QPainter* ) ) );
168         disconnect( myVP, SIGNAL( vpMouseEvent( QMouseEvent* ) ), this, SLOT( mouseEvent( QMouseEvent* ) ) );
169         disconnect( myVP, SIGNAL( vpKeyEvent( QKeyEvent* ) ), this, SLOT( keyEvent( QKeyEvent* ) ) );
170         disconnect( myVP, SIGNAL(contextMenuRequested( QContextMenuEvent * )),
171                     this, SIGNAL(contextMenuRequested( QContextMenuEvent * )) );
172         disconnect( myVP, SIGNAL( vpWheelEvent( QWheelEvent* ) ), this, SLOT( wheelEvent( QWheelEvent* ) ) );
173     }
174     myVP = vp;
175     if ( myVP )
176     {
177         connect( myVP, SIGNAL( vpDrawExternal( QPainter* ) ), this, SIGNAL( vfDrawExternal( QPainter* ) ) );
178         connect( myVP, SIGNAL( vpMouseEvent( QMouseEvent* ) ), this, SLOT( mouseEvent( QMouseEvent* ) ) );
179         connect( myVP, SIGNAL( vpKeyEvent( QKeyEvent* ) ), this, SLOT( keyEvent( QKeyEvent* ) ) );
180         connect( myVP, SIGNAL(contextMenuRequested( QContextMenuEvent * )),
181                  this, SIGNAL(contextMenuRequested( QContextMenuEvent * )) );
182         connect( myVP, SIGNAL( vpWheelEvent( QWheelEvent* ) ), this, SLOT( wheelEvent( QWheelEvent* ) ) );
183     }
184 }
185
186 /*!
187     Returns the viewport of this frame. [ public ]
188 */
189 GLViewer_ViewPort* GLViewer_ViewFrame::getViewPort() const
190 {
191     return myVP;
192 }
193
194 /*!
195     Set background of the viewport. [ public ]
196 */
197 void GLViewer_ViewFrame::setBackgroundColor( const QColor& color )
198 {
199     if ( myVP )
200         myVP->setBackgroundColor( color );
201 }
202
203 /*!
204     Returns background of the viewport. [ public ]
205 */
206 QColor GLViewer_ViewFrame::backgroundColor() const
207 {
208     if ( myVP )
209         return myVP->backgroundColor();
210     return QMainWindow::backgroundColor();
211 }
212
213 /*!
214     Sets the viewer for this view. [ public ]
215 */
216 void GLViewer_ViewFrame::setViewer( GLViewer_Viewer* v )
217 {
218     myViewer = v;
219 }
220
221 /*!
222     Returns the viewer of this view. [ public ]
223 */
224 GLViewer_Viewer* GLViewer_ViewFrame::getViewer() const
225 {
226     return myViewer;
227 }
228
229 /*!
230     Returns the preferred view size. [ virtual public ]
231 */
232 QSize GLViewer_ViewFrame::sizeHint() const
233 {
234     QWidget* p = parentWidget();
235     if ( p && p->inherits( "QWorkspaceChild" ) )
236         p = p->parentWidget();      /* QWorkspaceChild: internal impl class in QWorkspace */
237     if ( !p )
238         return QMainWindow::sizeHint();
239     return QSize( 9 * p->width() / 10 , 9 * p->height() / 10  );
240 }
241
242 /*!
243    Called by viewer's 'update()' method. Does nothing by default [ virtual public ]
244 */
245 void GLViewer_ViewFrame::onUpdate( int )
246 {
247 }
248
249 QImage GLViewer_ViewFrame::dumpView()
250 {
251     GLViewer_Widget* aWidget = ((GLViewer_ViewPort2d*)myVP)->getGLWidget();
252     int width, height;
253     width = aWidget->width();
254     height = aWidget->height();
255     
256     int imageSize = width*height*3;
257     unsigned char* imageBits = NULL;
258
259     int reserve_bytes = width % 4; //32 bits platform
260     imageSize = (width+reserve_bytes)*height*3;
261     imageBits = new unsigned char[imageSize];
262
263     
264 #ifdef WNT
265
266     int num;
267     HBITMAP hBmp;
268     HDC hdc_old, hdc;
269     HGLRC hglrc_old, hglrc;
270
271     BITMAPINFO bi;
272
273     hglrc_old = wglGetCurrentContext();
274     hdc_old = wglGetCurrentDC();
275
276     hdc = CreateCompatibleDC( hdc_old );
277     if( !hdc )
278     {
279         cout << "Can't create compatible DC. Last Error Code: " << GetLastError() << endl;
280         return;
281     }
282
283     int sizeBmi = Standard_Integer( sizeof(BITMAPINFO) + sizeof(RGBQUAD)*3 );
284     PBITMAPINFO pBmi = (PBITMAPINFO)( new char[sizeBmi] );
285     ZeroMemory( pBmi, sizeBmi );
286
287     pBmi->bmiHeader.biSize        = sizeof( BITMAPINFOHEADER ); //sizeBmi
288     pBmi->bmiHeader.biWidth       = width;
289     pBmi->bmiHeader.biHeight      = height;
290     pBmi->bmiHeader.biPlanes      = 1;
291     pBmi->bmiHeader.biBitCount    = 24;
292     pBmi->bmiHeader.biCompression = BI_RGB;
293
294     LPVOID ppvBits;
295     hBmp = CreateDIBSection ( hdc, pBmi, DIB_RGB_COLORS, &ppvBits, NULL, 0 );
296     SelectObject ( hdc, hBmp );
297     delete[] pBmi;
298
299     PIXELFORMATDESCRIPTOR pfd;
300     ZeroMemory( &pfd, sizeof( PIXELFORMATDESCRIPTOR ) );
301     pfd.nSize      = sizeof( PIXELFORMATDESCRIPTOR );
302     pfd.nVersion   = 1;
303     pfd.dwFlags    = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_BITMAP;
304     pfd.iPixelType = PFD_TYPE_RGBA;
305     pfd.cColorBits = 24;
306     pfd.cDepthBits = 32;
307     pfd.iLayerType = PFD_MAIN_PLANE;
308
309     int iPf = ChoosePixelFormat( hdc, &pfd);    
310     if( iPf == 0 )
311     {
312         if ( !DescribePixelFormat ( hdc, iPf, sizeof(PIXELFORMATDESCRIPTOR), &pfd ) )
313         {
314             cout << "Can't describe Pixel Format. Last Error Code: " << GetLastError() << endl;
315         }
316     }
317     if ( !SetPixelFormat(hdc, iPf, &pfd) )
318     {
319         cout << "Can't set Pixel Format. Last Error Code: " << GetLastError() << endl;
320     }
321
322     hglrc = wglCreateContext( hdc );
323     if( !hglrc )
324     {
325         cout << "Can't create new GL Context. Last Error Code: " << GetLastError() << endl;
326         return;
327     }
328     if( !wglMakeCurrent( hdc, hglrc) )
329     {
330         cout << "Can't make current new context!" << endl;
331         return;
332     }
333     
334     glViewport( 0, 0, width, height );
335
336     glMatrixMode( GL_PROJECTION );
337     glLoadIdentity();
338     GLfloat w_c = width / 2., h_c = height / 2.; 
339
340     gluOrtho2D( -w_c, w_c, -h_c, h_c ); 
341
342     glMatrixMode( GL_MODELVIEW );
343     glLoadIdentity();
344
345     //set background
346     QColor aColor = ((GLViewer_ViewPort2d*)myVP)->backgroundColor();
347     glClearColor( ( GLfloat )aColor.red() / 255,
348                   ( GLfloat )aColor.green() / 255,
349                   ( GLfloat )aColor.blue() / 255,
350                   1.0 );
351
352     aWidget->exportRepaint();
353
354       memset(&bi, 0, sizeof(BITMAPINFOHEADER));
355     bi.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
356     bi.bmiHeader.biPlanes      = 1;
357     bi.bmiHeader.biBitCount    = 24;
358     bi.bmiHeader.biHeight      = -height;
359     bi.bmiHeader.biWidth       = width;
360     bi.bmiHeader.biCompression = BI_RGB;
361
362     num = GetDIBits(hdc, hBmp, 0, height, imageBits, &bi, DIB_RGB_COLORS);
363
364     wglMakeCurrent( hdc_old, hglrc_old );
365     wglDeleteContext( hglrc );
366     
367
368 #else //XWindows
369 #endif
370
371     unsigned int* aPix = NULL;
372     QImage  anImage( width, height, 32 );
373     for( int i = 0; i < height; i++ )
374     {
375         memset( anImage.scanLine( i ), 0, sizeof(unsigned int)*width );
376         unsigned char* pos;
377         for( int j = 0; j < width; j++ )
378         {
379             pos = imageBits + i*width*3 + j*3 + reserve_bytes*i;
380             aPix = (unsigned int*)anImage.scanLine(i)+j;
381             *aPix = qRgb( *pos, *(pos+1), *(pos+2) );
382         }
383     }
384
385     delete [] imageBits;
386     return anImage;
387 }
388
389 void GLViewer_ViewFrame::onViewPan()
390 {
391     myViewer->activateTransform( GLViewer_Viewer::Pan );
392 }
393
394 void GLViewer_ViewFrame::onViewZoom()
395 {
396     myViewer->activateTransform( GLViewer_Viewer::Zoom );
397 }
398
399 void GLViewer_ViewFrame::onViewFitAll()
400 {
401     myViewer->activateTransform( GLViewer_Viewer::FitAll );
402 }
403
404 void GLViewer_ViewFrame::onViewFitArea()
405
406     myViewer->activateTransform( GLViewer_Viewer::FitRect );
407 }
408
409 void GLViewer_ViewFrame::onViewFitSelect()
410
411     myViewer->activateTransform( GLViewer_Viewer::FitSelect );
412 }
413
414 void GLViewer_ViewFrame::onViewGlobalPan()
415
416     myViewer->activateTransform( GLViewer_Viewer::PanGlobal );
417 }
418
419 void GLViewer_ViewFrame::onViewRotate()
420
421     //myViewer->activateTransform( GLViewer_Viewer::Rotate );
422 }
423
424 void GLViewer_ViewFrame::onViewReset()
425
426     myViewer->activateTransform( GLViewer_Viewer::Reset );
427 }
428   
429 //================================================================
430 // Function : mouseEvent
431 // Purpose  : dispatches mouse events
432 //================================================================
433 void GLViewer_ViewFrame::mouseEvent( QMouseEvent* e )
434 {
435   switch ( e->type() )
436   {
437   case QEvent::MouseButtonPress:
438     emit mousePressed( this, e );
439     break;
440   case QEvent::MouseButtonRelease:
441     emit mouseReleased( this, e );
442     break;
443   case QEvent::MouseButtonDblClick:
444     emit mouseDoubleClicked( this, e );
445     break;
446   case QEvent::MouseMove:
447     emit mouseMoving( this, e );
448     break;
449   default:
450     break;
451   }
452 }
453
454 //================================================================
455 // Function : keyEvent
456 // Purpose  : dispatches key events
457 //================================================================
458 void GLViewer_ViewFrame::keyEvent( QKeyEvent* e )
459 {
460   switch ( e->type() )
461   {
462   case QEvent::KeyPress:
463     emit keyPressed( this, e );
464     break;
465   case QEvent::KeyRelease:
466     emit keyReleased( this, e );
467     break;
468   default:
469     break;
470   }
471 }
472
473 //================================================================
474 // Function : wheelEvent
475 // Purpose  : dispatches wheel events
476 //================================================================
477 void GLViewer_ViewFrame::wheelEvent( QWheelEvent* e )
478 {
479   switch ( e->type() )
480   {
481   case QEvent::Wheel:
482     emit wheeling( this, e );
483     break;
484   default:
485     break;
486   }
487 }
488