Salome HOME
c8cd002b9b9a3bab4ca329b42979b8174d684be1
[modules/shaper.git] / src / XGUI / XGUI_Viewer.cpp
1 #include "XGUI_Viewer.h"
2 #include "XGUI_MainWindow.h"
3 #include "XGUI_ViewWindow.h"
4 #include "XGUI_ViewPort.h"
5
6 #include <QMdiArea>
7 #include <QMdiSubWindow>
8
9 #include <V3d_View.hxx>
10
11 #include <Aspect_DisplayConnection.hxx>
12 #include <Graphic3d.hxx>
13 #include <Graphic3d_GraphicDriver.hxx>
14 #include <Geom_Axis2Placement.hxx>
15 #include <AIS_Drawer.hxx>
16 #include <Prs3d_DatumAspect.hxx>
17 #include <Prs3d_LineAspect.hxx>
18 #include <V3d_View.hxx>
19 #include <Visual3d_View.hxx>
20
21 #ifdef WIN32
22 #include <WNT_Window.hxx>
23 #else
24 #include <Xw_Window.hxx>
25 #endif
26
27 XGUI_Viewer::InteractionStyle2StatesMap XGUI_Viewer::myStateMap;
28 XGUI_Viewer::InteractionStyle2ButtonsMap XGUI_Viewer::myButtonMap;
29 static bool isInitialized = false;
30
31
32 /*!
33     Creates viewer 3d [ static ]
34 */
35 Handle(V3d_Viewer) CreateViewer( const Standard_ExtString name,
36                                                      const Standard_CString displayName,
37                                                      const Standard_CString domain,
38                                                      const Standard_Real viewSize ,
39                                                      const V3d_TypeOfOrientation viewProjection,
40                                                      const Standard_Boolean computedMode,
41                                                      const Standard_Boolean defaultComputedMode )
42 {
43   static Handle(Graphic3d_GraphicDriver) aGraphicDriver;
44   if (aGraphicDriver.IsNull())
45   {
46     Handle(Aspect_DisplayConnection) aDisplayConnection;
47 #ifndef WIN32
48     aDisplayConnection = new Aspect_DisplayConnection( displayName );
49 #else
50     aDisplayConnection = new Aspect_DisplayConnection();
51 #endif
52     aGraphicDriver = Graphic3d::InitGraphicDriver( aDisplayConnection );
53   }
54
55   return new V3d_Viewer( aGraphicDriver, name, domain, viewSize, viewProjection,
56                          Quantity_NOC_GRAY30, V3d_ZBUFFER, V3d_GOURAUD, V3d_WAIT,
57                          computedMode, defaultComputedMode, V3d_TEX_NONE );
58 }
59
60
61 // VSR: Uncomment below line to allow texture background support in OCC viewer
62 #define OCC_ENABLE_TEXTURED_BACKGROUND
63
64 /*!
65   Get data for supported background modes: gradient types, identifiers and supported image formats
66 */
67 QString XGUI_Viewer::backgroundData( QStringList& gradList, QIntList& idList, QIntList& txtList )
68 {
69   gradList << tr("GT_HORIZONTALGRADIENT")    << tr("GT_VERTICALGRADIENT")       <<
70               tr("GT_FIRSTDIAGONALGRADIENT") << tr("GT_SECONDDIAGONALGRADIENT") <<
71               tr("GT_FIRSTCORNERGRADIENT")   << tr("GT_SECONDCORNERGRADIENT")   <<
72               tr("GT_THIRDCORNERGRADIENT")   << tr("GT_FORTHCORNERGRADIENT");
73   idList   << XGUI::HorizontalGradient << XGUI::VerticalGradient  <<
74               XGUI::Diagonal1Gradient  << XGUI::Diagonal2Gradient <<
75               XGUI::Corner1Gradient    << XGUI::Corner2Gradient   <<
76               XGUI::Corner3Gradient    << XGUI::Corner4Gradient;
77 #ifdef OCC_ENABLE_TEXTURED_BACKGROUND
78   txtList  << XGUI::CenterTexture << XGUI::TileTexture << XGUI::StretchTexture;
79 #endif
80   return tr("BG_IMAGE_FILES");
81 }
82
83
84
85 XGUI_Viewer::XGUI_Viewer(XGUI_MainWindow* theParent, bool DisplayTrihedron) :
86 QObject(theParent), 
87     myMainWindow(theParent),
88     myPreselectionEnabled(true),
89     mySelectionEnabled(true),
90     myMultiSelectionEnabled(true),
91     myIsRelative(true),
92     myInteractionStyle(XGUI::STANDARD),
93     myTrihedronSize(100),
94     myActiveView(0)
95 {
96     if ( !isInitialized ) {
97         isInitialized = true;
98
99         // standard interaction style
100         XGUI_Viewer::myStateMap[XGUI::STANDARD][XGUI::ZOOM]  = Qt::ControlModifier;
101         XGUI_Viewer::myButtonMap[XGUI::STANDARD][XGUI::ZOOM] = Qt::LeftButton;
102
103         XGUI_Viewer::myStateMap[XGUI::STANDARD][XGUI::PAN]   = Qt::ControlModifier;
104         XGUI_Viewer::myButtonMap[XGUI::STANDARD][XGUI::PAN]  = Qt::MidButton;
105
106         XGUI_Viewer::myStateMap[XGUI::STANDARD][XGUI::ROTATE]  = Qt::ControlModifier;
107         XGUI_Viewer::myButtonMap[XGUI::STANDARD][XGUI::ROTATE] = Qt::RightButton;
108
109         XGUI_Viewer::myStateMap[XGUI::STANDARD][XGUI::FIT_AREA]  = Qt::ControlModifier;
110         XGUI_Viewer::myButtonMap[XGUI::STANDARD][XGUI::FIT_AREA] = Qt::RightButton;
111
112         // "key free" interaction style
113         XGUI_Viewer::myStateMap[XGUI::KEY_FREE][XGUI::ZOOM]  = Qt::NoModifier;
114         XGUI_Viewer::myButtonMap[XGUI::KEY_FREE][XGUI::ZOOM] = Qt::RightButton;
115
116         XGUI_Viewer::myStateMap[XGUI::KEY_FREE][XGUI::PAN]   = Qt::NoModifier;
117         XGUI_Viewer::myButtonMap[XGUI::KEY_FREE][XGUI::PAN]  = Qt::MidButton;
118
119         XGUI_Viewer::myStateMap[XGUI::KEY_FREE][XGUI::ROTATE]  = Qt::NoModifier;
120         XGUI_Viewer::myButtonMap[XGUI::KEY_FREE][XGUI::ROTATE] = Qt::LeftButton;
121
122         XGUI_Viewer::myStateMap[XGUI::KEY_FREE][XGUI::FIT_AREA]  = Qt::NoModifier; // unused
123         XGUI_Viewer::myButtonMap[XGUI::KEY_FREE][XGUI::FIT_AREA] = Qt::NoButton;   // unused
124     }
125
126     // init CasCade viewers
127     myV3dViewer = CreateViewer(TCollection_ExtendedString("Viewer3d").ToExtString(),
128                                                    "", "", 1000.0, V3d_XposYnegZpos, Standard_True, Standard_True );
129     myV3dViewer->SetDefaultLights();
130
131     // init selector
132     myAISContext = new AIS_InteractiveContext( myV3dViewer );
133     myAISContext->SelectionColor( Quantity_NOC_WHITE );
134   
135     // display isoline on planar faces (box for ex.)
136     myAISContext->IsoOnPlane( true );
137   
138     if ( DisplayTrihedron )  {
139         Handle(Geom_Axis2Placement) anAxis = new Geom_Axis2Placement(gp::XOY());
140         myTrihedron = new AIS_Trihedron(anAxis);
141         myTrihedron->SetInfiniteState( Standard_True );
142     
143         Quantity_Color Col(193/255., 205/255., 193/255., Quantity_TOC_RGB);
144         myTrihedron->SetArrowColor( Col.Name() );
145         myTrihedron->SetSize(myTrihedronSize);
146         Handle(AIS_Drawer) drawer = myTrihedron->Attributes();
147         if (drawer->HasDatumAspect()) {
148             Handle(Prs3d_DatumAspect) daspect = drawer->DatumAspect();
149             daspect->FirstAxisAspect()->SetColor(Quantity_Color(1.0, 0.0, 0.0, Quantity_TOC_RGB));
150             daspect->SecondAxisAspect()->SetColor(Quantity_Color(0.0, 1.0, 0.0, Quantity_TOC_RGB));
151             daspect->ThirdAxisAspect()->SetColor(Quantity_Color(0.0, 0.0, 1.0, Quantity_TOC_RGB));
152         }
153     }
154     // set zooming style to standard
155     //myZoomingStyle = 0;
156 }
157
158
159 XGUI_Viewer::~XGUI_Viewer(void)
160 {
161     myAISContext.Nullify();
162     myV3dViewer.Nullify();
163 }
164
165
166 QMdiSubWindow* XGUI_Viewer::createView(V3d_TypeOfView theType)
167 {
168     // create view frame
169     XGUI_ViewWindow* view = new XGUI_ViewWindow(this, theType);
170     // get main view window (created by view frame)
171     //OCCViewer_ViewWindow* vw = view->getView(OCCViewer_ViewFrame::MAIN_VIEW);
172     // initialize main view window
173     //initView( vw );
174     // set default background for view window
175     //vw->setBackground( background(0) ); // 0 means MAIN_VIEW (other views are not yet created here)
176     //// connect signal from viewport
177     //connect(view->viewPort(), SIGNAL(vpClosed()), this, SLOT(onViewClosed()));
178     //connect(view->viewPort(), SIGNAL(vpMapped()), this, SLOT(onViewMapped()));
179     if (myViews.size() == 0) 
180         setTrihedronShown(true);
181
182     view->setBackground(XGUI_ViewBackground(XGUI::VerticalGradient, Qt::green, Qt::blue));
183
184     QMdiArea* aMDI = myMainWindow->mdiArea();
185     QMdiSubWindow* aWnd = aMDI->addSubWindow(view, Qt::FramelessWindowHint);
186     addView(aWnd);
187     aWnd->setGeometry(0,0, aMDI->width() / 2, aMDI->height() / 2);
188     aWnd->show();
189     return aWnd;
190 }
191
192 /*! Sets hot button
193  *\param theOper - hot operation
194  *\param theState - adding state to state map operations.
195  *\param theButton - adding state to button map operations.
196  */
197 void XGUI_Viewer::setHotButton( XGUI::InteractionStyle theInteractionStyle, XGUI::HotOperation theOper,
198                                    Qt::KeyboardModifiers theState, Qt::MouseButtons theButton )
199 {
200     myStateMap[theInteractionStyle][theOper]  = theState;
201     myButtonMap[theInteractionStyle][theOper] = theButton;
202 }
203
204 /*! Gets hot button for operation \a theOper.
205  *\param theOper - input hot operation
206  *\param theState - output state from state map operations.
207  *\param theButton - output state from button map operations.
208 */
209 void XGUI_Viewer::getHotButton( XGUI::InteractionStyle theInteractionStyle, XGUI::HotOperation theOper,
210                                    Qt::KeyboardModifiers& theState, Qt::MouseButtons& theButton )
211 {
212     theState  = myStateMap[theInteractionStyle][theOper];
213     theButton = myButtonMap[theInteractionStyle][theOper];
214 }
215
216 /*!
217   Changes visibility of trihedron to opposite
218 */
219 void XGUI_Viewer::toggleTrihedron()
220 {
221     setTrihedronShown( !isTrihedronVisible() );
222 }
223
224 /*!
225   \return true if trihedron is visible
226 */
227 bool XGUI_Viewer::isTrihedronVisible() const
228 {
229     return !myTrihedron.IsNull() && !myAISContext.IsNull() && myAISContext->IsDisplayed( myTrihedron );
230 }
231
232 /*!
233   Sets visibility state of trihedron
234   \param on - new state
235 */
236
237 void XGUI_Viewer::setTrihedronShown( const bool on )
238 {
239     if ( myTrihedron.IsNull() )
240         return;
241
242     if ( on ) {
243         myAISContext->Display( myTrihedron );
244         myAISContext->Deactivate(myTrihedron);
245     } else {
246         myAISContext->Erase( myTrihedron );
247     }
248 }
249
250 /*!
251   \return trihedron size
252 */
253 double XGUI_Viewer::trihedronSize() const
254 {
255     double sz = 0;
256     if ( !myTrihedron.IsNull() )
257         sz = myTrihedron->Size();
258     return sz;
259 }
260
261 /*!
262   Changes trihedron size
263   \param sz - new size
264 */
265 void XGUI_Viewer::setTrihedronSize( const double sz, bool isRelative )
266 {
267     if ( myTrihedronSize != sz || isRelative != myIsRelative) {
268         myTrihedronSize = sz; 
269         myIsRelative = isRelative;
270         updateTrihedron();
271     }
272 }
273
274 /*! 
275  * Update the size of the trihedron
276  */
277 void XGUI_Viewer::updateTrihedron() 
278 {
279     if ( myTrihedron.IsNull() )
280         return;
281
282     if(myIsRelative){
283         double newSz, oldSz;
284     
285         if(computeTrihedronSize(newSz, oldSz))
286             myTrihedron->SetSize(newSz);
287     
288     } else if(myTrihedron->Size() != myTrihedronSize) {
289         myTrihedron->SetSize(myTrihedronSize);
290     }
291 }
292
293 /*!
294   Get new and current trihedron size corresponding to the current model size
295 */
296 bool XGUI_Viewer::computeTrihedronSize( double& theNewSize, double& theSize )
297 {
298   theNewSize = 100;
299   theSize = 100;
300
301   //SRN: BUG IPAL8996, a usage of method ActiveView without an initialization
302   Handle(V3d_Viewer) viewer = v3dViewer();
303   viewer->InitActiveViews();
304   if(!viewer->MoreActiveViews()) return false;
305
306   Handle(V3d_View) view3d = viewer->ActiveView();
307   //SRN: END of fix
308
309   if ( view3d.IsNull() )
310     return false;
311
312   double Xmin = 0, Ymin = 0, Zmin = 0, Xmax = 0, Ymax = 0, Zmax = 0;
313   double aMaxSide;
314
315   view3d->View()->MinMaxValues( Xmin, Ymin, Zmin, Xmax, Ymax, Zmax );
316
317   if ( Xmin == RealFirst() || Ymin == RealFirst() || Zmin == RealFirst() ||
318        Xmax == RealLast()  || Ymax == RealLast()  || Zmax == RealLast() )
319     return false;
320
321   aMaxSide = Xmax - Xmin;
322   if ( aMaxSide < Ymax -Ymin ) aMaxSide = Ymax -Ymin;
323   if ( aMaxSide < Zmax -Zmin ) aMaxSide = Zmax -Zmin;
324
325   // IPAL21687
326   // The boundary box of the view may be initialized but nullified
327   // (case of infinite objects)
328   if ( aMaxSide < Precision::Confusion() )
329     return false;
330
331   static float EPS = 5.0E-3;
332   theSize = trihedron()->Size();
333   //theNewSize = aMaxSide*aSizeInPercents / 100.0;
334
335   return fabs( theNewSize - theSize ) > theSize * EPS ||
336          fabs( theNewSize - theSize) > theNewSize * EPS;
337 }
338
339
340 void XGUI_Viewer::onViewClosed(QMdiSubWindow* theView)
341 {
342     if ( !theView )
343         return;
344
345     emit deleteView( static_cast<XGUI_ViewWindow*>(theView->widget()) );
346     removeView( theView );
347
348     // if this is last view
349     if (myViews.size() == 0) {
350         Standard_Integer aViewsNb = 0;
351         for ( myV3dViewer->InitActiveViews(); myV3dViewer->MoreActiveViews(); myV3dViewer->NextActiveViews())
352             ++aViewsNb;
353         if ( aViewsNb < 2 ) {
354             //clean up presentations before last view is closed
355             myAISContext->RemoveAll(Standard_False);
356         }
357     }
358 }
359
360 /*!Remove view window \a theView from view manager.
361  *And close the last view, if it has \a theView.
362 */
363 void XGUI_Viewer::removeView( QMdiSubWindow* theView )
364 {
365     XGUI_ViewWindow* aWindow = static_cast<XGUI_ViewWindow*>(theView->widget());
366
367     aWindow->disconnect( this );
368     myViews.removeAt( myViews.indexOf( theView ) );
369     if ( myActiveView == theView )
370         myActiveView = 0;
371     if ( myViews.size() == 0 )
372         emit lastViewClosed();
373 }
374
375
376 /*void XGUI_Viewer::onViewMapped()
377 {
378   setTrihedronShown( true );
379 }*/
380
381
382 void XGUI_Viewer::addView(QMdiSubWindow* theView)
383 {
384     XGUI_ViewWindow* aWindow = dynamic_cast<XGUI_ViewWindow*>(theView->widget());
385
386     connect(aWindow, SIGNAL(closed(QMdiSubWindow*)),
387             this,    SLOT(onViewClosed(QMdiSubWindow*)));
388
389     connect(aWindow, SIGNAL(tryClosing(XGUI_ViewWindow*)),
390             this,    SIGNAL(tryCloseView(XGUI_ViewWindow*)));
391
392     connect(aWindow, SIGNAL(mousePressed(XGUI_ViewWindow*, QMouseEvent*)),
393             this,    SLOT(onMousePressed(XGUI_ViewWindow*, QMouseEvent*)));
394
395     connect(aWindow, SIGNAL(mouseReleased(XGUI_ViewWindow*, QMouseEvent*)),
396             this,    SIGNAL(mouseRelease(XGUI_ViewWindow*, QMouseEvent*)));
397
398     connect(aWindow, SIGNAL(mouseDoubleClicked(XGUI_ViewWindow*, QMouseEvent*)),
399             this,    SIGNAL(mouseDoubleClick(XGUI_ViewWindow*, QMouseEvent*)));
400
401     connect(aWindow, SIGNAL(mouseMoving(XGUI_ViewWindow*, QMouseEvent*)),
402             this,    SIGNAL(mouseMove(XGUI_ViewWindow*, QMouseEvent*)));
403
404     connect(aWindow, SIGNAL(keyPressed(XGUI_ViewWindow*, QKeyEvent*)),
405             this,    SIGNAL(keyPress(XGUI_ViewWindow*, QKeyEvent*)));
406
407     connect(aWindow, SIGNAL(keyReleased(XGUI_ViewWindow*, QKeyEvent*)),
408             this,    SIGNAL(keyRelease(XGUI_ViewWindow*, QKeyEvent*)));
409
410     connect(aWindow, SIGNAL(contextMenuRequested( QContextMenuEvent* )),
411             this,    SLOT  (onContextMenuRequested( QContextMenuEvent* )));
412
413     myViews.append(theView);
414 }
415
416 /*!
417     Emit activated for view \a view.
418 */
419 void XGUI_Viewer::onWindowActivated(QMdiSubWindow* view)
420 {
421     myActiveView = view;
422 }