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