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