1 #include "XGUI_Viewer.h"
2 #include "XGUI_MainWindow.h"
3 #include "XGUI_ViewWindow.h"
4 #include "XGUI_ViewPort.h"
5 #include "XGUI_Preferences.h"
7 #include <SUIT_ResourceMgr.h>
10 #include <QMdiSubWindow>
11 #include <QApplication>
12 #include <QMouseEvent>
15 #include <V3d_View.hxx>
17 #include <Aspect_DisplayConnection.hxx>
18 #include <Graphic3d.hxx>
19 #include <Graphic3d_GraphicDriver.hxx>
20 #include <Geom_Axis2Placement.hxx>
21 #include <AIS_Drawer.hxx>
22 #include <Prs3d_DatumAspect.hxx>
23 #include <Prs3d_LineAspect.hxx>
24 #include <V3d_View.hxx>
25 #include <Visual3d_View.hxx>
26 #include <AIS_ListOfInteractive.hxx>
27 #include <AIS_ListIteratorOfListOfInteractive.hxx>
28 #include <AIS_Shape.hxx>
31 #include <WNT_Window.hxx>
33 #include <Xw_Window.hxx>
36 XGUI_Viewer::InteractionStyle2StatesMap XGUI_Viewer::myStateMap;
37 XGUI_Viewer::InteractionStyle2ButtonsMap XGUI_Viewer::myButtonMap;
38 static bool isInitialized = false;
41 Creates viewer 3d [ static ]
43 Handle(V3d_Viewer) CreateViewer(const Standard_ExtString name, const Standard_CString displayName,
44 const Standard_CString domain, const Standard_Real viewSize,
45 const V3d_TypeOfOrientation viewProjection,
46 const Standard_Boolean computedMode,
47 const Standard_Boolean defaultComputedMode)
49 static Handle(Graphic3d_GraphicDriver) aGraphicDriver;
50 if (aGraphicDriver.IsNull()) {
51 Handle(Aspect_DisplayConnection) aDisplayConnection;
53 aDisplayConnection = new Aspect_DisplayConnection( displayName );
55 aDisplayConnection = new Aspect_DisplayConnection();
57 aGraphicDriver = Graphic3d::InitGraphicDriver(aDisplayConnection);
60 return new V3d_Viewer(aGraphicDriver, name, domain, viewSize, viewProjection, Quantity_NOC_GRAY30,
61 V3d_ZBUFFER, V3d_GOURAUD, V3d_WAIT, computedMode, defaultComputedMode,
65 // VSR: Uncomment below line to allow texture background support in OCC viewer
66 #define OCC_ENABLE_TEXTURED_BACKGROUND
69 Get data for supported background modes: gradient types, identifiers and supported image formats
71 QString XGUI_Viewer::backgroundData(QStringList& gradList, QIntList& idList, QIntList& txtList)
73 gradList << tr("Horizontal gradient") << tr("Vertical gradient") << tr("First diagonal gradient")
74 << tr("Second diagonal gradient") << tr("First corner gradient")
75 << tr("Second corner gradient") << tr("Third corner gradient")
76 << tr("Fourth corner gradient");
77 idList << XGUI::HorizontalGradient << XGUI::VerticalGradient << XGUI::Diagonal1Gradient
78 << XGUI::Diagonal2Gradient << XGUI::Corner1Gradient << XGUI::Corner2Gradient
79 << XGUI::Corner3Gradient << XGUI::Corner4Gradient;
80 #ifdef OCC_ENABLE_TEXTURED_BACKGROUND
81 txtList << XGUI::CenterTexture << XGUI::TileTexture << XGUI::StretchTexture;
83 return tr("Image files (*.bmp *.gif *.pix *.xwd *.rgb *.rs)");
86 XGUI_Viewer::XGUI_Viewer(XGUI_MainWindow* theParent, bool DisplayTrihedron)
88 myMainWindow(theParent),
89 myPreselectionEnabled(true),
90 mySelectionEnabled(true),
91 myMultiSelectionEnabled(true),
93 myInteractionStyle(XGUI::STANDARD),
101 // standard interaction style
102 XGUI_Viewer::myStateMap[XGUI::STANDARD][XGUI::ZOOM] = Qt::ControlModifier;
103 XGUI_Viewer::myButtonMap[XGUI::STANDARD][XGUI::ZOOM] = Qt::LeftButton;
105 XGUI_Viewer::myStateMap[XGUI::STANDARD][XGUI::PAN] = Qt::ControlModifier;
106 XGUI_Viewer::myButtonMap[XGUI::STANDARD][XGUI::PAN] = Qt::MidButton;
108 XGUI_Viewer::myStateMap[XGUI::STANDARD][XGUI::ROTATE] = Qt::ControlModifier;
109 XGUI_Viewer::myButtonMap[XGUI::STANDARD][XGUI::ROTATE] = Qt::RightButton;
111 XGUI_Viewer::myStateMap[XGUI::STANDARD][XGUI::FIT_AREA] = Qt::ControlModifier;
112 XGUI_Viewer::myButtonMap[XGUI::STANDARD][XGUI::FIT_AREA] = Qt::RightButton;
114 // "key free" interaction style
115 XGUI_Viewer::myStateMap[XGUI::KEY_FREE][XGUI::ZOOM] = Qt::NoModifier;
116 XGUI_Viewer::myButtonMap[XGUI::KEY_FREE][XGUI::ZOOM] = Qt::RightButton;
118 XGUI_Viewer::myStateMap[XGUI::KEY_FREE][XGUI::PAN] = Qt::NoModifier;
119 XGUI_Viewer::myButtonMap[XGUI::KEY_FREE][XGUI::PAN] = Qt::MidButton;
121 XGUI_Viewer::myStateMap[XGUI::KEY_FREE][XGUI::ROTATE] = Qt::NoModifier;
122 XGUI_Viewer::myButtonMap[XGUI::KEY_FREE][XGUI::ROTATE] = Qt::LeftButton;
124 XGUI_Viewer::myStateMap[XGUI::KEY_FREE][XGUI::FIT_AREA] = Qt::NoModifier; // unused
125 XGUI_Viewer::myButtonMap[XGUI::KEY_FREE][XGUI::FIT_AREA] = Qt::NoButton; // unused
128 // init CasCade viewers
129 myV3dViewer = CreateViewer(TCollection_ExtendedString("Viewer3d").ToExtString(), "", "", 1000.0,
130 V3d_XposYnegZpos, Standard_True, Standard_True);
131 myV3dViewer->SetDefaultLights();
134 myAISContext = new AIS_InteractiveContext(myV3dViewer);
135 myAISContext->SelectionColor(Quantity_NOC_WHITE);
137 // display isoline on planar faces (box for ex.)
138 myAISContext->IsoOnPlane(true);
140 if (DisplayTrihedron) {
141 Handle(Geom_Axis2Placement) anAxis = new Geom_Axis2Placement(gp::XOY());
142 myTrihedron = new AIS_Trihedron(anAxis);
143 myTrihedron->SetInfiniteState( Standard_True);
145 Quantity_Color Col(193 / 255., 205 / 255., 193 / 255., Quantity_TOC_RGB);
146 myTrihedron->SetArrowColor(Col.Name());
147 myTrihedron->SetSize(myTrihedronSize);
148 Handle(AIS_Drawer) drawer = myTrihedron->Attributes();
149 if (drawer->HasDatumAspect()) {
150 Handle(Prs3d_DatumAspect) daspect = drawer->DatumAspect();
151 daspect->FirstAxisAspect()->SetColor(Quantity_Color(1.0, 0.0, 0.0, Quantity_TOC_RGB));
152 daspect->SecondAxisAspect()->SetColor(Quantity_Color(0.0, 1.0, 0.0, Quantity_TOC_RGB));
153 daspect->ThirdAxisAspect()->SetColor(Quantity_Color(0.0, 0.0, 1.0, Quantity_TOC_RGB));
156 // set zooming style to standard
157 //myZoomingStyle = 0;
159 QMdiArea* aMDI = myMainWindow->mdiArea();
160 connect(aMDI, SIGNAL(subWindowActivated(QMdiSubWindow*)), this,
161 SLOT(onWindowActivated(QMdiSubWindow*)));
165 XGUI_Viewer::~XGUI_Viewer(void)
167 myAISContext.Nullify();
168 myV3dViewer.Nullify();
171 QMdiSubWindow* XGUI_Viewer::createView(V3d_TypeOfView theType)
174 XGUI_ViewWindow* view = new XGUI_ViewWindow(this, theType);
175 // get main view window (created by view frame)
176 //OCCViewer_ViewWindow* vw = view->getView(OCCViewer_ViewFrame::MAIN_VIEW);
177 // initialize main view window
179 // set default background for view window
180 //vw->setBackground( background(0) ); // 0 means MAIN_VIEW (other views are not yet created here)
181 // connect signal from viewport
182 //connect(view->viewPort(), SIGNAL(vpClosed()), this, SLOT(onViewClosed()));
183 //connect(view->viewPort(), SIGNAL(vpMapped()), this, SLOT(onViewMapped()));
184 if (myViews.size() == 0)
185 setTrihedronShown(true);
187 Qtx::BackgroundData aBk = XGUI_Preferences::resourceMgr()->backgroundValue("Viewer",
189 view->setBackground(aBk);
190 view->updateEnabledDrawMode();
192 QMdiArea* aMDI = myMainWindow->mdiArea();
193 QMdiSubWindow* aWnd = aMDI->addSubWindow(view, Qt::FramelessWindowHint);
195 aWnd->setGeometry(0, 0, aMDI->width() / 2, aMDI->height() / 2);
197 aWnd->setWindowTitle(QString("Viewer #%1").arg(++myWndIdCount));
198 emit viewCreated(view);
202 void XGUI_Viewer::updateFromResources()
204 Qtx::BackgroundData aBk = XGUI_Preferences::resourceMgr()->backgroundValue("Viewer",
206 foreach (QMdiSubWindow* aWnd, myViews)
208 XGUI_ViewWindow* aView = dynamic_cast<XGUI_ViewWindow*>(aWnd->widget());
210 aView->setBackground(aBk);
214 XGUI_ViewWindow* XGUI_Viewer::activeViewWindow() const
217 return dynamic_cast<XGUI_ViewWindow*>(myActiveView->widget());
221 void XGUI_Viewer::getSelectedObjects(AIS_ListOfInteractive& theList)
224 for (myAISContext->InitSelected(); myAISContext->MoreSelected(); myAISContext->NextSelected())
225 theList.Append(myAISContext->SelectedInteractive());
228 void XGUI_Viewer::getSelectedShapes(NCollection_List<TopoDS_Shape>& theList)
230 Handle(AIS_InteractiveContext) ic = AISContext();
232 for (ic->InitSelected(); ic->MoreSelected(); ic->NextSelected()) {
233 TopoDS_Shape aShape = ic->SelectedShape();
234 if (!aShape.IsNull())
235 theList.Append(aShape);
239 void XGUI_Viewer::setObjectsSelected(const AIS_ListOfInteractive& theList)
241 AIS_ListIteratorOfListOfInteractive aIt;
242 for (aIt.Initialize(theList); aIt.More(); aIt.Next())
243 myAISContext->AddOrRemoveSelected(aIt.Value(), false);
244 myAISContext->UpdateCurrentViewer();
248 *\param theOper - hot operation
249 *\param theState - adding state to state map operations.
250 *\param theButton - adding state to button map operations.
252 void XGUI_Viewer::setHotButton(XGUI::InteractionStyle theInteractionStyle,
253 XGUI::HotOperation theOper, Qt::KeyboardModifiers theState,
254 Qt::MouseButtons theButton)
256 myStateMap[theInteractionStyle][theOper] = theState;
257 myButtonMap[theInteractionStyle][theOper] = theButton;
260 /*! Gets hot button for operation \a theOper.
261 *\param theOper - input hot operation
262 *\param theState - output state from state map operations.
263 *\param theButton - output state from button map operations.
265 void XGUI_Viewer::getHotButton(XGUI::InteractionStyle theInteractionStyle,
266 XGUI::HotOperation theOper, Qt::KeyboardModifiers& theState,
267 Qt::MouseButtons& theButton)
269 theState = myStateMap[theInteractionStyle][theOper];
270 theButton = myButtonMap[theInteractionStyle][theOper];
274 Changes visibility of trihedron to opposite
276 void XGUI_Viewer::toggleTrihedron()
278 setTrihedronShown(!isTrihedronVisible());
282 \return true if trihedron is visible
284 bool XGUI_Viewer::isTrihedronVisible() const
286 return !myTrihedron.IsNull() && !myAISContext.IsNull() && myAISContext->IsDisplayed(myTrihedron);
290 Sets visibility state of trihedron
291 \param on - new state
294 void XGUI_Viewer::setTrihedronShown(bool on)
296 if (myTrihedron.IsNull())
300 myAISContext->Display(myTrihedron);
301 myAISContext->Deactivate(myTrihedron);
303 myAISContext->Erase(myTrihedron);
308 \return trihedron size
310 double XGUI_Viewer::trihedronSize() const
313 if (!myTrihedron.IsNull())
314 sz = myTrihedron->Size();
319 Changes trihedron size
322 void XGUI_Viewer::setTrihedronSize(const double sz, bool isRelative)
324 if (myTrihedronSize != sz || isRelative != myIsRelative) {
325 myTrihedronSize = sz;
326 myIsRelative = isRelative;
332 * Update the size of the trihedron
334 void XGUI_Viewer::updateTrihedron()
336 if (myTrihedron.IsNull())
342 if (computeTrihedronSize(newSz, oldSz))
343 myTrihedron->SetSize(newSz);
345 } else if (myTrihedron->Size() != myTrihedronSize) {
346 myTrihedron->SetSize(myTrihedronSize);
351 Get new and current trihedron size corresponding to the current model size
353 bool XGUI_Viewer::computeTrihedronSize(double& theNewSize, double& theSize)
358 //SRN: BUG IPAL8996, a usage of method ActiveView without an initialization
359 Handle(V3d_Viewer) viewer = v3dViewer();
360 viewer->InitActiveViews();
361 if (!viewer->MoreActiveViews())
364 Handle(V3d_View) view3d = viewer->ActiveView();
370 double Xmin = 0, Ymin = 0, Zmin = 0, Xmax = 0, Ymax = 0, Zmax = 0;
373 view3d->View()->MinMaxValues(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
375 if (Xmin == RealFirst() || Ymin == RealFirst() || Zmin == RealFirst() || Xmax == RealLast()
376 || Ymax == RealLast() || Zmax == RealLast())
379 aMaxSide = Xmax - Xmin;
380 if (aMaxSide < Ymax - Ymin)
381 aMaxSide = Ymax - Ymin;
382 if (aMaxSide < Zmax - Zmin)
383 aMaxSide = Zmax - Zmin;
386 // The boundary box of the view may be initialized but nullified
387 // (case of infinite objects)
388 if (aMaxSide < Precision::Confusion())
391 static float EPS = (float) 5.0E-3;
392 theSize = trihedron()->Size();
393 //theNewSize = aMaxSide*aSizeInPercents / 100.0;
395 return fabs(theNewSize - theSize) > theSize * EPS || fabs(theNewSize - theSize) > theNewSize * EPS;
398 void XGUI_Viewer::onViewClosed(QMdiSubWindow* theView)
403 emit deleteView(static_cast<XGUI_ViewWindow*>(theView->widget()));
406 // if this is last view
407 if (myViews.size() == 0) {
408 Standard_Integer aViewsNb = 0;
409 for (myV3dViewer->InitActiveViews(); myV3dViewer->MoreActiveViews();
410 myV3dViewer->NextActiveViews())
413 //clean up presentations before last view is closed
414 myAISContext->RemoveAll(Standard_False);
419 /*!Remove view window \a theView from view manager.
420 *And close the last view, if it has \a theView.
422 void XGUI_Viewer::removeView(QMdiSubWindow* theView)
424 XGUI_ViewWindow* aWindow = static_cast<XGUI_ViewWindow*>(theView->widget());
426 aWindow->disconnect(this);
427 myViews.removeAt(myViews.indexOf(theView));
428 if (myActiveView == theView)
430 if (myViews.size() == 0)
431 emit lastViewClosed();
434 /*void XGUI_Viewer::onViewMapped()
436 setTrihedronShown(true);
439 void XGUI_Viewer::addView(QMdiSubWindow* theView)
441 XGUI_ViewWindow* aWindow = dynamic_cast<XGUI_ViewWindow*>(theView->widget());
443 connect(aWindow, SIGNAL(closed(QMdiSubWindow*)), this, SLOT(onViewClosed(QMdiSubWindow*)));
445 connect(aWindow, SIGNAL(tryClosing(XGUI_ViewWindow*)), this,
446 SIGNAL(tryCloseView(XGUI_ViewWindow*)));
448 connect(aWindow, SIGNAL(mousePressed(XGUI_ViewWindow*, QMouseEvent*)), this,
449 SLOT(onMousePressed(XGUI_ViewWindow*, QMouseEvent*)));
451 connect(aWindow, SIGNAL(mouseDoubleClicked(XGUI_ViewWindow*, QMouseEvent*)), this,
452 SIGNAL(mouseDoubleClick(XGUI_ViewWindow*, QMouseEvent*)));
454 connect(aWindow, SIGNAL(mouseMoving(XGUI_ViewWindow*, QMouseEvent*)), this,
455 SIGNAL(mouseMove(XGUI_ViewWindow*, QMouseEvent*)));
457 connect(aWindow, SIGNAL(keyPressed(XGUI_ViewWindow*, QKeyEvent*)), this,
458 SIGNAL(keyPress(XGUI_ViewWindow*, QKeyEvent*)));
460 connect(aWindow, SIGNAL(keyReleased(XGUI_ViewWindow*, QKeyEvent*)), this,
461 SIGNAL(keyRelease(XGUI_ViewWindow*, QKeyEvent*)));
463 //connect(aWindow, SIGNAL(contextMenuRequested( QContextMenuEvent* )),
464 // this, SLOT (onContextMenuRequested( QContextMenuEvent* )));
465 connect(aWindow, SIGNAL(contextMenuRequested(QContextMenuEvent*)), this,
466 SIGNAL(contextMenuRequested(QContextMenuEvent*)));
468 connect(aWindow, SIGNAL(mouseMoving(XGUI_ViewWindow*, QMouseEvent*)), this,
469 SLOT(onMouseMove(XGUI_ViewWindow*, QMouseEvent*)));
471 connect(aWindow, SIGNAL(mouseReleased(XGUI_ViewWindow*, QMouseEvent*)), this,
472 SLOT(onMouseReleased(XGUI_ViewWindow*, QMouseEvent*)));
474 myViews.append(theView);
478 Emit activated for view \a view.
480 void XGUI_Viewer::onWindowActivated(QMdiSubWindow* view)
482 if (view && (view != myActiveView) && (!view->isMinimized())) {
484 ((XGUI_ViewWindow*) myActiveView->widget())->windowActivated();
485 QList<QMdiSubWindow*>::iterator aIt;
486 for (aIt = myViews.begin(); aIt != myViews.end(); ++aIt) {
487 if ((*aIt) != myActiveView) {
488 ((XGUI_ViewWindow*) (*aIt)->widget())->windowDeactivated();
494 void XGUI_Viewer::onWindowMinimized(QMdiSubWindow* theWnd)
496 if (myActiveView == theWnd) {
498 QList<QMdiSubWindow*>::iterator aIt;
499 for (aIt = myViews.begin(); aIt != myViews.end(); ++aIt) {
500 if (!(*aIt)->widget()->isMinimized()) {
502 onWindowActivated(*aIt);
510 SLOT: called on mouse button press, stores current mouse position as start point for transformations
512 void XGUI_Viewer::onMousePressed(XGUI_ViewWindow* theWindow, QMouseEvent* theEvent)
514 myStartPnt.setX(theEvent->x());
515 myStartPnt.setY(theEvent->y());
516 emit mousePress(theWindow, theEvent);
520 SLOT: called on mouse move, processes hilighting
522 void XGUI_Viewer::onMouseMove(XGUI_ViewWindow* theWindow, QMouseEvent* theEvent)
524 myCurPnt.setX(theEvent->x());
525 myCurPnt.setY(theEvent->y());
526 if (!mySelectionEnabled)
529 Handle(V3d_View) aView3d = theWindow->viewPort()->getView();
530 if (!aView3d.IsNull()) {
531 myAISContext->MoveTo(theEvent->x(), theEvent->y(), aView3d);
536 SLOT: called on mouse button release, finishes selection
538 void XGUI_Viewer::onMouseReleased(XGUI_ViewWindow* theWindow, QMouseEvent* theEvent)
540 if (!mySelectionEnabled || theEvent->button() != Qt::LeftButton) {
541 emit mouseRelease(theWindow, theEvent);
545 myEndPnt.setX(theEvent->x());
546 myEndPnt.setY(theEvent->y());
547 bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
550 // emit deselection();
552 if (myStartPnt == myEndPnt) {
553 // the MoveTo is necessary for the second click in the same point. Otherwise the selection is lost.
554 Handle(V3d_View) aView3d = theWindow->viewPort()->getView();
555 if (!aView3d.IsNull()) {
556 myAISContext->MoveTo(theEvent->x(), theEvent->y(), aView3d);
558 if (aHasShift && myMultiSelectionEnabled)
559 myAISContext->ShiftSelect();
561 myAISContext->Select();
563 if (aHasShift && myMultiSelectionEnabled)
564 myAISContext->ShiftSelect(myStartPnt.x(), myStartPnt.y(), myEndPnt.x(), myEndPnt.y(),
565 theWindow->viewPort()->getView(), false);
567 myAISContext->Select(myStartPnt.x(), myStartPnt.y(), myEndPnt.x(), myEndPnt.y(),
568 theWindow->viewPort()->getView(), false);
570 int Nb = myAISContext->NbSelected();
571 if (Nb > 1 && !myMultiSelectionEnabled) {
572 myAISContext->InitSelected();
573 Handle( SelectMgr_EntityOwner ) anOwner = myAISContext->SelectedOwner();
574 if (!anOwner.IsNull()) {
575 myAISContext->ClearSelected( Standard_False);
576 myAISContext->AddOrRemoveSelected(anOwner, Standard_False);
580 myAISContext->UpdateCurrentViewer();
582 emit mouseRelease(theWindow, theEvent);
583 emit selectionChanged();
586 //******************************************************
587 void XGUI_Viewer::setMultiSelectionEnabled(bool toEnable)
589 myMultiSelectionEnabled = toEnable;
590 updateViewsDrawMode();
593 //******************************************************
594 void XGUI_Viewer::setSelectionEnabled(bool toEnable)
596 mySelectionEnabled = toEnable;
597 updateViewsDrawMode();
600 //******************************************************
601 void XGUI_Viewer::updateViewsDrawMode() const
603 foreach(QMdiSubWindow* aWnd, myViews)
605 XGUI_ViewWindow* aView = static_cast<XGUI_ViewWindow*>(aWnd->widget());
606 aView->updateEnabledDrawMode();
610 //******************************************************
611 //void XGUI_Viewer::onContextMenuRequested(QContextMenuEvent* theEvent)
613 // XGUI_ViewWindow* aWnd = dynamic_cast<XGUI_ViewWindow*>(sender());
614 // if (!aWnd) return;
618 // // Include Viewer actions
619 // if (myActions.size() > 0) {
620 // aMenu.addActions(myActions);
621 // aMenu.addSeparator();
623 // if (aWnd->actions().size() > 0) {
624 // aMenu.addActions(aWnd->actions());
625 // aMenu.addSeparator();
628 // QMdiArea* aMDI = myMainWindow->mdiArea();
629 // if (aMenu.actions().size() > 0) {
630 // QMenu* aSubMenu = aMenu.addMenu(tr("Windows"));
631 // aSubMenu->addActions(aMDI->actions());
633 // aMenu.addActions(aMDI->actions());
635 // aMenu.exec(theEvent->globalPos());