Salome HOME
Transaction management in operations modifed.
[modules/gui.git] / src / GLViewer / GLViewer_Context.cxx
1 //  Copyright (C) 2005 OPEN CASCADE
2 //
3 //  This library is free software; you can redistribute it and/or
4 //  modify it under the terms of the GNU Lesser General Public
5 //  License as published by the Free Software Foundation; either
6 //  version 2.1 of the License.
7 //
8 //  This library is distributed in the hope that it will be useful,
9 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 //  Lesser General Public License for more details.
12 //
13 //  You should have received a copy of the GNU Lesser General Public
14 //  License along with this library; if not, write to the Free Software
15 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
18 //
19 //  Author : OPEN CASCADE
20 //
21
22 // File:      GLViewer_Context.cxx
23 // Created:   November, 2004
24
25 //================================================================
26 // Class       : GLViewer_AspectLine
27 // Description : Class for manage of presentations in GLViewer
28 //================================================================
29
30 #include "GLViewer_Context.h"
31
32 #include "GLViewer_Group.h"
33 #include "GLViewer_Object.h"
34 #include "GLViewer_Viewer2d.h"
35 #include "GLViewer_ViewPort2d.h"
36
37 #include <TColStd_SequenceOfInteger.hxx>
38
39 #define TOLERANCE  12
40
41 //=======================================================================
42 // Function: GLViewer_Context
43 // Purpose :
44 //=======================================================================
45 GLViewer_Context::GLViewer_Context( GLViewer_Viewer2d* v ) :
46        myGLViewer2d( v ),
47        myHighlightColor( Quantity_NOC_CYAN1 ),
48        mySelectionColor( Quantity_NOC_RED ),
49        myTolerance( TOLERANCE )
50 {
51   myUpdateAll = true;
52
53   myLastPicked = 0;
54   myLastPickedChanged = false;
55
56   myHFlag = GL_TRUE;
57   mySFlag = GL_TRUE;
58
59   mySelCurIndex = 0;
60 }
61
62 //=======================================================================
63 // Function: ~GLViewer_Context
64 // Purpose :
65 //=======================================================================
66 GLViewer_Context::~GLViewer_Context()
67 {
68     myActiveObjects.clear();
69     myInactiveObjects.clear();
70     mySelectedObjects.clear();
71 }
72
73 //=======================================================================
74 // Function: MoveTo
75 // Purpose :
76 //=======================================================================
77 int GLViewer_Context::MoveTo( int xi, int yi, bool byCircle )
78 {
79     GLfloat x = (GLfloat)xi;
80     GLfloat y = (GLfloat)yi;
81     myGLViewer2d->transPoint( x, y );
82
83     myXhigh = x;
84     myYhigh = y;  
85
86     GLboolean isHigh = GL_FALSE;
87     GLboolean onObject = GL_FALSE;
88
89     GLViewer_Object* aPrevLastPicked = myLastPicked;
90     GLViewer_Object* lastPicked = 0;
91
92     ObjList anUpdatedObjects;
93   
94     if( myActiveObjects.isEmpty() )
95         return -1;
96
97     ObjList::iterator it = myActiveObjects.end();
98     ObjList::iterator itEnd = myActiveObjects.begin();
99     for( it--; ; --it )
100     {
101         GLViewer_Object* object = *it;
102
103         GLViewer_Rect* rect = object->getUpdateRect();
104         if( rect->contains( GLViewer_Pnt( x, y ) ) )
105         {
106             onObject = GL_TRUE;
107             object->highlight( x, y, myTolerance, GL_FALSE );
108             isHigh = object->isHighlighted();
109         }
110
111         if( isHigh )
112         {
113             lastPicked = object;
114             break;
115         }
116
117         if( it == itEnd )
118             break;
119     }
120
121     if( !myHFlag )
122     {
123         myLastPicked = lastPicked;
124         return -1;
125     }
126
127     if ( !onObject )
128     {
129         //cout << 0 << endl;
130         it = myActiveObjects.begin();
131         itEnd = myActiveObjects.end();
132
133         for( ; it != itEnd; ++it )
134             (*it)->unhighlight();
135
136         anUpdatedObjects.append( (*it) );
137
138         myLastPicked = 0;
139         myLastPickedChanged = aPrevLastPicked != myLastPicked;
140
141         if( myLastPickedChanged )
142             myGLViewer2d->updateAll();  
143
144         return 0;
145     }
146
147     if( !myLastPicked && isHigh )
148     {
149         //cout << 1 << endl;
150         myLastPicked = lastPicked;
151         anUpdatedObjects.append( myLastPicked );
152     }
153     else if( myLastPicked && !isHigh )
154     {
155         //cout << 2 << endl;
156         myLastPicked->unhighlight();
157         anUpdatedObjects.append( myLastPicked );
158         myLastPicked = 0;
159     }
160     else if( myLastPicked && isHigh )
161     {
162         //cout << 3 << endl;
163         myLastPicked->highlight( x, y, myTolerance, byCircle );
164         anUpdatedObjects.append( myLastPicked );
165         if( myLastPicked != lastPicked )
166         {
167             myLastPicked->unhighlight();
168             myLastPicked = lastPicked;
169             anUpdatedObjects.append( myLastPicked );
170         }
171     }
172
173     myLastPickedChanged = ( aPrevLastPicked != myLastPicked );
174
175     if( myLastPickedChanged || myUpdateAll )
176         myGLViewer2d->updateAll();
177     else
178         myGLViewer2d->activateDrawers( anUpdatedObjects, TRUE, TRUE );
179
180     return 0;
181 }
182
183 //=======================================================================
184 // Function: Select
185 // Purpose :
186 //=======================================================================
187 int GLViewer_Context::Select( bool Append, bool byCircle )
188 {
189     ObjList::Iterator it, itEnd, oit, oitEnd;
190     SelectionStatus status = SS_Invalid;
191
192     bool updateAll = false;
193
194     ObjList aList;
195
196     if ( !mySFlag )
197         return status;//invalid
198
199     if( myHFlag && myLastPicked )
200     {
201         if( mySelectedObjects.count() == 1 && mySelectedObjects.first() == myLastPicked )
202             status = SS_LocalChanged;
203
204         if ( !Append )
205         {
206             for( it = mySelectedObjects.begin(), itEnd = mySelectedObjects.end() ; it != itEnd; ++it )
207                     if( myLastPicked != *it )
208                 {
209                         updateAll = (*it)->unselect() || updateAll;
210                         aList.append( *it );
211                 }
212
213             if( updateAll || myUpdateAll )
214                 myGLViewer2d->updateAll();
215             else
216                 myGLViewer2d->activateDrawers( aList, TRUE, TRUE );
217
218             if( mySelectedObjects.count() != 0 && status == SS_Invalid )
219                 status = SS_GlobalChanged;
220             mySelectedObjects.clear();
221         } 
222         else if( myLastPicked->isSelected() && status != SS_LocalChanged )
223         {
224             mySelectedObjects.remove( myLastPicked );
225             myLastPicked->unselect();
226             myGLViewer2d->updateAll();
227
228             if( mySelectedObjects.count() != 0 && status == SS_Invalid )
229               status = SS_GlobalChanged;
230
231             return status;
232         }
233
234         if ( myLastPicked->select( myXhigh, myYhigh, myTolerance, GLViewer_Rect(), false, byCircle, Append )
235              && mySelectedObjects.findIndex( myLastPicked ) == -1 )
236         {
237             mySelectedObjects.append( myLastPicked );
238             myGLViewer2d->activateDrawer( myLastPicked, TRUE, TRUE );
239
240             if( status == SS_Invalid )
241                 status = SS_GlobalChanged;
242         }
243         else if( status == SS_LocalChanged )
244             status = SS_GlobalChanged;
245
246         return status;
247     }
248
249     if( myHFlag && !myLastPicked )
250     {
251         if ( !Append )
252         {
253             for( it = mySelectedObjects.begin(), itEnd = mySelectedObjects.end() ; it != itEnd; ++it )
254                     if ( myLastPicked != *it )
255                 {
256                         updateAll = (*it)->unselect() || updateAll;
257                         aList.append( *it );
258                 }
259
260             if( updateAll || myUpdateAll )
261                 myGLViewer2d->updateAll();
262             else
263                 myGLViewer2d->activateDrawers( aList, TRUE, TRUE );
264
265             if( mySelectedObjects.count() != 0 )
266                 status = SS_GlobalChanged;
267
268             mySelectedObjects.clear();
269         }
270         return status;
271     }
272
273     if( !myHFlag )
274     {
275         bool isSel = false;
276         GLfloat aXScale;
277         GLfloat aYScale;
278         GLViewer_ViewPort2d* vp = ( GLViewer_ViewPort2d* )myGLViewer2d->getActiveView()->getViewPort();
279         vp->getScale( aXScale, aYScale );
280
281         if ( !Append )
282         {
283             for( it = mySelectedObjects.begin(), itEnd = mySelectedObjects.end() ; it != itEnd; ++it )
284                 if( myLastPicked != *it )
285                 {
286                     updateAll = (*it)->unselect() || updateAll;
287                     aList.append( *it );
288                 }
289
290             if( updateAll || myUpdateAll )
291                 myGLViewer2d->updateAll();
292             else
293                 myGLViewer2d->activateDrawers( aList, TRUE, TRUE );
294
295             if( mySelectedObjects.count() != 0 )
296                 status = SS_GlobalChanged;
297
298             mySelectedObjects.clear();
299         }        
300
301         for( oit = myActiveObjects.begin(), oitEnd = myActiveObjects.end(); oit != oitEnd; ++oit )
302         {
303             (*oit)->setScale( aXScale, aYScale );
304             GLViewer_Rect* rect = (*oit)->getUpdateRect();
305
306             if( rect->contains( GLViewer_Pnt( myXhigh, myXhigh ) ) )
307             {
308                 (*oit)->select( myXhigh, myYhigh, myTolerance, GLViewer_Rect(), false, byCircle, Append );
309                 isSel = (*oit)->isSelected();
310             }
311             if( isSel )
312             {
313                 myLastPicked = *oit;
314                 mySelectedObjects.append( myLastPicked );
315                 myGLViewer2d->activateDrawer( myLastPicked, TRUE, TRUE );
316                 status = SS_GlobalChanged;
317                 return status;
318             }
319         }
320     }
321         
322     return SS_NoChanged;
323 }
324
325 //=======================================================================
326 // Function: SelectByRect
327 // Purpose :
328 //=======================================================================
329 int GLViewer_Context::SelectByRect( const QRect& theRect, bool Append )
330 {
331     GLfloat aXScale;
332     GLfloat aYScale;
333     GLViewer_ViewPort2d* vp = ( GLViewer_ViewPort2d* )myGLViewer2d->getActiveView()->getViewPort();
334     vp->getScale( aXScale, aYScale );
335
336     SelectionStatus status = SS_NoChanged;
337
338     ObjList aList;
339     ObjList::Iterator it, itEnd;
340
341     if ( !mySFlag || myActiveObjects.empty() )
342         return SS_Invalid;
343
344     bool updateAll = false;
345     if( !Append )
346     {
347         if( mySelectedObjects.count() != 0 )
348             status = SS_GlobalChanged;
349
350         for( it = mySelectedObjects.begin(), itEnd = mySelectedObjects.end(); it != itEnd; ++it )
351         {
352             updateAll = (*it)->unselect() || updateAll;
353             aList.append( *it );
354         }
355         mySelectedObjects.clear();
356     }
357
358     for( it = myActiveObjects.begin(), itEnd = myActiveObjects.end(); it != itEnd; ++it )
359     {
360         bool isSel = false;
361         (*it)->setScale( aXScale, aYScale );
362         QRect rect = myGLViewer2d->getQRect( *( (*it)->getRect() ) );
363
364         if( rect.intersects( theRect ) )
365         {
366             GLViewer_Rect aRect = myGLViewer2d->getGLVRect( theRect );
367             (*it)->select( myXhigh, myYhigh, myTolerance, aRect, false, false, Append );
368             isSel = (*it)->isSelected();
369         }
370
371         if( isSel && mySelectedObjects.findIndex( *it ) == -1 )
372         {
373             aList.append( *it );
374             mySelectedObjects.append( *it );
375             status = SS_GlobalChanged;
376         }
377     }
378
379     if( updateAll || myUpdateAll )
380         myGLViewer2d->updateAll();
381     else
382         myGLViewer2d->activateDrawers( aList, TRUE, TRUE );
383
384     return status;
385 }
386
387 //=======================================================================
388 // Function: SetHighlightColor
389 // Purpose :
390 //=======================================================================
391 void GLViewer_Context::SetHighlightColor( Quantity_NameOfColor aCol )
392 {
393   myHighlightColor = aCol;
394   
395   Quantity_Color colorH( aCol );
396   int redH = 255 * (int)colorH.Red();
397   int greenH = 255 * (int)colorH.Green();
398   int blueH = 255 * (int)colorH.Blue();
399   QColor colH = QColor( redH, greenH, blueH );
400
401   Quantity_Color colorS( mySelectionColor );
402   int redS = 255 * (int)colorS.Red();
403   int greenS = 255 * (int)colorS.Green();
404   int blueS = 255 * (int)colorS.Blue();
405   QColor colS = QColor( redS, greenS, blueS );
406
407   myGLViewer2d->updateColors( colH, colS);
408 }
409
410 //=======================================================================
411 // Function: SetSelectionColor
412 // Purpose :
413 //=======================================================================
414 void GLViewer_Context::SetSelectionColor( Quantity_NameOfColor aCol )
415 {
416   mySelectionColor = aCol;
417   
418   Quantity_Color colorH( myHighlightColor );
419   int redH = 255 * (int)colorH.Red();
420   int greenH = 255 * (int)colorH.Green();
421   int blueH = 255 * (int)colorH.Blue();
422   QColor colH = QColor( redH, greenH, blueH );
423
424   Quantity_Color colorS( aCol );
425   int redS = 255 * (int)colorS.Red();
426   int greenS = 255 * (int)colorS.Green();
427   int blueS = 255 * (int)colorS.Blue();
428   QColor colS = QColor( redS, greenS, blueS );
429
430   myGLViewer2d->updateColors( colH, colS);
431 }
432
433 //=======================================================================
434 // Function: NbSelected
435 // Purpose :
436 //=======================================================================
437 int GLViewer_Context::NbSelected()
438 {
439   return mySelectedObjects.count();
440 }
441
442 //=======================================================================
443 // Function: InitSelected
444 // Purpose :
445 //=======================================================================
446 void GLViewer_Context::InitSelected()
447 {
448   mySelCurIndex = 0;
449 }
450
451 //=======================================================================
452 // Function: MoreSelected
453 // Purpose :
454 //=======================================================================
455 bool GLViewer_Context::MoreSelected()
456 {
457   return ( mySelCurIndex < NbSelected() );
458 }
459
460 //=======================================================================
461 // Function: NextSelected
462 // Purpose :
463 //=======================================================================
464 bool GLViewer_Context::NextSelected()
465 {
466   if ( mySelCurIndex >= 0 && mySelCurIndex < NbSelected() )
467   {
468     mySelCurIndex++;
469     return TRUE;
470   }
471
472   return FALSE;
473 }
474
475 //=======================================================================
476 // Function: SelectedObject
477 // Purpose :
478 //=======================================================================
479 GLViewer_Object* GLViewer_Context::SelectedObject()
480 {
481     return mySelectedObjects[ mySelCurIndex ];
482 }
483
484 //=======================================================================
485 // Function: isSelected
486 // Purpose :
487 //=======================================================================
488 bool  GLViewer_Context::isSelected( GLViewer_Object* theObj )
489 {
490     return mySelectedObjects.contains( theObj );
491 }
492
493 //=======================================================================
494 // Function: insertObject
495 // Purpose :
496 //=======================================================================
497 int GLViewer_Context::insertObject( GLViewer_Object* object, bool display, bool isActive )
498 {
499 //  cout << "GLViewer_Context::insertObject" << endl;
500
501     if( !object )
502         return -1;
503
504     if( isActive )
505     {
506         myActiveObjects.append( object );
507         if( display )
508         {
509             //QRect* rect = object->getRect()->toQRect();
510             //myGLViewer2d->updateBorders( *rect );
511             myGLViewer2d->activateDrawer( object, FALSE );
512         }
513     }
514     else
515         myInactiveObjects.append( object );
516
517     return myActiveObjects.count() + myInactiveObjects.count();
518 }
519
520 //=======================================================================
521 // Function: replaceObject
522 // Purpose :
523 //=======================================================================
524 bool GLViewer_Context::replaceObject( GLViewer_Object* oldObject, GLViewer_Object* newObject )
525 {
526     if( !oldObject || !newObject )
527         return false;
528
529   if( myActiveObjects.contains( oldObject ) )
530   {
531     myActiveObjects.remove( oldObject );
532     myActiveObjects.append( newObject );
533     return true;
534   }
535
536   if( myInactiveObjects.contains( oldObject ) )
537   {
538     myInactiveObjects.remove( oldObject );
539     myInactiveObjects.append( newObject );
540     return true;
541   }
542
543   return false;
544 }
545
546 //=======================================================================
547 // Function: updateScales
548 // Purpose :
549 //=======================================================================
550 void GLViewer_Context::updateScales( GLfloat scX, GLfloat scY )
551 {
552   if( scX <= 0 || scY <= 0 )
553       return;
554
555   ObjList::iterator it, itEnd;
556
557   for( it = myActiveObjects.begin(), itEnd = myActiveObjects.end(); it != itEnd; ++it )
558       (*it)->setScale( scX, scY );
559
560   for( it = myInactiveObjects.begin(), itEnd = myInactiveObjects.end(); it != itEnd; ++it )
561       (*it)->setScale( scX, scY );
562 }
563
564 //=======================================================================
565 // Function: clearHighlighted
566 // Purpose :
567 //=======================================================================
568 void GLViewer_Context::clearHighlighted( bool updateViewer )
569 {
570   if( myHFlag && myLastPicked )
571   {
572     myLastPicked->unhighlight();
573     myLastPicked = 0;
574     
575     if( updateViewer )
576       myGLViewer2d->updateAll();
577   }
578 }
579
580 //=======================================================================
581 // Function: clearSelected
582 // Purpose :
583 //=======================================================================
584 void GLViewer_Context::clearSelected( bool updateViewer )
585 {
586   if( !mySFlag )
587     return;
588
589   ObjList::Iterator it, itEnd;
590   ObjList aList;
591
592   for( it = mySelectedObjects.begin(), itEnd = mySelectedObjects.end(); it != itEnd; ++it )
593   {
594     (*it)->unselect();
595     aList.append( *it );
596   }          
597         
598   if( updateViewer )
599     myGLViewer2d->activateDrawers( aList, TRUE );
600   mySelectedObjects.clear();    
601 }
602
603 //=======================================================================
604 // Function: setSelected
605 // Purpose :
606 //=======================================================================
607 void GLViewer_Context::setSelected( GLViewer_Object* object, bool updateViewer )
608 {
609   if( !object )
610     return;
611
612   if( myActiveObjects.contains( object ) && !mySelectedObjects.contains( object ) )
613   {
614     object->setSelected( TRUE );
615     mySelectedObjects.append( object );
616   }
617      
618   if( updateViewer )
619     myGLViewer2d->activateDrawer( object, TRUE, TRUE );
620 }
621
622 //=======================================================================
623 // Function: remSelected
624 // Purpose :
625 //=======================================================================
626 void GLViewer_Context::remSelected( GLViewer_Object* object, bool updateViewer )
627 {
628   if( !object || !mySelectedObjects.contains( object ) )
629     return;
630   
631   mySelectedObjects.remove( object );
632   object->unselect();
633   
634   if( updateViewer )
635     myGLViewer2d->activateDrawer( object, TRUE, TRUE );
636 }
637
638 //=======================================================================
639 // Function: eraseObject
640 // Purpose :
641 //=======================================================================
642 void GLViewer_Context::eraseObject( GLViewer_Object* theObject, bool theUpdateViewer )
643 {
644     if( !theObject || !myActiveObjects.contains( theObject ) )
645         return;
646
647     theObject->unhighlight();
648     theObject->unselect();
649     theObject->setVisible( false );
650
651     if( theUpdateViewer )
652         myGLViewer2d->updateAll();
653 }
654
655 //=======================================================================
656 // Function: deleteObject
657 // Purpose :
658 //=======================================================================
659 void GLViewer_Context::deleteObject( GLViewer_Object* theObject, bool updateViewer )
660 {
661     if( !theObject ||
662         ( !myActiveObjects.contains( theObject ) && !myInactiveObjects.contains( theObject ) ) )
663         return;
664
665     if( myActiveObjects.contains( theObject ) )      
666         myActiveObjects.remove( theObject );
667     else if( myInactiveObjects.contains( theObject ) )
668         myInactiveObjects.remove( theObject );
669     else 
670         return;
671      
672     if( mySelectedObjects.contains( theObject ) )
673         mySelectedObjects.remove( theObject );
674
675     GLViewer_Group* aGroup = theObject->getGroup();
676     if( aGroup )
677         aGroup->removeObject( theObject );
678
679     if( myLastPicked == theObject )
680         myLastPicked = 0;
681
682     myGLViewer2d->updateAll();
683 }
684
685 //=======================================================================
686 // Function: setActive
687 // Purpose :
688 //=======================================================================
689 bool GLViewer_Context::setActive( GLViewer_Object* theObject )
690 {
691   if( !theObject || !myInactiveObjects.contains( theObject ) )
692     return false;
693
694   myInactiveObjects.remove( theObject );
695   myActiveObjects.append( theObject );
696   return true;
697 }
698
699 //=======================================================================
700 // Function: setInactive
701 // Purpose :
702 //=======================================================================
703 bool GLViewer_Context::setInactive( GLViewer_Object* theObject )
704 {
705   if( !theObject || !myActiveObjects.contains( theObject ) )
706     return false;
707
708   myActiveObjects.remove( theObject );
709   myInactiveObjects.append( theObject );
710   return true;
711 }