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