Salome HOME
Join modifications from BR_Dev_For_4_0 tag V4_1_1.
[modules/gui.git] / src / OCCViewer / OCCViewer_ViewModel.cxx
1 // Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
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.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "OCCViewer_ViewModel.h"
21 #include "OCCViewer_ViewWindow.h"
22 #include "OCCViewer_VService.h"
23 #include "OCCViewer_ViewPort3d.h"
24
25 #include "SUIT_ViewWindow.h"
26 #include "SUIT_Desktop.h"
27 #include "SUIT_Session.h"
28
29 #include <qpainter.h>
30 #include <qapplication.h>
31 #include <qcolordialog.h>
32 #include <qpalette.h>
33 #include <qpopupmenu.h>
34
35 #include <AIS_Axis.hxx>
36 #include <AIS_Drawer.hxx>
37 #include <AIS_ListIteratorOfListOfInteractive.hxx>
38
39 #include <Geom_Axis2Placement.hxx>
40 #include <Prs3d_DatumAspect.hxx>
41 #include <Prs3d_LineAspect.hxx>
42
43 /*!
44   Constructor
45   \param DisplayTrihedron - is trihedron displayed
46 */
47 OCCViewer_Viewer::OCCViewer_Viewer( bool DisplayTrihedron )
48 : SUIT_ViewModel(),
49 myBgColor( Qt::black )
50 {
51   // init CasCade viewers
52   myV3dViewer = OCCViewer_VService::Viewer3d( "", (short*) "Viewer3d", "", 1000.,
53                                               V3d_XposYnegZpos, true, true );
54
55   myV3dViewer->Init();
56
57   myV3dCollector = OCCViewer_VService::Viewer3d( "", (short*) "Collector3d", "", 1000.,
58                                                  V3d_XposYnegZpos, true, true );
59   myV3dCollector->Init();
60
61   // init selector
62   myAISContext = new AIS_InteractiveContext( myV3dViewer, myV3dCollector);
63
64   myAISContext->SelectionColor( Quantity_NOC_WHITE );
65   
66   // display isoline on planar faces (box for ex.)
67   myAISContext->IsoOnPlane( true );
68
69   clearViewAspects();
70
71   /* create trihedron */
72   if( DisplayTrihedron )
73   {
74     Handle(Geom_Axis2Placement) anAxis = new Geom_Axis2Placement(gp::XOY());
75     myTrihedron = new AIS_Trihedron(anAxis);
76     myTrihedron->SetInfiniteState( Standard_True );
77
78     Quantity_Color Col(193/255., 205/255., 193/255., Quantity_TOC_RGB);
79     //myTrihedron->SetColor( Col );
80     myTrihedron->SetArrowColor( Col.Name() );
81     myTrihedron->SetSize(100);
82     Handle(AIS_Drawer) drawer = myTrihedron->Attributes();
83     if (drawer->HasDatumAspect()) {
84         Handle(Prs3d_DatumAspect) daspect = drawer->DatumAspect();
85         daspect->FirstAxisAspect()->SetColor(Quantity_Color(1.0, 0.0, 0.0, Quantity_TOC_RGB));
86         daspect->SecondAxisAspect()->SetColor(Quantity_Color(0.0, 1.0, 0.0, Quantity_TOC_RGB));
87         daspect->ThirdAxisAspect()->SetColor(Quantity_Color(0.0, 0.0, 1.0, Quantity_TOC_RGB));
88     }
89
90     myAISContext->Display(myTrihedron);
91     myAISContext->Deactivate(myTrihedron);
92   }
93
94   // selection
95   mySelectionEnabled = true;
96   myMultiSelectionEnabled = true;
97 }
98
99 /*!
100   Destructor
101 */
102 OCCViewer_Viewer::~OCCViewer_Viewer() 
103 {
104 }
105
106 /*!
107   \return background color of viewer
108 */
109 QColor OCCViewer_Viewer::backgroundColor() const
110 {
111   return myBgColor;
112 }
113
114 /*!
115   Sets background color
116   \param c - new background color
117 */
118 void OCCViewer_Viewer::setBackgroundColor( const QColor& c )
119 {
120   if ( c.isValid() )
121     myBgColor = c;
122 }
123
124 /*!
125   Start initialization of view window
126   \param view - view window to be initialized
127 */
128 void OCCViewer_Viewer::initView( OCCViewer_ViewWindow* view )
129 {
130   if ( view ) {
131     view->initLayout();
132     view->initSketchers();
133     
134     OCCViewer_ViewPort3d* vp3d = view->getViewPort();
135     if ( vp3d )
136       vp3d->setBackgroundColor( myBgColor );
137   }
138 }
139
140 /*!
141   Creates new view window
142   \param theDesktop - main window of application
143 */
144 SUIT_ViewWindow* OCCViewer_Viewer::createView( SUIT_Desktop* theDesktop )
145 {
146   OCCViewer_ViewWindow* view = new OCCViewer_ViewWindow(theDesktop, this);
147   initView( view );
148   return view;
149 }
150
151 /*!
152   Sets new view manager
153   \param theViewManager - new view manager
154 */
155 void OCCViewer_Viewer::setViewManager(SUIT_ViewManager* theViewManager)
156 {
157   SUIT_ViewModel::setViewManager(theViewManager);
158   if (theViewManager) {
159     connect(theViewManager, SIGNAL(mousePress(SUIT_ViewWindow*, QMouseEvent*)), 
160             this, SLOT(onMousePress(SUIT_ViewWindow*, QMouseEvent*)));
161
162     connect(theViewManager, SIGNAL(mouseMove(SUIT_ViewWindow*, QMouseEvent*)), 
163             this, SLOT(onMouseMove(SUIT_ViewWindow*, QMouseEvent*)));
164
165     connect(theViewManager, SIGNAL(mouseRelease(SUIT_ViewWindow*, QMouseEvent*)), 
166             this, SLOT(onMouseRelease(SUIT_ViewWindow*, QMouseEvent*)));
167   }
168 }
169
170 /*!
171   SLOT: called on mouse button press, stores current mouse position as start point for transformations
172 */
173 void OCCViewer_Viewer::onMousePress(SUIT_ViewWindow* theWindow, QMouseEvent* theEvent)
174 {
175   myStartPnt.setX(theEvent->x()); myStartPnt.setY(theEvent->y());
176 }
177
178 /*!
179   SLOT: called on mouse move, processes transformation or hilighting
180 */
181 void OCCViewer_Viewer::onMouseMove(SUIT_ViewWindow* theWindow, QMouseEvent* theEvent)
182 {
183   if (!mySelectionEnabled) return;
184   if (!theWindow->inherits("OCCViewer_ViewWindow")) return;
185
186   OCCViewer_ViewWindow* aView = (OCCViewer_ViewWindow*) theWindow;
187   if ( isSelectionEnabled() )
188     myAISContext->MoveTo(theEvent->x(), theEvent->y(), aView->getViewPort()->getView());
189 }
190
191
192 /*!
193   SLOT: called on mouse button release, finishes transformation or selection
194 */
195 void OCCViewer_Viewer::onMouseRelease(SUIT_ViewWindow* theWindow, QMouseEvent* theEvent)
196 {
197   if (!mySelectionEnabled) return;
198   if (theEvent->button() != Qt::LeftButton) return;
199   if (!theWindow->inherits("OCCViewer_ViewWindow")) return;
200
201
202   myEndPnt.setX(theEvent->x()); myEndPnt.setY(theEvent->y());
203   OCCViewer_ViewWindow* aView = (OCCViewer_ViewWindow*) theWindow;
204   bool aHasShift = (theEvent->state() & Qt::ShiftButton);
205   
206   if (!aHasShift) emit deselection();
207
208   if (myStartPnt == myEndPnt)
209   {
210     if (aHasShift && myMultiSelectionEnabled)
211       myAISContext->ShiftSelect();
212     else
213       myAISContext->Select();
214   }
215   else
216   {
217     if (aHasShift && myMultiSelectionEnabled)
218       myAISContext->ShiftSelect(myStartPnt.x(), myStartPnt.y(),
219                                 myEndPnt.x(), myEndPnt.y(),
220                                 aView->getViewPort()->getView(), Standard_False );
221     else
222       myAISContext->Select(myStartPnt.x(), myStartPnt.y(),
223                            myEndPnt.x(), myEndPnt.y(),
224                            aView->getViewPort()->getView(), Standard_False );
225
226     int Nb = myAISContext->NbSelected();
227     if( Nb>1 && !myMultiSelectionEnabled )
228     {
229         myAISContext->InitSelected();
230         Handle( SelectMgr_EntityOwner ) anOwner = myAISContext->SelectedOwner();
231         if( !anOwner.IsNull() )
232         {
233             myAISContext->ClearSelected( Standard_False );
234             myAISContext->AddOrRemoveSelected( anOwner, Standard_False );
235         }
236     }
237
238     myAISContext->UpdateCurrentViewer();
239   }
240   emit selectionChanged();
241 }
242
243
244 /*!
245   Sets selection enabled status
246   \param isEnabled - new status
247 */
248 void OCCViewer_Viewer::enableSelection(bool isEnabled)
249 {
250   mySelectionEnabled = isEnabled;
251   //!! To be done for view windows
252   if ( !myViewManager )
253     return;
254
255   QPtrVector<SUIT_ViewWindow> wins = myViewManager->getViews();
256   for ( int i = 0; i < (int)wins.count(); i++ )
257   {
258     OCCViewer_ViewWindow* win = ::qt_cast<OCCViewer_ViewWindow*>( wins.at( i ) );
259     if ( win )
260       win->updateEnabledDrawMode();
261   }
262 }
263
264 /*!
265   Sets multiselection enabled status
266   \param isEnabled - new status
267 */
268 void OCCViewer_Viewer::enableMultiselection(bool isEnable)
269 {
270   myMultiSelectionEnabled = isEnable;
271   //!! To be done for view windows
272   if ( !myViewManager )
273     return;
274
275   QPtrVector<SUIT_ViewWindow> wins = myViewManager->getViews();
276   for ( int i = 0; i < (int)wins.count(); i++ )
277   {
278     OCCViewer_ViewWindow* win = ::qt_cast<OCCViewer_ViewWindow*>( wins.at( i ) );
279     if ( win )
280       win->updateEnabledDrawMode();
281   }
282 }
283
284 /*!
285   Builds popup for occ viewer
286 */
287 void OCCViewer_Viewer::contextMenuPopup(QPopupMenu* thePopup)
288 {
289   thePopup->insertItem( tr( "MEN_DUMP_VIEW" ), this, SLOT( onDumpView() ) );
290   thePopup->insertItem( tr( "MEN_CHANGE_BACKGROUD" ), this, SLOT( onChangeBgColor() ) );
291
292   thePopup->insertSeparator();
293
294   OCCViewer_ViewWindow* aView = (OCCViewer_ViewWindow*)(myViewManager->getActiveView());
295   if ( aView && !aView->getToolBar()->isVisible() )
296     thePopup->insertItem( tr( "MEN_SHOW_TOOLBAR" ), this, SLOT( onShowToolbar() ) );
297 }
298
299 /*!
300   SLOT: called on dump view operation is activated, stores scene to raster file
301 */
302 void OCCViewer_Viewer::onDumpView()
303 {
304   OCCViewer_ViewWindow* aView = (OCCViewer_ViewWindow*)(myViewManager->getActiveView());
305   if ( aView )
306     aView->onDumpView();
307 }
308
309 /*!
310   SLOT: called if background color is to be changed changed, passes new color to view port
311 */
312 void OCCViewer_Viewer::onChangeBgColor()
313 {
314   OCCViewer_ViewWindow* aView = (OCCViewer_ViewWindow*)(myViewManager->getActiveView());
315   if( !aView )
316     return;
317   OCCViewer_ViewPort3d* aViewPort3d = aView->getViewPort();
318   if( !aViewPort3d )
319     return;
320   QColor aColorActive = aViewPort3d->backgroundColor();
321
322   QColor selColor = QColorDialog::getColor( aColorActive, aView);
323   if ( selColor.isValid() )
324     aViewPort3d->setBackgroundColor(selColor);
325 }
326
327 /*!
328   SLOT: called when popup item "Show toolbar" is activated, shows toolbar of active view window
329 */
330 void OCCViewer_Viewer::onShowToolbar() {
331   OCCViewer_ViewWindow* aView = (OCCViewer_ViewWindow*)(myViewManager->getActiveView());
332   if ( aView )
333     aView->getToolBar()->show();    
334 }
335
336 /*!
337   Updates OCC 3D viewer
338 */
339 void OCCViewer_Viewer::update()
340 {
341   if (!myV3dViewer.IsNull())
342     myV3dViewer->Update();
343
344   OCCViewer_ViewWindow* aView = (OCCViewer_ViewWindow*)(myViewManager->getActiveView());
345   if ( aView )
346     aView->updateGravityCoords();
347 }
348
349 /*!
350   \return objects selected in 3D viewer
351   \param theList - list to be filled with selected objects
352 */
353 void OCCViewer_Viewer::getSelectedObjects(AIS_ListOfInteractive& theList)
354 {
355   theList.Clear();
356   for (myAISContext->InitSelected(); myAISContext->MoreSelected(); myAISContext->NextSelected())
357     theList.Append(myAISContext->SelectedInteractive());
358 }
359
360 /*!
361   Selects objects in 3D viewer. Other selected objects are left as selected
362   \param theList - list objects to be selected
363 */
364 void OCCViewer_Viewer::setObjectsSelected(const AIS_ListOfInteractive& theList)
365 {
366   AIS_ListIteratorOfListOfInteractive aIt;
367   for (aIt.Initialize(theList); aIt.More(); aIt.Next())
368     myAISContext->AddOrRemoveSelected(aIt.Value(), false);
369   myAISContext->UpdateCurrentViewer();
370 }
371
372 /*!
373   Auxiliary method to emit signal selectionChanged()
374 */
375 void OCCViewer_Viewer::performSelectionChanged()
376 {
377     emit selectionChanged();
378 }
379
380 /*!
381   SLOT, clears view aspects
382 */
383 void OCCViewer_Viewer::onClearViewAspects()
384 {
385     clearViewAspects();
386 }
387
388 /*!
389   Clears view aspects
390 */
391 void OCCViewer_Viewer::clearViewAspects()
392 {
393         myViewAspects.clear();
394 }
395
396 /*!
397   \return const reference to list of view aspects
398 */
399 const viewAspectList& OCCViewer_Viewer::getViewAspects()
400 {
401         return myViewAspects;
402 }
403
404 /*!
405   Appends new view aspect
406   \param aParams - new view aspects
407 */
408 void OCCViewer_Viewer::appendViewAspect( const viewAspect& aParams )
409 {
410         myViewAspects.append( aParams );
411 }
412
413 /*!
414   Replaces old view aspects by new ones
415   \param aViewList - list of new view aspects
416 */
417 void OCCViewer_Viewer::updateViewAspects( const viewAspectList& aViewList )
418 {
419         myViewAspects = aViewList;
420 }
421
422 /*!
423   Hilights/unhilights object in viewer
424   \param obj - object to be updated
425   \param hilight - if it is true, object will be hilighted, otherwise it will be unhilighted
426   \param update - update current viewer
427 */
428 bool OCCViewer_Viewer::highlight( const Handle(AIS_InteractiveObject)& obj,
429                                   bool hilight, bool update )
430 {
431   bool isInLocal = myAISContext->HasOpenedContext();
432   if( !obj.IsNull() )
433     if( !isInLocal )
434     {
435       if ( hilight && !myAISContext->IsSelected( obj ) )
436         myAISContext->AddOrRemoveCurrentObject( obj, false );
437       else if ( !hilight && myAISContext->IsSelected( obj ) )
438         myAISContext->AddOrRemoveCurrentObject( obj, false );
439     }
440
441   if ( update )
442     myV3dViewer->Redraw();
443     
444   return false;
445 }
446
447 /*!
448   Unhilights all objects in viewer
449   \param updateviewer - update current viewer
450 */
451 bool OCCViewer_Viewer::unHighlightAll( bool updateviewer )
452 {
453   if ( myAISContext->HasOpenedContext() )
454     myAISContext->ClearSelected( updateviewer );
455   else
456     myAISContext->ClearCurrents( updateviewer );
457   return false;
458 }
459
460 /*!
461   \return true if object is in viewer or in collector
462   \param obj - object to be checked
463   \param onlyInViewer - search object only in viewer (so object must be displayed)
464 */
465 bool OCCViewer_Viewer::isInViewer( const Handle(AIS_InteractiveObject)& obj,
466                                    bool onlyInViewer )
467 {
468   AIS_ListOfInteractive List;
469   myAISContext->DisplayedObjects(List);
470
471   if( !onlyInViewer )
472   {
473     AIS_ListOfInteractive List1;
474     myAISContext->ObjectsInCollector(List1);
475     List.Append(List1);
476   }
477
478   AIS_ListIteratorOfListOfInteractive ite(List);
479   for ( ; ite.More(); ite.Next() )
480     if( ite.Value()==obj )
481       return true;
482
483   return false;
484 }
485
486 /*!
487   \return true if object is displayed in viewer
488   \param obj - object to be checked
489 */
490 bool OCCViewer_Viewer::isVisible( const Handle(AIS_InteractiveObject)& obj )
491 {
492   return myAISContext->IsDisplayed( obj );
493 }
494
495 /*!
496   Sets color of object
497   \param obj - object to be updated
498   \param color - new color
499   \param update - update current viewer
500 */
501 void OCCViewer_Viewer::setColor( const Handle(AIS_InteractiveObject)& obj,
502                                  const QColor& color,
503                                  bool update )
504 {
505   if( !obj.IsNull() )
506   {
507     Quantity_Color CSFColor = Quantity_Color ( color.red() / 255.,
508                                                color.green() / 255.,
509                                                color.blue() / 255.,
510                                                Quantity_TOC_RGB );
511     obj->SetColor( CSFColor );
512   }
513
514   if( update )
515     myV3dViewer->Update();
516 }
517
518 /*!
519   Changes display mode of object
520   \param obj - object to be processed
521   \param mode - new display mode
522   \param update - update current viewer
523 */
524 void OCCViewer_Viewer::switchRepresentation( const Handle(AIS_InteractiveObject)& obj,
525                                              int mode, bool update )
526 {
527   myAISContext->SetDisplayMode( obj, (Standard_Integer)mode, update );
528   if( update )
529     myV3dViewer->Update();
530 }
531
532 /*!
533   Changes transparency of object
534   \param obj - object to be processed
535   \param trans - new transparency
536   \param update - update current viewer
537 */
538 void OCCViewer_Viewer::setTransparency( const Handle(AIS_InteractiveObject)& obj,
539                                         float trans, bool update )
540 {
541   myAISContext->SetTransparency( obj, trans, false );
542   myAISContext->Redisplay( obj, Standard_False, Standard_True );
543   if( update )
544     myV3dViewer->Update();
545 }
546
547 /*!
548   Changes visibility of trihedron to opposite
549 */
550 void OCCViewer_Viewer::toggleTrihedron()
551 {
552   setTrihedronShown( !isTrihedronVisible() );
553 }
554
555 /*!
556   \return true if trihedron is visible
557 */
558 bool OCCViewer_Viewer::isTrihedronVisible() const
559 {
560   return !myTrihedron.IsNull() && !myAISContext.IsNull() && myAISContext->IsDisplayed( myTrihedron );
561 }
562
563 /*!
564   Sets visibility state of trihedron
565   \param on - new state
566 */
567
568 void OCCViewer_Viewer::setTrihedronShown( const bool on )
569 {
570   if ( myTrihedron.IsNull() )
571     return;
572
573   if ( on )
574     myAISContext->Display( myTrihedron );
575   else
576     myAISContext->Erase( myTrihedron );
577 }
578
579 /*!
580   \return trihedron size
581 */
582 double OCCViewer_Viewer::trihedronSize() const
583 {
584   double sz = 0;
585   if ( !myTrihedron.IsNull() )
586     sz = myTrihedron->Size();
587   return sz;
588 }
589
590 /*!
591   Changes trihedron size
592   \param sz - new size
593 */
594 void OCCViewer_Viewer::setTrihedronSize( const double sz )
595 {
596   if ( !myTrihedron.IsNull() )
597     myTrihedron->SetSize( sz );
598 }
599
600 /*!
601   Set number of isolines
602   \param u - u-isolines (first parametric co-ordinate)
603   \param v - v-isolines (second parametric co-ordinate)
604 */
605 void OCCViewer_Viewer::setIsos( const int u, const int v )
606 {
607   Handle(AIS_InteractiveContext) ic = getAISContext();
608   if ( ic.IsNull() )
609   return;
610
611   ic->SetIsoNumber( u, AIS_TOI_IsoU );
612   ic->SetIsoNumber( v, AIS_TOI_IsoV );
613 }
614
615 /*!
616   \return number of isolines
617   \param u - to return u-isolines (first parametric co-ordinate)
618   \param v - to return v-isolines (second parametric co-ordinate)
619 */
620 void OCCViewer_Viewer::isos( int& u, int& v ) const
621 {
622   Handle(AIS_InteractiveContext) ic = getAISContext();
623   if ( !ic.IsNull() )
624   {
625     u = ic->IsoNumber( AIS_TOI_IsoU );
626     v = ic->IsoNumber( AIS_TOI_IsoV );
627   }
628 }