Salome HOME
Update from BR_V5_DEV 13Feb2009
[modules/gui.git] / src / GLViewer / GLViewer_ViewPort2d.cxx
1 //  Copyright (C) 2007-2008  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.
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 //  Author : OPEN CASCADE
23 // File:      GLViewer_ViewPort2d.cxx
24 // Created:   November, 2004
25 //
26 /* GLViewer_ViewPort2d Source File */
27
28 //#include <GLViewerAfx.h>
29 #include "GLViewer_ViewPort2d.h"
30 #include "GLViewer_Viewer2d.h"
31 #include "GLViewer_ViewFrame.h"
32 #include "GLViewer_MimeData.h"
33 #include "GLViewer_Context.h"
34 #include "GLViewer_Compass.h"
35 #include "GLViewer_Grid.h"
36 #include "GLViewer_Drawer.h"
37
38 // TODO: Porting to Qt4
39 //#include <QtxToolTip.h>
40
41 #include <QHBoxLayout>
42 #include <QMouseEvent>
43 #include <QRect>
44 //#include <QMenu>
45 //#include <QToolTip>
46 #include <QApplication>
47 #include <QClipboard>
48 #include <QBitmap>
49 #include <QLabel>
50 #include <QWidget>
51 #include <QRubberBand>
52
53 #define WIDTH       640
54 #define HEIGHT      480
55 #define MARGIN      100
56
57 #define GRID_XSIZE  100
58 #define GRID_YSIZE  100
59
60 int static aLastViewPostId = 0;
61
62 void rotate_point( float& theX, float& theY, float theAngle )
63 {
64     float aTempX = theX * cos(theAngle) - theY * sin(theAngle);
65     float aTempY = theX * sin(theAngle) + theY * cos(theAngle);
66     theX = aTempX;
67     theY = aTempY;
68 }
69
70 /*!
71   Constructor
72 */
73 GLViewer_ViewPort2d::GLViewer_ViewPort2d( QWidget* parent, GLViewer_ViewFrame* theViewFrame )
74 : GLViewer_ViewPort( parent ),
75   myMargin( MARGIN ), myWidth( WIDTH ), myHeight( HEIGHT ),
76   myXScale( 1.0 ), myYScale( 1.0 ), myXOldScale( 1.0 ), myYOldScale( 1.0 ),
77   myXPan( 0.0 ), myYPan( 0.0 ),
78   myIsMouseReleaseBlock( false ),
79   myRectBand( 0 )
80 {
81   if ( !theViewFrame )
82     myViewFrame = (GLViewer_ViewFrame*)parent;
83   else
84     myViewFrame = theViewFrame;
85
86   myGrid = 0;
87   myCompass = 0;
88   myBorder = new GLViewer_Rect();
89
90   QBoxLayout* qbl = new QHBoxLayout( this );
91   qbl->setSpacing( 0 );
92   qbl->setMargin( 0 );
93
94   myGLWidget = new GLViewer_Widget( this, 0 ) ;
95   qbl->addWidget( myGLWidget );
96   myGLWidget->setFocusProxy( this );
97   setMouseTracking( TRUE );
98
99   myIsDragProcess = noDrag;
100   //myCurDragMousePos = QPoint();
101   myCurDragPosX = NULL;
102   myCurDragPosY = NULL;
103
104   myIsPulling = false;
105
106   myViewPortId = aLastViewPostId;
107   aLastViewPostId++;
108
109   mypFirstPoint = NULL;
110   mypLastPoint = NULL;
111
112     // TODO: Porting to Qt4
113     /*myObjectTip = new QtxToolTip( myGLWidget );///GLViewer_ObjectTip( this );
114     myObjectTip->setShowDelayTime( 60000 );
115     connect( myObjectTip, SIGNAL( maybeTip( QPoint, QString&, QFont&, QRect&, QRect& ) ),
116              this, SLOT( onMaybeTip( QPoint, QString&, QFont&, QRect&, QRect& ) ) );*/
117 //    myGLWidget->installEventFilter( myObjectTip );
118 }
119
120 /*!
121   Destructor
122 */
123 GLViewer_ViewPort2d::~GLViewer_ViewPort2d()
124 {
125     if( myCompass )
126         delete myCompass;
127
128     if( myGrid )
129         delete myGrid;
130
131     delete myBorder;
132     delete myGLWidget;
133
134     if ( myRectBand ) myRectBand->hide();
135     delete myRectBand;
136 }
137
138 /*!
139   SLOT: initializes drag process
140 */
141 void GLViewer_ViewPort2d::onStartDragObject( )
142 {
143     if( myIsDragProcess == noDrag )
144     {
145         myIsDragProcess = initDrag;
146         QCursor::setPos( (int)(*myCurDragPosX), (int)(*myCurDragPosY) );
147         //myCurDragMousePos = QPoint( 0, 0 );
148         delete myCurDragPosX;
149         delete myCurDragPosY;
150         myCurDragPosX = NULL;
151         myCurDragPosY = NULL;
152         return;
153     }
154 }
155
156 /*!
157   SLOT: cuts object to clipboard
158 */
159 void GLViewer_ViewPort2d::onCutObject()
160 {
161     /*GLViewer_Object* aMovingObject = ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext()->getCurrentObject();
162     if( aMovingObject )
163     {
164         GLViewer_MimeSource* aMimeSource = new GLViewer_MimeSource();
165         aMimeSource->setObject( aMovingObject );
166
167         QClipboard *aClipboard = QApplication::clipboard();
168         aClipboard->clear();
169         aClipboard->setData( aMimeSource );
170
171         ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext()->deleteObject( aMovingObject );
172     }*/
173     GLViewer_Context* aContext = ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext();
174     int aObjNum = aContext->NbSelected();
175     if( aObjNum > 0 )
176     {
177         QList<GLViewer_Object*> aObjects;
178         GLViewer_MimeData* aMimeData = new GLViewer_MimeData();
179         aContext->InitSelected();
180         for( ; aContext->MoreSelected(); aContext->NextSelected() )
181             aObjects.append( aContext->SelectedObject() );
182
183         //aMimeData->setObjects( aObjects ); ouv 6.05.04
184
185         QClipboard *aClipboard = QApplication::clipboard();
186         aClipboard->clear();
187         aClipboard->setMimeData( aMimeData );
188
189         for( int i = 0; i < aObjNum; i++ )
190             aContext->deleteObject( aObjects[i] );
191     }
192 }
193
194 /*!
195   SLOT: copies object to clipboard
196 */
197 void GLViewer_ViewPort2d::onCopyObject()
198 {
199     /*GLViewer_Object* aMovingObject = ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext()->getCurrentObject();
200     if( aMovingObject )
201     {
202         GLViewer_MimeSource* aMimeSource = new GLViewer_MimeSource();
203         aMimeSource->setObject( aMovingObject );
204
205         QClipboard *aClipboard = QApplication::clipboard();
206         aClipboard->clear();
207         aClipboard->setData( aMimeSource );
208     }
209     */
210     GLViewer_Context* aContext = ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext();
211     int aObjNum = aContext->NbSelected();
212     if( aObjNum > 0 )
213     {
214         QList<GLViewer_Object*> aObjects;
215         GLViewer_MimeData* aMimeData = new GLViewer_MimeData();
216         aContext->InitSelected();
217         for( ; aContext->MoreSelected(); aContext->NextSelected() )
218             aObjects.append( aContext->SelectedObject() );
219
220         //aMimeData->setObjects( aObjects ); ouv 6.05.04
221
222         QClipboard *aClipboard = QApplication::clipboard();
223         aClipboard->clear();
224         aClipboard->setMimeData( aMimeData );
225     }
226 }
227
228 /*!
229   SLOT: pastes object from clipboard
230 */
231 void GLViewer_ViewPort2d::onPasteObject()
232 {
233     /*QClipboard *aClipboard = QApplication::clipboard();
234     QMimeSource* aMimeSource = aClipboard->data();
235     if( aMimeSource->provides( "GLViewer_Object" ) )
236     {
237         const char* aType;
238         int i = 1;
239         QByteArray anArray;
240         do
241         {
242             aType = aMimeSource->format( i );
243             anArray = aMimeSource->encodedData( aType );
244             if( anArray.size() != 0 )
245                 break;
246             i++;
247         }
248         while( aType != 0 );
249         if( anArray.size() == 0 )
250             return;
251
252         GLViewer_Object* aObject = GLViewer_MimeSource::getObject( anArray, aType );
253         if( !aObject )
254             return;
255
256         ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext()->insertObject( aObject, true );
257     }
258     */
259     /* ouv 6.05.04
260     QClipboard *aClipboard = QApplication::clipboard();
261
262     QMimeSource* aMimeSource = aClipboard->data();
263     if( aMimeSource->provides( "GLViewer_Objects" ) )
264     {
265         QByteArray anArray = aMimeSource->encodedData( "GLViewer_Objects" );
266         QList<GLViewer_Object*> aObjects = GLViewer_MimeSource::getObjects( anArray, "GLViewer_Objects" );
267         if( aObjects.empty() )
268             return;
269         GLViewer_Context* aContext = ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext();
270         for( int i = 0; i < aObjects.count(); i++ )
271             aContext->insertObject( aObjects[i], true );
272     }
273     */
274 }
275
276 /*!
277   SLOT: called when object is being dragged
278 */
279 void GLViewer_ViewPort2d::onDragObject( QMouseEvent* e )
280 {
281   //cout << "---GLViewer_ViewPort2d::onDragObject()---" << endl;
282   GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
283   GLViewer_Context* aContext = aViewer->getGLContext();
284   GLViewer_Object* anObject = aContext->getCurrentObject();
285
286   if( !aContext )
287     return;
288
289   float aX = e->pos().x();
290   float anY = e->pos().y();
291   aViewer->transPoint( aX, anY );
292
293   if( myCurDragPosX == NULL && myCurDragPosY == NULL )
294   {
295     myCurDragPosX = new float(aX);
296     myCurDragPosY = new float(anY);
297     return;
298   }
299
300   //QPoint aNewPos = e->pos();
301   //GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
302
303   if( anObject && (e->buttons() & Qt::LeftButton ) )
304   {
305     if( aContext->isSelected( anObject ) )
306     {
307       for( aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected() )
308       {
309         GLViewer_Object* aMovingObject = aContext->SelectedObject();
310         if( aMovingObject )
311           aMovingObject->moveObject( aX - *myCurDragPosX, anY - *myCurDragPosY);
312       }
313     }
314     else
315       anObject->moveObject( aX - *myCurDragPosX, anY - *myCurDragPosY);
316   }
317   else if( aContext->NbSelected() && (e->buttons() & Qt::MidButton ) )
318     for( aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected() )
319         (aContext->SelectedObject())->moveObject( aX - *myCurDragPosX, anY - *myCurDragPosY);
320
321   delete myCurDragPosX;
322   delete myCurDragPosY;
323   myCurDragPosX = new float(aX);
324   myCurDragPosY = new float(anY);
325
326   myGLWidget->updateGL();
327 }
328
329 /*!
330     Emits 'mouseEvent' signal. [ virtual protected ]
331 */
332 void GLViewer_ViewPort2d::mousePressEvent( QMouseEvent* e )
333 {
334     emit vpMouseEvent( e );
335
336     GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
337     GLViewer_Context* aContext = aViewer->getGLContext();
338
339     GLViewer_Object* anObject = NULL;
340     if( aContext )
341         anObject = aContext->getCurrentObject();
342
343     bool accel = e->modifiers() & GLViewer_ViewTransformer::accelKey();
344     if( ( anObject && !( accel || e->button() == Qt::RightButton ) ) ||
345         ( aContext->NbSelected() && !accel && e->button() == Qt::MidButton )  )
346     {
347         myIsDragProcess = inDrag;
348     }
349 }
350
351 /*!
352     Emits 'mouseEvent' signal. [ virtual protected ]
353 */
354 void GLViewer_ViewPort2d::mouseMoveEvent( QMouseEvent* e )
355 {
356     emit vpMouseEvent( e );
357
358     if( myIsDragProcess == inDrag )
359         onDragObject( e );
360
361     /*GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
362     GLViewer_Context* aContext = aViewer->getGLContext();
363
364     GLViewer_Object* anObj = aContext->getCurrentObject();
365     if( anObj && aContext->currentObjectIsChanged() )
366     {
367         //cout << "GLViewer_ViewPort2d::mouseMoveEvent{QToolTip::add}" << endl;
368         //QToolTip::remove( myGLWidget );
369         QRect* aRect = (aViewer->getWinObjectRect(anObj));
370         //QToolTip::add( myGLWidget, *aRect, anObj->getToolTipText() );
371         myGLWidget->addToolTip( anObj->getToolTipText(), *aRect );
372     }
373     if(!anObj)
374     {
375         //cout << "GLViewer_ViewPort2d::mouseMoveEvent{QToolTip::remove}" << endl;
376         //QRect* aRect = (aViewer->getWinObjectRect(anObj));
377         //QToolTip::remove( myGLWidget, *aRect );
378         myGLWidget->removeToolTip();
379     }*/
380 }
381
382 /*!
383     Emits 'mouseEvent' signal. [ virtual protected ]
384 */
385 void GLViewer_ViewPort2d::mouseReleaseEvent( QMouseEvent* e )
386 {
387     if ( myIsMouseReleaseBlock )
388     {
389       // skip mouse release after double click
390       myIsMouseReleaseBlock = false;
391       return;
392     }
393
394     /* show popup menu */
395     if ( e->button() == Qt::RightButton )
396     {
397         //QPopupMenu* popup = createPopup();
398         //if ( popup && popup->count() )
399         //    popup->exec( QCursor::pos() );
400         //destroyPopup( /*popup*/ );
401     }
402     emit vpMouseEvent( e );
403
404     if( myIsDragProcess == inDrag )
405     {
406       bool isAnyMoved = false;
407       GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
408       GLViewer_Context* aContext = aViewer->getGLContext();
409       GLViewer_Object* aMovingObject;
410       for( aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected() )
411       {
412         aMovingObject = aContext->SelectedObject();
413         if( aMovingObject )
414           isAnyMoved = aMovingObject->finishMove() || isAnyMoved;
415       }
416
417       aMovingObject = aContext->getCurrentObject();
418       if( aMovingObject )
419         isAnyMoved = aMovingObject->finishMove() || isAnyMoved;
420
421       myIsDragProcess = noDrag;
422       //myCurDragMousePos.setX( 0 );
423       //myCurDragMousePos.setY( 0 );
424       delete myCurDragPosX;
425       delete myCurDragPosY;
426       myCurDragPosX = NULL;
427       myCurDragPosY = NULL;
428
429       if( isAnyMoved )
430       {
431         emit objectMoved();
432         aViewer->updateBorders();
433       }
434     }
435 }
436
437 /*!
438   Custom mouse double click event handler
439 */
440 void GLViewer_ViewPort2d::mouseDoubleClickEvent( QMouseEvent * e )
441 {
442   //redefined to block mouse release after mouse double click
443   myIsMouseReleaseBlock = true;
444   // invoke base implementation
445   GLViewer_ViewPort::mouseDoubleClickEvent( e );
446 }
447
448 /*!
449   Creates or deletes compass
450   \param on - if it is true, then to create
451 */
452 void GLViewer_ViewPort2d::turnCompass( GLboolean on )
453 {
454     if( on )
455         myCompass = new GLViewer_Compass( Qt::green, 30, GLViewer_Compass::TopRight, 10, 5, 12, 3 );
456     else if( myCompass )
457         delete myCompass;
458 }
459
460 /*!
461   Creates or deletes grid
462   \param on - if it is true, then to create
463 */
464 void GLViewer_ViewPort2d::turnGrid( GLboolean on )
465 {
466     if( on )
467     {
468         myGrid = new GLViewer_Grid( 2*WIDTH, 2*HEIGHT,
469                                     2*WIDTH, 2*HEIGHT,
470                                     GRID_XSIZE, GRID_YSIZE,
471                                     myXPan, myYPan,
472                                     myXScale, myYScale );
473     }
474     else if( myGrid )
475         delete myGrid;
476 }
477
478 /*!
479   Changes grid color
480   \param gridColor - new grid color
481   \param axisColor - new axis color
482 */
483 void GLViewer_ViewPort2d::setGridColor( const QColor gridColor, const QColor axisColor )
484 {
485     if( myGrid )
486     {
487         myGrid->setGridColor( ( GLfloat )gridColor.red() / 255,
488                   ( GLfloat )gridColor.green() / 255,
489                   ( GLfloat )gridColor.blue() / 255 );
490         myGrid->setAxisColor( ( GLfloat )axisColor.red() / 255,
491                   ( GLfloat )axisColor.green() / 255,
492                   ( GLfloat )axisColor.blue() / 255 );
493     }
494 }
495
496 /*!
497   Changes background color
498   \param color - new background color
499 */
500 void GLViewer_ViewPort2d::setBackgroundColor( const QColor& color )
501 {
502     GLViewer_ViewPort::setBackgroundColor( color );
503     myGLWidget->makeCurrent();
504     glClearColor( ( GLfloat )color.red() / 255,
505             ( GLfloat )color.green() / 255,
506             ( GLfloat )color.blue() / 255, 1.0 );
507     myGLWidget->repaint();
508 }
509
510 /*!
511   \return background color
512 */
513 QColor GLViewer_ViewPort2d::backgroundColor() const
514 {
515     return GLViewer_ViewPort::backgroundColor();
516 }
517
518 /*!
519   Resize view
520 */
521 void GLViewer_ViewPort2d::initResize( int x, int y )
522 {
523     float xa, xb, ya, yb;
524     xa = myBorder->left() - myMargin;
525     xb = myBorder->right() + myMargin;
526     ya = myBorder->top() - myMargin;
527     yb = myBorder->bottom() + myMargin;
528
529     GLfloat zoom, xzoom, yzoom;
530     GLfloat w = x;
531     GLfloat h = y;
532     bool max = FALSE;
533
534     xzoom = (GLfloat)x / myWidth;
535     yzoom = (GLfloat)y / myHeight;
536
537     if ( ( xzoom < yzoom ) && ( xzoom < 1 ) )
538         zoom = xzoom;
539     else if ( ( yzoom < xzoom ) && ( yzoom < 1 ) )
540         zoom = yzoom;
541     else
542     {
543         max = TRUE;
544         zoom = xzoom > yzoom ? xzoom : yzoom;
545     }
546
547     if ( !max && ( ! ( ( ( myXPan + w/2 ) < xb * myXScale * zoom ) ||
548              ( ( myXPan - w/2 ) > xa * myXScale * zoom ) ||
549              ( ( myYPan + h/2 ) < yb * myYScale * zoom ) ||
550              ( ( myYPan - h/2 ) > ya * myYScale * zoom ) ) ) )
551         zoom = 1;
552
553     if ( max && ( ( ( myXPan + w/2 ) < xb * myXScale * zoom ) ||
554             ( ( myXPan - w/2 ) > xa * myXScale * zoom ) ||
555             ( ( myYPan + h/2 ) < yb * myYScale * zoom ) ||
556             ( ( myYPan - h/2 ) > ya * myYScale * zoom ) ) )
557         zoom = 1;
558
559     myWidth = x;
560     myHeight = y;
561
562     myXScale *= zoom;
563     myYScale = myXScale;
564
565     if ( myGrid )
566         myGrid->setResize( 2*x, 2*y, zoom );
567
568     myGLWidget->setScale( myXScale, myYScale, 1.0 );
569 }
570
571 /*!
572   Custom paint event handler
573 */
574 void GLViewer_ViewPort2d::paintEvent( QPaintEvent* e )
575 {
576     //cout << "GLViewer_ViewPort2d::paintEvent" << endl;
577     myGLWidget->updateGL();
578     GLViewer_ViewPort::paintEvent( e );
579 }
580
581 /*!
582   Custom resize event handler
583 */
584 void GLViewer_ViewPort2d::resizeEvent( QResizeEvent* e )
585 {
586     //cout << "GLViewer_ViewPort2d::resizeEvent" << endl;
587     GLViewer_ViewPort::resizeEvent( e );
588 }
589
590 /*!
591   Resets view to start state
592 */
593 void GLViewer_ViewPort2d::reset()
594 {
595     //cout << "GLViewer_ViewPort2d::reset" << endl;
596
597     GLint val[4];
598     GLint vpWidth, vpHeight;
599
600     myGLWidget->makeCurrent();
601     glGetIntegerv( GL_VIEWPORT, val );
602     vpWidth = val[2];
603     vpHeight = val[3];
604
605     GLint w = myGLWidget->getWidth();
606     GLint h = myGLWidget->getHeight();
607     GLfloat zoom = vpWidth / ( GLfloat )w < vpHeight / ( GLfloat )h ?
608                  vpWidth / ( GLfloat )w : vpHeight / ( GLfloat )h;
609
610     if( myGrid )
611     {
612         myGrid->setPan( 0.0, 0.0 );
613         myGrid->setZoom( zoom / myXScale );
614     }
615
616     myXPan = 0.0;
617     myYPan = 0.0;
618     myXScale = zoom;
619     myYScale = zoom;
620
621     myGLWidget->setPan( myXPan, myYPan, 0.0 );
622     myGLWidget->setScale( myXScale, myYScale, 1.0 );
623     myGLWidget->setRotationAngle( 0.0 );
624     myGLWidget->setRotation( 0.0, 0.0, 0.0, 1.0 );
625     myGLWidget->updateGL();
626 }
627
628 /*!
629   Sets offset to view
630   \param dx - X offset
631   \param dy - Y offset
632 */
633 void GLViewer_ViewPort2d::pan( int dx, int dy )
634 {
635     //cout << "GLViewer_ViewPort2d::pan " << dx << " " << dy << endl;
636
637     /*myXPan += dx / myXScale;
638     myYPan += dy / myYScale;
639
640     float ra, rx, ry, rz;
641     myGLWidget->getRotation( ra, rx, ry, rz );
642     GLfloat angle = ra * PI / 180.;
643
644     if( myGrid )
645         myGrid->setPan( myXPan*cos(angle) + myYPan*sin(angle),
646                         -myXPan*sin(angle) + myYPan*cos(angle) );
647
648     */
649     float ra, rx, ry, rz;
650     myGLWidget->getRotation( ra, rx, ry, rz );
651     GLfloat angle = ra * PI / 180.;
652
653     myXPan += (dx*cos(angle) + dy*sin(angle)) / myXScale;
654     myYPan += (-dx*sin(angle) + dy*cos(angle)) / myXScale;
655
656     if( myGrid )
657         myGrid->setPan( myXPan, myYPan );
658
659     myGLWidget->setPan( myXPan, myYPan, 0.0 );
660     myGLWidget->setScale( myXScale, myYScale, 1.0 );
661     myGLWidget->updateGL();
662 }
663
664 /*!
665   Sets view center in global coords
666   \param x, y - global co-ordinates of center
667 */
668 void GLViewer_ViewPort2d::setCenter( int x, int y )
669 {
670     //cout << "GLViewer_ViewPort2d::setCenter" << endl;
671
672     GLint val[4];
673     GLint vpWidth, vpHeight;
674
675     myGLWidget->makeCurrent();
676     glGetIntegerv( GL_VIEWPORT, val );
677     vpWidth = val[2];
678     vpHeight = val[3];
679
680     myXPan -= ( x - vpWidth/2 ) / myXScale;
681     myYPan += ( y - vpHeight/2 ) / myYScale;
682
683     if( myGrid )
684     {
685         myGrid->setPan( myXPan, myYPan );
686         myGrid->setZoom( myXOldScale / myXScale );
687     }
688
689     myXScale = myXOldScale;
690     myYScale = myYOldScale;
691
692     myGLWidget->setPan( myXPan, myYPan, 0.0 );
693     myGLWidget->setScale( myXScale, myYScale, 1.0 );
694     myGLWidget->updateGL();
695 }
696
697 /*!
698   Process zoming transformation with mouse tracking from ( x0, y0 ) to ( x1, y1 )
699 */
700 void GLViewer_ViewPort2d::zoom( int x0, int y0, int x, int y )
701 {
702     //cout << "GLViewer_ViewPort2d::zoom" << endl;
703
704     float dx, dy, zm;
705     dx = x - x0;
706     dy = y - y0;
707
708     if ( dx == 0. && dy == 0. )
709         return;
710
711     zm = sqrt(dx * dx + dy * dy) / 100. + 1;
712     zm = (dx > 0.) ?  zm : 1. / zm;
713
714     //backup values
715     float bX = myXScale;
716     float bY = myYScale;
717     myXScale *= zm;
718     myYScale *= zm;
719
720     if( myGrid )
721     {
722         if( myGrid->setZoom( zm ) )
723         {
724             myGLWidget->setPan( myXPan, myYPan, 0.0 );
725             myGLWidget->setScale( myXScale, myYScale, 1.0 );
726             myGLWidget->updateGL();
727         }
728         else
729         {// undo
730             myXScale = bX;
731             myYScale = bY;
732         }
733     }
734     else
735     {
736         myGLWidget->setPan( myXPan, myYPan, 0.0 );
737         myGLWidget->setScale( myXScale, myYScale, 1.0 );
738         myGLWidget->updateGL();
739     }
740 }
741
742 /*!
743   Transforms view by rectangle
744   \param rect - rectangle
745 */
746 void GLViewer_ViewPort2d::fitRect( const QRect& rect )
747 {
748     float x0, x1, y0, y1;
749     float dx, dy, zm, centerX, centerY;
750
751     GLint val[4];
752     GLint vpWidth, vpHeight;
753
754     myGLWidget->makeCurrent();
755     glGetIntegerv( GL_VIEWPORT, val );
756     vpWidth = val[2];
757     vpHeight = val[3];
758
759     x0 = rect.left();
760     x1 = rect.right();
761     y0 = rect.top();
762     y1 = rect.bottom();
763
764     dx = fabs( x1 - x0 );
765     dy = fabs( y1 - y0 );
766     centerX = ( x0 + x1 ) / 2.;
767     centerY = ( y0 + y1 ) / 2.;
768
769     if ( dx == 0. || dy == 0. )
770         return;
771
772     zm = vpWidth / dx < vpHeight / dy ? vpWidth / dx : vpHeight / dy;
773
774     float aDX = ( vpWidth / 2. - centerX ) / myXScale;
775     float aDY = ( vpHeight / 2. - centerY ) / myYScale;
776
777     float ra, rx, ry, rz;
778     myGLWidget->getRotation( ra, rx, ry, rz );
779     GLfloat angle = ra * PI / 180.;
780
781     myXPan += (aDX*cos(angle) - aDY*sin(angle));
782     myYPan -= (aDX*sin(angle) + aDY*cos(angle));
783
784     if( myGrid )
785         myGrid->setPan( myXPan, myYPan );
786
787     myXScale *= zm;
788     myYScale = myXScale;
789
790     if( myGrid )
791         myGrid->setZoom( zm );
792
793     myGLWidget->setPan( myXPan, myYPan, 0.0 );
794     myGLWidget->setScale( myXScale, myYScale, 1.0 );
795     myGLWidget->updateGL();
796 }
797
798 /*!
799   Transforms view by selection
800 */
801 void GLViewer_ViewPort2d::fitSelect()
802 {
803   GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
804   GLViewer_Context* aContext = aViewer->getGLContext();
805   if( !aContext )
806     return;
807
808   QRect aSelRect;
809   for( aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected() )
810     aSelRect |= *(aViewer->getWinObjectRect( aContext->SelectedObject() ));
811
812   if( aSelRect.isValid() )
813   {
814     aSelRect.setTop( aSelRect.top() - SELECTION_RECT_GAP );
815     aSelRect.setBottom( aSelRect.bottom() + SELECTION_RECT_GAP );
816     aSelRect.setLeft( aSelRect.left() - SELECTION_RECT_GAP );
817     aSelRect.setRight( aSelRect.right() + SELECTION_RECT_GAP );
818     fitRect( aSelRect );
819   }
820 }
821
822 /*!
823   Transform view by view borders
824   \param keepScale - if it is true, zoom does not change
825 */
826 void GLViewer_ViewPort2d::fitAll( bool keepScale, bool withZ )
827 {
828     //cout << "GLViewer_ViewPort2d::fitAll" << endl;
829
830     float xa, xb, ya, yb;
831     float dx, dy, zm;
832     float xScale, yScale;
833
834     myMargin = qMax( myBorder->width(), myBorder->height() ) / 5;
835
836     xa = myBorder->left() - myMargin;
837     xb = myBorder->right() + myMargin;
838     ya = myBorder->bottom() - myMargin;
839     yb = myBorder->top() + myMargin;
840
841     float aPoints[8] = { xa, ya, xb, ya, xa, yb, xb, yb };
842
843     float ra, rx, ry, rz;
844     myGLWidget->getRotation( ra, rx, ry, rz );
845     float angle = ra * PI / 180.;
846
847     int i;
848     for( i = 0; i < 7; i = i + 2 )
849         rotate_point( aPoints[i], aPoints[i+1], angle );
850
851     float aBorders[4] = { aPoints[0], aPoints[0], aPoints[1], aPoints[1] };
852
853     for( i = 2; i < 7; i = i + 2 )
854     {
855         if( aBorders[0] < aPoints[i] )
856             aBorders[0] = aPoints[i];
857         if( aBorders[1] > aPoints[i] )
858             aBorders[1] = aPoints[i];
859
860         if( aBorders[2] < aPoints[i+1] )
861             aBorders[2] = aPoints[i+1];
862         if( aBorders[3] > aPoints[i+1] )
863             aBorders[3] = aPoints[i+1];
864     }
865
866     GLint val[4];
867     GLint vpWidth, vpHeight;
868
869     myGLWidget->makeCurrent();
870     glGetIntegerv( GL_VIEWPORT, val );
871     vpWidth = val[2];
872     vpHeight = val[3];
873
874     dx = fabs( aBorders[1] - aBorders[0] );
875     dy = fabs( aBorders[3] - aBorders[2] );
876
877     myXPan = -( aBorders[0] + aBorders[1] ) / 2;
878     myYPan = -( aBorders[2] + aBorders[3] ) / 2;
879
880
881     if( keepScale )
882     {
883         myXOldScale = myXScale;
884         myYOldScale = myYScale;
885     }
886
887     xScale = myXScale;
888     yScale = myYScale;
889     if( dx && dy )
890         zm = vpWidth / dx < vpHeight / dy ? vpWidth / dx : vpHeight / dy;
891     else
892         zm = 1.0;
893     myXScale = zm;
894     myYScale = zm;
895
896
897     if( myGrid )
898     {
899         myGrid->setPan( myXPan, myYPan );
900         if( dx > dy )
901             myGrid->setZoom(  zm / xScale );
902         else
903             myGrid->setZoom( zm / yScale );
904     }
905
906     myGLWidget->setPan( myXPan, myYPan, 0.0 );
907     myGLWidget->setScale( myXScale, myYScale, 1.0 );
908     myGLWidget->updateGL();
909
910     if( keepScale )
911         emit vpUpdateValues();
912 }
913
914 /*!
915   Begins rotation
916   \param x, y - start point
917 */
918 void GLViewer_ViewPort2d::startRotation( int x, int y )
919 {
920     myGLWidget->setRotationStart( x, y, 1.0 );
921 }
922
923 /*!
924   Performs rotation
925   \param intX, intY - current point
926 */
927 void GLViewer_ViewPort2d::rotate( int intX, int intY )
928 {
929     GLint val[4];
930     GLint vpWidth, vpHeight;
931
932     myGLWidget->makeCurrent();
933     glGetIntegerv( GL_VIEWPORT, val );
934     vpWidth = val[2];
935     vpHeight = val[3];
936
937     float x = intX, y = intY;
938     float x0 = vpWidth/2;
939     float y0 = vpHeight/2;
940
941     float xs, ys, zs, dx, dy;
942     myGLWidget->getRotationStart( xs, ys, zs );
943
944     xs = xs - x0;
945     x = x - x0;
946     dx = x - xs;
947     ys = y0 - ys;
948     y = y0 - y;
949     dy = y - ys;
950
951     float l1 = pow( double( xs*xs + ys*ys ), 0.5 );
952     float l2 = pow( double( x*x + y*y ), 0.5 );
953     float l = pow( double( dx*dx + dy*dy ), 0.5 );
954
955     double mult = xs * y - x * ys;
956     short sign;
957     if( mult > 0 ) sign = 1;
958     else if( mult < 0 ) sign = -1;
959     else sign = 0;
960
961     float anglePrev = myGLWidget->getRotationAngle();
962     float angleNew = sign * acos( ( l1*l1 + l2*l2 - l*l ) / ( 2 * l1 * l2 )) * 180. / PI;
963     float angle = anglePrev + angleNew;
964
965     // GLfloat anAngle = angle * PI / 180.; unused
966
967     float ra, rx, ry, rz;
968     myGLWidget->getRotation( ra, rx, ry, rz );
969     myGLWidget->setRotation( angle, rx, ry, rz );
970     myGLWidget->updateGL();
971 }
972
973 /*!
974   Finishes rotation
975 */
976 void GLViewer_ViewPort2d::endRotation()
977 {
978     float ra, rx, ry, rz;
979     myGLWidget->getRotation( ra, rx, ry, rz );
980     myGLWidget->setRotationAngle( ra );
981 }
982
983 /*!
984   Draws compass
985 */
986 void GLViewer_ViewPort2d::drawCompass()
987 {
988     if( !myCompass->getVisible() )
989         return;
990
991     GLfloat xScale, yScale, xPan, yPan;
992
993     int xPos = getWidth();
994     int yPos = getHeight();
995
996     int cPos = myCompass->getPos();
997     int cSize = myCompass->getSize();
998     QColor cCol = myCompass->getColor();
999     int cWidthTop = myCompass->getArrowWidthTop();
1000     int cWidthBot = myCompass->getArrowWidthBottom();
1001     int cHeightTop = myCompass->getArrowHeightTop();
1002     int cHeightBot = myCompass->getArrowHeightBottom();
1003
1004     GLfloat colorR = (cCol.red())/255;
1005     GLfloat colorG = (cCol.green())/255;
1006     GLfloat colorB = (cCol.blue())/255;
1007
1008     float delX = cSize * 0.5;
1009     float delY = cSize * 0.5;
1010
1011     getScale( xScale, yScale );
1012     getPan( xPan, yPan);
1013
1014     float centerX = (xPos/2 - delX - cSize)/xScale;
1015     float centerY = (yPos/2 - delY - cSize)/yScale;
1016
1017     switch ( cPos )
1018     {
1019     case GLViewer_Compass::TopLeft:
1020             centerX = -centerX;
1021             break;
1022         case GLViewer_Compass::BottomLeft:
1023             centerX = -centerX;
1024             centerY = -centerY;
1025             break;
1026         case GLViewer_Compass::BottomRight:
1027             centerY = -centerY;
1028             break;
1029         default: break;
1030     }
1031
1032     float ra, rx, ry, rz;
1033     myGLWidget->getRotation( ra, rx, ry, rz );
1034     GLfloat angle = ra * PI / 180.;
1035     GLfloat /*r = 0.0,*/ x = 0.0 , y = 0.0;
1036
1037     rotate_point( centerX, centerY, -angle );
1038
1039     centerX -= xPan;
1040     centerY -= yPan;
1041
1042     glColor3f( colorR, colorG, colorB );
1043     glBegin( GL_POLYGON );
1044     //arrow
1045         x = centerX;                      y = centerY + cSize / yScale;
1046         glVertex2f( x, y );
1047         //point #2
1048         x = centerX + cWidthTop / xScale; y = centerY + ( cSize - cHeightTop ) / yScale ;
1049         glVertex2f( x, y );
1050         //point #3
1051         x = centerX + cWidthBot / xScale; y = centerY + ( cSize - cHeightTop ) / yScale ;
1052         glVertex2f( x, y );
1053         //point #4
1054         x = centerX + cWidthBot / xScale; y = centerY - cSize/yScale;
1055         glVertex2f( x, y );
1056         //point #5
1057         x = centerX;                      y = centerY - (cSize - cHeightBot) / yScale ;
1058         glVertex2f( x, y );
1059         //point #6
1060         x = centerX - cWidthBot / xScale; y = centerY - cSize/yScale;
1061         glVertex2f( x, y );
1062         //point #7
1063         x = centerX - cWidthBot / xScale; y = centerY + ( cSize - cHeightTop ) / yScale ;
1064         glVertex2f( x, y );
1065         //point #8
1066         x = centerX - cWidthTop / xScale; y = centerY + ( cSize - cHeightTop ) / yScale ;
1067         glVertex2f( x, y );
1068     glEnd();
1069     glLineWidth( 2.0 );
1070     glEnable( GL_LINE_SMOOTH );
1071     glBegin(GL_LINE_LOOP);
1072     //circle
1073         float aCircAngle = 0;
1074         for ( int i = 0; i < 20 * SEGMENTS + 1; i++ )
1075         {
1076             x = centerX + cos(aCircAngle) * cSize / xScale;
1077             y = centerY + sin(aCircAngle) * cSize / yScale;
1078             glVertex2f( x, y );
1079             aCircAngle += float( STEP ) / 2;
1080         }
1081     glEnd();
1082
1083     GLdouble        modelMatrix[16], projMatrix[16];
1084     GLint           viewport[4];
1085     GLdouble        winxN, winyN, winz;
1086     GLdouble        winxE, winyE;
1087     GLdouble        winxS, winyS;
1088     GLdouble        winxW, winyW;
1089     GLuint          aTextList;
1090
1091     GLViewer_TexFont* aFont = myCompass->getFont();
1092     float widN = (float)aFont->getStringWidth( "N" );
1093     float widW = (float)aFont->getStringWidth( "W" );
1094     float widS = (float)aFont->getStringWidth( "S" );
1095     float widE = (float)aFont->getStringWidth( "E" );
1096     float heightL = (float)aFont->getStringHeight();
1097
1098     float xGapN = - widN/2 *( 1.0 + sin(angle) );
1099     float xGapS = - widS/2 *( 1.0 - sin(angle) );
1100     float xGapW = - widW/2 *( 1.0 + cos(angle) );
1101     float xGapE = - widE/2 *( 1.0 - cos(angle) );
1102
1103     float yGapN = - heightL/2 *( 1.0 - cos(angle) ) * 0.75;
1104     float yGapS = - heightL/2 *( 1.0 + cos(angle) ) * 0.75;
1105     float yGapW = - heightL/2 *( 1.0 + sin(angle) ) * 0.75;
1106     float yGapE = - heightL/2 *( 1.0 - sin(angle) ) * 0.75;
1107
1108     glGetIntegerv (GL_VIEWPORT, viewport);
1109     glGetDoublev (GL_MODELVIEW_MATRIX, modelMatrix);
1110     glGetDoublev (GL_PROJECTION_MATRIX, projMatrix);
1111
1112     gluProject (centerX, centerY + cSize / yScale, 0, modelMatrix, projMatrix, viewport, &winxN, &winyN, &winz);
1113     gluProject (centerX + cSize / xScale, centerY, 0, modelMatrix, projMatrix, viewport, &winxE, &winyE, &winz);
1114     gluProject (centerX, centerY - cSize / yScale, 0, modelMatrix, projMatrix, viewport, &winxS, &winyS, &winz);
1115     gluProject (centerX - cSize / xScale, centerY, 0, modelMatrix, projMatrix, viewport, &winxW, &winyW, &winz);
1116
1117     glColor3f( 1.0, 1.0, 1.0 );
1118
1119     aTextList = glGenLists( 1 );
1120     glNewList( aTextList, GL_COMPILE );
1121
1122     glMatrixMode(GL_PROJECTION);
1123     glPushMatrix();
1124     glLoadIdentity();
1125     glOrtho(0,viewport[2],0,viewport[3],-100,100);
1126     glMatrixMode(GL_MODELVIEW);
1127     glPushMatrix();
1128     glLoadIdentity();
1129
1130     aFont->drawString( "N", winxN + xGapN, winyN + yGapN );
1131     aFont->drawString( "E", winxE + xGapE, winyE + yGapE );
1132     aFont->drawString( "S", winxS + xGapS, winyS + yGapS );
1133     aFont->drawString( "W", winxW + xGapW, winyW + yGapW );
1134
1135     glMatrixMode(GL_PROJECTION);
1136     glPopMatrix();
1137     glMatrixMode(GL_MODELVIEW);
1138     glPopMatrix();
1139
1140     glEndList();
1141
1142     if ( aTextList != -1 )
1143         glCallList( aTextList );
1144 }
1145
1146 /*!
1147   \return blocking status for current started operations
1148 */
1149 BlockStatus GLViewer_ViewPort2d::currentBlock()
1150 {
1151     if( myIsDragProcess == inDrag && myCurDragPosX != NULL && myCurDragPosY != NULL)
1152         return BlockStatus(BS_Highlighting | BS_Selection);
1153
1154     if( mypFirstPoint && mypLastPoint )
1155         return BlockStatus(BS_Highlighting | BS_Selection);
1156
1157     return BS_NoBlock;
1158 }
1159
1160 /*!
1161   Initializes rectangle selection
1162   \param x, y - start point
1163 */
1164 void GLViewer_ViewPort2d::startSelectByRect( int x, int y )
1165 {
1166     if( !mypFirstPoint && !mypLastPoint )
1167     {
1168         mypFirstPoint = new QPoint( x, y );
1169         mypLastPoint = new QPoint( x, y );
1170     }
1171
1172     if ( !myRectBand ) {
1173       myRectBand = new QRubberBand( QRubberBand::Rectangle, this );
1174       QPalette palette;
1175       palette.setColor(myRectBand->foregroundRole(), Qt::white);
1176       myRectBand->setPalette(palette);
1177     }
1178     myRectBand->hide();
1179 }
1180
1181 /*!
1182   Draws rectangle selection
1183   \param x, y - current point
1184 */
1185 void GLViewer_ViewPort2d::drawSelectByRect( int x, int y )
1186 {
1187     if( mypFirstPoint && mypLastPoint )
1188     {
1189         myRectBand->hide();    /* erase */
1190
1191         mypLastPoint->setX( x );
1192         mypLastPoint->setY( y );
1193
1194         QRect aRect = selectionRect();
1195         myRectBand->setGeometry( aRect );    /* draw */
1196         myRectBand->setVisible( aRect.isValid() );
1197     }
1198
1199 }
1200
1201 /*!
1202   Finishes rectangle selection
1203 */
1204 void GLViewer_ViewPort2d::finishSelectByRect()
1205 {
1206     if( mypFirstPoint && mypLastPoint )
1207     {
1208
1209
1210         if ( myRectBand ) myRectBand->hide();    /* erase */
1211
1212         delete mypFirstPoint;
1213         delete mypLastPoint;
1214
1215         mypFirstPoint = NULL;
1216         mypLastPoint = NULL;
1217
1218         delete myRectBand;
1219         myRectBand = 0;
1220     }
1221 }
1222
1223 /*!
1224   \return rectangle selection
1225 */
1226 QRect GLViewer_ViewPort2d::selectionRect()
1227 {
1228     QRect aRect;
1229     if( mypFirstPoint && mypLastPoint )
1230     {
1231         aRect.setLeft( qMin( mypFirstPoint->x(), mypLastPoint->x() ) );
1232         aRect.setTop( qMin( mypFirstPoint->y(), mypLastPoint->y() ) );
1233         aRect.setRight( qMax( mypFirstPoint->x(), mypLastPoint->x() ) );
1234         aRect.setBottom( qMax( mypFirstPoint->y(), mypLastPoint->y() ) );
1235     }
1236
1237     return aRect;
1238 }
1239
1240 /*!
1241 */
1242 bool GLViewer_ViewPort2d::startPulling( GLViewer_Pnt point )
1243 {
1244     GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
1245     GLViewer_Context* aContext = aViewer->getGLContext();
1246     ObjList anObjects = aContext->getObjects();
1247
1248     for( ObjList::Iterator it = anObjects.begin(); it != anObjects.end(); ++it )
1249     {
1250         GLViewer_Object* anObject = *it;
1251         GLViewer_Rect aRect = anObject->getPullingRect();
1252
1253         if( aRect.contains( point ) && anObject->startPulling( point ) )
1254         {
1255             myIsPulling = true;
1256             myPullingObject = anObject;
1257             setCursor( *getHandCursor() );
1258             return true;
1259         }
1260     }
1261
1262     return false;
1263 }
1264
1265 /*!
1266 */
1267 void GLViewer_ViewPort2d::drawPulling( GLViewer_Pnt point )
1268 {
1269     GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
1270     GLViewer_Context* aContext = aViewer->getGLContext();
1271     ObjList anObjects = aContext->getObjects();
1272
1273     GLViewer_Object* aLockedObject = 0;
1274     for( ObjList::Iterator it = anObjects.begin(); it != anObjects.end(); ++it )
1275     {
1276         GLViewer_Object* anObject = *it;
1277         if( !anObject->getVisible() )
1278             continue;
1279
1280         GLViewer_Rect aRect = anObject->getPullingRect();
1281
1282         if( aRect.contains( point ) && anObject->portContains( point ) )
1283         {
1284             aLockedObject = anObject;
1285             break;
1286         }
1287     }
1288
1289     myPullingObject->pull( point, aLockedObject );
1290 }
1291
1292 /*!
1293 */
1294 void GLViewer_ViewPort2d::finishPulling()
1295 {
1296     myIsPulling = false;
1297     myPullingObject->finishPulling();
1298     setCursor( *getDefaultCursor() );
1299 }
1300
1301 /*!
1302   Convert rectangle in window co-ordinates to GL co-ordinates
1303   \return converted rectangle
1304 */
1305 GLViewer_Rect GLViewer_ViewPort2d::win2GLV( const QRect& theRect ) const
1306 {
1307   GLViewer_Rect aRect;
1308
1309   GLdouble        modelMatrix[16], projMatrix[16];
1310   GLint           viewport[4];
1311
1312   GLdouble        objx1, objy1;
1313   GLdouble        objx2, objy2;
1314   GLdouble        objz;
1315
1316   glGetIntegerv (GL_VIEWPORT, viewport);
1317   glGetDoublev (GL_MODELVIEW_MATRIX, modelMatrix);
1318   glGetDoublev (GL_PROJECTION_MATRIX, projMatrix);
1319
1320   gluUnProject( theRect.left(), viewport[3] - theRect.top(), 0, modelMatrix, projMatrix, viewport, &objx1, &objy1, &objz );
1321   gluUnProject( theRect.right(), viewport[3] - theRect.bottom(), 0, modelMatrix, projMatrix, viewport, &objx2, &objy2, &objz );
1322
1323   aRect.setLeft( objx1 );
1324   aRect.setTop( objy1 );
1325   aRect.setRight( objx2 );
1326   aRect.setBottom( objy2 );
1327
1328   return aRect;
1329 }
1330
1331 /*!
1332   Convert rectangle in GL co-ordinates to window co-ordinates
1333   \return converted rectangle
1334 */
1335 QRect GLViewer_ViewPort2d::GLV2win( const GLViewer_Rect& theRect ) const
1336 {
1337   QRect aRect;
1338
1339   GLdouble        modelMatrix[16], projMatrix[16];
1340   GLint           viewport[4];
1341
1342   GLdouble        winx1, winy1;
1343   GLdouble        winx2, winy2;
1344   GLdouble        winz;
1345
1346   glGetIntegerv (GL_VIEWPORT, viewport);
1347   glGetDoublev (GL_MODELVIEW_MATRIX, modelMatrix);
1348   glGetDoublev (GL_PROJECTION_MATRIX, projMatrix);
1349
1350   gluProject( theRect.left(), theRect.top(), 0, modelMatrix, projMatrix, viewport, &winx1, &winy1, &winz );
1351   gluProject( theRect.right(), theRect.bottom(), 0, modelMatrix, projMatrix, viewport, &winx2, &winy2, &winz );
1352
1353   aRect.setLeft( (int)winx1 );
1354   aRect.setTop( viewport[3] - (int)winy1 );
1355   aRect.setRight( (int)winx2 );
1356   aRect.setBottom( viewport[3] - (int)winy2 );
1357
1358   return aRect;
1359 }
1360
1361 /*!
1362   SLOT: called when tooltip should be shown
1363 */
1364 void GLViewer_ViewPort2d::onMaybeTip( QPoint thePoint, QString& theText, QFont& theFont, QRect& theTextReg, QRect& theRegion )
1365 {
1366   GLViewer_Context* aContext = ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext();
1367
1368   GLViewer_Object* anObj = aContext->getCurrentObject();
1369   if( anObj )
1370   {
1371     theText = anObj->getToolTipText();
1372     if( theText.isEmpty() )
1373       theText = anObj->getName();
1374
1375     QStringList aList;
1376     if( anObj->isTooTipHTML() )
1377       aList = theText.split( "<br>", QString::SkipEmptyParts );
1378     else
1379       aList = theText.split( "\n", QString::SkipEmptyParts );
1380
1381     if( !aList.isEmpty() )
1382     {
1383       int index = 0;
1384       int str_size = aList.first().length();
1385       for( int i = 1, size = aList.count(); i < size; i++ )
1386       {
1387         if ( str_size < (int)aList[i].length() )
1388         {
1389           index = i;
1390           str_size = aList[i].length();
1391         }
1392       }
1393       theFont = font();
1394       int cur_height = 24;
1395       QCursor* aCursor = QApplication::overrideCursor();
1396       if( aCursor )
1397       {
1398         const QBitmap* aBitmap = aCursor->bitmap();
1399         if( aBitmap )
1400           cur_height = aBitmap->height();
1401       }
1402
1403       //temp
1404       QSize aSize = QLabel( theText, 0 ).sizeHint();
1405       theTextReg = QRect( thePoint.x(), thePoint.y() + cur_height,
1406                           aSize.width(), aSize.height() );
1407       theRegion = QRect( thePoint.x(), thePoint.y(), 1, 1 );
1408     }
1409   }
1410 }