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.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : OPEN CASCADE
22 // File: GLViewer_ViewFrame.cxx
23 // Created: November, 2004
25 //#include <GLViewerAfx.h>
26 #include "GLViewer_ViewFrame.h"
27 #include "GLViewer_Viewer.h"
28 #include "GLViewer_Viewer2d.h"
29 #include "GLViewer_ViewPort2d.h"
31 #include <SUIT_Desktop.h>
32 #include <SUIT_Session.h>
33 #include <SUIT_ToolButton.h>
34 #include <SUIT_ResourceMgr.h>
35 #include <SUIT_MessageBox.h>
38 #include <qfiledialog.h>
46 GLViewer_ViewFrame::GLViewer_ViewFrame( SUIT_Desktop* d, GLViewer_Viewer* vw )
47 : SUIT_ViewWindow( d ),
51 QFrame* client = new QFrame( this );
52 setCentralWidget( client );
54 QBoxLayout* layout = new QHBoxLayout( client, 1, 1 );
55 layout->setAutoAdd( true );
57 GLViewer_ViewPort2d* vp = new GLViewer_ViewPort2d( client, this );
58 //vp->turnGrid( true );
59 //vp->turnCompass( true );
60 //vp->enablePopup( false );
62 setBackgroundColor( Qt::white );
64 myToolBar = new QToolBar(this);
65 myToolBar->setCloseMode(QDockWindow::Undocked);
66 myToolBar->setLabel(tr("LBL_TOOLBAR_LABEL"));
74 GLViewer_ViewFrame::~GLViewer_ViewFrame()
79 Creates actions of GL view frame
81 void GLViewer_ViewFrame::createActions()
83 if (!myActionsMap.isEmpty()) return;
84 SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
88 aAction = new QAction(tr("MNU_DUMP_VIEW"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_DUMP" ) ),
89 tr( "MNU_DUMP_VIEW" ), 0, this);
90 aAction->setStatusTip(tr("DSC_DUMP_VIEW"));
91 connect(aAction, SIGNAL(activated()), this, SLOT(onViewDump()));
92 myActionsMap[ DumpId ] = aAction;
95 aAction = new QAction(tr("MNU_FITALL"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_FITALL" ) ),
96 tr( "MNU_FITALL" ), 0, this);
97 aAction->setStatusTip(tr("DSC_FITALL"));
98 connect(aAction, SIGNAL(activated()), this, SLOT(onViewFitAll()));
99 myActionsMap[ FitAllId ] = aAction;
102 aAction = new QAction(tr("MNU_FITRECT"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_FITAREA" ) ),
103 tr( "MNU_FITRECT" ), 0, this);
104 aAction->setStatusTip(tr("DSC_FITRECT"));
105 connect(aAction, SIGNAL(activated()), this, SLOT(onViewFitArea()));
106 myActionsMap[ FitRectId ] = aAction;
109 aAction = new QAction(tr("MNU_FITSELECT"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_FITSELECT" ) ),
110 tr( "MNU_FITSELECT" ), 0, this);
111 aAction->setStatusTip(tr("DSC_FITSELECT"));
112 connect(aAction, SIGNAL(activated()), this, SLOT(onViewFitSelect()));
113 myActionsMap[ FitSelectId ] = aAction;
116 aAction = new QAction(tr("MNU_ZOOM_VIEW"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_ZOOM" ) ),
117 tr( "MNU_ZOOM_VIEW" ), 0, this);
118 aAction->setStatusTip(tr("DSC_ZOOM_VIEW"));
119 connect(aAction, SIGNAL(activated()), this, SLOT(onViewZoom()));
120 myActionsMap[ ZoomId ] = aAction;
123 aAction = new QAction(tr("MNU_PAN_VIEW"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_PAN" ) ),
124 tr( "MNU_PAN_VIEW" ), 0, this);
125 aAction->setStatusTip(tr("DSC_PAN_VIEW"));
126 connect(aAction, SIGNAL(activated()), this, SLOT(onViewPan()));
127 myActionsMap[ PanId ] = aAction;
130 aAction = new QAction(tr("MNU_GLOBALPAN_VIEW"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_GLOBALPAN" ) ),
131 tr( "MNU_GLOBALPAN_VIEW" ), 0, this);
132 aAction->setStatusTip(tr("DSC_GLOBALPAN_VIEW"));
133 connect(aAction, SIGNAL(activated()), this, SLOT(onViewGlobalPan()));
134 myActionsMap[ GlobalPanId ] = aAction;
136 aAction = new QAction(tr("MNU_RESET_VIEW"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_RESET" ) ),
137 tr( "MNU_RESET_VIEW" ), 0, this);
138 aAction->setStatusTip(tr("DSC_RESET_VIEW"));
139 connect(aAction, SIGNAL(activated()), this, SLOT(onViewReset()));
140 myActionsMap[ ResetId ] = aAction;
144 Creates toolbar of GL view frame
146 void GLViewer_ViewFrame::createToolBar()
148 myActionsMap[DumpId]->addTo(myToolBar);
150 SUIT_ToolButton* aScaleBtn = new SUIT_ToolButton(myToolBar);
151 aScaleBtn->AddAction(myActionsMap[FitAllId]);
152 aScaleBtn->AddAction(myActionsMap[FitRectId]);
153 aScaleBtn->AddAction(myActionsMap[FitSelectId]);
154 aScaleBtn->AddAction(myActionsMap[ZoomId]);
156 SUIT_ToolButton* aPanBtn = new SUIT_ToolButton(myToolBar);
157 aPanBtn->AddAction(myActionsMap[PanId]);
158 aPanBtn->AddAction(myActionsMap[GlobalPanId]);
160 myActionsMap[ResetId]->addTo(myToolBar);
164 Sets the viewport for this frame
166 void GLViewer_ViewFrame::setViewPort( GLViewer_ViewPort* vp )
173 disconnect( myVP, SIGNAL( vpDrawExternal( QPainter* ) ), this, SIGNAL( vfDrawExternal( QPainter* ) ) );
174 disconnect( myVP, SIGNAL( vpMouseEvent( QMouseEvent* ) ), this, SLOT( mouseEvent( QMouseEvent* ) ) );
175 disconnect( myVP, SIGNAL( vpKeyEvent( QKeyEvent* ) ), this, SLOT( keyEvent( QKeyEvent* ) ) );
176 disconnect( myVP, SIGNAL( vpWheelEvent( QWheelEvent* ) ), this, SLOT( wheelEvent( QWheelEvent* ) ) );
177 disconnect( myVP, SIGNAL( contextMenuRequested( QContextMenuEvent* ) ),
178 this, SIGNAL( contextMenuRequested( QContextMenuEvent* ) ) );
183 connect( myVP, SIGNAL( vpDrawExternal( QPainter* ) ), this, SIGNAL( vfDrawExternal( QPainter* ) ) );
184 connect( myVP, SIGNAL( vpMouseEvent( QMouseEvent* ) ), this, SLOT( mouseEvent( QMouseEvent* ) ) );
185 connect( myVP, SIGNAL( vpKeyEvent( QKeyEvent* ) ), this, SLOT( keyEvent( QKeyEvent* ) ) );
186 connect( myVP, SIGNAL( vpWheelEvent( QWheelEvent* ) ), this, SLOT( wheelEvent( QWheelEvent* ) ) );
187 connect( myVP, SIGNAL( contextMenuRequested( QContextMenuEvent* ) ),
188 this, SIGNAL( contextMenuRequested( QContextMenuEvent* ) ) );
193 Returns the viewport of this frame. [ public ]
195 GLViewer_ViewPort* GLViewer_ViewFrame::getViewPort() const
201 Set background of the viewport. [ public ]
203 void GLViewer_ViewFrame::setBackgroundColor( const QColor& color )
206 myVP->setBackgroundColor( color );
210 Returns background of the viewport. [ public ]
212 QColor GLViewer_ViewFrame::backgroundColor() const
215 return myVP->backgroundColor();
216 return QMainWindow::backgroundColor();
220 Sets the viewer for this view. [ public ]
222 void GLViewer_ViewFrame::setViewer( GLViewer_Viewer* v )
228 Returns the viewer of this view. [ public ]
230 GLViewer_Viewer* GLViewer_ViewFrame::getViewer() const
236 Returns the preferred view size. [ virtual public ]
238 QSize GLViewer_ViewFrame::sizeHint() const
240 QWidget* p = parentWidget();
241 if ( p && p->inherits( "QWorkspaceChild" ) )
242 p = p->parentWidget();
244 return QMainWindow::sizeHint();
245 return QSize( 9 * p->width() / 10 , 9 * p->height() / 10 );
249 Called by viewer's 'update()' method. Does nothing by default [ virtual public ]
251 void GLViewer_ViewFrame::onUpdate( int )
255 //#include <windows.h>
258 SLOT: called on dump view operation is activated, stores scene to raster file
260 void GLViewer_ViewFrame::onViewDump()
262 GLViewer_Widget* aWidget = ((GLViewer_ViewPort2d*)myVP)->getGLWidget();
264 width = aWidget->width();
265 height = aWidget->height();
267 int imageSize = width*height*3;
268 unsigned char* imageBits = NULL;
270 int reserve_bytes = width % 4; //32 bits platform
271 imageSize = (width+reserve_bytes)*height*3;
272 imageBits = new unsigned char[imageSize];
280 HGLRC hglrc_old, hglrc;
284 hglrc_old = wglGetCurrentContext();
285 hdc_old = wglGetCurrentDC();
287 hdc = CreateCompatibleDC( hdc_old );
290 cout << "Can't create compatible DC. Last Error Code: " << GetLastError() << endl;
294 int sizeBmi = Standard_Integer( sizeof(BITMAPINFO) + sizeof(RGBQUAD)*3 );
295 PBITMAPINFO pBmi = (PBITMAPINFO)( new char[sizeBmi] );
296 ZeroMemory( pBmi, sizeBmi );
298 pBmi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); //sizeBmi
299 pBmi->bmiHeader.biWidth = width;
300 pBmi->bmiHeader.biHeight = height;
301 pBmi->bmiHeader.biPlanes = 1;
302 pBmi->bmiHeader.biBitCount = 24;
303 pBmi->bmiHeader.biCompression = BI_RGB;
306 hBmp = CreateDIBSection ( hdc, pBmi, DIB_RGB_COLORS, &ppvBits, NULL, 0 );
307 SelectObject ( hdc, hBmp );
310 PIXELFORMATDESCRIPTOR pfd;
311 ZeroMemory( &pfd, sizeof( PIXELFORMATDESCRIPTOR ) );
312 pfd.nSize = sizeof( PIXELFORMATDESCRIPTOR );
314 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_BITMAP;
315 pfd.iPixelType = PFD_TYPE_RGBA;
318 pfd.iLayerType = PFD_MAIN_PLANE;
320 int iPf = ChoosePixelFormat( hdc, &pfd);
323 if ( !DescribePixelFormat ( hdc, iPf, sizeof(PIXELFORMATDESCRIPTOR), &pfd ) )
325 cout << "Can't describe Pixel Format. Last Error Code: " << GetLastError() << endl;
328 if ( !SetPixelFormat(hdc, iPf, &pfd) )
330 cout << "Can't set Pixel Format. Last Error Code: " << GetLastError() << endl;
333 hglrc = wglCreateContext( hdc );
336 cout << "Can't create new GL Context. Last Error Code: " << GetLastError() << endl;
339 if( !wglMakeCurrent( hdc, hglrc) )
341 cout << "Can't make current new context!" << endl;
345 glViewport( 0, 0, width, height );
347 glMatrixMode( GL_PROJECTION );
349 GLfloat w_c = width / 2., h_c = height / 2.;
351 gluOrtho2D( -w_c, w_c, -h_c, h_c );
353 glMatrixMode( GL_MODELVIEW );
357 QColor aColor = ((GLViewer_ViewPort2d*)myVP)->backgroundColor();
358 glClearColor( ( GLfloat )aColor.red() / 255,
359 ( GLfloat )aColor.green() / 255,
360 ( GLfloat )aColor.blue() / 255,
363 aWidget->exportRepaint();
365 memset(&bi, 0, sizeof(BITMAPINFOHEADER));
366 bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
367 bi.bmiHeader.biPlanes = 1;
368 bi.bmiHeader.biBitCount = 24;
369 bi.bmiHeader.biHeight = -height;
370 bi.bmiHeader.biWidth = width;
371 bi.bmiHeader.biCompression = BI_RGB;
373 num = GetDIBits(hdc, hBmp, 0, height, imageBits, &bi, DIB_RGB_COLORS);
375 wglMakeCurrent( hdc_old, hglrc_old );
376 wglDeleteContext( hglrc );
382 unsigned int* aPix = NULL;
383 QImage anImage( width, height, 32 );
384 for( int i = 0; i < height; i++ )
386 memset( anImage.scanLine( i ), 0, sizeof(unsigned int)*width );
388 for( int j = 0; j < width; j++ )
390 pos = imageBits + i*width*3 + j*3 + reserve_bytes*i;
391 aPix = (unsigned int*)anImage.scanLine(i)+j;
392 *aPix = qRgb( *pos, *(pos+1), *(pos+2) );
398 QString aFilter( "*.bmp\n*.png" );
400 QFileDialog aFileDlg( QDir::current().absPath(), aFilter, this );
401 aFileDlg.setCaption( tr( "DUMP_VIEW_SAVE_FILE_DLG_CAPTION" ) );
402 aFileDlg.setMode( QFileDialog::AnyFile );
404 if( !aFileDlg.exec() )
407 QString aFileName = aFileDlg.selectedFile();
408 QString aFileExt = aFileDlg.selectedFilter();
410 if( aFileName.isEmpty() )
412 SUIT_MessageBox::error1( this,
413 tr( "DUMP_VIEW_ERROR_DLG_CAPTION" ),
414 tr( "DUMP_VIEW_ERROR_DLG_TEXT" ),
418 QString aSaveOp = "BMP";
419 QString aTypedFileExt = QFileInfo( aFileName ).extension( false ).lower();
421 if( aFileExt == "*.bmp" )
423 if( aTypedFileExt.isEmpty() )
427 else if( aFileExt == "*.png" )
428 if( aTypedFileExt.isEmpty() )
433 // if( !anImage.save( aFileName, aSaveOp ) )
435 if( !aWidget->grabFrameBuffer().save( aFileName, aSaveOp ) )
438 SUIT_MessageBox::error1( this,
439 tr( "DUMP_VIEW_ERROR_DLG_CAPTION" ),
440 tr( "DUMP_VIEW_ERROR_DLG_TEXT" ),
448 void GLViewer_ViewFrame::onViewPan()
450 myViewer->activateTransform( GLViewer_Viewer::Pan );
456 void GLViewer_ViewFrame::onViewZoom()
458 myViewer->activateTransform( GLViewer_Viewer::Zoom );
464 void GLViewer_ViewFrame::onViewFitAll()
466 myViewer->activateTransform( GLViewer_Viewer::FitAll );
472 void GLViewer_ViewFrame::onViewFitArea()
474 myViewer->activateTransform( GLViewer_Viewer::FitRect );
480 void GLViewer_ViewFrame::onViewFitSelect()
482 myViewer->activateTransform( GLViewer_Viewer::FitSelect );
488 void GLViewer_ViewFrame::onViewGlobalPan()
490 myViewer->activateTransform( GLViewer_Viewer::PanGlobal );
496 void GLViewer_ViewFrame::onViewRotate()
498 //myViewer->activateTransform( GLViewer_Viewer::Rotate );
502 Start reset default view aspects
504 void GLViewer_ViewFrame::onViewReset()
506 myViewer->activateTransform( GLViewer_Viewer::Reset );
510 Dispatches mouse events
512 void GLViewer_ViewFrame::mouseEvent( QMouseEvent* e )
516 case QEvent::MouseButtonPress:
517 emit mousePressed( this, e );
519 case QEvent::MouseButtonRelease:
520 emit mouseReleased( this, e );
522 case QEvent::MouseButtonDblClick:
523 emit mouseDoubleClicked( this, e );
525 case QEvent::MouseMove:
526 emit mouseMoving( this, e );
534 Dispatches key events
536 void GLViewer_ViewFrame::keyEvent( QKeyEvent* e )
540 case QEvent::KeyPress:
541 emit keyPressed( this, e );
543 case QEvent::KeyRelease:
544 emit keyReleased( this, e );
552 Dispatches wheel events
554 void GLViewer_ViewFrame::wheelEvent( QWheelEvent* e )
559 emit wheeling( this, e );
567 \return the visual parameters of this view as a formated string
569 QString GLViewer_ViewFrame::getVisualParameters()
572 if ( myVP && myVP->inherits( "GLViewer_ViewPort2d" ) ) {
573 GLViewer_ViewPort2d* vp2d = (GLViewer_ViewPort2d*)myVP;
574 GLfloat xSc, ySc, xPan, yPan;
575 vp2d->getScale( xSc, ySc );
576 vp2d->getPan( xPan, yPan );
577 retStr.sprintf( "%.12e*%.12e*%.12e*%.12e", xSc, ySc, xPan, yPan );
583 The method restores visual parameters of this view from a formated string
585 void GLViewer_ViewFrame::setVisualParameters( const QString& parameters )
587 QStringList paramsLst = QStringList::split( '*', parameters, true );
588 if ( myVP && myVP->inherits( "GLViewer_ViewPort2d" ) && paramsLst.size() == 4) {
589 GLViewer_ViewPort2d* vp2d = (GLViewer_ViewPort2d*)myVP;
591 GLfloat xSc, ySc, xPan, yPan;
592 xSc = paramsLst[0].toDouble();
593 ySc = paramsLst[1].toDouble();
594 xPan = paramsLst[2].toDouble();
595 yPan = paramsLst[3].toDouble();
597 vp2d->getGLWidget()->setScale( xSc, ySc, 1. );
598 vp2d->getGLWidget()->setPan( xPan, yPan, 0. );