Salome HOME
updated copyright message
[modules/gui.git] / src / GLViewer / GLViewer_ViewFrame.cxx
index 14e2305abae6ac18696a2dade2e0e02d1a9dd413..343812dfbd15afd6ecc3517ec839d1aad1d4b0e7 100644 (file)
@@ -1,34 +1,52 @@
-// File:      GLViewer_ViewFrame.cxx
-// Created:   November, 2004
-// Author:    OCC team
-// Copyright (C) CEA 2004
-
-/***************************************************************************
-**  Class:   GLViewer_ViewFrame
-**  Descr:   Frame window for viewport in QAD-based application
-**  Module:  QAD
-**  Created: UI team, 05.09.00
-****************************************************************************/
+// Copyright (C) 2007-2023  CEA, EDF, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
 
 #include "GLViewer_ViewFrame.h"
-
 #include "GLViewer_Viewer.h"
-#include "GLViewer_Viewer2d.h"
 #include "GLViewer_ViewPort2d.h"
 
+#include <QtxToolBar.h>
+#include <QtxMultiAction.h>
+#include <QtxActionToolMgr.h>
+
 #include <SUIT_Desktop.h>
-#include <SUIT_Application.h>
 #include <SUIT_Session.h>
-#include <SUIT_ToolButton.h>
 #include <SUIT_ResourceMgr.h>
-#include <SUIT_Tools.h>
-#include <QtxAction.h>
 #include <SUIT_MessageBox.h>
 
-#include <qcolor.h>
-#include <qimage.h>
-#include <qlayout.h>
-#include <qstring.h>
+#include <QColor>
+#include <QFileDialog>
+#include <QImage>
+#include <QHBoxLayout>
+#include <QString>
+#include <QFrame>
+#include <QMouseEvent>
+#include <QKeyEvent>
+#include <QWheelEvent>
+
+#ifdef WIN32
+#include <Standard_Integer.hxx>
+#include <iostream>
+#endif
 
 /*!
     Constructor
@@ -38,22 +56,18 @@ GLViewer_ViewFrame::GLViewer_ViewFrame( SUIT_Desktop* d, GLViewer_Viewer* vw )
 myViewer( vw ),
 myVP( 0 )
 {
-    QFrame* client = new QFrame( this );    
+    QFrame* client = new QFrame( this );
     setCentralWidget( client );
 
-    QBoxLayout* layout = new QHBoxLayout( client, 1, 1 );
-    layout->setAutoAdd( true );
+    QBoxLayout* layout = new QHBoxLayout( client );
+    layout->setMargin( 0 );
+    layout->setSpacing( 0 );
 
     GLViewer_ViewPort2d* vp = new GLViewer_ViewPort2d( client, this );
-    //vp->turnGrid( true );
-    //vp->turnCompass( true );
-    //vp->enablePopup( false );
     setViewPort( vp );
     setBackgroundColor( Qt::white );
+    layout->addWidget( vp );
 
-    myToolBar = new QToolBar(this);
-    myToolBar->setCloseMode(QDockWindow::Undocked);
-    myToolBar->setLabel(tr("LBL_TOOLBAR_LABEL"));
     createActions();
     createToolBar();
 }
@@ -65,93 +79,93 @@ GLViewer_ViewFrame::~GLViewer_ViewFrame()
 {
 }
 
-//================================================================
-// Function : createActions
-// Purpose  : 
-//================================================================
+/*!
+  Creates actions of GL view frame
+*/
 void GLViewer_ViewFrame::createActions()
 {
-  if ( !myActionsMap.isEmpty() )
-    return;
-
-  QtxAction* aAction;
   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
+  QtxAction* aAction;
 
   // Dump view
   aAction = new QtxAction(tr("MNU_DUMP_VIEW"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_DUMP" ) ),
-                           tr( "MNU_DUMP_VIEW" ), 0, this);
+                          tr( "MNU_DUMP_VIEW" ), 0, this);
   aAction->setStatusTip(tr("DSC_DUMP_VIEW"));
-  connect(aAction, SIGNAL(activated()), this, SLOT(onViewDump()));
-  myActionsMap[ DumpId ] = aAction;
+  connect(aAction, SIGNAL(triggered()), this, SLOT(onDumpView()));
+  toolMgr()->registerAction( aAction, DumpId );
 
   // FitAll
   aAction = new QtxAction(tr("MNU_FITALL"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_FITALL" ) ),
-                           tr( "MNU_FITALL" ), 0, this);
+                          tr( "MNU_FITALL" ), 0, this);
   aAction->setStatusTip(tr("DSC_FITALL"));
-  connect(aAction, SIGNAL(activated()), this, SLOT(onViewFitAll()));
-  myActionsMap[ FitAllId ] = aAction;
+  connect(aAction, SIGNAL(triggered()), this, SLOT(onViewFitAll()));
+  toolMgr()->registerAction( aAction, FitAllId );
 
   // FitRect
   aAction = new QtxAction(tr("MNU_FITRECT"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_FITAREA" ) ),
-                           tr( "MNU_FITRECT" ), 0, this);
+                          tr( "MNU_FITRECT" ), 0, this);
   aAction->setStatusTip(tr("DSC_FITRECT"));
-  connect(aAction, SIGNAL(activated()), this, SLOT(onViewFitArea()));
-  myActionsMap[ FitRectId ] = aAction;
+  connect(aAction, SIGNAL(triggered()), this, SLOT(onViewFitArea()));
+  toolMgr()->registerAction( aAction, FitRectId );
 
   // FitSelect
   aAction = new QtxAction(tr("MNU_FITSELECT"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_FITSELECT" ) ),
-                         tr( "MNU_FITSELECT" ), 0, this);
+                          tr( "MNU_FITSELECT" ), 0, this);
   aAction->setStatusTip(tr("DSC_FITSELECT"));
-  connect(aAction, SIGNAL(activated()), this, SLOT(onViewFitSelect()));
-  myActionsMap[ FitSelectId ] = aAction;
+  connect(aAction, SIGNAL(triggered()), this, SLOT(onViewFitSelect()));
+  toolMgr()->registerAction( aAction, FitSelectId );
 
   // Zoom
   aAction = new QtxAction(tr("MNU_ZOOM_VIEW"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_ZOOM" ) ),
-                           tr( "MNU_ZOOM_VIEW" ), 0, this);
+                          tr( "MNU_ZOOM_VIEW" ), 0, this);
   aAction->setStatusTip(tr("DSC_ZOOM_VIEW"));
-  connect(aAction, SIGNAL(activated()), this, SLOT(onViewZoom()));
-  myActionsMap[ ZoomId ] = aAction;
+  connect(aAction, SIGNAL(triggered()), this, SLOT(onViewZoom()));
+  toolMgr()->registerAction( aAction, ZoomId );
 
   // Panning
   aAction = new QtxAction(tr("MNU_PAN_VIEW"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_PAN" ) ),
-                           tr( "MNU_PAN_VIEW" ), 0, this);
+                          tr( "MNU_PAN_VIEW" ), 0, this);
   aAction->setStatusTip(tr("DSC_PAN_VIEW"));
-  connect(aAction, SIGNAL(activated()), this, SLOT(onViewPan()));
-  myActionsMap[ PanId ] = aAction;
+  connect(aAction, SIGNAL(triggered()), this, SLOT(onViewPan()));
+  toolMgr()->registerAction( aAction, PanId );
 
   // Global Panning
   aAction = new QtxAction(tr("MNU_GLOBALPAN_VIEW"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_GLOBALPAN" ) ),
-                           tr( "MNU_GLOBALPAN_VIEW" ), 0, this);
+                          tr( "MNU_GLOBALPAN_VIEW" ), 0, this);
   aAction->setStatusTip(tr("DSC_GLOBALPAN_VIEW"));
-  connect(aAction, SIGNAL(activated()), this, SLOT(onViewGlobalPan()));
-  myActionsMap[ GlobalPanId ] = aAction;
+  connect(aAction, SIGNAL(triggered()), this, SLOT(onViewGlobalPan()));
+  toolMgr()->registerAction( aAction, GlobalPanId );
 
   aAction = new QtxAction(tr("MNU_RESET_VIEW"), aResMgr->loadPixmap( "GLViewer", tr( "ICON_GL_RESET" ) ),
-                           tr( "MNU_RESET_VIEW" ), 0, this);
+                          tr( "MNU_RESET_VIEW" ), 0, this);
   aAction->setStatusTip(tr("DSC_RESET_VIEW"));
-  connect(aAction, SIGNAL(activated()), this, SLOT(onViewReset()));
-  myActionsMap[ ResetId ] = aAction;
+  connect(aAction, SIGNAL(triggered()), this, SLOT(onViewReset()));
+  toolMgr()->registerAction( aAction, ResetId );
 }
 
-//================================================================
-// Function : createToolBar
-// Purpose  : 
-//================================================================
+/*!
+  Creates toolbar of GL view frame
+*/
 void GLViewer_ViewFrame::createToolBar()
 {
-  myActionsMap[DumpId]->addTo(myToolBar);
-
-  SUIT_ToolButton* aScaleBtn = new SUIT_ToolButton(myToolBar);
-  aScaleBtn->AddAction(myActionsMap[FitAllId]);
-  aScaleBtn->AddAction(myActionsMap[FitRectId]);
-  aScaleBtn->AddAction(myActionsMap[FitSelectId]);
-  aScaleBtn->AddAction(myActionsMap[ZoomId]);
-
-  SUIT_ToolButton* aPanBtn = new SUIT_ToolButton(myToolBar);
-  aPanBtn->AddAction(myActionsMap[PanId]);
-  aPanBtn->AddAction(myActionsMap[GlobalPanId]);
-
-  myActionsMap[ResetId]->addTo(myToolBar);
+  int tid = toolMgr()->createToolBar( tr( "LBL_TOOLBAR_LABEL" ),             // title (language-dependant)
+                                     QString( "GLViewerViewOperations" ),   // name (language-independant)
+                                     false );                               // disable floatable toolbar
+  toolMgr()->append( DumpId, tid );
+
+  QtxMultiAction* aScaleAction = new QtxMultiAction( this );
+  aScaleAction->insertAction( toolMgr()->action( FitAllId ) );
+  aScaleAction->insertAction( toolMgr()->action( FitRectId ) );
+  aScaleAction->insertAction( toolMgr()->action( FitSelectId ) );
+  aScaleAction->insertAction( toolMgr()->action( ZoomId ) );
+  toolMgr()->append( aScaleAction, tid );
+
+  QtxMultiAction* aPanAction = new QtxMultiAction( this );
+  aPanAction->insertAction( toolMgr()->action( PanId ) );
+  aPanAction->insertAction( toolMgr()->action( GlobalPanId ) );
+  toolMgr()->append( aPanAction, tid );
+
+  toolMgr()->append( toolMgr()->action( ResetId ), tid );
 }
 
 /*!
@@ -167,9 +181,9 @@ void GLViewer_ViewFrame::setViewPort( GLViewer_ViewPort* vp )
         disconnect( myVP, SIGNAL( vpDrawExternal( QPainter* ) ), this, SIGNAL( vfDrawExternal( QPainter* ) ) );
         disconnect( myVP, SIGNAL( vpMouseEvent( QMouseEvent* ) ), this, SLOT( mouseEvent( QMouseEvent* ) ) );
         disconnect( myVP, SIGNAL( vpKeyEvent( QKeyEvent* ) ), this, SLOT( keyEvent( QKeyEvent* ) ) );
-        disconnect( myVP, SIGNAL(contextMenuRequested( QContextMenuEvent * )),
-                    this, SIGNAL(contextMenuRequested( QContextMenuEvent * )) );
         disconnect( myVP, SIGNAL( vpWheelEvent( QWheelEvent* ) ), this, SLOT( wheelEvent( QWheelEvent* ) ) );
+        disconnect( myVP, SIGNAL( contextMenuRequested( QContextMenuEvent* ) ),
+                    this, SIGNAL( contextMenuRequested( QContextMenuEvent* ) ) );
     }
     myVP = vp;
     if ( myVP )
@@ -177,9 +191,9 @@ void GLViewer_ViewFrame::setViewPort( GLViewer_ViewPort* vp )
         connect( myVP, SIGNAL( vpDrawExternal( QPainter* ) ), this, SIGNAL( vfDrawExternal( QPainter* ) ) );
         connect( myVP, SIGNAL( vpMouseEvent( QMouseEvent* ) ), this, SLOT( mouseEvent( QMouseEvent* ) ) );
         connect( myVP, SIGNAL( vpKeyEvent( QKeyEvent* ) ), this, SLOT( keyEvent( QKeyEvent* ) ) );
-        connect( myVP, SIGNAL(contextMenuRequested( QContextMenuEvent * )),
-                 this, SIGNAL(contextMenuRequested( QContextMenuEvent * )) );
         connect( myVP, SIGNAL( vpWheelEvent( QWheelEvent* ) ), this, SLOT( wheelEvent( QWheelEvent* ) ) );
+        connect( myVP, SIGNAL( contextMenuRequested( QContextMenuEvent* ) ),
+                 this, SIGNAL( contextMenuRequested( QContextMenuEvent* ) ) );
     }
 }
 
@@ -207,7 +221,7 @@ QColor GLViewer_ViewFrame::backgroundColor() const
 {
     if ( myVP )
         return myVP->backgroundColor();
-    return QMainWindow::backgroundColor();
+    return palette().color( backgroundRole() );
 }
 
 /*!
@@ -233,7 +247,7 @@ QSize GLViewer_ViewFrame::sizeHint() const
 {
     QWidget* p = parentWidget();
     if ( p && p->inherits( "QWorkspaceChild" ) )
-        p = p->parentWidget();      /* QWorkspaceChild: internal impl class in QWorkspace */
+        p = p->parentWidget();
     if ( !p )
         return QMainWindow::sizeHint();
     return QSize( 9 * p->width() / 10 , 9 * p->height() / 10  );
@@ -246,214 +260,90 @@ void GLViewer_ViewFrame::onUpdate( int )
 {
 }
 
-void GLViewer_ViewFrame::onViewDump()
-{
-    GLViewer_Widget* aWidget = ((GLViewer_ViewPort2d*)myVP)->getGLWidget();
-    int width, height;
-    width = aWidget->width();
-    height = aWidget->height();
-    
-    int imageSize = width*height*3;
-    unsigned char* imageBits = NULL;
-
-    int reserve_bytes = width % 4; //32 bits platform
-    imageSize = (width+reserve_bytes)*height*3;
-    imageBits = new unsigned char[imageSize];
-
-    
-#ifdef WNT
-
-    int num;
-    HBITMAP hBmp;
-    HDC hdc_old, hdc;
-    HGLRC hglrc_old, hglrc;
-
-    BITMAPINFO bi;
-
-    hglrc_old = wglGetCurrentContext();
-    hdc_old = wglGetCurrentDC();
-
-    hdc = CreateCompatibleDC( hdc_old );
-    if( !hdc )
-    {
-        cout << "Can't create compatible DC. Last Error Code: " << GetLastError() << endl;
-        return;
-    }
-
-    int sizeBmi = Standard_Integer( sizeof(BITMAPINFO) + sizeof(RGBQUAD)*3 );
-    PBITMAPINFO pBmi = (PBITMAPINFO)( new char[sizeBmi] );
-    ZeroMemory( pBmi, sizeBmi );
-
-    pBmi->bmiHeader.biSize        = sizeof( BITMAPINFOHEADER ); //sizeBmi
-    pBmi->bmiHeader.biWidth       = width;
-    pBmi->bmiHeader.biHeight      = height;
-    pBmi->bmiHeader.biPlanes      = 1;
-    pBmi->bmiHeader.biBitCount    = 24;
-    pBmi->bmiHeader.biCompression = BI_RGB;
-
-    LPVOID ppvBits;
-    hBmp = CreateDIBSection ( hdc, pBmi, DIB_RGB_COLORS, &ppvBits, NULL, 0 );
-    SelectObject ( hdc, hBmp );
-    delete[] pBmi;
-
-    PIXELFORMATDESCRIPTOR pfd;
-    ZeroMemory( &pfd, sizeof( PIXELFORMATDESCRIPTOR ) );
-    pfd.nSize      = sizeof( PIXELFORMATDESCRIPTOR );
-    pfd.nVersion   = 1;
-    pfd.dwFlags    = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_BITMAP;
-    pfd.iPixelType = PFD_TYPE_RGBA;
-    pfd.cColorBits = 24;
-    pfd.cDepthBits = 32;
-    pfd.iLayerType = PFD_MAIN_PLANE;
-
-    int iPf = ChoosePixelFormat( hdc, &pfd);    
-    if( iPf == 0 )
-    {
-        if ( !DescribePixelFormat ( hdc, iPf, sizeof(PIXELFORMATDESCRIPTOR), &pfd ) )
-        {
-            cout << "Can't describe Pixel Format. Last Error Code: " << GetLastError() << endl;
-        }
-    }
-    if ( !SetPixelFormat(hdc, iPf, &pfd) )
-    {
-        cout << "Can't set Pixel Format. Last Error Code: " << GetLastError() << endl;
-    }
-
-    hglrc = wglCreateContext( hdc );
-    if( !hglrc )
-    {
-        cout << "Can't create new GL Context. Last Error Code: " << GetLastError() << endl;
-        return;
-    }
-    if( !wglMakeCurrent( hdc, hglrc) )
-    {
-        cout << "Can't make current new context!" << endl;
-        return;
-    }
-    
-    glViewport( 0, 0, width, height );
-
-    glMatrixMode( GL_PROJECTION );
-    glLoadIdentity();
-    GLfloat w_c = width / 2., h_c = height / 2.; 
-
-    gluOrtho2D( -w_c, w_c, -h_c, h_c ); 
-
-    glMatrixMode( GL_MODELVIEW );
-    glLoadIdentity();
-
-    //set background
-    QColor aColor = ((GLViewer_ViewPort2d*)myVP)->backgroundColor();
-    glClearColor( ( GLfloat )aColor.red() / 255,
-                  ( GLfloat )aColor.green() / 255,
-                  ( GLfloat )aColor.blue() / 255,
-                  1.0 );
-
-    aWidget->exportRepaint();
-
-      memset(&bi, 0, sizeof(BITMAPINFOHEADER));
-    bi.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
-    bi.bmiHeader.biPlanes      = 1;
-    bi.bmiHeader.biBitCount    = 24;
-    bi.bmiHeader.biHeight      = -height;
-    bi.bmiHeader.biWidth       = width;
-    bi.bmiHeader.biCompression = BI_RGB;
-
-    num = GetDIBits(hdc, hBmp, 0, height, imageBits, &bi, DIB_RGB_COLORS);
-
-    wglMakeCurrent( hdc_old, hglrc_old );
-    wglDeleteContext( hglrc );
-    
-
-#else //XWindows
-#endif
-
-    unsigned int* aPix = NULL;
-    QImage  anImage( width, height, 32 );
-    for( int i = 0; i < height; i++ )
-    {
-        memset( anImage.scanLine( i ), 0, sizeof(unsigned int)*width );
-        unsigned char* pos;
-        for( int j = 0; j < width; j++ )
-        {
-            pos = imageBits + i*width*3 + j*3 + reserve_bytes*i;
-            aPix = (unsigned int*)anImage.scanLine(i)+j;
-            *aPix = qRgb( *pos, *(pos+1), *(pos+2) );
-        }
-    }
-
-    delete [] imageBits;
+//#include <windows.h>
 
-    SUIT_Application* app = getViewManager()->study()->application();
-
-    QString aFileName = app->getFileName( false, QString::null, QString( "*.bmp;*.png" ), tr( "DUMP_VIEW_SAVE_FILE_DLG_CAPTION" ), 0 );
-
-    if( aFileName.isEmpty() ) // cancelled
-      return;
+/*!
+  SLOT: called on dump view operation is activated, stores scene to raster file
+*/
 
-    QString aSaveOp = SUIT_Tools::extension( aFileName ).upper();
+QImage GLViewer_ViewFrame::dumpView()
+{
+  QImage img;
 
-    if ( aSaveOp != "BMP" && aSaveOp != "PNG" ) {
-      SUIT_MessageBox::error1( this,
-                              tr( "DUMP_VIEW_ERROR_DLG_CAPTION" ),
-                              tr( "DUMP_VIEW_ERROR_UNSUPPORTED_FORMAT" ).arg( aSaveOp ),
-                              tr( "BUT_OK" ) );
-      return;
-    }
+  GLViewer_Widget* aWidget = ((GLViewer_ViewPort2d*)myVP)->getGLWidget();
+  if ( aWidget )
+    img = aWidget->grabFrameBuffer();
 
-    if( !anImage.save( aFileName, aSaveOp ) )
-    {
-        SUIT_MessageBox::error1( this,
-                                tr( "DUMP_VIEW_ERROR_DLG_CAPTION" ),
-                                tr( "DUMP_VIEW_ERROR_DLG_TEXT" ),
-                                tr( "BUT_OK" ) );
-    }
+  return img;
 }
 
+/*!
+  Start panning
+*/
 void GLViewer_ViewFrame::onViewPan()
 {
     myViewer->activateTransform( GLViewer_Viewer::Pan );
 }
 
+/*!
+  Start zooming
+*/
 void GLViewer_ViewFrame::onViewZoom()
 {
     myViewer->activateTransform( GLViewer_Viewer::Zoom );
 }
 
+/*!
+  Start fit all
+*/
 void GLViewer_ViewFrame::onViewFitAll()
 {
     myViewer->activateTransform( GLViewer_Viewer::FitAll );
 }
 
+/*!
+  Start fit area
+*/
 void GLViewer_ViewFrame::onViewFitArea()
-{ 
+{
     myViewer->activateTransform( GLViewer_Viewer::FitRect );
 }
 
+/*!
+  Start fit selected
+*/
 void GLViewer_ViewFrame::onViewFitSelect()
-{ 
+{
     myViewer->activateTransform( GLViewer_Viewer::FitSelect );
 }
 
+/*!
+  Start global panning
+*/
 void GLViewer_ViewFrame::onViewGlobalPan()
-{ 
+{
     myViewer->activateTransform( GLViewer_Viewer::PanGlobal );
 }
 
+/*!
+  Start rotating
+*/
 void GLViewer_ViewFrame::onViewRotate()
-{ 
+{
     //myViewer->activateTransform( GLViewer_Viewer::Rotate );
 }
 
+/*!
+  Start reset default view aspects
+*/
 void GLViewer_ViewFrame::onViewReset()
-{ 
+{
     myViewer->activateTransform( GLViewer_Viewer::Reset );
 }
-  
-//================================================================
-// Function : mouseEvent
-// Purpose  : dispatches mouse events
-//================================================================
+
+/*!
+  Dispatches mouse events
+*/
 void GLViewer_ViewFrame::mouseEvent( QMouseEvent* e )
 {
   switch ( e->type() )
@@ -475,10 +365,9 @@ void GLViewer_ViewFrame::mouseEvent( QMouseEvent* e )
   }
 }
 
-//================================================================
-// Function : keyEvent
-// Purpose  : dispatches key events
-//================================================================
+/*!
+  Dispatches key events
+*/
 void GLViewer_ViewFrame::keyEvent( QKeyEvent* e )
 {
   switch ( e->type() )
@@ -494,10 +383,9 @@ void GLViewer_ViewFrame::keyEvent( QKeyEvent* e )
   }
 }
 
-//================================================================
-// Function : wheelEvent
-// Purpose  : dispatches wheel events
-//================================================================
+/*!
+  Dispatches wheel events
+*/
 void GLViewer_ViewFrame::wheelEvent( QWheelEvent* e )
 {
   switch ( e->type() )
@@ -509,3 +397,39 @@ void GLViewer_ViewFrame::wheelEvent( QWheelEvent* e )
     break;
   }
 }
+
+/*!
+  \return the visual parameters of this view as a formated string
+*/
+QString GLViewer_ViewFrame::getVisualParameters()
+{
+  QString retStr;
+  if ( myVP && myVP->inherits( "GLViewer_ViewPort2d" ) ) {
+    GLViewer_ViewPort2d* vp2d = (GLViewer_ViewPort2d*)myVP;
+    GLfloat xSc, ySc, xPan, yPan;
+    vp2d->getScale( xSc, ySc );
+    vp2d->getPan( xPan, yPan );
+    retStr.sprintf( "%.12e*%.12e*%.12e*%.12e", xSc, ySc, xPan, yPan );
+  }
+  return retStr;
+}
+
+/*!
+  The method restores visual parameters of this view from a formated string
+*/
+void GLViewer_ViewFrame::setVisualParameters( const QString& parameters )
+{
+  QStringList paramsLst = parameters.split( '*' );
+  if ( myVP && myVP->inherits( "GLViewer_ViewPort2d" ) && paramsLst.size() == 4) {
+    GLViewer_ViewPort2d* vp2d = (GLViewer_ViewPort2d*)myVP;
+
+    GLfloat xSc, ySc, xPan, yPan;
+    xSc = paramsLst[0].toDouble();
+    ySc = paramsLst[1].toDouble();
+    xPan = paramsLst[2].toDouble();
+    yPan = paramsLst[3].toDouble();
+
+    vp2d->getGLWidget()->setScale( xSc, ySc, 1. );
+    vp2d->getGLWidget()->setPan( xPan, yPan, 0. );
+  }
+}