1 // Copyright (C) 2005 OPEN CASCADE
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.
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.
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
17 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
19 // Author : OPEN CASCADE
22 // File: GLViewer_ViewFrame.cxx
23 // Created: November, 2004
25 /***************************************************************************
26 ** Class: GLViewer_ViewFrame
27 ** Descr: Frame window for viewport in QAD-based application
29 ** Created: UI team, 05.09.00
30 ****************************************************************************/
32 //#include <GLViewerAfx.h>
33 #include "GLViewer_ViewFrame.h"
34 #include "GLViewer_Viewer.h"
35 #include "GLViewer_Viewer2d.h"
36 #include "GLViewer_ViewPort2d.h"
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>
45 #include <qfiledialog.h>
53 GLViewer_ViewFrame::GLViewer_ViewFrame( SUIT_Desktop* d, GLViewer_Viewer* vw )
54 : SUIT_ViewWindow( d ),
58 QFrame* client = new QFrame( this );
59 setCentralWidget( client );
61 QBoxLayout* layout = new QHBoxLayout( client, 1, 1 );
62 layout->setAutoAdd( true );
64 GLViewer_ViewPort2d* vp = new GLViewer_ViewPort2d( client, this );
65 //vp->turnGrid( true );
66 //vp->turnCompass( true );
67 //vp->enablePopup( false );
69 setBackgroundColor( Qt::white );
71 myToolBar = new QToolBar(this);
72 myToolBar->setCloseMode(QDockWindow::Undocked);
73 myToolBar->setLabel(tr("LBL_TOOLBAR_LABEL"));
81 GLViewer_ViewFrame::~GLViewer_ViewFrame()
85 //================================================================
86 // Function : createActions
88 //================================================================
89 void GLViewer_ViewFrame::createActions()
91 if (!myActionsMap.isEmpty()) return;
92 SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
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;
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;
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;
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;
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;
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;
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;
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;
151 //================================================================
152 // Function : createToolBar
154 //================================================================
155 void GLViewer_ViewFrame::createToolBar()
157 myActionsMap[DumpId]->addTo(myToolBar);
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]);
165 SUIT_ToolButton* aPanBtn = new SUIT_ToolButton(myToolBar);
166 aPanBtn->AddAction(myActionsMap[PanId]);
167 aPanBtn->AddAction(myActionsMap[GlobalPanId]);
169 myActionsMap[ResetId]->addTo(myToolBar);
173 Sets the viewport for this frame
175 void GLViewer_ViewFrame::setViewPort( GLViewer_ViewPort* vp )
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* ) ) );
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* ) ) );
202 Returns the viewport of this frame. [ public ]
204 GLViewer_ViewPort* GLViewer_ViewFrame::getViewPort() const
210 Set background of the viewport. [ public ]
212 void GLViewer_ViewFrame::setBackgroundColor( const QColor& color )
215 myVP->setBackgroundColor( color );
219 Returns background of the viewport. [ public ]
221 QColor GLViewer_ViewFrame::backgroundColor() const
224 return myVP->backgroundColor();
225 return QMainWindow::backgroundColor();
229 Sets the viewer for this view. [ public ]
231 void GLViewer_ViewFrame::setViewer( GLViewer_Viewer* v )
237 Returns the viewer of this view. [ public ]
239 GLViewer_Viewer* GLViewer_ViewFrame::getViewer() const
245 Returns the preferred view size. [ virtual public ]
247 QSize GLViewer_ViewFrame::sizeHint() const
249 QWidget* p = parentWidget();
250 if ( p && p->inherits( "QWorkspaceChild" ) )
251 p = p->parentWidget(); /* QWorkspaceChild: internal impl class in QWorkspace */
253 return QMainWindow::sizeHint();
254 return QSize( 9 * p->width() / 10 , 9 * p->height() / 10 );
258 Called by viewer's 'update()' method. Does nothing by default [ virtual public ]
260 void GLViewer_ViewFrame::onUpdate( int )
264 //#include <windows.h>
266 void GLViewer_ViewFrame::onViewDump()
268 GLViewer_Widget* aWidget = ((GLViewer_ViewPort2d*)myVP)->getGLWidget();
270 width = aWidget->width();
271 height = aWidget->height();
273 int imageSize = width*height*3;
274 unsigned char* imageBits = NULL;
276 int reserve_bytes = width % 4; //32 bits platform
277 imageSize = (width+reserve_bytes)*height*3;
278 imageBits = new unsigned char[imageSize];
286 HGLRC hglrc_old, hglrc;
290 hglrc_old = wglGetCurrentContext();
291 hdc_old = wglGetCurrentDC();
293 hdc = CreateCompatibleDC( hdc_old );
296 cout << "Can't create compatible DC. Last Error Code: " << GetLastError() << endl;
300 int sizeBmi = Standard_Integer( sizeof(BITMAPINFO) + sizeof(RGBQUAD)*3 );
301 PBITMAPINFO pBmi = (PBITMAPINFO)( new char[sizeBmi] );
302 ZeroMemory( pBmi, sizeBmi );
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;
312 hBmp = CreateDIBSection ( hdc, pBmi, DIB_RGB_COLORS, &ppvBits, NULL, 0 );
313 SelectObject ( hdc, hBmp );
316 PIXELFORMATDESCRIPTOR pfd;
317 ZeroMemory( &pfd, sizeof( PIXELFORMATDESCRIPTOR ) );
318 pfd.nSize = sizeof( PIXELFORMATDESCRIPTOR );
320 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_BITMAP;
321 pfd.iPixelType = PFD_TYPE_RGBA;
324 pfd.iLayerType = PFD_MAIN_PLANE;
326 int iPf = ChoosePixelFormat( hdc, &pfd);
329 if ( !DescribePixelFormat ( hdc, iPf, sizeof(PIXELFORMATDESCRIPTOR), &pfd ) )
331 cout << "Can't describe Pixel Format. Last Error Code: " << GetLastError() << endl;
334 if ( !SetPixelFormat(hdc, iPf, &pfd) )
336 cout << "Can't set Pixel Format. Last Error Code: " << GetLastError() << endl;
339 hglrc = wglCreateContext( hdc );
342 cout << "Can't create new GL Context. Last Error Code: " << GetLastError() << endl;
345 if( !wglMakeCurrent( hdc, hglrc) )
347 cout << "Can't make current new context!" << endl;
351 glViewport( 0, 0, width, height );
353 glMatrixMode( GL_PROJECTION );
355 GLfloat w_c = width / 2., h_c = height / 2.;
357 gluOrtho2D( -w_c, w_c, -h_c, h_c );
359 glMatrixMode( GL_MODELVIEW );
363 QColor aColor = ((GLViewer_ViewPort2d*)myVP)->backgroundColor();
364 glClearColor( ( GLfloat )aColor.red() / 255,
365 ( GLfloat )aColor.green() / 255,
366 ( GLfloat )aColor.blue() / 255,
369 aWidget->exportRepaint();
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;
379 num = GetDIBits(hdc, hBmp, 0, height, imageBits, &bi, DIB_RGB_COLORS);
381 wglMakeCurrent( hdc_old, hglrc_old );
382 wglDeleteContext( hglrc );
388 unsigned int* aPix = NULL;
389 QImage anImage( width, height, 32 );
390 for( int i = 0; i < height; i++ )
392 memset( anImage.scanLine( i ), 0, sizeof(unsigned int)*width );
394 for( int j = 0; j < width; j++ )
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) );
404 QString aFilter( "*.bmp\n*.png" );
406 QFileDialog aFileDlg( QDir::current().absPath(), aFilter, this );
407 aFileDlg.setCaption( tr( "DUMP_VIEW_SAVE_FILE_DLG_CAPTION" ) );
408 aFileDlg.setMode( QFileDialog::AnyFile );
410 if( !aFileDlg.exec() )
413 QString aFileName = aFileDlg.selectedFile();
414 QString aFileExt = aFileDlg.selectedFilter();
416 if( aFileName.isEmpty() )
418 SUIT_MessageBox::error1( this,
419 tr( "DUMP_VIEW_ERROR_DLG_CAPTION" ),
420 tr( "DUMP_VIEW_ERROR_DLG_TEXT" ),
424 QString aSaveOp = "BMP";
425 QString aTypedFileExt = QFileInfo( aFileName ).extension( false ).lower();
427 if( aFileExt == "*.bmp" )
429 if( aTypedFileExt.isEmpty() )
433 else if( aFileExt == "*.png" )
434 if( aTypedFileExt.isEmpty() )
439 // if( !anImage.save( aFileName, aSaveOp ) )
441 if( !aWidget->grabFrameBuffer().save( aFileName, aSaveOp ) )
444 SUIT_MessageBox::error1( this,
445 tr( "DUMP_VIEW_ERROR_DLG_CAPTION" ),
446 tr( "DUMP_VIEW_ERROR_DLG_TEXT" ),
451 void GLViewer_ViewFrame::onViewPan()
453 myViewer->activateTransform( GLViewer_Viewer::Pan );
456 void GLViewer_ViewFrame::onViewZoom()
458 myViewer->activateTransform( GLViewer_Viewer::Zoom );
461 void GLViewer_ViewFrame::onViewFitAll()
463 myViewer->activateTransform( GLViewer_Viewer::FitAll );
466 void GLViewer_ViewFrame::onViewFitArea()
468 myViewer->activateTransform( GLViewer_Viewer::FitRect );
471 void GLViewer_ViewFrame::onViewFitSelect()
473 myViewer->activateTransform( GLViewer_Viewer::FitSelect );
476 void GLViewer_ViewFrame::onViewGlobalPan()
478 myViewer->activateTransform( GLViewer_Viewer::PanGlobal );
481 void GLViewer_ViewFrame::onViewRotate()
483 //myViewer->activateTransform( GLViewer_Viewer::Rotate );
486 void GLViewer_ViewFrame::onViewReset()
488 myViewer->activateTransform( GLViewer_Viewer::Reset );
491 //================================================================
492 // Function : mouseEvent
493 // Purpose : dispatches mouse events
494 //================================================================
495 void GLViewer_ViewFrame::mouseEvent( QMouseEvent* e )
499 case QEvent::MouseButtonPress:
500 emit mousePressed( this, e );
502 case QEvent::MouseButtonRelease:
503 emit mouseReleased( this, e );
505 case QEvent::MouseButtonDblClick:
506 emit mouseDoubleClicked( this, e );
508 case QEvent::MouseMove:
509 emit mouseMoving( this, e );
516 //================================================================
517 // Function : keyEvent
518 // Purpose : dispatches key events
519 //================================================================
520 void GLViewer_ViewFrame::keyEvent( QKeyEvent* e )
524 case QEvent::KeyPress:
525 emit keyPressed( this, e );
527 case QEvent::KeyRelease:
528 emit keyReleased( this, e );
535 //================================================================
536 // Function : wheelEvent
537 // Purpose : dispatches wheel events
538 //================================================================
539 void GLViewer_ViewFrame::wheelEvent( QWheelEvent* e )
544 emit wheeling( this, e );