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