Salome HOME
Updated copyright comment
[modules/gui.git] / src / GLViewer / GLViewer_Viewer2d.cxx
1 // Copyright (C) 2007-2024  CEA, EDF, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  Author : OPEN CASCADE
24 // File:      GLViewer_Viewer2d.cxx
25 // Created:   November, 2004
26 //#include <GLViewerAfx.h>
27 //
28 #include "GLViewer_Viewer2d.h"
29 #include "GLViewer_Object.h"
30 #include "GLViewer_ViewFrame.h"
31 #include "GLViewer_BaseObjects.h"
32 #include "GLViewer_CoordSystem.h"
33 #include "GLViewer_Context.h"
34 #include "GLViewer_Drawer.h"
35 #include "GLViewer_Selector2d.h"
36 #include "GLViewer_ViewPort2d.h"
37
38 #include "SUIT_Desktop.h"
39 #include "SUIT_ViewWindow.h"
40 #include "SUIT_ViewManager.h"
41
42 #include <QMenu>
43 #include <QRect>
44 #include <QFile>
45 #include <QPolygon>
46 #include <QMouseEvent>
47 #include <QColorDialog>
48
49 /*!
50   Constructor
51   \param title - viewer title
52 */
53 GLViewer_Viewer2d::GLViewer_Viewer2d( const QString& title) :
54 GLViewer_Viewer( title )
55 {
56   myGLContext = new GLViewer_Context( this );
57
58   createSelector();
59
60   mySelMode = GLViewer_Viewer::Multiple;
61
62   myDrawers.clear();
63 }
64
65 /*!
66   Destructor
67 */
68 GLViewer_Viewer2d::~GLViewer_Viewer2d()
69 {    
70     //myGLSketcher = 0;
71     //delete myGLSketcher;
72   GLViewer_TexFont::clearTextBases();
73 }
74
75 /*!Create new instance of view window on desktop \a theDesktop.
76  *\retval SUIT_ViewWindow* - created view window pointer.
77  */
78 SUIT_ViewWindow* GLViewer_Viewer2d::createView( SUIT_Desktop* theDesktop )
79 {
80     return new GLViewer_ViewFrame( theDesktop, this );
81 }
82
83 /*!
84   Adds item for change background color
85   \param thePopup - menu
86 */
87 void GLViewer_Viewer2d::addPopupItems( QMenu* thePopup )
88 {
89   // CTH8434. "Change background color" menu item is available if there are no selected objects
90   if ( getSelector() == 0 || getSelector()->numSelected() == 0 )
91   {
92     if( thePopup->actions().count() > 0 )
93         thePopup->addSeparator();
94     thePopup->addAction( tr( "CHANGE_BGCOLOR" ), this, SLOT( onChangeBgColor() ) );
95   }
96 }
97
98 /*!
99   Changes background color
100 */
101 void GLViewer_Viewer2d::onChangeBgColor()
102 {
103   if( !getActiveView() )
104     return;
105   GLViewer_ViewPort2d* vp = ( ( GLViewer_ViewPort2d* )getActiveView()->getViewPort() );
106
107   QColor selColor = QColorDialog::getColor( vp->backgroundColor(), vp );        
108   if ( selColor.isValid() ) {
109     vp->setBackgroundColor( selColor );
110   }
111 }
112
113 /*!
114   Updates colors for all drawers (does not work)
115 */
116 void GLViewer_Viewer2d::updateColors( QColor /*colorH*/, QColor /*colorS*/ )
117 {
118   activateAllDrawers( true );
119 }
120
121 /*!
122   Updates rect of global scene by adding new rectangle
123   \param theRect - rectangle
124 */
125 void GLViewer_Viewer2d::updateBorders( GLViewer_Rect* theRect )
126 {
127   QVector<SUIT_ViewWindow*> views = getViewManager()->getViews();
128   for ( int i = 0, n = views.count(); i < n; i++ )
129   {
130     GLViewer_Rect* border = ( ( GLViewer_ViewPort2d* )((GLViewer_ViewFrame*)views[i])->getViewPort() )->getBorder();
131
132     border->setLeft( qMin( border->left(), theRect->left() ) );
133     border->setRight( qMax( border->right(), theRect->right() ) );
134     border->setBottom( qMin( border->bottom(), theRect->bottom() ) );
135     border->setTop( qMax( border->top(), theRect->top() ) );
136   }
137 }
138
139 /*!
140   Recomputes global scene rect
141 */
142 void GLViewer_Viewer2d::updateBorders()
143 {
144     QVector<SUIT_ViewWindow*> views = getViewManager()->getViews();
145
146     ObjList anObjects = myGLContext->getObjects();
147     ObjList::Iterator beginIt = anObjects.begin();
148     ObjList::Iterator endIt = anObjects.end();
149     for ( int i = 0, n = views.count(); i < n; i++ )
150     {
151         GLViewer_Rect* border = ( ( GLViewer_ViewPort2d* )((GLViewer_ViewFrame*)views[i])->getViewPort() )->getBorder();
152         if ( !border )
153           continue;
154         border->setIsEmpty( true );
155         // initialise border by default values to avoid old values
156         border->setCoords( 0, 0, 0, 0 );
157         for ( ObjList::Iterator it = beginIt; it != endIt; ++it )
158         {
159             GLViewer_Object* anObject = *it;
160             GLViewer_Rect* aRect = anObject->getRect();
161             if( !anObject->isSelectable() || !anObject->getVisible() )
162                 continue;
163
164             if( border->isEmpty() )
165             {
166                 border->setIsEmpty( false );
167                 border->setCoords( aRect->left(), aRect->right(), aRect->bottom(), aRect->top() );
168             }
169             else
170             {
171                 border->setLeft( qMin( border->left(), aRect->left() ) );
172                 border->setRight( qMax( border->right(), aRect->right() ) );
173                 border->setBottom( qMin( border->bottom(), aRect->bottom() ) );
174                 border->setTop( qMax( border->top(), aRect->top() ) );
175             }
176         }
177     }
178 }
179
180 /*!
181   Redraws all active objects by updating all drawers in all views
182 */
183 void GLViewer_Viewer2d::updateAll()
184 {
185   if ( !getActiveView() )
186     return;
187
188   QVector<SUIT_ViewWindow*> views = getViewManager()->getViews();
189   for ( int i = 0, n = views.count(); i < n; i++ )
190     ( ( GLViewer_ViewPort2d* )( ( GLViewer_ViewFrame* )views[i] )->getViewPort() )->getGLWidget()->updateGL();
191 }
192
193 /*!
194    \param onlyUpdate is passed to method activateAllDrawers drawers
195 */
196 void GLViewer_Viewer2d::updateDrawers( GLboolean update, GLfloat /*scX*/, GLfloat /*scY*/ )
197 {
198     activateAllDrawers( update );
199 }
200
201 /*!
202   Activates drawers for objects from list \param theObjects only
203 */
204 void GLViewer_Viewer2d::activateDrawers( QList<GLViewer_Object*>& theObjects, bool onlyUpdate, GLboolean swap )
205 {
206     //cout << "GLViewer_Viewer2d::activateDrawers " << (int)onlyUpdate << " " << (int)swap << endl;
207     QList<GLViewer_Drawer*>::Iterator anIt = myDrawers.begin();
208     QList<GLViewer_Drawer*>::Iterator endDIt = myDrawers.end();
209     for( ; anIt != endDIt; anIt++ )
210         (*anIt)->clear();
211
212     QList<GLViewer_Drawer*> anActiveDrawers;
213     QList<GLViewer_Object*>::Iterator endOIt = theObjects.end();
214
215     for( QList<GLViewer_Object*>::Iterator oit = theObjects.begin(); oit != endOIt; ++oit )
216     {
217         GLViewer_Drawer* aDrawer = (*oit)->getDrawer();
218         if( !aDrawer )
219         {
220             anIt = myDrawers.begin();
221             endDIt = myDrawers.end();
222
223             for( ; anIt != endDIt; anIt++ )
224                 if( (*anIt)->getObjectType() == (*oit)->getObjectType() )
225                 {
226                     (*oit)->setDrawer( *anIt );
227                     aDrawer = *anIt;
228                     break;
229                 }
230
231             if( !aDrawer )
232             {
233                 myDrawers.append( (*oit)->createDrawer() );
234                 aDrawer = (*oit)->getDrawer();
235             }
236         }
237         if ( !aDrawer )
238           continue;
239         aDrawer->addObject( (*oit) );
240
241         int aPriority = aDrawer->getPriority();
242
243         if( anActiveDrawers.indexOf( aDrawer ) != -1 )
244             continue;
245
246         QList<GLViewer_Drawer*>::Iterator aDIt = anActiveDrawers.begin();
247         QList<GLViewer_Drawer*>::Iterator aDEndIt = anActiveDrawers.end();
248         for( ; aDIt != aDEndIt; ++aDIt )
249             if( (*aDIt)->getPriority() > aPriority )
250                 break;
251
252         anActiveDrawers.insert( aDIt, aDrawer );
253     } 
254
255     QList<GLViewer_Drawer*>::Iterator aDIt = anActiveDrawers.begin();
256     QList<GLViewer_Drawer*>::Iterator aDEndIt = anActiveDrawers.end();
257
258     QVector<SUIT_ViewWindow*> views = getViewManager()->getViews();
259     for ( int i = 0, n = views.count(); i < n; i++ )
260     {
261         float xScale, yScale;
262         GLViewer_ViewPort2d* vp = ( GLViewer_ViewPort2d* )((GLViewer_ViewFrame*)views[i])->getViewPort();
263         vp->getScale( xScale, yScale );
264         vp->getGLWidget()->makeCurrent();
265
266         for( ; aDIt != aDEndIt; aDIt++ )
267         {
268             GLViewer_Drawer* aDrawer = *aDIt;
269             if( aDrawer )
270                 aDrawer->create( xScale, yScale, onlyUpdate );
271         }
272 /*
273         // draw border
274         GLViewer_Rect* border = ( ( GLViewer_ViewPort2d* )((GLViewer_ViewFrame*)views[i])->getViewPort() )->getBorder();
275         (*aDIt)->drawRectangle( border, Qt::blue );
276
277         QString coords = QString::number( border->left() ) + " " + QString::number( border->right() ) + " " +
278                          QString::number( border->bottom() ) + " " + QString::number( border->top() );
279         (*aDIt)->drawText( "Border : " + coords, border->left(), border->top() + 10 / yScale,
280                            Qt::blue, &QFont( "Courier", 8, QFont::Normal ), 2 );
281 */
282         if ( swap )
283            vp->getGLWidget()->swapBuffers();
284     }
285
286     ( ( GLViewer_ViewPort2d* )getActiveView()->getViewPort() )->getGLWidget()->makeCurrent();
287 }
288
289 /*!
290   Activates drawer for \param theObject
291 */
292 void GLViewer_Viewer2d::activateDrawer( GLViewer_Object* theObject, bool onlyUpdate, GLboolean swap )
293 {
294   ObjList aList;
295   aList.append( theObject );
296   activateDrawers( aList, onlyUpdate, swap );
297 }
298
299 /*!
300    \param onlyUpdate is passed to drawers
301 */
302 void GLViewer_Viewer2d::activateAllDrawers( bool onlyUpdate, GLboolean swap )
303 {
304     if ( !getActiveView() )
305       return;
306
307     ObjList anActiveObjs;
308     const ObjList& objs = myGLContext->getObjects();
309     for( ObjList::const_iterator it = objs.begin(); it != objs.end(); ++it )
310     {
311       GLViewer_Object* obj = (GLViewer_Object*)(*it);
312       if( obj->getVisible() )
313           anActiveObjs.append( obj );
314     }
315
316     activateDrawers( anActiveObjs, onlyUpdate, swap );
317 }
318
319 /*!
320   Creates set of marker
321   \param theMarkersNum - number of markers 
322   \param theMarkersRad - radius of markers
323 */
324 void GLViewer_Viewer2d::onCreateGLMarkers( int theMarkersNum, int theMarkersRad )
325 {
326     if ( !getActiveView() )
327       return;
328
329     GLViewer_MarkerSet* aMarkerSet = new GLViewer_MarkerSet( theMarkersNum, theMarkersRad );
330     getGLContext()->insertObject( aMarkerSet );
331
332     GLViewer_ViewPort2d* vp = ( GLViewer_ViewPort2d* )getActiveView()->getViewPort();
333     int vpWidth = vp->getWidth();
334     int vpHeight = vp->getHeight();
335
336     float* aXCoord = new float[ theMarkersNum ];
337     float* anYCoord = new float[ theMarkersNum ];
338
339     srand( 1 );
340     for ( long i = 0; i < theMarkersNum; i++ )  
341     {
342         aXCoord[i] = cos( PI * (rand() / (GLfloat)RAND_MAX) ) * ((GLfloat)vpWidth / 2.);
343         anYCoord[i] = cos( PI * (rand() / (GLfloat)RAND_MAX) ) * ((GLfloat)vpHeight / 2.);
344     }
345
346     aMarkerSet->setXCoord( aXCoord, theMarkersNum );
347     aMarkerSet->setYCoord( anYCoord, theMarkersNum );
348     aMarkerSet->compute();
349
350     updateBorders( aMarkerSet->getRect() );
351     
352     activateAllDrawers( false );
353     activateTransform( GLViewer_Viewer::FitAll );
354
355     delete[] aXCoord;
356     delete[] anYCoord;
357 }
358
359 /*!
360   Creates GL polyline
361   \param theAnglesNum - number of angles
362   \param theRadius - radius
363   \param thePolylineNumber - number
364 */
365 void GLViewer_Viewer2d::onCreateGLPolyline( int theAnglesNum, int theRadius, int thePolylineNumber )
366 {
367     if ( !getActiveView() )
368       return;
369
370     GLViewer_ViewPort2d* vp = ( GLViewer_ViewPort2d* )getActiveView()->getViewPort();
371     int vpWidth = vp->getWidth();
372     int vpHeight = vp->getHeight();
373
374     float* aXCoord = new float[ theAnglesNum ];
375     float* anYCoord = new float[ theAnglesNum ];
376
377     //srand( ( unsigned )time( NULL ) );
378     srand( 1 );
379     for( int j = 0; j < thePolylineNumber; j++)
380     {
381         GLViewer_Polyline* aPolyline = new GLViewer_Polyline( theAnglesNum, theRadius );
382         getGLContext()->insertObject( aPolyline );
383
384         float aXOffset = cos( PI * (rand() / (GLfloat)RAND_MAX) ) * ((GLfloat)vpWidth / 2.);
385         float anYOffset = cos( PI * (rand() / (GLfloat)RAND_MAX) ) * ((GLfloat)vpHeight / 2.);
386         for( int i = 0; i < theAnglesNum; i++ )  
387         {
388             aXCoord[i] = cos( 2. * PI * i / theAnglesNum ) * theRadius + aXOffset;
389             anYCoord[i] = sin( 2. * PI * i / theAnglesNum ) * theRadius + anYOffset;
390         }
391
392         aPolyline->setHighSelAll( true );
393         aPolyline->setClosed( true );
394         aPolyline->setXCoord( aXCoord, theAnglesNum );
395         aPolyline->setYCoord( anYCoord, theAnglesNum );
396         aPolyline->compute();
397
398         updateBorders( aPolyline->getRect() );
399     }
400     
401     activateAllDrawers( false );
402     activateTransform( GLViewer_Viewer::FitAll );
403
404     delete[] aXCoord;
405     delete[] anYCoord;
406 }
407
408 /*!
409   Creates text
410   \param theStr - text string
411   \param theTextNumber - number
412 */
413 void GLViewer_Viewer2d::onCreateGLText( QString theStr, int theTextNumber )
414 {
415     if ( !getActiveView() )
416       return;
417
418     if( theTextNumber <= 0 )
419         return;
420     
421     GLViewer_ViewPort2d* vp = ( GLViewer_ViewPort2d* )getActiveView()->getViewPort();
422     int vpWidth = vp->getWidth();
423     int vpHeight = vp->getHeight();
424
425     //srand( ( unsigned )time( NULL ) );
426     srand( 1 );
427     for( int j = 0; j < theTextNumber; j++)
428     {
429         float aXPos = cos( PI * (rand() / (GLfloat)RAND_MAX) ) * ((GLfloat)vpWidth / 2.);
430         float anYPos = cos( PI * (rand() / (GLfloat)RAND_MAX) ) * ((GLfloat)vpHeight / 2.);
431         QColor aColor( 255, 0, 255 );
432
433         GLViewer_TextObject* aText = new GLViewer_TextObject( theStr, aXPos, anYPos, aColor  );
434         aText->compute();
435         getGLContext()->insertObject( aText );
436
437         updateBorders( aText->getRect() );
438     }
439
440     activateAllDrawers( false );
441 }
442
443 /*!
444   Translates point from global CS to curreent viewer CS
445   \param x, y - co-ordinates to be translated
446 */
447 void GLViewer_Viewer2d::transPoint( GLfloat& x, GLfloat& y )
448 {
449     if ( !getActiveView() )
450       return;
451
452     GLfloat xScale, yScale;
453     GLfloat xPan, yPan;
454
455     GLViewer_ViewPort2d* curvp = ( GLViewer_ViewPort2d* )getActiveView()->getViewPort();
456
457     curvp->getScale( xScale, yScale );
458     curvp->getPan( xPan, yPan );
459
460     GLfloat a = curvp->getGLWidget()->getRotationAngle() * PI / 180.;
461     
462     x = (  x - ( GLfloat )curvp->getWidth()  / 2 ) / xScale;
463     y = ( -y + ( GLfloat )curvp->getHeight() / 2 ) / yScale;
464
465     GLfloat x1 = x;
466     GLfloat y1 = y;
467
468     x = x1 * cos(a) + y1 * sin(a);
469     y = -x1 * sin(a) + y1 * cos(a);
470
471     x -= xPan;
472     y -= yPan;
473 }
474
475 /*!
476   \return object rect in window CS
477   \param theObject - object
478 */
479 QRect* GLViewer_Viewer2d::getWinObjectRect( GLViewer_Object* theObject )
480 {
481     if ( !getActiveView() )
482       return 0;
483
484     GLfloat xScale, yScale;
485     GLfloat xPan, yPan;
486
487     GLViewer_ViewPort2d* curvp = ( GLViewer_ViewPort2d* )getActiveView()->getViewPort();
488     GLfloat aWidth = curvp->getWidth();
489     GLfloat aHeight = curvp->getHeight();
490
491
492     curvp->getScale( xScale, yScale );
493     curvp->getPan( xPan, yPan );
494
495     QRect aObjRect = theObject->getRect()->toQRect();
496     float aLeft = aObjRect.left() + xPan, aRight = aObjRect.right() + xPan;
497     float aTop = aObjRect.top() + yPan, aBot = aObjRect.bottom() + yPan;
498
499     GLfloat anAngle = curvp->getGLWidget()->getRotationAngle() * PI / 180.;
500
501     QPolygon aPointArray(4);
502     aPointArray[0] = QPoint( (int)(aLeft*cos(anAngle) - aTop*sin(anAngle)),
503                              (int)(aLeft*sin(anAngle) + aTop*cos(anAngle)) );
504     aPointArray[1] = QPoint( (int)(aRight*cos(anAngle) - aTop*sin(anAngle)),
505                              (int)(aRight*sin(anAngle) + aTop*cos(anAngle)) );
506     aPointArray[2] = QPoint( (int)(aRight*cos(anAngle) - aBot*sin(anAngle)),
507                              (int)(aRight*sin(anAngle) + aBot*cos(anAngle)) );
508     aPointArray[3] = QPoint( (int)(aLeft*cos(anAngle) - aBot*sin(anAngle)),
509                              (int)(aLeft*sin(anAngle) + aBot*cos(anAngle)) );
510
511     int aMinLeft = aPointArray[0].x(), aMaxRight = aPointArray[0].x(), 
512         aMinTop = aPointArray[0].y(), aMaxBottom = aPointArray[0].y();
513     for( int i = 1; i < 4; i++ )
514     {
515         int x = aPointArray[i].x();
516         int y = aPointArray[i].y();
517         aMinLeft = qMin( aMinLeft,x );
518         aMaxRight = qMax( aMaxRight, x );
519         aMinTop = qMin( aMinTop, y );
520         aMaxBottom = qMax( aMaxBottom, y );
521     }
522
523     aLeft = (aMinLeft/* + xPan*/)*xScale + aWidth / 2;
524     aRight = (aMaxRight/* + xPan*/)*xScale + aWidth / 2;
525
526     aTop = -( (aMaxBottom/* + yPan*/)*yScale - aHeight / 2 );
527     aBot = -( (aMinTop/* + yPan*/)*yScale - aHeight / 2 );    
528
529     QRect* newRect = new QRect( (int)aLeft, (int)aTop, (int)(aRight-aLeft), (int)(aBot-aTop) );
530     
531     return newRect;
532 }
533
534 /*!
535   Translates rect in window CS to rect in global CS
536   \param theRect - rectangle to be translated
537   \return transformed rect
538 */
539 GLViewer_Rect GLViewer_Viewer2d::getGLVRect( const QRect& theRect ) const
540 {
541   if ( !getActiveView() )
542       return GLViewer_Rect();
543
544   GLViewer_ViewPort2d* vp = ( GLViewer_ViewPort2d* )getActiveView()->getViewPort();
545
546   if( !vp )
547     return GLViewer_Rect();
548
549   return vp->win2GLV( theRect );
550 }
551
552 /*!
553   Translates rect in global CS to rect in window CS
554   \param theRect - rectangle to be translated
555   \return transformed rect
556 */
557 QRect GLViewer_Viewer2d::getQRect( const GLViewer_Rect& theRect ) const
558 {
559   if ( !getActiveView() )
560       return QRect();
561
562   GLViewer_ViewPort2d* vp = ( GLViewer_ViewPort2d* )getActiveView()->getViewPort();
563
564   if( !vp )
565     return QRect();
566
567   return vp->GLV2win( theRect );
568 }
569
570 /*!
571   \return new selector
572 */
573 GLViewer_Selector* GLViewer_Viewer2d::createSelector()
574 {
575   return new GLViewer_Selector2d( this, getGLContext() );
576 }
577
578 /*!
579   \return new Transformer 
580   \param type - type of new transformer
581 */
582 GLViewer_ViewTransformer* GLViewer_Viewer2d::createTransformer( int type )
583 {
584     return new GLViewer_View2dTransformer( this, type );
585 }
586
587 /*!
588   Custom mouse event handler
589 */
590 void GLViewer_Viewer2d::onMouseEvent( SUIT_ViewWindow*, QMouseEvent* e )
591 {
592     if ( !getActiveView() )
593         return;
594
595     //if ( testRotation( e ) )
596     //    return;
597
598     switch( e->type() )
599     {
600         case QEvent::MouseButtonPress :
601         case QEvent::MouseMove :
602         case QEvent::MouseButtonRelease :
603             //if( myGLSketcher->getType() != None )
604             //    myGLSketcher->sketch( e );
605         default: break;
606     }
607
608     GLViewer_Viewer::onMouseEvent( 0, e );
609 }
610
611 /*!
612   Rotation transformation
613 */
614 bool GLViewer_Viewer2d::testRotation( QMouseEvent* e )
615 {
616   if ( ( (int)e->button() == GLViewer_View2dTransformer::rotateButton() ) && // todo Qt::MouseButton is unsigned int: comparison of int with uint
617          ( e->type() == QEvent::MouseButtonPress ) &&
618          ( e->modifiers() & GLViewer_ViewTransformer::accelKey() ) )
619     {
620         activateTransform( GLViewer_Viewer::Rotate );
621         return true;
622     }
623     return false;
624 }
625
626 /*!
627   Inserts text lines as header for file
628   \param aType - file type
629   \param hFile - file instance
630 */
631 void GLViewer_Viewer2d::insertHeader( VectorFileType aType, QFile& hFile )
632 {
633     if( aType == POST_SCRIPT )
634     {
635         QString header = "%!PS-Adobe-3.0\n";
636         header += "%%Creator: OpenCascade 2004\n";
637         header += "%%Title: Our document\n";        
638         header += "%%PageOrder: Ascend\n";      
639         header += "%%Orientation: Portrait\n";
640         header += "%%LanguageLevel: 2\n";
641
642         header += "%%Pages: 1\n";
643         header += "%%Page: 1\n\n";
644         
645         hFile.write( header.toLatin1() );
646     }
647     else if( aType == HPGL )
648     {
649         QString header = "[Esc].(;\n";
650         header += "[Esc].I81;;17:\n";
651         header += "[Esc].N;19:\n";
652         header += "IN;\n";
653         header += "SC;\n";
654         header += "PU;\n";
655         header += "SP1;\n";
656         header += "LT;\n";
657         header += "VS36;\n";
658         
659         hFile.write( header.toLatin1() );
660     }
661 }
662
663 /*!
664   Inserts text lines as ending for file
665   \param aType - file type
666   \param hFile - file instance
667 */
668 void GLViewer_Viewer2d::insertEnding( VectorFileType aType, QFile& hFile )
669 {
670     if( aType == POST_SCRIPT )
671     {
672         QString ending = "showpage\n\n%%EOF";
673         hFile.write( ending.toLatin1() );
674     }
675     else if( aType == HPGL )
676     {
677         QString ending = "PU;PA0,0;SP;EC;PG1;EC1;OE\n"; 
678         hFile.write( ending.toLatin1() );
679     }
680 }
681
682 inline void mm2custom( GLViewer_Viewer2d::VectorFileType aType, double& value )
683 {
684     if( aType==GLViewer_Viewer2d::POST_SCRIPT )
685         value*=2.8346; //mm to pt
686
687     else if( aType==GLViewer_Viewer2d::HPGL )
688         value*=40;     //mm to plu (there are 40 plues in mm)
689 #ifdef WIN32
690     else if( aType==GLViewer_Viewer2d::ENH_METAFILE )
691         value*=100;    //this unit is 1/100 mm
692 #endif 
693 }
694
695 /*!
696   Translates current view content to vector file
697   \param aType - type of file
698   \param FileName - name of file,
699   \param aPType - paper size type
700   \param mmLeft, mmRight, mmTop, mmBottom - margins
701 */
702 bool GLViewer_Viewer2d::translateTo( VectorFileType aType, QString FileName, PaperType aPType, 
703                                   double mmLeft, double mmRight, double mmTop, double mmBottom )
704 {
705     if ( !getActiveView() )
706       return false;
707
708         QFile hFile( FileName.toUtf8() );
709
710 #ifdef WIN32
711     HDC hMetaFileDC;
712 #endif
713
714     GLViewer_ViewPort2d* aCurVP = (GLViewer_ViewPort2d*) getActiveView()->getViewPort();
715
716     GLfloat xPan, yPan;
717     aCurVP->getPan( xPan, yPan );
718     GLfloat aRotation = aCurVP->getGLWidget()->getRotationAngle() * 3.14159265 / 180.0;
719
720     GLViewer_CoordSystem aViewerCS( GLViewer_CoordSystem::Cartesian, xPan, yPan, 1.0, 1.0, aRotation );
721
722     double AW = Sizes[2*int(aPType)], 
723            AH = Sizes[2*int(aPType)+1]; //size of Axx paper in mm
724
725     mm2custom( aType, mmLeft ); //we translate mm to custom units
726     mm2custom( aType, mmRight );
727     mm2custom( aType, mmTop );
728     mm2custom( aType, mmBottom );
729     mm2custom( aType, AW );
730     mm2custom( aType, AH );
731
732     float xScale, yScale;
733     aCurVP->getScale( xScale, yScale );
734
735     double VPWidth = aCurVP->getWidth()/xScale,   //the width in reference units
736            VPHeight = aCurVP->getHeight()/yScale;
737
738     double k1 = ( AW-mmLeft-mmRight ) / VPWidth,
739            k2 = ( AH-mmTop-mmBottom ) / VPHeight;
740
741     if( k1>k2 )
742         k1 = k2; //We select the minimum
743
744     double hdelta = ( AW-mmLeft-mmRight - VPWidth * k1 )/2.0, //addition in horizontal
745            vdelta = ( AH-mmTop-mmBottom - VPHeight * k1 )/2.0; //addition in vertical
746
747     mmLeft   += hdelta; //The real free space on the left and right borders
748     mmRight  += hdelta;
749     mmTop    += vdelta;
750     mmBottom += vdelta;
751
752     GLViewer_CoordSystem aPaperCS( GLViewer_CoordSystem::Cartesian, 
753         -(mmLeft/k1+VPWidth/2.0), -(mmBottom/k1+VPHeight/2.0), 1/k1, 1/k1 );
754
755     if( aType==POST_SCRIPT || aType==HPGL )
756     {
757         hFile.open( QIODevice::ReadWrite | QIODevice::Truncate );
758         hFile.seek( 0 );
759         insertHeader( aType, hFile );
760     }
761 #ifdef WIN32
762     else if( aType==ENH_METAFILE )
763     {
764         RECT r; 
765         r.left = 0; r.right = AW; 
766         r.top = 0; r.bottom = AH; 
767         HDC screen_dc = GetDC( 0 ); //The screen device context
768         HDC bitDC = CreateCompatibleDC ( screen_dc ); //The context compatible with screen
769
770 #ifdef UNICODE
771         LPTSTR str = new TCHAR[FileName.length() + 1];
772         str[FileName.toWCharArray(str)] = '\0';
773         LPTSTR empty = L"";
774 #else  
775         QByteArray arr = FileName.toLatin1();
776         LPTSTR str = arr.constData();
777         LPTSTR empty = "";
778 #endif
779
780         hMetaFileDC = CreateEnhMetaFile( bitDC, str, &r, empty );
781 #ifdef UNICODE
782         delete str;
783 #endif 
784         SetMapMode( hMetaFileDC, MM_HIMETRIC );
785         SetWindowOrgEx( hMetaFileDC, 0, r.bottom, NULL );
786         HRGN ClipRgn = CreateRectRgn( 0, 0, AW, AH );
787         SelectClipRgn( hMetaFileDC, ClipRgn );
788
789         LOGBRUSH aBrushData;
790         aBrushData.lbColor = RGB( 255, 255, 255 );      
791         aBrushData.lbStyle = BS_SOLID;
792
793         FillRect( hMetaFileDC, &r, CreateBrushIndirect( &aBrushData ) );
794
795         ReleaseDC( 0, screen_dc );
796         DeleteDC( bitDC );
797
798         aCurVP->getGLWidget()->translateBackgroundToEMF( hMetaFileDC, &aViewerCS, &aPaperCS );  
799     }
800 #endif
801
802     if( aType==POST_SCRIPT )
803     {
804         QString temp = "%1 %2 %3 %4 rectclip\n\n",
805                 aBuffer = temp.arg( mmLeft ).arg( mmBottom ).
806                                arg( AW-mmLeft-mmRight ).arg( AH-mmBottom-mmTop );
807         //It is set clipping path
808
809         hFile.write( aBuffer.toLatin1() );
810
811         aCurVP->getGLWidget()->translateBackgroundToPS( hFile, &aViewerCS, &aPaperCS );
812     }
813
814     bool result = true;
815     for( int i=0, n=myDrawers.count(); i<n; i++ )
816         if( aType==POST_SCRIPT )
817             result &= myDrawers[ i ]->translateToPS( hFile, &aViewerCS, &aPaperCS );
818         else if( aType==HPGL )
819             result &= myDrawers[ i ]->translateToHPGL( hFile, &aViewerCS, &aPaperCS );
820 #ifdef WIN32
821         else if( aType==ENH_METAFILE )
822             result &= myDrawers[ i ]->translateToEMF( hMetaFileDC, &aViewerCS, &aPaperCS );
823 #endif
824
825     if( aType==POST_SCRIPT || aType==HPGL )
826     {
827         insertEnding( aType, hFile);
828         hFile.close();
829     }
830 #ifdef WIN32
831     else if( aType==ENH_METAFILE )  
832         DeleteEnhMetaFile( CloseEnhMetaFile( hMetaFileDC ) );
833 #endif
834
835     return true;
836 }
837
838 /*!
839   Repaints view
840   \param theView - view to be repainted. If it is NULL then all views will be repainted
841 */
842 void GLViewer_Viewer2d::repaintView( GLViewer_ViewFrame* theView, bool makeCurrent )
843 {
844     GLViewer_ViewFrame* aCurView;
845     if( !theView )
846         aCurView = (GLViewer_ViewFrame*)getActiveView();
847     else
848         aCurView = theView;
849     
850     if ( !aCurView )
851       return;
852
853     ObjList anActiveObjs;
854     const ObjList& objs = myGLContext->getObjects();
855     for( ObjList::const_iterator it = objs.begin(); it != objs.end(); ++it )
856     {
857       GLViewer_Object* obj = (GLViewer_Object*)(*it);
858       if( obj->getVisible() )
859           anActiveObjs.append( obj );
860     }
861
862     float xScale;
863     float yScale;
864
865     QList<GLViewer_Drawer*>::Iterator anIt = myDrawers.begin();
866     QList<GLViewer_Drawer*>::Iterator endDIt = myDrawers.end();
867     for( ; anIt != endDIt; anIt++ )
868             (*anIt)->clear();
869
870     QList<GLViewer_Drawer*> anActiveDrawers;
871     QList<GLViewer_Object*>::Iterator endOIt = anActiveObjs.end();
872
873     for( QList<GLViewer_Object*>::Iterator oit = anActiveObjs.begin(); oit != endOIt; ++oit )
874     {
875         GLViewer_Drawer* aDrawer = (*oit)->getDrawer();
876         if( !aDrawer )
877         {
878             anIt = myDrawers.begin();            
879
880             for( ; anIt != endDIt; anIt++ )
881                 if( (*anIt)->getObjectType() == (*oit)->getObjectType() )
882                 {
883                     (*oit)->setDrawer( *anIt );
884                     aDrawer = *anIt;
885                     break;
886                 }
887
888             if( !aDrawer ) //are not exists
889             {
890                 myDrawers.append( (*oit)->createDrawer() );
891                 aDrawer = (*oit)->getDrawer();
892             }
893         }
894         aDrawer->addObject( (*oit) );
895         if( anActiveDrawers.indexOf( aDrawer ) == -1 )
896             anActiveDrawers.append( aDrawer );
897     } 
898
899     QList<GLViewer_Drawer*>::Iterator aDIt = anActiveDrawers.begin();
900     QList<GLViewer_Drawer*>::Iterator aDEndIt = anActiveDrawers.end();
901
902     GLViewer_ViewPort2d* vp = ( GLViewer_ViewPort2d* )aCurView->getViewPort();
903     vp->getScale( xScale, yScale );
904
905     if( makeCurrent )
906         vp->getGLWidget()->makeCurrent();
907
908     for( ; aDIt != aDEndIt; aDIt++ )
909         (*aDIt)->create( xScale, yScale, false );
910     
911 //    if ( swap )
912     vp->getGLWidget()->swapBuffers();
913
914 //    ( ( GLViewer_ViewPort2d* )getActiveView()->getViewPort() )->getGLWidget()->makeCurrent();
915 }
916
917 /*!
918   Starts some operation on mouse event
919 */
920 void GLViewer_Viewer2d::startOperations( QMouseEvent* e )
921 {
922     GLViewer_ViewPort2d* vp = ( GLViewer_ViewPort2d* )((GLViewer_ViewFrame*)getActiveView())->getViewPort();
923
924     float x = e->pos().x();
925     float y = e->pos().y();
926     transPoint( x, y );
927     GLViewer_Pnt point( x, y );
928
929     if( e->button() == Qt::LeftButton && !myGLContext->getCurrentObject() && vp->startPulling( point ) )
930         return;
931
932     if( e->button() == Qt::LeftButton && !(vp->currentBlock() & BS_Selection) && !myGLContext->getCurrentObject() )
933         vp->startSelectByRect( e->x(), e->y() );
934 }
935
936 /*!
937   Updates started operation on mouse event
938 */
939 bool GLViewer_Viewer2d::updateOperations( QMouseEvent* e )
940 {
941     GLViewer_ViewPort2d* vp = ( GLViewer_ViewPort2d* )((GLViewer_ViewFrame*)getActiveView())->getViewPort();
942
943     if( vp->isPulling() )
944     {
945         float x = e->pos().x();
946         float y = e->pos().y();
947         transPoint( x, y );
948
949         vp->drawPulling( GLViewer_Pnt( x, y ) );
950         updateAll();
951         return true;
952     }
953
954     if( !myGLContext->getCurrentObject() )
955     {
956         vp->drawSelectByRect( e->x(), e->y() );
957         return true;
958     }
959     return false;
960 }
961
962 /*!
963   Completes started operation on mouse event
964 */
965 void GLViewer_Viewer2d::finishOperations( QMouseEvent* e )
966 {
967     GLViewer_ViewPort2d* vp = ( GLViewer_ViewPort2d* )((GLViewer_ViewFrame*)getActiveView())->getViewPort();
968
969     if( vp->isPulling() )
970     {
971         vp->finishPulling();
972         updateAll();
973         return;
974     }
975
976     if( !myGLContext->getCurrentObject() )
977     {
978         QRect aSelRect = vp->selectionRect();
979         vp->finishSelectByRect();
980         if ( getSelector() && !aSelRect.isNull() )
981         {            
982             bool append = bool ( e->modifiers() & GLViewer_Selector::appendKey() );
983             getSelector()->select( aSelRect, append );
984         }
985     }
986 }
987
988 /*!
989   Starts some operation on mouse wheel event
990 */
991 void GLViewer_Viewer2d::startOperations( QWheelEvent* e )
992 {
993     bool zoomIn = e->delta() > 0;
994     bool update = false;
995     for( myGLContext->InitSelected(); myGLContext->MoreSelected(); myGLContext->NextSelected() )
996     {
997         GLViewer_Object* anObject = myGLContext->SelectedObject();
998         update = anObject->updateZoom( zoomIn ) || update;
999     }
1000
1001     emit wheelZoomChange( zoomIn );
1002
1003     if( update )
1004         updateAll();
1005 }
1006
1007
1008 int GLViewer_View2dTransformer::rotateBtn = Qt::RightButton;
1009
1010 /*!
1011   Constructor
1012 */
1013 GLViewer_View2dTransformer::GLViewer_View2dTransformer( GLViewer_Viewer* viewer, int typ )
1014 : GLViewer_ViewTransformer( viewer, typ )
1015 {
1016     if ( type() == GLViewer_Viewer::Rotate )
1017         initTransform( true );
1018 }
1019
1020 /*!
1021   Destructor
1022 */
1023 GLViewer_View2dTransformer::~GLViewer_View2dTransformer()
1024 {
1025     if ( type() == GLViewer_Viewer::Rotate )
1026         initTransform( false );
1027 }
1028
1029 /*!
1030     Redefined to provide specific 3D transfomations. [ virtual public ]
1031 */
1032 void GLViewer_View2dTransformer::exec()
1033 {
1034     if ( !myViewer->getActiveView() )
1035       return;
1036
1037     /* additional transforms */
1038     GLViewer_ViewPort* vp = myViewer->getActiveView()->getViewPort();
1039     GLViewer_ViewPort2d* avp = (GLViewer_ViewPort2d*)vp;
1040     switch ( myType )
1041     {
1042         case GLViewer_Viewer::Rotate:
1043             myMajorBtn = rotateButton();
1044             avp->setCursor( *avp->getRotCursor() );
1045             break;
1046         default:
1047             GLViewer_ViewTransformer::exec();
1048     }
1049 }
1050
1051 /*!
1052     Handles rotation. [ protected virtual ]
1053 */
1054 void GLViewer_View2dTransformer::onTransform( TransformState state )
1055 {
1056     if ( !myViewer->getActiveView() )
1057       return;
1058
1059     GLViewer_ViewPort* vp = myViewer->getActiveView()->getViewPort();
1060     GLViewer_ViewPort2d* avp = (GLViewer_ViewPort2d*)vp;
1061     if ( type() == GLViewer_Viewer::Rotate )
1062     {
1063         switch ( state )
1064         {
1065             case Debut:
1066                 if ( myButtonState & myMajorBtn )
1067                     avp->startRotation( myStart.x(), myStart.y() );
1068                 break;
1069             case EnTrain:
1070                 if ( myButtonState & myMajorBtn )
1071                     avp->rotate( myCurr.x(), myCurr.y() );
1072                 break;
1073             case Fin:
1074                 avp->endRotation();
1075                 break;
1076             default: break;
1077         }
1078     }
1079     GLViewer_ViewTransformer::onTransform( state );
1080 }