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