Salome HOME
New item (FontItem), allowing to show information about font setting and to select...
[modules/gui.git] / src / GLViewer / GLViewer_BaseObjects.cxx
1 /***************************************************************************
2 **  Class:   GLViewer_BaseObjects
3 **  Descr:   Internal OpenGL Objects
4 **  Module:  GLViewer
5 **  Created: UI team, 02.09.02
6 ****************************************************************************/
7
8 //#include <GLViewerAfx.h>
9 #include "GLViewer_BaseObjects.h"
10 #include "GLViewer_BaseDrawers.h"
11 #include "GLViewer_AspectLine.h"
12 #include "GLViewer_CoordSystem.h"
13 #include "GLViewer_Text.h"
14 #include "GLViewer_Group.h"
15
16 #include "GLViewer_Drawer.h"
17
18 //#include <cmath>
19 //using namespace std;
20
21 /***************************************************************************
22 **  Class:   GLViewer_MarkerSet
23 **  Descr:   OpenGL MarkerSet
24 **  Module:  GLViewer
25 **  Created: UI team, 03.09.02
26 ****************************************************************************/
27
28 GLViewer_MarkerSet::GLViewer_MarkerSet( int number, float size, const QString& toolTip ) :
29   GLViewer_Object(),
30   myNumber( 0 ),
31   myXCoord( 0 ),
32   myYCoord( 0 )       
33 {
34     
35     myMarkerSize = size;
36     myHNumbers.clear();
37     myUHNumbers.clear();
38     mySelNumbers.clear();
39     myUSelNumbers.clear();
40     myCurSelNumbers.clear();
41     myPrevHNumbers.clear();    
42
43     myType = "GLViewer_MarkerSet";
44     myToolTipText = toolTip;
45     
46     setNumMarkers( number );    
47 }
48
49 GLViewer_MarkerSet::~GLViewer_MarkerSet()
50 {
51     if ( myXCoord )
52         delete[] myXCoord;
53     if ( myYCoord )
54         delete[] myYCoord;
55 }
56
57 void AddCoordsToHPGL( QString& buffer, QString command, GLViewer_CoordSystem* aViewerCS, 
58                       GLViewer_CoordSystem* aPaperCS, double x, double y, bool NewLine = true )
59 {
60     if( aViewerCS && aPaperCS )
61         aViewerCS->transform( *aPaperCS, x, y );
62
63     QString temp = command + "%1, %2;";
64     buffer += temp.arg( x ).arg( y );
65     if( NewLine )
66         buffer += ";\n";
67 }
68
69 void AddCoordsToPS( QString& buffer, QString command, GLViewer_CoordSystem* aViewerCS, 
70                     GLViewer_CoordSystem* aPaperCS, double x, double y, bool NewLine = true )
71 {
72     if( aViewerCS && aPaperCS )
73         aViewerCS->transform( *aPaperCS, x, y );
74
75     QString temp = "%1 %2 "+command;    
76     buffer += temp.arg( x ).arg( y );
77     if( NewLine )
78         buffer += "\n";
79 }
80
81 void AddLineAspectToPS( QString& buffer, GLViewer_AspectLine* anAspect, 
82                         GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aPaperCS )
83 {
84     if( anAspect )
85     {
86         QColor col1, col2, col3;
87         anAspect->getLineColors( col1, col2, col3 );
88
89         float aWidth = anAspect->getLineWidth();
90         int aLineType = anAspect->getLineType();
91
92         QString temp = "%1 %2 %3 setrgbcolor\n";
93         double rr = 1 - double( col1.red() ) / 255.0, //color inverting
94                gg = 1 - double( col1.green() ) / 255.0,
95                bb = 1 - double( col1.blue() ) / 255.0;
96
97         buffer += temp.arg( rr ).arg( gg ).arg( bb );
98
99         double x_stretch, y_stretch;
100         aViewerCS->getStretching( *aPaperCS, x_stretch, y_stretch );
101         buffer += temp.arg( x_stretch * aWidth )+" setlinewidth\n";
102
103         if( aLineType==0 ) //solid
104             buffer += "[] 0 setdash\n";
105         else if( aLineType==1 ) //strip
106             buffer += "[2] 0 setdash\n";
107     }
108 }
109
110 #ifdef WIN32
111 HPEN AddLineAspectToEMF( HDC hDC, GLViewer_AspectLine* anAspect, 
112                          GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aPaperCS )
113 {
114     if( anAspect )
115     {
116         QColor col1, col2, col3;
117         anAspect->getLineColors( col1, col2, col3 );
118
119         double x_stretch, y_stretch;
120         aViewerCS->getStretching( *aPaperCS, x_stretch, y_stretch );
121
122         double aWidth = anAspect->getLineWidth()*x_stretch;
123         int aLineType = anAspect->getLineType();
124
125         return CreatePen( PS_SOLID, aWidth, RGB( 255-col1.red(), 255-col1.green(), 255-col1.blue() ) );
126     }
127     else
128         return NULL;
129 }
130 #endif
131
132 bool GLViewer_MarkerSet::translateToPS( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aPSCS )
133 {   
134     int noPoints = 20;
135
136     QString aBuffer = "newpath\n";
137
138     AddLineAspectToPS( aBuffer, getAspectLine(), aViewerCS, aPSCS );
139
140     for( int i=0; i<myNumber; i++ )
141     {       
142         aBuffer += "\n";
143
144         double x_stretch, y_stretch;
145         aViewerCS->getStretching( *aPSCS, x_stretch, y_stretch );
146
147         double x0 = myXCoord[i],
148                y0 = myYCoord[i],
149                r  = myMarkerSize,
150                x, y;
151
152         for( int j=0; j<=noPoints; j++ )
153         {
154             x = x0 + r*cos( double(j)*2*PI/double(noPoints) );
155             y = y0 + r*sin( double(j)*2*PI/double(noPoints) );          
156             if( j==0 )
157                 AddCoordsToPS( aBuffer, "moveto", aViewerCS, aPSCS, x, y, true );               
158             else
159                 AddCoordsToPS( aBuffer, "lineto", aViewerCS, aPSCS, x, y, true );
160         }
161     }
162     aBuffer+="closepath\nstroke\n";
163
164     hFile.writeBlock( aBuffer.ascii(), aBuffer.length() );
165
166     return true;
167 }
168
169 bool GLViewer_MarkerSet::translateToHPGL( QFile& hFile, GLViewer_CoordSystem* aViewerCS,
170                                        GLViewer_CoordSystem* aHPGLCS )
171 {
172     int noPoints = 20;
173     QString aBuffer;
174     for( int i=0; i<myNumber; i++ )
175     {
176         aBuffer = "";
177
178         double x_stretch, y_stretch;
179         aViewerCS->getStretching( *aHPGLCS, x_stretch, y_stretch );
180
181         double x0 = myXCoord[i],
182                y0 = myYCoord[i],
183                r  = myMarkerSize,
184                x, y;
185
186         AddCoordsToHPGL( aBuffer, "PA", aViewerCS, aHPGLCS, x0+r, y0 );
187         aBuffer+="PD;\n";
188         for( int j=1; j<=noPoints; j++ )
189         {
190             x = x0 + r*cos( double(j)*2*PI/double(noPoints) );
191             y = y0 + r*sin( double(j)*2*PI/double(noPoints) );
192             AddCoordsToHPGL( aBuffer, "PD", aViewerCS, aHPGLCS, x, y );
193         }
194         aBuffer+="PU;\n";
195
196         hFile.writeBlock( aBuffer.ascii(), aBuffer.length() );
197     }
198
199     return true;
200 }
201
202 #ifdef WIN32
203 bool GLViewer_MarkerSet::translateToEMF( HDC dc, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aEMFCS )
204 {
205     int noPoints = 20;
206     if( !aViewerCS || !aEMFCS )
207         return false;
208     
209     HPEN pen = AddLineAspectToEMF( dc, getAspectLine(), aViewerCS, aEMFCS );
210     HGDIOBJ old = SelectObject( dc, pen );
211
212     for( int i=0; i<myNumber; i++ )
213     {
214         double x0 = myXCoord[i],
215                y0 = myYCoord[i],
216                r  = myMarkerSize,
217                x, y;
218
219         for( int j=0; j<=noPoints; j++ )
220         {
221             x = x0 + r*cos( double(j)*2*PI/double(noPoints) );
222             y = y0 + r*sin( double(j)*2*PI/double(noPoints) );
223             aViewerCS->transform( *aEMFCS, x, y );
224             if( j==0 )
225                 MoveToEx( dc, x, y, NULL );
226             else
227                 LineTo( dc, x, y );
228         }
229     }
230
231     SelectObject( dc, old );
232     if( pen )
233         DeleteObject( pen );
234     return true;
235 }
236 #endif
237
238
239 void GLViewer_MarkerSet::compute()
240 {
241 //  cout << "GLViewer_MarkerSet::compute" << endl;
242   GLfloat xa = myXCoord[0]; 
243   GLfloat xb = myXCoord[0]; 
244   GLfloat ya = myYCoord[0]; 
245   GLfloat yb = myYCoord[0]; 
246
247   for ( int i = 0; i < myNumber; i++ )  
248   {
249     xa = QMIN( xa, myXCoord[i] );
250     xb = QMAX( xb, myXCoord[i] );
251     ya = QMIN( ya, myYCoord[i] );
252     yb = QMAX( yb, myYCoord[i] );
253   }
254   
255   myXGap = ( xb - xa ) / 10;
256   myYGap = ( yb - ya ) / 10;
257
258   myRect->setLeft( xa - myXGap );
259   myRect->setTop( yb + myYGap ); 
260   myRect->setRight( xb + myXGap );
261   myRect->setBottom( ya - myYGap );
262 }
263
264 GLViewer_Drawer* GLViewer_MarkerSet::createDrawer()
265 {
266 //  cout << "GLViewer_MarkerSet::createDrawer" << endl;
267   return myDrawer = new GLViewer_MarkerDrawer();
268 }
269
270
271 GLboolean GLViewer_MarkerSet::highlight( GLfloat x, GLfloat y, GLfloat tol, GLboolean isCircle )
272 {
273     if( !myIsVisible )
274         return false;
275 //  cout << "GLViewer_MarkerSet::highlight " << x <<" " << y << " " << tol << endl;
276   int count = 0;
277   GLfloat xdist, ydist, radius;
278   QValueList<int>::Iterator it;
279   QValueList<int> curHNumbers;
280   bool isFound;
281   GLboolean update;
282   int cnt = 0;
283
284   radius = tol - myMarkerSize / 2.;
285   
286   myUHNumbers += myHNumbers;
287   myHNumbers.clear();
288
289   for ( int i = 0; i < myNumber; i++ ) 
290   {
291     xdist = ( myXCoord[i] - x ) * myXScale;
292     ydist = ( myYCoord[i] - y ) * myYScale;
293
294 //    if ( isCircle && ( xdist * xdist + ydist * ydist <= radius * radius ) ||
295     if ( isCircle && ( xdist * xdist + ydist * ydist <= myMarkerSize * myMarkerSize ) ||
296     !isCircle && ( fabs( xdist ) <= radius && fabs( ydist ) <= radius ) )
297     {
298       isFound = FALSE;
299       count++;
300       for ( it = myCurSelNumbers.begin(); it != myCurSelNumbers.end(); ++it )
301         if( i == *it )
302         {
303           isFound = TRUE;
304           curHNumbers.append( i );
305         }
306       
307       if( !isFound )
308           myHNumbers.append( i );
309       else
310         cnt++;
311     }
312   }
313   myCurSelNumbers = curHNumbers;
314
315   myIsHigh = ( GLboolean )count;
316   update = ( GLboolean )( myHNumbers != myPrevHNumbers );
317
318   myPrevHNumbers = myHNumbers;
319
320   //cout << "GLViewer_MarkerSet::highlight complete with " << (int)myIsHigh << endl;
321   return update;
322 }
323
324 GLboolean GLViewer_MarkerSet::unhighlight()
325 {
326   if( !myHNumbers.isEmpty() )
327   {
328     myUHNumbers += myHNumbers;
329     myPrevHNumbers.clear();
330     myHNumbers.clear();
331     //??? myCurSelNumbers.clear();
332     return GL_TRUE;
333   }
334   
335   return GL_FALSE;
336 }
337
338 GLboolean GLViewer_MarkerSet::select( GLfloat x, GLfloat y, GLfloat tol, GLViewer_Rect rect, GLboolean isFull,
339                                       GLboolean isCircle, GLboolean isShift )
340 {
341     if( !myIsVisible )
342         return false;
343 //  cout << "GLViewer_MarkerSet::select " << x << " " << y << endl;
344   int count = 0;
345   GLfloat xdist, ydist, radius;
346   QValueList<int>::Iterator it;
347   QValueList<int>::Iterator it1;
348   QValueList<int>::Iterator remIt;
349   QValueList<int>::Iterator curIt;
350
351   radius = tol - myMarkerSize / 2.;
352
353   if( radius < myMarkerSize / 2.)
354     radius = myMarkerSize / 2.;
355
356   count = isShift ? mySelNumbers.count() : 0;
357
358   myUSelNumbers = mySelNumbers;
359
360   if ( !isShift )
361   {
362     mySelNumbers.clear();
363     myCurSelNumbers.clear();
364   }
365
366   for ( int i = 0; i < myNumber; i++ ) 
367   {
368     xdist = ( myXCoord[i] - x ) * myXScale;
369     ydist = ( myYCoord[i] - y ) * myYScale;
370
371     //if ( isCircle && ( xdist * xdist + ydist * ydist <= radius * radius ) ||
372     if ( isCircle && ( xdist * xdist + ydist * ydist <= myMarkerSize * myMarkerSize ) ||
373           !isCircle && ( fabs( xdist ) <= radius && fabs( ydist ) <= radius ) )
374     {
375       count++;
376       if ( isShift )
377       {
378         bool isFound = FALSE;
379           for( it = mySelNumbers.begin(); it != mySelNumbers.end(); ++it )
380             if ( *it == i )
381             {
382               myUSelNumbers.append( *it );
383             remIt = it;
384               isFound = TRUE;
385               break;
386             }
387
388           if ( !isFound )
389         {
390           mySelNumbers.append( i );
391             myCurSelNumbers.append( i );
392             for ( it1 = myHNumbers.begin(); it1 != myHNumbers.end(); ++it1 )
393               if( i == *it1 )
394               {
395                 myHNumbers.remove( it1 );
396                 break;
397               }
398       for ( it1 = myUHNumbers.begin(); it1 != myUHNumbers.end(); ++it1 )
399         if( i == *it1 )
400         {
401           myUHNumbers.remove( it1 );
402           break;
403         }
404         }
405     else
406         {
407       mySelNumbers.remove( remIt );
408       for ( curIt = myCurSelNumbers.begin(); curIt != myCurSelNumbers.end(); ++curIt )
409         if( *curIt == *remIt)
410         {
411           myCurSelNumbers.remove( curIt );
412           break;
413         }
414       for ( it1 = myHNumbers.begin(); it1 != myHNumbers.end(); ++it1 )
415         if( i == *it1 )
416         {
417           myHNumbers.remove( it1 );
418           break;
419         }
420       for ( it1 = myUHNumbers.begin(); it1 != myUHNumbers.end(); ++it1 )
421         if( i == *it1 )
422         {
423           myUHNumbers.remove( it1 );
424           break;
425         }
426         }
427       }
428       else
429       {
430     mySelNumbers.append( i );
431     myCurSelNumbers.append( i );
432     for ( it1 = myHNumbers.begin(); it1 != myHNumbers.end(); ++it1 )
433       if( i == *it1 )
434       {
435         myHNumbers.remove( it1 );
436         break;
437       }
438     for ( it1 = myUHNumbers.begin(); it1 != myUHNumbers.end(); ++it1 )
439       if( i == *it1 )
440           {
441         myUHNumbers.remove( it1 );
442         break;
443       }        
444       }     
445     }
446   }
447
448   for( it = mySelNumbers.begin(); it != mySelNumbers.end(); ++it )
449     for( it1 = myUSelNumbers.begin(); it1 != myUSelNumbers.end(); ++it1 )
450       if( *it == *it1 )
451       {
452         it1 = myUSelNumbers.remove( it1 );
453         it1--;
454       }
455   
456   myIsSel = (GLboolean)count;
457
458 //  cout << "GLViewer_MarkerSet::select complete with " << (int)myIsSel << endl;
459   return myIsSel;
460 }
461
462 GLboolean GLViewer_MarkerSet::unselect()
463 {
464   if( !mySelNumbers.isEmpty() )
465   {
466     myUSelNumbers = mySelNumbers;
467     mySelNumbers.clear();
468     myCurSelNumbers.clear();
469     return GL_TRUE;
470   }
471
472   return GL_FALSE;
473 }
474
475 GLViewer_Rect* GLViewer_MarkerSet::getUpdateRect()
476 {
477   GLViewer_Rect* rect = new GLViewer_Rect();
478   
479   rect->setLeft( myRect->left() + myXGap - myMarkerSize / myXScale );
480   rect->setTop( myRect->top() + myYGap + myMarkerSize / myYScale ); 
481   rect->setRight( myRect->right() - myXGap + myMarkerSize / myXScale );
482   rect->setBottom( myRect->bottom() - myYGap - myMarkerSize / myYScale );
483   //cout << " Additional tolerance " << myMarkerSize / myYScale << endl;
484   //rect->setLeft( myRect->left() - myMarkerSize / myXScale );
485   //rect->setTop( myRect->top() - myMarkerSize / myYScale ); 
486   //rect->setRight( myRect->right() + myMarkerSize / myXScale );
487   //rect->setBottom( myRect->bottom() + myMarkerSize / myYScale );
488   
489   return rect;
490 }
491
492
493 void GLViewer_MarkerSet::setXCoord( GLfloat* xCoord, int size )
494 {
495   myXCoord = new GLfloat[ size ];
496   for( int i = 0; i < size; i++ )
497      myXCoord[i] = xCoord[i];
498 }
499
500 void GLViewer_MarkerSet::setYCoord( GLfloat* yCoord, int size )
501 {
502   myYCoord = new GLfloat[ size ];
503   for( int i = 0; i < size; i++ )
504      myYCoord[i] = yCoord[i];
505 }
506
507 void GLViewer_MarkerSet::setNumMarkers( GLint number )
508 {
509   if ( myNumber == number )
510     return;
511     
512   if ( myXCoord && myYCoord )
513   {
514     delete[] myXCoord;
515     delete[] myYCoord;
516   }
517
518   myNumber = number;
519   myXCoord = new GLfloat[ myNumber ];
520   myYCoord = new GLfloat[ myNumber ];
521 }
522 /*
523 void GLViewer_MarkerSet::onSelectionDone( bool append)
524 {
525   mySelectedIndexes.Clear();
526   QValueList<int>::Iterator it;
527   //for( it = myMarkers->mySelNumbers.begin(); it != myMarkers->mySelNumbers.end(); ++it )
528   //  mySelectedIndexes.Append( *it / 2 ); //!!!
529
530   emit dvMarkersSelected( mySelectedIndexes );
531 }
532
533 void GLViewer_MarkerSet::onSelectionCancel()
534 {
535   mySelectedIndexes.Clear();
536   emit dvMarkersSelected( mySelectedIndexes );
537 }
538 */
539 void GLViewer_MarkerSet::exportNumbers( QValueList<int>& highlight,
540                      QValueList<int>& unhighlight,
541                      QValueList<int>& select,
542                      QValueList<int>& unselect )
543 {
544     highlight = myHNumbers;
545     unhighlight = myUHNumbers;
546     select = mySelNumbers;
547     unselect = myUSelNumbers;
548
549     myUHNumbers = myHNumbers;
550 }
551
552 bool GLViewer_MarkerSet::addOrRemoveSelected( int index )
553 {
554   if( index < 0 || index > myNumber )
555     return FALSE;
556
557   int n = mySelNumbers.findIndex( index );
558   if( n == -1 )
559     mySelNumbers.append( index );
560   else
561   {
562     QValueList<int>::Iterator it;
563     it = mySelNumbers.at( n );
564     mySelNumbers.remove( it );
565     myUSelNumbers.append( index );
566   }
567   return TRUE;
568 }
569
570 void GLViewer_MarkerSet::addSelected( const TColStd_SequenceOfInteger& seq )
571 {
572   for ( int i = 1; i <= seq.Length(); i++ )
573     if( mySelNumbers.findIndex( seq.Value( i ) ) == -1 )
574       mySelNumbers.append( seq.Value( i ) - 1 );
575 }
576
577 void GLViewer_MarkerSet::setSelected( const TColStd_SequenceOfInteger& seq )
578 {
579 //   for( QValueList<int>::Iterator it = mySelNumbers.begin(); it != mySelNumbers.end(); ++it )
580 //     if( myUSelNumbers.findIndex( *it ) == -1 )
581 //       myUSelNumbers.append( *it );
582
583   myUSelNumbers = mySelNumbers;
584   mySelNumbers.clear();
585     
586   for ( int i = 1; i <= seq.Length(); i++ )
587     mySelNumbers.append( seq.Value( i ) - 1 );
588 }
589
590 void GLViewer_MarkerSet::moveObject( float theX, float theY, bool fromGroup )
591 {
592     if( !fromGroup && myGroup)
593     {
594       myGroup->dragingObjects( theX, theY );
595       return;
596     }
597     for( int i = 0; i < myNumber;  i++ )
598     {
599         myXCoord[i] = myXCoord[i] + theX;
600         myYCoord[i] = myYCoord[i] + theY;
601     }
602     compute();    
603 }
604
605 QByteArray GLViewer_MarkerSet::getByteCopy()
606 {
607     int i = 0;
608     int anISize = sizeof( GLint );
609     int aFSize = sizeof( GLfloat );
610     
611     QByteArray aObject = GLViewer_Object::getByteCopy();
612
613     QByteArray aResult( anISize + 2*aFSize*myNumber + aFSize + aObject.size());
614
615     char* aPointer = (char*)&myNumber;
616     for( i = 0; i < anISize; i++, aPointer++ )
617         aResult[i] = *aPointer;
618
619     aPointer = (char*)myXCoord;
620     for( ; i < anISize + aFSize*myNumber; i++, aPointer++ )
621         aResult[i] = *aPointer;
622     aPointer = (char*)myYCoord;
623     for( ; i < anISize + 2*aFSize*myNumber; i++, aPointer++ )
624         aResult[i] = *aPointer;
625     
626     aPointer = (char*)&myMarkerSize;
627     for( ; i < anISize + 2*aFSize*myNumber + aFSize; i++, aPointer++ )
628         aResult[i] = *aPointer;
629         
630     
631     for( ; i < aResult.size(); i++ )
632         aResult[i] = aObject[i - anISize - 2*aFSize*myNumber - aFSize];
633
634     return aResult;
635 }
636
637 bool GLViewer_MarkerSet::initializeFromByteCopy( QByteArray theArray )
638 {
639     int i = 0;
640     int anISize = sizeof( GLint );
641     int aFSize = sizeof( GLfloat );
642
643     char* aPointer = (char*)&myNumber;
644     for( i = 0; i < anISize; i++, aPointer++ )
645         *aPointer = theArray[i];
646
647     int aSize = theArray.size();
648     if( aSize < anISize + 2*aFSize*myNumber + aFSize)
649         return false;
650
651     myXCoord = new GLfloat[myNumber];
652     myYCoord = new GLfloat[myNumber];
653     aPointer = (char*)myXCoord;
654     for( ; i < anISize + aFSize*myNumber; i++, aPointer++ )
655         *aPointer = theArray[i];
656     aPointer = (char*)myYCoord;
657     for( ; i < anISize + 2*aFSize*myNumber; i++, aPointer++ )
658         *aPointer = theArray[i];
659
660     aPointer = (char*)&myMarkerSize;
661     for( ; i < anISize + 2*aFSize*myNumber + aFSize; i++, aPointer++ )
662          *aPointer = theArray[i];
663          
664     int aCurIndex = anISize + 2*aFSize*myNumber + aFSize;
665     QByteArray aObject( aSize - aCurIndex );
666     for( ; i < aSize; i++ )
667         aObject[i - aCurIndex] = theArray[i];
668         
669
670     if( !GLViewer_Object::initializeFromByteCopy( aObject ) || myType != "GLViewer_MarkerSet" )
671         return false;
672
673     myHNumbers.clear();
674     myUHNumbers.clear();
675     mySelNumbers.clear();
676     myUSelNumbers.clear();
677     myCurSelNumbers.clear();
678     myPrevHNumbers.clear();
679
680     return true;        
681 }
682
683 /***************************************************************************
684 **  Class:   GLViewer_Polyline
685 **  Descr:   OpenGL Polyline
686 **  Module:  GLViewer
687 **  Created: UI team, 03.09.02
688 ****************************************************************************/
689
690 #define SECTIONS 100
691 #define DISTANTION 5
692
693 GLViewer_Polyline::GLViewer_Polyline( int number, float size, const QString& toolTip ):
694   GLViewer_Object(),
695   myNumber( 0 ),
696   myXCoord( 0 ),
697   myYCoord( 0 )       
698 {
699   myHighFlag = GL_TRUE;
700
701   myHNumbers.clear();
702   myUHNumbers.clear();
703   mySelNumbers.clear();
704   myUSelNumbers.clear();
705   myCurSelNumbers.clear();
706   myPrevHNumbers.clear();
707
708   setNumber( number );
709
710   myType = "GLViewer_Polyline";
711   myToolTipText = toolTip;
712 }
713
714 GLViewer_Polyline::~GLViewer_Polyline()
715 {
716   if ( myXCoord )
717     delete[] myXCoord;
718   if ( myYCoord )
719     delete[] myYCoord;
720 }
721
722 bool GLViewer_Polyline::translateToPS( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aPSCS )
723 {
724     QString aBuffer = "newpath\n";
725
726     AddLineAspectToPS( aBuffer, getAspectLine(), aViewerCS, aPSCS );
727
728     for( int i=0; i<myNumber; i++ )
729         if( i==0 )
730             AddCoordsToPS( aBuffer, "moveto", aViewerCS, aPSCS, myXCoord[i], myYCoord[i] );
731         else
732             AddCoordsToPS( aBuffer, "lineto", aViewerCS, aPSCS, myXCoord[i], myYCoord[i] );
733
734     if( myIsClosed )
735         AddCoordsToPS( aBuffer, "lineto", aViewerCS, aPSCS, myXCoord[0], myYCoord[0] );
736
737     aBuffer+="closepath\nstroke\n";
738     
739     hFile.writeBlock( aBuffer.ascii(), aBuffer.length() );
740
741     return true;
742 }
743
744 bool GLViewer_Polyline::translateToHPGL( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aHPGLCS )
745 {
746     QString aBuffer = "";
747     for( int i=0; i<myNumber; i++ )
748     {
749         AddCoordsToHPGL( aBuffer, "PA", aViewerCS, aHPGLCS, myXCoord[i], myYCoord[i] );
750         if( i==0 )
751             aBuffer+="PD;\n";
752     }
753
754     if( myIsClosed )
755         AddCoordsToHPGL( aBuffer, "PA", aViewerCS, aHPGLCS, myXCoord[0], myYCoord[0] );
756
757     aBuffer+="PU;\n";
758     
759     hFile.writeBlock( aBuffer.ascii(), aBuffer.length() );
760
761     return true;
762 }
763
764 #ifdef WIN32
765 bool GLViewer_Polyline::translateToEMF( HDC dc, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aEMFCS )
766 {
767     if( !aViewerCS || !aEMFCS )
768         return false;
769     
770     HPEN pen = AddLineAspectToEMF( dc, getAspectLine(), aViewerCS, aEMFCS );
771     HGDIOBJ old = SelectObject( dc, pen );
772
773     double x, y;
774     for( int i=0; i<myNumber; i++ )
775     {
776         x = myXCoord[i];
777         y = myYCoord[i];
778         aViewerCS->transform( *aEMFCS, x, y );
779         if( i==0 )
780             MoveToEx( dc, x, y, NULL );
781         else
782             LineTo( dc, x, y );
783     }
784
785     if( myIsClosed )
786     {
787         x = myXCoord[0];
788         y = myYCoord[0];
789         aViewerCS->transform( *aEMFCS, x, y );
790         LineTo( dc, x, y );
791     }
792
793     SelectObject( dc, old );
794     if( pen )
795         DeleteObject( pen );
796
797     return true;
798 }
799 #endif
800
801 void GLViewer_Polyline::compute()
802 {
803 //  cout << "GLViewer_MarkerSet::compute" << endl;
804   GLfloat xa = myXCoord[0]; 
805   GLfloat xb = myXCoord[0]; 
806   GLfloat ya = myYCoord[0]; 
807   GLfloat yb = myYCoord[0]; 
808
809   for ( int i = 0; i < myNumber; i++ )  
810   {
811     xa = QMIN( xa, myXCoord[i] );
812     xb = QMAX( xb, myXCoord[i] );
813     ya = QMIN( ya, myYCoord[i] );
814     yb = QMAX( yb, myYCoord[i] );
815   }
816
817   GLfloat xGap = ( xb - xa ) / 10;
818   GLfloat yGap = ( yb - ya ) / 10;
819
820   myRect->setLeft( xa - xGap );
821   myRect->setTop( yb + yGap ); 
822   myRect->setRight( xb + xGap );
823   myRect->setBottom( ya - yGap );
824 }
825
826 GLViewer_Rect* GLViewer_Polyline::getUpdateRect()
827 {
828     GLViewer_Rect* rect = new GLViewer_Rect();
829
830     rect->setLeft( myRect->left() - myXGap );
831     rect->setTop( myRect->top() + myYGap ); 
832     rect->setRight( myRect->right() + myXGap );
833     rect->setBottom( myRect->bottom() - myYGap );
834
835     return rect;
836 }
837
838 GLViewer_Drawer* GLViewer_Polyline::createDrawer()
839 {
840 //  cout << "GLViewer_MarkerSet::createDrawer" << endl;
841     return myDrawer = new GLViewer_PolylineDrawer();
842 }
843
844 GLboolean GLViewer_Polyline::highlight( GLfloat x, GLfloat y, GLfloat tol, GLboolean isCircle )
845 {
846     if( !myIsVisible )
847         return false;
848     GLfloat xa, xb, ya, yb, l;
849     GLfloat rsin, rcos, r, ra, rb;
850     GLboolean update;
851     GLboolean highlighted = myIsHigh;
852
853     myIsHigh = GL_FALSE;
854
855     int c = 0;
856     if( myIsClosed )
857         c = 1;
858
859     for( int i = 0; i < myNumber-1+c; i++ ) 
860     {
861         xa = myXCoord[i];
862         ya = myYCoord[i];
863         if( i != myNumber-1 )
864         {
865               xb = myXCoord[i+1];
866               yb = myYCoord[i+1];
867         }
868         else
869         {    
870               xb = myXCoord[0];      
871               yb = myYCoord[0];
872         }
873
874         l = sqrt( (xb-xa)*(xb-xa) + (yb-ya)*(yb-ya) );
875         rsin = (yb-ya) / l;
876         rcos = (xb-xa) / l;
877         r = ( (x-xa)*(y-yb) - (x-xb)*(y-ya) ) / ( rsin*(ya-yb) + rcos*(xa-xb) );
878         ra = sqrt( (x-xa)*(x-xa) + (y-ya)*(y-ya) );
879         rb = sqrt( (x-xb)*(x-xb) + (y-yb)*(y-yb) );
880         if( fabs( r ) * myXScale <= DISTANTION && ra <= l + DISTANTION && rb <= l + DISTANTION )
881         {
882             myIsHigh = GL_TRUE;
883             break;
884         }
885     }
886
887     if( !myHighFlag && myIsHigh )
888         myIsHigh = GL_FALSE;
889     else
890         myHighFlag = GL_TRUE;
891
892     update = ( GLboolean )( myIsHigh != highlighted );
893
894 //  cout << "GLViewer_Polyline::highlight complete with " << (int)myIsHigh << endl;
895     return update;
896 }
897
898 GLboolean GLViewer_Polyline::unhighlight()
899 {
900 //   if( !myHNumbers.isEmpty() )
901 //   {
902 //     myUHNumbers = myHNumbers;
903 //     myHNumbers.clear();
904 //     return GL_TRUE;
905 //   }
906
907   if( myIsHigh )
908   {
909     myIsHigh = GL_FALSE;
910     return GL_TRUE;
911   }
912
913   return GL_FALSE;
914 }
915
916 GLboolean GLViewer_Polyline::select( GLfloat x, GLfloat y, GLfloat tol, GLViewer_Rect rect, GLboolean isFull,
917                                      GLboolean isCircle, GLboolean isShift )
918 {
919     if( !myIsVisible )
920         return false;
921     GLfloat xa, xb, ya, yb, l;
922     GLfloat rsin, rcos, r, ra, rb;
923     GLboolean update;
924     GLboolean selected = myIsSel;
925
926     myIsSel = GL_FALSE;
927
928     int c = 0;
929     if( myIsClosed )
930         c = 1;
931
932     for( int i = 0; i < myNumber-1+c; i++ ) 
933     {
934         xa = myXCoord[i];
935         ya = myYCoord[i];
936         if( i != myNumber-1 )
937         {
938             xb = myXCoord[i+1];
939             yb = myYCoord[i+1];
940         }
941         else
942         {
943             xb = myXCoord[0];
944             yb = myYCoord[0];
945         }
946
947         l = sqrt( (xb-xa)*(xb-xa) + (yb-ya)*(yb-ya) );
948         rsin = (yb-ya) / l;
949         rcos = (xb-xa) / l;
950         r = ( (x-xa)*(y-yb) - (x-xb)*(y-ya) ) / ( rsin*(ya-yb) + rcos*(xa-xb) );
951         ra = sqrt( (x-xa)*(x-xa) + (y-ya)*(y-ya) );
952         rb = sqrt( (x-xb)*(x-xb) + (y-yb)*(y-yb) );
953         if( fabs( r ) * myXScale <= DISTANTION && ra <= l + DISTANTION && rb <= l + DISTANTION )
954         {
955             myIsSel = GL_TRUE;
956             break;
957         }
958     }
959
960     if ( myIsSel )
961     {
962         myHighFlag = GL_FALSE;
963         myIsHigh = GL_FALSE;
964     }
965     else
966         myHighFlag = GL_TRUE;
967
968     update = ( GLboolean )( myIsSel != selected );
969
970     //  cout << "GLViewer_Polyline::select complete with " << (int)myIsSel << endl;
971
972     //  return update;  !!!!!!!!!!!!!!!!!!!!!!!!!!! no here
973     return myIsSel;
974 }
975
976 GLboolean GLViewer_Polyline::unselect()
977 {
978 //   if( !mySelNumbers.isEmpty() )
979 //   {
980 //     myUSelNumbers = mySelNumbers;
981 //     mySelNumbers.clear();
982 //     myCurSelNumbers.clear();
983 //     return GL_TRUE;
984 //   }
985
986   if( myIsSel )
987   {
988     myIsSel = GL_FALSE;
989     return GL_TRUE;
990   }
991
992   return GL_FALSE;
993 }
994
995 void GLViewer_Polyline::setXCoord( GLfloat* xCoord, int size )
996 {
997   myXCoord = new GLfloat[ size ];
998   for( int i = 0; i < size; i++ )
999      myXCoord[i] = xCoord[i];
1000 }
1001
1002 void GLViewer_Polyline::setYCoord( GLfloat* yCoord, int size )
1003 {
1004   myYCoord = new GLfloat[ size ];
1005   for( int i = 0; i < size; i++ )
1006      myYCoord[i] = yCoord[i];
1007 }
1008
1009 void GLViewer_Polyline::setNumber( GLint number )
1010 {
1011   if ( myNumber == number )
1012     return;
1013     
1014   if ( myXCoord && myYCoord )
1015   {
1016     delete[] myXCoord;
1017     delete[] myYCoord;
1018   }
1019
1020   myNumber = number;
1021   myXCoord = new GLfloat[ myNumber ];
1022   myYCoord = new GLfloat[ myNumber ];
1023 }
1024 /*
1025 void GLViewer_Polyline::onSelectionDone( bool append)
1026 {
1027   mySelectedIndexes.Clear();
1028   QValueList<int>::Iterator it;
1029   //for( it = myMarkers->mySelNumbers.begin(); it != myMarkers->mySelNumbers.end(); ++it )
1030   //  mySelectedIndexes.Append( *it / 2 ); //!!!
1031 }
1032
1033 void GLViewer_Polyline::onSelectionCancel()
1034 {
1035   mySelectedIndexes.Clear();
1036 }
1037 */
1038 void GLViewer_Polyline::exportNumbers( QValueList<int>& highlight,
1039                      QValueList<int>& unhighlight,
1040                      QValueList<int>& select,
1041                      QValueList<int>& unselect )
1042 {
1043   highlight = myHNumbers;
1044   unhighlight = myUHNumbers;
1045   select = mySelNumbers;
1046   unselect = myUSelNumbers;
1047 }
1048
1049 void GLViewer_Polyline::moveObject( float theX, float theY, bool fromGroup )
1050 {
1051   if( !fromGroup && myGroup)
1052   {
1053     myGroup->dragingObjects( theX, theY );
1054     return;
1055   }
1056   for( int i = 0; i < myNumber;  i++ )
1057   {
1058       myXCoord[i] = myXCoord[i] + theX;
1059       myYCoord[i] = myYCoord[i] + theY;
1060   }
1061   compute();    
1062 }
1063
1064 QByteArray GLViewer_Polyline::getByteCopy()
1065 {
1066     int i = 0;
1067     int anISize = sizeof( GLint );
1068     int aFSize = sizeof( GLfloat );
1069     int aBSize = sizeof( GLboolean );
1070
1071     QByteArray aObject = GLViewer_Object::getByteCopy();
1072
1073     QByteArray aResult( aFSize*myNumber*2 + anISize + 2*aBSize + aObject.size());
1074
1075     char* aPointer = (char*)&myNumber;
1076     for( i = 0; i < anISize; i++, aPointer++ )
1077         aResult[i] = *aPointer;
1078
1079     aPointer = (char*)myXCoord;
1080     for( ; i < anISize + aFSize*myNumber; i++, aPointer++ )
1081         aResult[i] = *aPointer;
1082     aPointer = (char*)myYCoord;
1083     for( ; i < anISize + 2*aFSize*myNumber; i++, aPointer++ )
1084         aResult[i] = *aPointer;
1085     
1086     aPointer = (char*)&myIsClosed;
1087     for( ; i < anISize + 2*aFSize*myNumber + aBSize; i++, aPointer++ )
1088         aResult[i] = *aPointer;
1089     aPointer = (char*)&myHighSelAll;
1090     for( ; i < anISize + 2*aFSize*myNumber + 2*aBSize; i++, aPointer++ )
1091         aResult[i] = *aPointer;
1092
1093     for( ; i < aResult.size(); i++ )
1094         aResult[i] = aObject[i - anISize - 2*aFSize*myNumber - 2*aBSize];
1095
1096     return aResult;
1097 }
1098
1099
1100 bool GLViewer_Polyline::initializeFromByteCopy( QByteArray theArray )
1101 {
1102     int i = 0;
1103     int anISize = sizeof( GLint );
1104     int aFSize = sizeof( GLfloat );
1105     int aBSize = sizeof( GLboolean );
1106
1107     char* aPointer = (char*)&myNumber;
1108     for( i = 0; i < anISize; i++, aPointer++ )
1109         *aPointer = theArray[i];
1110
1111     int aSize = theArray.size();
1112     if( aSize < aFSize*myNumber*2 + anISize + 2*aBSize )
1113         return false;
1114
1115     myXCoord = new GLfloat[myNumber];
1116     myYCoord = new GLfloat[myNumber];
1117     aPointer = (char*)myXCoord;
1118     for( ; i < anISize + aFSize*myNumber; i++, aPointer++ )
1119         *aPointer = theArray[i];
1120     aPointer = (char*)myYCoord;
1121     for( ; i < anISize + 2*aFSize*myNumber; i++, aPointer++ )
1122         *aPointer = theArray[i];
1123
1124     aPointer = (char*)&myIsClosed;
1125     for( ; i < anISize + 2*aFSize*myNumber + aBSize; i++, aPointer++ )
1126          *aPointer = theArray[i];
1127     aPointer = (char*)&myHighSelAll;
1128     for( ; i < anISize + 2*aFSize*myNumber + 2*aBSize; i++, aPointer++ )
1129          *aPointer = theArray[i];
1130
1131     int aCurIndex = anISize + 2*aFSize*myNumber + 2*aBSize;
1132     QByteArray aObject( aSize - aCurIndex );
1133     for( ; i < aSize; i++ )
1134         aObject[i - aCurIndex] = theArray[i];
1135
1136     if( !GLViewer_Object::initializeFromByteCopy( aObject ) || myType != "GLViewer_Polyline" )
1137         return false;
1138
1139     myHNumbers.clear();
1140     myUHNumbers.clear();
1141     mySelNumbers.clear();
1142     myUSelNumbers.clear();
1143     myCurSelNumbers.clear();
1144     myPrevHNumbers.clear();
1145
1146     return true;        
1147 }
1148
1149 /***************************************************************************
1150 **  Class:   GLViewer_TextObject
1151 **  Descr:   Text as Object for OpenGL
1152 **  Module:  GLViewer
1153 **  Created: UI team, 12.02.04
1154 ****************************************************************************/
1155
1156 GLViewer_TextObject::GLViewer_TextObject( const QString& theStr, float xPos, float yPos, 
1157                                     const QColor& color, const QString& toolTip )
1158                                     : GLViewer_Object()
1159 {
1160     myGLText = new GLViewer_Text( theStr, xPos, yPos, color );
1161     myWidth = 0;
1162     myHeight = 0;
1163
1164     myHighFlag = GL_TRUE;
1165
1166     myToolTipText = toolTip;
1167 }
1168 GLViewer_TextObject::~GLViewer_TextObject()
1169 {
1170   if ( myGLText )
1171     delete myGLText;
1172 }
1173
1174 bool GLViewer_TextObject::translateToPS( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aPSCS )
1175 {
1176     QString aText = myGLText->getText();    
1177     float xPos, yPos;
1178     myGLText->getPosition( xPos, yPos );
1179
1180     QString aBuffer = "/Times-Roman findfont\n";
1181     aBuffer += "12 scalefont setfont\n";
1182
1183     AddCoordsToPS( aBuffer, "moveto", aViewerCS, aPSCS, double(xPos), double(yPos) );
1184     aBuffer += "(" + aText + ") show\n";
1185
1186     hFile.writeBlock( aBuffer.ascii(), aBuffer.length() );
1187
1188     return true;
1189 }
1190
1191 bool GLViewer_TextObject::translateToHPGL( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aHPGLCS )
1192 {
1193     QString aText = myGLText->getText();    
1194     float xPos, yPos;
1195     myGLText->getPosition( xPos, yPos );
1196
1197     QString aBuffer = "";
1198     AddCoordsToHPGL( aBuffer, "PA", aViewerCS, aHPGLCS, double(xPos), double(yPos) );
1199     
1200     aBuffer = "LB" + aText + "#;";
1201     
1202     hFile.writeBlock( aBuffer.ascii(), aBuffer.length() );
1203
1204     return true;
1205 }
1206
1207 #ifdef WIN32
1208 bool GLViewer_TextObject::translateToEMF( HDC dc, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aEMFCS )
1209 {
1210     QString aText = myGLText->getText();    
1211     float xPos, yPos;
1212     myGLText->getPosition( xPos, yPos );
1213
1214     double x = double( xPos ), 
1215            y = double( yPos );
1216
1217     aViewerCS->transform( *aEMFCS, x, y );
1218     const char* str = aText.ascii();
1219
1220     int nHeight = 35*14;       // height of font
1221     int nWidth = 35*12;        // average character width
1222     int nEscapement = 0;       // angle of escapement
1223     int nOrientation = 0;      // base-line orientation angle
1224     int fnWeight = FW_NORMAL;  // font weight
1225     DWORD fdwItalic = FALSE;    // italic attribute option
1226     DWORD fdwUnderline = FALSE; // underline attribute option
1227     DWORD fdwStrikeOut = FALSE; // strikeout attribute option
1228     DWORD fdwCharSet = ANSI_CHARSET; // character set identifier
1229     DWORD fdwOutputPrecision = OUT_DEFAULT_PRECIS;  // output precision
1230     DWORD fdwClipPrecision = CLIP_DEFAULT_PRECIS;    // clipping precision
1231     DWORD fdwQuality = PROOF_QUALITY;          // output quality
1232     DWORD fdwPitchAndFamily = FIXED_PITCH | FF_DONTCARE;   // pitch and family
1233     LPCTSTR lpszFace = NULL;         // typeface name
1234
1235
1236     HFONT aFont = CreateFont( nHeight, nWidth, nEscapement, nOrientation, fnWeight, fdwItalic,
1237                               fdwUnderline, fdwStrikeOut, fdwCharSet, fdwOutputPrecision, 
1238                               fdwClipPrecision, fdwQuality, fdwPitchAndFamily, lpszFace );
1239     LOGBRUSH aBrushData;
1240     aBrushData.lbStyle = BS_HOLLOW;
1241
1242     HBRUSH aBrush = CreateBrushIndirect( &aBrushData );
1243
1244     HGDIOBJ old1 = SelectObject( dc, aFont );
1245     HGDIOBJ old2 = SelectObject( dc, aBrush );
1246
1247     TextOut( dc, x, y, str, aText.length() );
1248
1249     SelectObject ( dc, old1 );
1250     SelectObject ( dc, old2 );
1251
1252     DeleteObject( aFont );
1253
1254     return true;
1255 }
1256 #endif
1257
1258 GLViewer_Drawer* GLViewer_TextObject::createDrawer()
1259 {
1260     myDrawer = new GLViewer_TextDrawer();
1261     compute();
1262     return myDrawer;
1263 }
1264
1265 void GLViewer_TextObject::compute()
1266 {
1267     float xPos, yPos;
1268     QString aStr = myGLText->getText();
1269     myGLText->getPosition( xPos, yPos );
1270
1271     myWidth = myGLText->getWidth();
1272     myHeight = myGLText->getHeight();
1273     myRect->setLeft( xPos );
1274     myRect->setTop( yPos + myHeight  ); 
1275     myRect->setRight( xPos + myWidth );
1276     myRect->setBottom( yPos );
1277 }
1278
1279 void GLViewer_TextObject::setDrawer( GLViewer_Drawer* theDrawer )
1280 {
1281     myDrawer = theDrawer;
1282     //compute();
1283 }
1284
1285 GLViewer_Rect* GLViewer_TextObject::getUpdateRect()
1286 {    
1287     GLViewer_Rect* rect = new GLViewer_Rect();
1288
1289     float xPos, yPos;
1290     QString aStr = myGLText->getText();
1291     myGLText->getPosition( xPos, yPos );
1292
1293     rect->setLeft( myRect->left() + myXGap - myWidth / myXScale );
1294     rect->setTop( myRect->top() + myYGap + myHeight / myYScale );
1295     rect->setRight( myRect->right() - myXGap + myWidth / myXScale );
1296     rect->setBottom( myRect->bottom() - myYGap - myHeight / myYScale );
1297
1298     return rect;
1299 }
1300
1301 GLboolean GLViewer_TextObject::highlight( GLfloat theX, GLfloat theY, GLfloat theTol, GLboolean isCircle )
1302 {
1303     if( !myIsVisible )
1304         return false;
1305
1306     float xPos, yPos;
1307     myGLText->getPosition( xPos, yPos );
1308
1309     QRect aRect;
1310     aRect.setLeft( (int)xPos );
1311     aRect.setRight( (int)(xPos + myWidth / myXScale) );
1312     aRect.setTop( (int)yPos );// - myHeight / myYScale );
1313     aRect.setBottom( (int)(yPos + myHeight / myYScale) );
1314
1315     //cout << "theX: " << theX << "  theY: " << theY << endl;
1316     //cout << "aRect.left(): " << aRect.left() << "  aRect.right(): " << aRect.right() << endl;
1317     //cout << "aRect.top(): " << aRect.top() << "  aRect.bottom(): " << aRect.bottom() << endl;
1318
1319     QRegion obj( aRect );
1320     QRegion intersection;
1321     QRect region;
1322
1323     region.setLeft( (int)(theX - theTol) );
1324     region.setRight( (int)(theX + theTol) );
1325     region.setTop( (int)(theY - theTol) );
1326     region.setBottom( (int)(theY + theTol) );
1327
1328     QRegion circle( (int)(theX - theTol), (int)(theY - theTol),
1329                       (int)(2 * theTol), (int)(2 * theTol), QRegion::Ellipse );
1330     if( isCircle )
1331         intersection = obj.intersect( circle );
1332     else
1333         intersection = obj.intersect( region );
1334     
1335     if( intersection.isEmpty() )
1336         myIsHigh = false;
1337     else
1338         myIsHigh = true;
1339     
1340     if( !myHighFlag && myIsHigh )
1341         myIsHigh = GL_FALSE;
1342     else
1343         myHighFlag = GL_TRUE;
1344
1345     return myIsHigh;
1346 }
1347
1348 GLboolean GLViewer_TextObject::unhighlight()
1349 {
1350     if( myIsHigh )
1351     {
1352         myIsHigh = GL_FALSE;
1353         return GL_TRUE;
1354     }
1355
1356     return GL_FALSE;
1357 }
1358
1359 GLboolean GLViewer_TextObject::select( GLfloat theX, GLfloat theY, GLfloat theTol, GLViewer_Rect rect,
1360                                        GLboolean isFull, GLboolean isCircle, GLboolean isShift )
1361
1362     if( !myIsVisible )
1363         return false;
1364
1365     QRegion obj( myRect->toQRect() );
1366     QRegion intersection;
1367     QRect region;
1368
1369     region.setLeft( (int)(theX - theTol) );
1370     region.setRight( (int)(theX + theTol) );
1371     region.setTop( (int)(theY - theTol) );
1372     region.setBottom( (int)(theY + theTol) );
1373
1374     QRegion circle( (int)(theX - theTol), (int)(theY - theTol),
1375                       (int)(2 * theTol), (int)(2 * theTol), QRegion::Ellipse );
1376     if( isCircle )
1377         intersection = obj.intersect( circle );
1378     else
1379         intersection = obj.intersect( region );
1380     
1381     if( intersection.isEmpty() )
1382         myIsSel = false;
1383     else
1384         myIsSel = true;
1385
1386     if ( myIsSel )
1387     {
1388         myHighFlag = GL_FALSE;
1389         myIsHigh = GL_FALSE;
1390     }
1391     else
1392         myHighFlag = GL_TRUE;
1393
1394     return myIsSel;
1395 }
1396
1397 GLboolean GLViewer_TextObject::unselect()
1398 {
1399     if( myIsSel )
1400     {
1401         myIsSel = GL_FALSE;
1402         return GL_TRUE;
1403     }
1404
1405     return GL_FALSE;
1406 }
1407
1408 void GLViewer_TextObject::moveObject( float theX, float theY, bool fromGroup )
1409 {
1410   if( !fromGroup && myGroup)
1411   {
1412     myGroup->dragingObjects( theX, theY );
1413     return;
1414   }
1415   float aX, anY;
1416   myGLText->getPosition( aX, anY );
1417   aX += theX;
1418   anY += theY;
1419   myGLText->setPosition( aX, anY );
1420   compute();
1421 }
1422
1423 QByteArray GLViewer_TextObject::getByteCopy()
1424 {
1425     QByteArray aObject = GLViewer_Object::getByteCopy();
1426
1427     return aObject;
1428 }
1429
1430 bool GLViewer_TextObject::initializeFromByteCopy( QByteArray theArray )
1431 {
1432     if( !GLViewer_Object::initializeFromByteCopy( theArray ) || myType != "GLViewer_TextObject" )
1433         return false;
1434
1435     myHighFlag = true;
1436     return true;        
1437 }