2 #include "XGUI_ViewPort.h"
3 #include "XGUI_ViewWindow.h"
4 #include "XGUI_Viewer.h"
5 #include "XGUI_Constants.h"
10 #include <QApplication>
12 #include <V3d_OrthographicView.hxx>
13 #include <V3d_PerspectiveView.hxx>
14 #include <Visual3d_View.hxx>
15 #include <Graphic3d_GraphicDriver.hxx>
18 #include <WNT_Window.hxx>
20 #include <Xw_Window.hxx>
25 static double rx = 0.;
26 static double ry = 0.;
29 static Standard_Boolean zRotation = Standard_False;
33 Create native view window for CasCade view [ static ]
35 Handle(Aspect_Window) CreateCasWindow(const Handle(V3d_View)& view, WId winId)
37 Aspect_Handle aWindowHandle = (Aspect_Handle) winId;
39 Handle(WNT_Window) viewWindow = new WNT_Window(aWindowHandle);
41 Handle(Aspect_DisplayConnection) aDispConnection = view->Viewer()->Driver()->GetDisplayConnection();
42 Handle(Xw_Window) viewWindow = new Xw_Window( aDispConnection, aWindowHandle );
48 //************************************************************************
49 //************************************************************************
50 //************************************************************************
51 XGUI_ViewPort::XGUI_ViewPort(XGUI_ViewWindow* theParent,
52 const Handle(V3d_Viewer)& theViewer,
53 V3d_TypeOfView theType)
55 myPaintersRedrawing(false),
57 myIsAdvancedZoomingEnabled(false),
61 setMouseTracking(true);
62 setBackgroundRole(QPalette::NoRole);
64 // set focus policy to threat QContextMenuEvent from keyboard
65 setFocusPolicy(Qt::StrongFocus);
66 setAttribute(Qt::WA_PaintOnScreen);
67 setAttribute(Qt::WA_NoSystemBackground);
68 setAutoFillBackground(false);
70 if (theType == V3d_ORTHOGRAPHIC) {
71 myOrthoView = new V3d_OrthographicView(theViewer);
72 myActiveView = myOrthoView;
75 myPerspView = new V3d_PerspectiveView(theViewer);
76 myActiveView = myPerspView;
78 myActiveView->SetSurfaceDetail(V3d_TEX_ALL);
81 //***********************************************
82 XGUI_ViewPort::~XGUI_ViewPort()
86 //***********************************************
87 bool XGUI_ViewPort::mapView(const Handle(V3d_View)& theView)
89 if (!setWindow(theView))
92 if (!mapped(theView)) {
93 theView->SetWindow(myWindow);
94 //if (theView != activeView())
95 //theView->View()->Deactivate();
98 /* create static trihedron (16551: EDF PAL 501) */
99 //OCCViewer_ViewWindow* aVW = dynamic_cast<OCCViewer_ViewWindow*>( parentWidget()->parentWidget()->parentWidget() );
101 // OCCViewer_Viewer* aViewModel = dynamic_cast<OCCViewer_Viewer*>( aVW->getViewManager()->getViewModel() );
102 // if ( aViewModel && aViewModel->isStaticTrihedronDisplayed() ){
103 //theView->ZBufferTriedronSetup();
104 theView->TriedronDisplay(Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.05, V3d_ZBUFFER);
113 //***********************************************
114 bool XGUI_ViewPort::setWindow(const Handle(V3d_View)& theView)
116 if (!myWindow.IsNull())
119 if (theView.IsNull())
122 attachWindow(theView, CreateCasWindow(theView, winId()));
124 myWindow = theView->Window();
125 return !myWindow.IsNull();
128 //***********************************************
129 bool XGUI_ViewPort::mapped(const Handle(V3d_View)& theView) const
131 return (!theView.IsNull() && theView->View()->IsDefined());
134 //***********************************************
135 void XGUI_ViewPort::updateBackground()
137 if (activeView().IsNull())
139 if (!myBackground.isValid())
142 // VSR: Important note on below code.
143 // In OCCT (in version 6.5.2), things about the background drawing
144 // are not straightforward and not clearly understandable:
145 // - Horizontal gradient is drawn vertically (!), well ok, from top side to bottom one.
146 // - Vertical gradient is drawn horizontally (!), from right side to left one (!!!).
147 // - First and second diagonal gradients are confused.
148 // - Image texture, once set, can not be removed (!).
149 // - Texture image fill mode Aspect_FM_NONE is not taken into account (and means the same
150 // as Aspect_FM_CENTERED).
151 // - The only way to cancel gradient background (and get back to single colored) is to
152 // set gradient background style to Aspect_GFM_NONE while passing two colors is also needed
153 // (see V3d_View::SetBgGradientColors() function).
154 // - Also, it is impossible to draw texture image above the gradiented background (only above
156 // In OCCT 6.5.3 all above mentioned problems are fixed; so, above comment should be removed as soon
157 // as SALOME is migrated to OCCT 6.5.3. The same concerns #ifdef statements in the below code
158 switch(myBackground.mode()) {
159 case XGUI::ColorBackground: {
160 QColor c = myBackground.color();
162 // Unset texture should be done here
164 Quantity_Color qCol(c.red() / 255., c.green() / 255., c.blue() / 255., Quantity_TOC_RGB);
165 activeView()->SetBgGradientStyle(Aspect_GFM_NONE); // cancel gradient background
166 activeView()->SetBgImageStyle(Aspect_FM_NONE); // cancel texture background
167 // then change background color
168 activeView()->SetBackgroundColor(qCol);
170 activeView()->Update();
174 case XGUI::SimpleGradientBackground: {
176 int type = myBackground.gradient(c1, c2);
177 if (c1.isValid() && type >= XGUI::HorizontalGradient && type <= XGUI::LastGradient) {
178 // Unset texture should be done here
180 // Get colors and set-up gradiented background
183 Quantity_Color qCol1(c1.red() / 255., c1.green() / 255., c1.blue() / 255., Quantity_TOC_RGB);
184 Quantity_Color qCol2(c2.red() / 255., c2.green() / 255., c2.blue() / 255., Quantity_TOC_RGB);
185 activeView()->SetBgImageStyle(Aspect_FM_NONE); // cancel texture background
187 case XGUI::HorizontalGradient:
188 activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_HOR,
191 case XGUI::VerticalGradient:
192 activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_VER,
195 case XGUI::Diagonal1Gradient:
196 activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_DIAG1,
199 case XGUI::Diagonal2Gradient:
200 activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_DIAG2,
203 case XGUI::Corner1Gradient:
204 activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_CORNER1,
207 case XGUI::Corner2Gradient:
208 activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_CORNER2,
211 case XGUI::Corner3Gradient:
212 activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_CORNER3,
215 case XGUI::Corner4Gradient:
216 activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_CORNER4,
225 case XGUI::CustomGradientBackground:
226 // NOT IMPLEMENTED YET
231 // VSR: In OCCT before v6.5.3 below code can't be used because of very ugly bug - it has been impossible to
232 // clear the background texture image as soon as it was once set to the viewer.
233 if (myBackground.isTextureShown()) {
235 int textureMode = myBackground.texture(fileName);
236 QFileInfo fi(fileName);
237 if (!fileName.isEmpty() && fi.exists()) {
238 // set texture image: file name and fill mode
239 switch(textureMode) {
240 case XGUI::CenterTexture:
241 activeView()->SetBackgroundImage(fi.absoluteFilePath().toLatin1().constData(),
244 case XGUI::TileTexture:
245 activeView()->SetBackgroundImage(fi.absoluteFilePath().toLatin1().constData(),
248 case XGUI::StretchTexture:
249 activeView()->SetBackgroundImage(fi.absoluteFilePath().toLatin1().constData(),
255 activeView()->Update();
260 //***********************************************
261 void XGUI_ViewPort::attachWindow(const Handle(V3d_View)& theView,
262 const Handle(Aspect_Window)& theWnd)
264 if (!theView.IsNull()) {
265 theView->SetWindow(theWnd);
270 //***********************************************
271 void XGUI_ViewPort::paintEvent(QPaintEvent* theEvent)
274 /* X11 : map before show doesn't work */
275 if ( !mapped( activeView() ) )
276 mapView( activeView() );
278 if (!myWindow.IsNull()) {
279 QApplication::syncX();
280 QRect rc = theEvent->rect();
281 //if ( !myPaintersRedrawing ) {
282 //activeView()->Redraw();
283 activeView()->Redraw(rc.x(), rc.y(), rc.width(), rc.height());
287 //if ( myPaintersRedrawing ) {
288 // QPainter p( this );
289 // //emit vpDrawExternal( &p );
290 // myPaintersRedrawing = false;
294 //***********************************************
295 void XGUI_ViewPort::resizeEvent(QResizeEvent* theEvent)
298 /* Win32 : map before first show to avoid flicker */
299 if (!mapped(activeView()))
300 mapView(activeView());
302 QApplication::syncX();
303 if (!activeView().IsNull()) {
304 activeView()->MustBeResized();
309 //***********************************************
310 QImage XGUI_ViewPort::dumpView(QRect theRect, bool toUpdate)
312 Handle(V3d_View) view = getView();
318 if (theRect.isNull()) {
322 aWidth = theRect.width();
323 aHeight = theRect.height();
325 QApplication::syncX();
327 unsigned char* data = new unsigned char[aWidth * aHeight * 4];
330 if (theRect.isNull()) {
333 p = mapFromParent(geometry().topLeft());
336 view->Redraw(theRect.x(), theRect.y(), theRect.width(), theRect.height());
337 p = theRect.topLeft();
339 glReadPixels(p.x(), p.y(), aWidth, aHeight, GL_RGBA, GL_UNSIGNED_BYTE, data);
341 QImage anImage(data, aWidth, aHeight, QImage::Format_ARGB32);
342 anImage = anImage.mirrored();
343 anImage = anImage.rgbSwapped();
348 Inits 'rotation' transformation.
350 void XGUI_ViewPort::startRotation(int x, int y, int theRotationPointType,
351 const gp_Pnt& theSelectedPoint)
353 if (!activeView().IsNull()) {
354 switch(theRotationPointType) {
356 activeView()->StartRotation(x, y, 0.45);
363 activeView()->Size(X, Y);
364 rx = Standard_Real(activeView()->Convert(X));
365 ry = Standard_Real(activeView()->Convert(Y));
367 activeView()->Rotate(0., 0., 0., theSelectedPoint.X(), theSelectedPoint.Y(),
368 theSelectedPoint.Z(),
371 Quantity_Ratio zRotationThreshold;
372 zRotation = Standard_False;
373 zRotationThreshold = 0.45;
374 if (zRotationThreshold > 0.) {
375 Standard_Real dx = Abs(sx - rx / 2.);
376 Standard_Real dy = Abs(sy - ry / 2.);
377 Standard_Real dd = zRotationThreshold * (rx + ry) / 2.;
378 if (dx > dd || dy > dd)
379 zRotation = Standard_True;
385 activeView()->DepthFitAll();
390 Rotates the viewport.
392 void XGUI_ViewPort::rotate(int x, int y, int theRotationPointType, const gp_Pnt& theSelectedPoint)
394 if (!activeView().IsNull()) {
395 switch(theRotationPointType) {
397 activeView()->Rotation(x, y);
402 dz = atan2(Standard_Real(x) - rx / 2., ry / 2. - Standard_Real(y))
403 - atan2(sx - rx / 2., ry / 2. - sy);
406 dx = (Standard_Real(x) - sx) * M_PI / rx;
407 dy = (sy - Standard_Real(y)) * M_PI / ry;
411 activeView()->Rotate(dx, dy, dz, theSelectedPoint.X(), theSelectedPoint.Y(),
412 theSelectedPoint.Z(),
418 emit vpTransformed();
420 // setZSize( getZSize() );
424 Resets the viewport after 'rotation'.
426 void XGUI_ViewPort::endRotation()
428 if (!activeView().IsNull()) {
429 activeView()->ZFitAll(1.);
430 activeView()->SetZSize(0.);
431 activeView()->Update();
432 emit vpTransformed();
437 Inits 'zoom' transformation.
439 void XGUI_ViewPort::startZoomAtPoint(int x, int y)
441 if (!activeView().IsNull()/* && isAdvancedZoomingEnabled() */)
442 activeView()->StartZoomAtPoint(x, y);
446 Centers the viewport.
448 void XGUI_ViewPort::setCenter(int x, int y)
450 if (!activeView().IsNull()) {
451 activeView()->Place(x, y, myScale);
452 emit vpTransformed();
457 Called at 'pan' transformation.
459 void XGUI_ViewPort::pan(int dx, int dy)
461 if (!activeView().IsNull()) {
462 activeView()->Pan(dx, dy, 1.0);
463 emit vpTransformed();
468 Called at 'window fit' transformation.
470 void XGUI_ViewPort::fitRect(const QRect& rect)
472 if (!activeView().IsNull()) {
473 activeView()->WindowFit(rect.left(), rect.top(), rect.right(), rect.bottom());
474 emit vpTransformed();
479 Called at 'zoom' transformation.
481 void XGUI_ViewPort::zoom(int x0, int y0, int x, int y)
483 if (!activeView().IsNull()) {
484 if (isAdvancedZoomingEnabled())
485 activeView()->ZoomAtPoint(x0, y0, x, y);
487 activeView()->Zoom(x0 + y0, 0, x + y, 0);
488 emit vpTransformed();
493 Sets the background data
495 void XGUI_ViewPort::setBackground(const XGUI_ViewBackground& bgData)
497 if (bgData.isValid()) {
498 myBackground = bgData;
500 emit vpChangeBackground(myBackground);
504 void XGUI_ViewPort::fitAll(bool theKeepScale, bool theWithZ, bool theUpd)
506 if ( activeView().IsNull() )
510 myScale = activeView()->Scale();
512 Standard_Real aMargin = 0.01;
513 activeView()->FitAll( aMargin, theWithZ, theUpd );
514 activeView()->SetZSize(0.);
515 emit vpTransformed( );
518 void XGUI_ViewPort::syncronizeWith( const XGUI_ViewPort* ref )
520 Handle(V3d_View) refView = ref->getView();
521 Handle(V3d_View) tgtView = getView();
523 /* The following params are copied:
524 - view type( ortho/persp )
525 - position of view point
526 - orientation of high point
527 - position of the eye
534 /* we'll update after setting all params */
535 tgtView->SetImmediateUpdate( Standard_False );
538 if ( refView->Type() == V3d_PERSPECTIVE )
539 tgtView->SetFocale( refView->Focale() );
542 Standard_Real x, y, z;
543 refView->At( x, y, z ); tgtView->SetAt( x, y, z );
544 refView->Up( x, y, z ); tgtView->SetUp( x, y, z );
545 refView->Eye( x, y, z ); tgtView->SetEye( x, y, z );
546 refView->Proj( x, y, z ); tgtView->SetProj( x, y, z );
547 refView->Center( x, y ); tgtView->SetCenter( x, y );
548 tgtView->SetScale( refView->Scale() );
549 tgtView->SetTwist( refView->Twist() );
553 tgtView->SetImmediateUpdate( Standard_True );