1 #include "XGUI_ViewPort.h"
2 #include "XGUI_ViewWindow.h"
3 #include "XGUI_Viewer.h"
4 #include "XGUI_Constants.h"
9 #include <QApplication>
11 #include <V3d_OrthographicView.hxx>
12 #include <V3d_PerspectiveView.hxx>
13 #include <Visual3d_View.hxx>
14 #include <Graphic3d_GraphicDriver.hxx>
17 #include <WNT_Window.hxx>
19 #include <Xw_Window.hxx>
24 static double rx = 0.;
25 static double ry = 0.;
28 static Standard_Boolean zRotation = Standard_False;
31 Create native view window for CasCade view [ static ]
33 Handle(Aspect_Window) CreateCasWindow(const Handle(V3d_View)& view, WId winId)
35 Aspect_Handle aWindowHandle = (Aspect_Handle) winId;
37 Handle(WNT_Window) viewWindow = new WNT_Window(aWindowHandle);
39 Handle(Aspect_DisplayConnection) aDispConnection = view->Viewer()->Driver()->GetDisplayConnection();
40 Handle(Xw_Window) viewWindow = new Xw_Window( aDispConnection, aWindowHandle );
45 //************************************************************************
46 //************************************************************************
47 //************************************************************************
48 XGUI_ViewPort::XGUI_ViewPort(XGUI_ViewWindow* theParent, const Handle(V3d_Viewer)& theViewer,
49 V3d_TypeOfView theType)
51 myPaintersRedrawing(false),
53 myIsAdvancedZoomingEnabled(false),
57 setMouseTracking(true);
58 setBackgroundRole(QPalette::NoRole);
60 // set focus policy to threat QContextMenuEvent from keyboard
61 setFocusPolicy(Qt::StrongFocus);
62 setAttribute(Qt::WA_PaintOnScreen);
63 setAttribute(Qt::WA_NoSystemBackground);
64 setAutoFillBackground(false);
66 if (theType == V3d_ORTHOGRAPHIC) {
67 myOrthoView = new V3d_OrthographicView(theViewer);
68 myActiveView = myOrthoView;
71 myPerspView = new V3d_PerspectiveView(theViewer);
72 myActiveView = myPerspView;
74 myActiveView->SetSurfaceDetail(V3d_TEX_ALL);
77 //***********************************************
78 XGUI_ViewPort::~XGUI_ViewPort()
82 //***********************************************
83 bool XGUI_ViewPort::mapView(const Handle(V3d_View)& theView)
85 if (!setWindow(theView))
88 if (!mapped(theView)) {
89 theView->SetWindow(myWindow);
90 //if (theView != activeView())
91 //theView->View()->Deactivate();
94 /* create static trihedron (16551: EDF PAL 501) */
95 //OCCViewer_ViewWindow* aVW = dynamic_cast<OCCViewer_ViewWindow*>( parentWidget()->parentWidget()->parentWidget() );
97 // OCCViewer_Viewer* aViewModel = dynamic_cast<OCCViewer_Viewer*>( aVW->getViewManager()->getViewModel() );
98 // if ( aViewModel && aViewModel->isStaticTrihedronDisplayed() ){
99 //theView->ZBufferTriedronSetup();
100 theView->TriedronDisplay(Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.05, V3d_ZBUFFER);
109 //***********************************************
110 bool XGUI_ViewPort::setWindow(const Handle(V3d_View)& theView)
112 if (!myWindow.IsNull())
115 if (theView.IsNull())
118 attachWindow(theView, CreateCasWindow(theView, winId()));
120 myWindow = theView->Window();
121 return !myWindow.IsNull();
124 //***********************************************
125 bool XGUI_ViewPort::mapped(const Handle(V3d_View)& theView) const
127 return (!theView.IsNull() && theView->View()->IsDefined());
130 //***********************************************
131 void XGUI_ViewPort::updateBackground()
133 if (activeView().IsNull())
135 if (!myBackground.isValid())
138 // VSR: Important note on below code.
139 // In OCCT (in version 6.5.2), things about the background drawing
140 // are not straightforward and not clearly understandable:
141 // - Horizontal gradient is drawn vertically (!), well ok, from top side to bottom one.
142 // - Vertical gradient is drawn horizontally (!), from right side to left one (!!!).
143 // - First and second diagonal gradients are confused.
144 // - Image texture, once set, can not be removed (!).
145 // - Texture image fill mode Aspect_FM_NONE is not taken into account (and means the same
146 // as Aspect_FM_CENTERED).
147 // - The only way to cancel gradient background (and get back to single colored) is to
148 // set gradient background style to Aspect_GFM_NONE while passing two colors is also needed
149 // (see V3d_View::SetBgGradientColors() function).
150 // - Also, it is impossible to draw texture image above the gradiented background (only above
152 // In OCCT 6.5.3 all above mentioned problems are fixed; so, above comment should be removed as soon
153 // as SALOME is migrated to OCCT 6.5.3. The same concerns #ifdef statements in the below code
154 switch (myBackground.mode()) {
155 case Qtx::ColorBackground: {
156 QColor c = myBackground.color();
158 // Unset texture should be done here
160 Quantity_Color qCol(c.red() / 255., c.green() / 255., c.blue() / 255., Quantity_TOC_RGB);
161 activeView()->SetBgGradientStyle(Aspect_GFM_NONE); // cancel gradient background
162 activeView()->SetBgImageStyle(Aspect_FM_NONE); // cancel texture background
163 // then change background color
164 activeView()->SetBackgroundColor(qCol);
166 activeView()->Update();
170 case Qtx::SimpleGradientBackground: {
172 int type = myBackground.gradient(c1, c2);
173 if (c1.isValid() && type >= XGUI::HorizontalGradient && type <= XGUI::LastGradient) {
174 // Unset texture should be done here
176 // Get colors and set-up gradiented background
179 Quantity_Color qCol1(c1.red() / 255., c1.green() / 255., c1.blue() / 255.,
181 Quantity_Color qCol2(c2.red() / 255., c2.green() / 255., c2.blue() / 255.,
183 activeView()->SetBgImageStyle(Aspect_FM_NONE); // cancel texture background
185 case XGUI::HorizontalGradient:
186 activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_HOR,
189 case XGUI::VerticalGradient:
190 activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_VER,
193 case XGUI::Diagonal1Gradient:
194 activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_DIAG1,
197 case XGUI::Diagonal2Gradient:
198 activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_DIAG2,
201 case XGUI::Corner1Gradient:
202 activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_CORNER1,
205 case XGUI::Corner2Gradient:
206 activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_CORNER2,
209 case XGUI::Corner3Gradient:
210 activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_CORNER3,
213 case XGUI::Corner4Gradient:
214 activeView()->SetBgGradientColors(qCol1, qCol2, Aspect_GFM_CORNER4,
223 case Qtx::CustomGradientBackground:
224 // NOT IMPLEMENTED YET
229 // VSR: In OCCT before v6.5.3 below code can't be used because of very ugly bug - it has been impossible to
230 // clear the background texture image as soon as it was once set to the viewer.
231 if (myBackground.isTextureShown()) {
233 int textureMode = myBackground.texture(fileName);
234 QFileInfo fi(fileName);
235 if (!fileName.isEmpty() && fi.exists()) {
236 // set texture image: file name and fill mode
237 switch (textureMode) {
238 case XGUI::CenterTexture:
239 activeView()->SetBackgroundImage(fi.absoluteFilePath().toLatin1().constData(),
242 case XGUI::TileTexture:
243 activeView()->SetBackgroundImage(fi.absoluteFilePath().toLatin1().constData(),
246 case XGUI::StretchTexture:
247 activeView()->SetBackgroundImage(fi.absoluteFilePath().toLatin1().constData(),
253 activeView()->Update();
258 //***********************************************
259 void XGUI_ViewPort::attachWindow(const Handle(V3d_View)& theView,
260 const Handle(Aspect_Window)& theWnd)
262 if (!theView.IsNull()) {
263 theView->SetWindow(theWnd);
268 //***********************************************
269 void XGUI_ViewPort::paintEvent(QPaintEvent* theEvent)
272 /* X11 : map before show doesn't work */
273 if ( !mapped( activeView() ) )
274 mapView( activeView() );
276 if (!myWindow.IsNull()) {
277 QApplication::syncX();
278 QRect rc = theEvent->rect();
279 //if ( !myPaintersRedrawing ) {
280 //activeView()->Redraw();
281 activeView()->Redraw(rc.x(), rc.y(), rc.width(), rc.height());
285 //if ( myPaintersRedrawing ) {
286 // QPainter p( this );
287 // //emit vpDrawExternal( &p );
288 // myPaintersRedrawing = false;
292 //***********************************************
293 void XGUI_ViewPort::resizeEvent(QResizeEvent* theEvent)
296 /* Win32 : map before first show to avoid flicker */
297 if (!mapped(activeView()))
298 mapView(activeView());
300 QApplication::syncX();
301 if (!activeView().IsNull()) {
302 activeView()->MustBeResized();
307 //***********************************************
308 QImage XGUI_ViewPort::dumpView(unsigned char*& theData, QRect theRect, bool toUpdate)
310 Handle(V3d_View) view = getView();
316 if (theRect.isNull()) {
320 aWidth = theRect.width();
321 aHeight = theRect.height();
323 QApplication::syncX();
325 theData = new unsigned char[aWidth * aHeight * 4];
328 if (theRect.isNull()) {
331 p = mapFromParent(geometry().topLeft());
334 view->Redraw(theRect.x(), theRect.y(), theRect.width(), theRect.height());
335 p = theRect.topLeft();
337 glReadPixels(p.x(), p.y(), aWidth, aHeight, GL_RGBA, GL_UNSIGNED_BYTE, theData);
339 QImage anImage(theData, aWidth, aHeight, QImage::Format_ARGB32);
340 anImage = anImage.mirrored();
341 anImage = anImage.rgbSwapped();
346 Inits 'rotation' transformation.
348 void XGUI_ViewPort::startRotation(int x, int y, int theRotationPointType,
349 const gp_Pnt& theSelectedPoint)
351 if (!activeView().IsNull()) {
352 switch (theRotationPointType) {
354 activeView()->StartRotation(x, y, 0.45);
361 activeView()->Size(X, Y);
362 rx = Standard_Real(activeView()->Convert(X));
363 ry = Standard_Real(activeView()->Convert(Y));
365 activeView()->Rotate(0., 0., 0., theSelectedPoint.X(), theSelectedPoint.Y(),
366 theSelectedPoint.Z(),
369 Quantity_Ratio zRotationThreshold;
370 zRotation = Standard_False;
371 zRotationThreshold = 0.45;
372 if (zRotationThreshold > 0.) {
373 Standard_Real dx = Abs(sx - rx / 2.);
374 Standard_Real dy = Abs(sy - ry / 2.);
375 Standard_Real dd = zRotationThreshold * (rx + ry) / 2.;
376 if (dx > dd || dy > dd)
377 zRotation = Standard_True;
383 activeView()->DepthFitAll();
388 Rotates the viewport.
390 void XGUI_ViewPort::rotate(int x, int y, int theRotationPointType, const gp_Pnt& theSelectedPoint)
392 if (!activeView().IsNull()) {
393 switch (theRotationPointType) {
395 activeView()->Rotation(x, y);
400 dz = atan2(Standard_Real(x) - rx / 2., ry / 2. - Standard_Real(y))
401 - atan2(sx - rx / 2., ry / 2. - sy);
404 dx = (Standard_Real(x) - sx) * M_PI / rx;
405 dy = (sy - Standard_Real(y)) * M_PI / ry;
409 activeView()->Rotate(dx, dy, dz, theSelectedPoint.X(), theSelectedPoint.Y(),
410 theSelectedPoint.Z(),
416 emit vpTransformed();
418 // setZSize( getZSize() );
422 Resets the viewport after 'rotation'.
424 void XGUI_ViewPort::endRotation()
426 if (!activeView().IsNull()) {
427 activeView()->ZFitAll(1.);
428 activeView()->SetZSize(0.);
429 activeView()->Update();
430 emit vpTransformed();
435 Inits 'zoom' transformation.
437 void XGUI_ViewPort::startZoomAtPoint(int x, int y)
439 if (!activeView().IsNull()/* && isAdvancedZoomingEnabled() */)
440 activeView()->StartZoomAtPoint(x, y);
444 Centers the viewport.
446 void XGUI_ViewPort::setCenter(int x, int y)
448 if (!activeView().IsNull()) {
449 activeView()->Place(x, y, myScale);
450 emit vpTransformed();
455 Called at 'pan' transformation.
457 void XGUI_ViewPort::pan(int dx, int dy)
459 if (!activeView().IsNull()) {
460 activeView()->Pan(dx, dy, 1.0);
461 emit vpTransformed();
466 Called at 'window fit' transformation.
468 void XGUI_ViewPort::fitRect(const QRect& rect)
470 if (!activeView().IsNull()) {
471 activeView()->WindowFit(rect.left(), rect.top(), rect.right(), rect.bottom());
472 emit vpTransformed();
477 Called at 'zoom' transformation.
479 void XGUI_ViewPort::zoom(int x0, int y0, int x, int y)
481 if (!activeView().IsNull()) {
482 if (isAdvancedZoomingEnabled())
483 activeView()->ZoomAtPoint(x0, y0, x, y);
485 activeView()->Zoom(x0 + y0, 0, x + y, 0);
486 emit vpTransformed();
491 Sets the background data
493 void XGUI_ViewPort::setBackground(const Qtx::BackgroundData& bgData)
495 if (bgData.isValid()) {
496 myBackground = bgData;
498 emit vpChangeBackground(myBackground);
502 void XGUI_ViewPort::fitAll(bool theKeepScale, bool theWithZ, bool theUpd)
504 if (activeView().IsNull())
508 myScale = activeView()->Scale();
510 Standard_Real aMargin = 0.01;
511 activeView()->FitAll(aMargin, theWithZ, theUpd);
512 activeView()->SetZSize(0.);
513 emit vpTransformed();
516 void XGUI_ViewPort::syncronizeWith(const XGUI_ViewPort* ref)
518 Handle(V3d_View) refView = ref->getView();
519 Handle(V3d_View) tgtView = getView();
521 /* The following params are copied:
522 - view type( ortho/persp )
523 - position of view point
524 - orientation of high point
525 - position of the eye
532 /* we'll update after setting all params */
533 tgtView->SetImmediateUpdate( Standard_False);
536 if (refView->Type() == V3d_PERSPECTIVE)
537 tgtView->SetFocale(refView->Focale());
540 Standard_Real x, y, z;
541 refView->At(x, y, z);
542 tgtView->SetAt(x, y, z);
543 refView->Up(x, y, z);
544 tgtView->SetUp(x, y, z);
545 refView->Eye(x, y, z);
546 tgtView->SetEye(x, y, z);
547 refView->Proj(x, y, z);
548 tgtView->SetProj(x, y, z);
549 refView->Center(x, y);
550 tgtView->SetCenter(x, y);
551 tgtView->SetScale(refView->Scale());
552 tgtView->SetTwist(refView->Twist());
556 tgtView->SetImmediateUpdate( Standard_True);