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