Salome HOME
77b61accaf6fe7d7f38c01183e33e98a3c6cb573
[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 {
95     if ( !isInitialized ) {
96         isInitialized = true;
97
98         // standard interaction style
99         XGUI_Viewer::myStateMap[XGUI::STANDARD][XGUI::ZOOM]  = Qt::ControlModifier;
100         XGUI_Viewer::myButtonMap[XGUI::STANDARD][XGUI::ZOOM] = Qt::LeftButton;
101
102         XGUI_Viewer::myStateMap[XGUI::STANDARD][XGUI::PAN]   = Qt::ControlModifier;
103         XGUI_Viewer::myButtonMap[XGUI::STANDARD][XGUI::PAN]  = Qt::MidButton;
104
105         XGUI_Viewer::myStateMap[XGUI::STANDARD][XGUI::ROTATE]  = Qt::ControlModifier;
106         XGUI_Viewer::myButtonMap[XGUI::STANDARD][XGUI::ROTATE] = Qt::RightButton;
107
108         XGUI_Viewer::myStateMap[XGUI::STANDARD][XGUI::FIT_AREA]  = Qt::ControlModifier;
109         XGUI_Viewer::myButtonMap[XGUI::STANDARD][XGUI::FIT_AREA] = Qt::RightButton;
110
111         // "key free" interaction style
112         XGUI_Viewer::myStateMap[XGUI::KEY_FREE][XGUI::ZOOM]  = Qt::NoModifier;
113         XGUI_Viewer::myButtonMap[XGUI::KEY_FREE][XGUI::ZOOM] = Qt::RightButton;
114
115         XGUI_Viewer::myStateMap[XGUI::KEY_FREE][XGUI::PAN]   = Qt::NoModifier;
116         XGUI_Viewer::myButtonMap[XGUI::KEY_FREE][XGUI::PAN]  = Qt::MidButton;
117
118         XGUI_Viewer::myStateMap[XGUI::KEY_FREE][XGUI::ROTATE]  = Qt::NoModifier;
119         XGUI_Viewer::myButtonMap[XGUI::KEY_FREE][XGUI::ROTATE] = Qt::LeftButton;
120
121         XGUI_Viewer::myStateMap[XGUI::KEY_FREE][XGUI::FIT_AREA]  = Qt::NoModifier; // unused
122         XGUI_Viewer::myButtonMap[XGUI::KEY_FREE][XGUI::FIT_AREA] = Qt::NoButton;   // unused
123     }
124
125     // init CasCade viewers
126     myV3dViewer = CreateViewer(TCollection_ExtendedString("Viewer3d").ToExtString(),
127                                                    "", "", 1000.0, V3d_XposYnegZpos, Standard_True, Standard_True );
128     myV3dViewer->SetDefaultLights();
129
130     // init selector
131     myAISContext = new AIS_InteractiveContext( myV3dViewer );
132     myAISContext->SelectionColor( Quantity_NOC_WHITE );
133   
134     // display isoline on planar faces (box for ex.)
135     myAISContext->IsoOnPlane( true );
136   
137     if ( DisplayTrihedron )  {
138         Handle(Geom_Axis2Placement) anAxis = new Geom_Axis2Placement(gp::XOY());
139         myTrihedron = new AIS_Trihedron(anAxis);
140         myTrihedron->SetInfiniteState( Standard_True );
141     
142         Quantity_Color Col(193/255., 205/255., 193/255., Quantity_TOC_RGB);
143         myTrihedron->SetArrowColor( Col.Name() );
144         myTrihedron->SetSize(myTrihedronSize);
145         Handle(AIS_Drawer) drawer = myTrihedron->Attributes();
146         if (drawer->HasDatumAspect()) {
147             Handle(Prs3d_DatumAspect) daspect = drawer->DatumAspect();
148             daspect->FirstAxisAspect()->SetColor(Quantity_Color(1.0, 0.0, 0.0, Quantity_TOC_RGB));
149             daspect->SecondAxisAspect()->SetColor(Quantity_Color(0.0, 1.0, 0.0, Quantity_TOC_RGB));
150             daspect->ThirdAxisAspect()->SetColor(Quantity_Color(0.0, 0.0, 1.0, Quantity_TOC_RGB));
151         }
152     }
153     // set zooming style to standard
154     //myZoomingStyle = 0;
155 }
156
157
158 XGUI_Viewer::~XGUI_Viewer(void)
159 {
160     myAISContext.Nullify();
161     myV3dViewer.Nullify();
162 }
163
164
165 QMdiSubWindow* XGUI_Viewer::createView(V3d_TypeOfView theType)
166 {
167     // create view frame
168     XGUI_ViewWindow* view = new XGUI_ViewWindow(this, theType);
169     // get main view window (created by view frame)
170     //OCCViewer_ViewWindow* vw = view->getView(OCCViewer_ViewFrame::MAIN_VIEW);
171     // initialize main view window
172     //initView( vw );
173     // set default background for view window
174     //vw->setBackground( background(0) ); // 0 means MAIN_VIEW (other views are not yet created here)
175     //// connect signal from viewport
176     connect(view->viewPort(), SIGNAL(vpClosed()), this, SLOT(onViewClosed()));
177     connect(view->viewPort(), SIGNAL(vpMapped()), this, SLOT(onViewMapped()));
178
179     view->setBackground(XGUI_ViewBackground(XGUI::VerticalGradient, Qt::green, Qt::blue));
180
181     QMdiArea* aMDI = myMainWindow->mdiArea();
182     QMdiSubWindow* aWnd = aMDI->addSubWindow(view, Qt::FramelessWindowHint);
183     aWnd->setGeometry(0,0, aMDI->width() / 2, aMDI->height() / 2);
184     aWnd->show();
185     return aWnd;
186 }
187
188 /*! Sets hot button
189  *\param theOper - hot operation
190  *\param theState - adding state to state map operations.
191  *\param theButton - adding state to button map operations.
192  */
193 void XGUI_Viewer::setHotButton( XGUI::InteractionStyle theInteractionStyle, XGUI::HotOperation theOper,
194                                    Qt::KeyboardModifiers theState, Qt::MouseButtons theButton )
195 {
196     myStateMap[theInteractionStyle][theOper]  = theState;
197     myButtonMap[theInteractionStyle][theOper] = theButton;
198 }
199
200 /*! Gets hot button for operation \a theOper.
201  *\param theOper - input hot operation
202  *\param theState - output state from state map operations.
203  *\param theButton - output state from button map operations.
204 */
205 void XGUI_Viewer::getHotButton( XGUI::InteractionStyle theInteractionStyle, XGUI::HotOperation theOper,
206                                    Qt::KeyboardModifiers& theState, Qt::MouseButtons& theButton )
207 {
208     theState  = myStateMap[theInteractionStyle][theOper];
209     theButton = myButtonMap[theInteractionStyle][theOper];
210 }
211
212 /*!
213   Changes visibility of trihedron to opposite
214 */
215 void XGUI_Viewer::toggleTrihedron()
216 {
217     setTrihedronShown( !isTrihedronVisible() );
218 }
219
220 /*!
221   \return true if trihedron is visible
222 */
223 bool XGUI_Viewer::isTrihedronVisible() const
224 {
225     return !myTrihedron.IsNull() && !myAISContext.IsNull() && myAISContext->IsDisplayed( myTrihedron );
226 }
227
228 /*!
229   Sets visibility state of trihedron
230   \param on - new state
231 */
232
233 void XGUI_Viewer::setTrihedronShown( const bool on )
234 {
235     if ( myTrihedron.IsNull() )
236         return;
237
238     if ( on ) {
239         myAISContext->Display( myTrihedron );
240         myAISContext->Deactivate(myTrihedron);
241     } else {
242         myAISContext->Erase( myTrihedron );
243     }
244 }
245
246 /*!
247   \return trihedron size
248 */
249 double XGUI_Viewer::trihedronSize() const
250 {
251     double sz = 0;
252     if ( !myTrihedron.IsNull() )
253         sz = myTrihedron->Size();
254     return sz;
255 }
256
257 /*!
258   Changes trihedron size
259   \param sz - new size
260 */
261 void XGUI_Viewer::setTrihedronSize( const double sz, bool isRelative )
262 {
263     if ( myTrihedronSize != sz || isRelative != myIsRelative) {
264         myTrihedronSize = sz; 
265         myIsRelative = isRelative;
266         updateTrihedron();
267     }
268 }
269
270 /*! 
271  * Update the size of the trihedron
272  */
273 void XGUI_Viewer::updateTrihedron() 
274 {
275     if ( myTrihedron.IsNull() )
276         return;
277
278     if(myIsRelative){
279         double newSz, oldSz;
280     
281         if(computeTrihedronSize(newSz, oldSz))
282             myTrihedron->SetSize(newSz);
283     
284     } else if(myTrihedron->Size() != myTrihedronSize) {
285         myTrihedron->SetSize(myTrihedronSize);
286     }
287 }
288
289 /*!
290   Get new and current trihedron size corresponding to the current model size
291 */
292 bool XGUI_Viewer::computeTrihedronSize( double& theNewSize, double& theSize )
293 {
294   theNewSize = 100;
295   theSize = 100;
296
297   //SRN: BUG IPAL8996, a usage of method ActiveView without an initialization
298   Handle(V3d_Viewer) viewer = v3dViewer();
299   viewer->InitActiveViews();
300   if(!viewer->MoreActiveViews()) return false;
301
302   Handle(V3d_View) view3d = viewer->ActiveView();
303   //SRN: END of fix
304
305   if ( view3d.IsNull() )
306     return false;
307
308   double Xmin = 0, Ymin = 0, Zmin = 0, Xmax = 0, Ymax = 0, Zmax = 0;
309   double aMaxSide;
310
311   view3d->View()->MinMaxValues( Xmin, Ymin, Zmin, Xmax, Ymax, Zmax );
312
313   if ( Xmin == RealFirst() || Ymin == RealFirst() || Zmin == RealFirst() ||
314        Xmax == RealLast()  || Ymax == RealLast()  || Zmax == RealLast() )
315     return false;
316
317   aMaxSide = Xmax - Xmin;
318   if ( aMaxSide < Ymax -Ymin ) aMaxSide = Ymax -Ymin;
319   if ( aMaxSide < Zmax -Zmin ) aMaxSide = Zmax -Zmin;
320
321   // IPAL21687
322   // The boundary box of the view may be initialized but nullified
323   // (case of infinite objects)
324   if ( aMaxSide < Precision::Confusion() )
325     return false;
326
327   static float EPS = 5.0E-3;
328   theSize = trihedron()->Size();
329   //theNewSize = aMaxSide*aSizeInPercents / 100.0;
330
331   return fabs( theNewSize - theSize ) > theSize * EPS ||
332          fabs( theNewSize - theSize) > theNewSize * EPS;
333 }
334
335
336 void XGUI_Viewer::onViewClosed()
337 {
338   Standard_Integer aViewsNb = 0;
339   for ( myV3dViewer->InitActiveViews(); myV3dViewer->MoreActiveViews(); myV3dViewer->NextActiveViews())
340     ++aViewsNb;
341   if ( aViewsNb < 2 ) {
342     //clean up presentations before last view is closed
343     myAISContext->RemoveAll(Standard_False);
344   }
345 }
346
347 void XGUI_Viewer::onViewMapped()
348 {
349   setTrihedronShown( true );
350 }
351