Salome HOME
Update viewer on delete an item
[modules/shaper.git] / src / XGUI / XGUI_Displayer.cpp
index 7028e4a352baa2f520b64c54c63a6547a8d3dd7c..ccad93e0e2325f4d0a776c4c8a9044ebb5b3af85 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 //
 // You should have received a copy of the GNU Lesser General Public
 // License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
-// See http://www.salome-platform.org/ or
-// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
 #include "XGUI_Displayer.h"
@@ -37,7 +36,8 @@
 #include <ModelAPI_Object.h>
 #include <ModelAPI_Tools.h>
 #include <ModelAPI_AttributeIntArray.h>
-#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_ResultConstruction.h>
 
 #include <ModuleBase_BRepOwner.h>
 #include <ModuleBase_IModule.h>
 #include <ModuleBase_ResultPrs.h>
 #include <ModuleBase_Tools.h>
 #include <ModuleBase_ViewerPrs.h>
+#include <ModuleBase_IViewer.h>
 
 #include <GeomAPI_Shape.h>
 #include <GeomAPI_IPresentable.h>
 #include <GeomAPI_ICustomPrs.h>
+#include <GeomAPI_Pnt.h>
+#include <GeomAPI_IScreenParams.h>
 
 #include <SUIT_ResourceMgr.h>
 
@@ -83,6 +86,7 @@
 
 #include <Events_Loop.h>
 #include <ModelAPI_Events.h>
+#include <Config_PropManager.h>
 
 #include <set>
 
@@ -93,12 +97,12 @@ const int MOUSE_SENSITIVITY_IN_PIXEL = 10;
 //#define DEBUG_FEATURE_REDISPLAY
 //#define DEBUG_SELECTION_FILTERS
 
-//#define DEBUG_COMPOSILID_DISPLAY
-
 //#define DEBUG_OCCT_SHAPE_SELECTION
 
 #define CLEAR_OUTDATED_SELECTION_BEFORE_REDISPLAY
 
+//#define DEBUG_VIEWER_BLOCKED_COUNT
+
 //**************************************************************
 void displayedObjects(const Handle(AIS_InteractiveContext)& theAIS, AIS_ListOfInteractive& theList)
 {
@@ -140,76 +144,36 @@ bool XGUI_Displayer::display(ObjectPtr theObject, bool theUpdateViewer)
 {
   bool aDisplayed = false;
   if (isVisible(theObject)) {
-#ifdef DEBUG_COMPOSILID_DISPLAY
-    ResultCompSolidPtr aCompsolidResult =
-      std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(theObject);
-    if (aCompsolidResult.get()) {
-      for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) {
-        ResultPtr aSubResult = aCompsolidResult->subResult(i);
-        if (aSubResult.get())
-          redisplay(aSubResult, false);
-      }
-      if (theUpdateViewer)
-        updateViewer();
-    }
-    else
-#endif
     aDisplayed = redisplay(theObject, theUpdateViewer);
   } else {
     AISObjectPtr anAIS;
     GeomPresentablePtr aPrs = std::dynamic_pointer_cast<GeomAPI_IPresentable>(theObject);
     bool isShading = false;
     if (aPrs.get() != NULL) {
-      anAIS = aPrs->getAISObject(anAIS);
-      if (anAIS.get()) {
-        // correct deviation coefficient for
-        /*Handle(AIS_InteractiveObject) anAISPrs = anAIS->impl<Handle(AIS_InteractiveObject)>();
-        if (!anAISPrs.IsNull()) {
-          Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(anAISPrs);
-          if (!aShapePrs.IsNull()) {
-            TopoDS_Shape aShape = aShapePrs->Shape();
-            if (!aShape.IsNull())
-              //ModuleBase_Tools::setDefaultDeviationCoefficient(aShape, anAISPrs->Attributes());
-          }
-        }*/
+      GeomScreenParamsPtr aScreen = std::dynamic_pointer_cast<GeomAPI_IScreenParams>(theObject);
+      if (aScreen.get()) {
+        aScreen->setScreenPlane(getScreenPlane());
+        aScreen->setViewScale(getViewScale());
       }
+      anAIS = aPrs->getAISObject(anAIS);
     } else {
-      ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
-      if (aResult.get() != NULL) {
-#ifdef DEBUG_COMPOSILID_DISPLAY
-        ResultCompSolidPtr aCompsolidResult =
-          std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(theObject);
-        if (aCompsolidResult.get()) {
-          for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) {
-            ResultPtr aSubResult = aCompsolidResult->subResult(i);
-            if (aSubResult.get())
-              display(aSubResult, false);
-          }
-          if (theUpdateViewer)
-            updateViewer();
-        }
-        else {
-#endif
-        std::shared_ptr<GeomAPI_Shape> aShapePtr = ModelAPI_Tools::shape(aResult);
-        if (aShapePtr.get() != NULL) {
-          anAIS = AISObjectPtr(new GeomAPI_AISObject());
-          Handle(AIS_InteractiveObject) anAISPrs =
-            myWorkshop->module()->createPresentation(aResult);
-          if (anAISPrs.IsNull())
-            anAISPrs = new ModuleBase_ResultPrs(aResult);
-          else {
-            Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(anAISPrs);
-            if (!aShapePrs.IsNull())
-              ModuleBase_Tools::setPointBallHighlighting((AIS_Shape*) aShapePrs.get());
+      Handle(AIS_InteractiveObject) anAISPrs =
+        myWorkshop->module()->createPresentation(theObject);
+      if (anAISPrs.IsNull()) {
+        ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
+        if (aResult.get() != NULL) {
+          std::shared_ptr<GeomAPI_Shape> aShapePtr = ModelAPI_Tools::shape(aResult);
+          if (aShapePtr.get() != NULL) {
+             anAISPrs = new ModuleBase_ResultPrs(aResult);
           }
-          anAIS->setImpl(new Handle(AIS_InteractiveObject)(anAISPrs));
-          //anAIS->createShape(aShapePtr);
-          isShading = true;
         }
-#ifdef DEBUG_COMPOSILID_DISPLAY
-        } // close else
-#endif
       }
+      Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(anAISPrs);
+      if (!aShapePrs.IsNull())
+        ModuleBase_Tools::setPointBallHighlighting((AIS_Shape*)aShapePrs.get());
+      anAIS = AISObjectPtr(new GeomAPI_AISObject());
+      anAIS->setImpl(new Handle(AIS_InteractiveObject)(anAISPrs));
+      isShading = true;
     }
     if (anAIS)
       aDisplayed = display(theObject, anAIS, isShading, theUpdateViewer);
@@ -217,6 +181,7 @@ bool XGUI_Displayer::display(ObjectPtr theObject, bool theUpdateViewer)
   return aDisplayed;
 }
 
+
 //**************************************************************
 bool canBeShaded(Handle(AIS_InteractiveObject) theAIS, ModuleBase_IModule* theModule)
 {
@@ -282,7 +247,7 @@ bool XGUI_Displayer::erase(ObjectPtr theObject, const bool theUpdateViewer)
   if (aContext.IsNull())
     return aErased;
 
-  AISObjectPtr anObject = myResult2AISObjectMap[theObject];
+  AISObjectPtr anObject = myResult2AISObjectMap.value(theObject);
   if (anObject) {
     Handle(AIS_InteractiveObject) anAIS = anObject->impl<Handle(AIS_InteractiveObject)>();
     if (!anAIS.IsNull()) {
@@ -321,12 +286,18 @@ bool XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer)
 
   GeomPresentablePtr aPrs = std::dynamic_pointer_cast<GeomAPI_IPresentable>(theObject);
   if (aPrs) {
+    GeomScreenParamsPtr aScreen = std::dynamic_pointer_cast<GeomAPI_IScreenParams>(theObject);
+    if (aScreen.get()) {
+      aScreen->setScreenPlane(getScreenPlane());
+      aScreen->setViewScale(getViewScale());
+    }
     AISObjectPtr aAIS_Obj = aPrs->getAISObject(aAISObj);
     if (!aAIS_Obj) {
       aRedisplayed = erase(theObject, theUpdateViewer);
       return aRedisplayed;
     }
     if (aAIS_Obj != aAISObj) {
+      erase(theObject, theUpdateViewer);
       appendResultObject(theObject, aAIS_Obj);
     }
     aAISIO = aAIS_Obj->impl<Handle(AIS_InteractiveObject)>();
@@ -370,7 +341,10 @@ bool XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer)
 #ifdef CLEAR_OUTDATED_SELECTION_BEFORE_REDISPLAY
       myWorkshop->selector()->deselectPresentation(aAISIO);
 #endif
-      aContext->Redisplay(aAISIO, false);
+      if (aContext->IsDisplayed(aAISIO))
+        aContext->Redisplay(aAISIO, false);
+      else
+        aContext->Display(aAISIO, false);
 
       #ifdef TINSPECTOR
       if (getCallBack()) getCallBack()->Redisplay(aAISIO);
@@ -396,11 +370,16 @@ void XGUI_Displayer::redisplayObjects()
   // redisplay objects visualized in the viewer
   static Events_ID EVENT_DISP = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
   static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
-  QObjectPtrList aDisplayed = myWorkshop->displayer()->displayedObjects();
+  QObjectPtrList aDisplayed = displayedObjects();
   QObjectPtrList::const_iterator anIt = aDisplayed.begin(), aLast = aDisplayed.end();
   for (; anIt != aLast; anIt++) {
     aECreator->sendUpdated(*anIt, EVENT_DISP);
   }
+  XGUI_ViewerProxy* aViewer = myWorkshop->viewer();
+  if (aViewer->isColorScaleVisible()) {
+    aViewer->setupColorScale();
+    aViewer->setColorScaleShown(true);
+  }
   Events_Loop::loop()->flush(EVENT_DISP);
 }
 
@@ -432,12 +411,12 @@ bool XGUI_Displayer::isVisible(XGUI_Displayer* theDisplayer, const ObjectPtr& th
     // compsolid is not visualized in the viewer,
     // but should have presentation when all sub solids are
     // visible. It is useful for highlight presentation where compsolid shape is selectable
-    if (!aVisible && aResult.get() && aResult->groupName() == ModelAPI_ResultCompSolid::group()) {
-      ResultCompSolidPtr aCompsolidResult =
-        std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aResult);
+    if (!aVisible && aResult.get() && aResult->groupName() == ModelAPI_ResultBody::group()) {
+      ResultBodyPtr aCompsolidResult = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aResult);
       if (aCompsolidResult.get() != NULL) { // change colors for all sub-solids
-        bool anAllSubsVisible = aCompsolidResult->numberOfSubs() > 0;
-        for(int i = 0; i < aCompsolidResult->numberOfSubs() && anAllSubsVisible; i++) {
+        int aNumberOfSubs = aCompsolidResult->numberOfSubs();
+        bool anAllSubsVisible = aNumberOfSubs > 0;
+        for(int i = 0; i < aNumberOfSubs && anAllSubsVisible; i++) {
           anAllSubsVisible = theDisplayer->isVisible(aCompsolidResult->subResult(i));
         }
         aVisible = anAllSubsVisible;
@@ -500,7 +479,7 @@ void XGUI_Displayer::setSelected(const  QList<ModuleBase_ViewerPrsPtr>& theValue
       ObjectPtr anObject = aPrs->object();
       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
       if (aResult.get() && isVisible(aResult)) {
-        AISObjectPtr anObj = myResult2AISObjectMap[aResult];
+        AISObjectPtr anObj = myResult2AISObjectMap.value(aResult);
         Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
         if (!anAIS.IsNull()) {
           // The methods are replaced in order to provide multi-selection, e.g. restore selection
@@ -542,8 +521,13 @@ bool XGUI_Displayer::eraseAll(const bool theUpdateViewer)
   bool aErased = false;
   Handle(AIS_InteractiveContext) aContext = AISContext();
   if (!aContext.IsNull()) {
-    foreach (ObjectPtr aObj, myResult2AISObjectMap.keys()) {
+#ifdef OPTIMIZE_PRS
+    foreach(ObjectPtr aObj, myResult2AISObjectMap.objects()) {
+      AISObjectPtr aAISObj = myResult2AISObjectMap.value(aObj);
+#else
+    foreach(ObjectPtr aObj, myResult2AISObjectMap.keys()) {
       AISObjectPtr aAISObj = myResult2AISObjectMap[aObj];
+#endif
       // erase an object
       Handle(AIS_InteractiveObject) anIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
       if (!anIO.IsNull()) {
@@ -570,10 +554,14 @@ bool XGUI_Displayer::eraseAll(const bool theUpdateViewer)
 //**************************************************************
 AISObjectPtr XGUI_Displayer::getAISObject(ObjectPtr theObject) const
 {
+#ifdef OPTIMIZE_PRS
+  return myResult2AISObjectMap.value(theObject);
+#else
   AISObjectPtr anIO;
   if (myResult2AISObjectMap.contains(theObject))
     anIO = myResult2AISObjectMap[theObject];
   return anIO;
+#endif
 }
 
 //**************************************************************
@@ -586,15 +574,20 @@ ObjectPtr XGUI_Displayer::getObject(const AISObjectPtr& theIO) const
 //**************************************************************
 ObjectPtr XGUI_Displayer::getObject(const Handle(AIS_InteractiveObject)& theIO) const
 {
+#ifdef OPTIMIZE_PRS
+  ObjectPtr anObject = myResult2AISObjectMap.value(theIO);
+#else
   ObjectPtr anObject;
-  foreach (ObjectPtr anObj, myResult2AISObjectMap.keys()) {
-    AISObjectPtr aAIS = myResult2AISObjectMap[anObj];
+  ResultToAISMap::const_iterator aMapIter = myResult2AISObjectMap.cbegin();
+  for (; aMapIter != myResult2AISObjectMap.cend(); aMapIter++) {
+    const AISObjectPtr& aAIS = aMapIter.value();
     Handle(AIS_InteractiveObject) anAIS = aAIS->impl<Handle(AIS_InteractiveObject)>();
     if (anAIS == theIO)
-      anObject = anObj;
+      anObject = aMapIter.key();
     if (anObject.get())
       break;
   }
+#endif
   if (!anObject.get()) {
     std::shared_ptr<GeomAPI_AISObject> anAISObj = AISObjectPtr(new GeomAPI_AISObject());
     if (!theIO.IsNull()) {
@@ -614,6 +607,10 @@ bool XGUI_Displayer::enableUpdateViewer(const bool isEnabled)
   else
     myViewerBlockedRecursiveCount++;
 
+#ifdef DEBUG_VIEWER_BLOCKED_COUNT
+  std::cout << "myViewerBlockedRecursiveCount = " << myViewerBlockedRecursiveCount << std::endl;
+#endif
+
   if (myNeedUpdate && isUpdateEnabled()) {
     updateViewer();
     myNeedUpdate = false;
@@ -621,16 +618,16 @@ bool XGUI_Displayer::enableUpdateViewer(const bool isEnabled)
   return aWasEnabled;
 }
 
-//**************************************************************
-bool XGUI_Displayer::isUpdateEnabled() const
-{
-  return myViewerBlockedRecursiveCount == 0;
-}
-
 //**************************************************************
 void XGUI_Displayer::updateViewer() const
 {
   Handle(AIS_InteractiveContext) aContext = AISContext();
+
+#ifdef DEBUG_VIEWER_BLOCKED_COUNT
+  std::cout << "updateViewer: " << (myViewerBlockedRecursiveCount == 0 ? " done" : " later")
+            << std::endl;
+#endif
+
   if (!aContext.IsNull() && isUpdateEnabled()) {
     //myWorkshop->viewer()->Zfitall();
     aContext->UpdateCurrentViewer();
@@ -650,6 +647,18 @@ Handle(AIS_InteractiveContext) XGUI_Displayer::AISContext() const
       selectionActivate()->deactivateTrihedron(true);
     aContext->DefaultDrawer()->VIsoAspect()->SetNumber(0);
     aContext->DefaultDrawer()->UIsoAspect()->SetNumber(0);
+
+    ModuleBase_IViewer::DefaultHighlightDrawer = aContext->HighlightStyle();
+    // Commented out according to discussion in bug #2825
+    //Handle(Prs3d_Drawer) aSelStyle = aContext->SelectionStyle();
+    //double aDeflection =
+    //  QString(ModelAPI_ResultConstruction::DEFAULT_DEFLECTION().c_str()).toDouble();
+    //try {
+    //  aDeflection = Config_PropManager::real("Visualization", "construction_deflection");
+    //} catch (...) {}
+
+    //ModuleBase_IViewer::DefaultHighlightDrawer->SetDeviationCoefficient(aDeflection);
+    //aSelStyle->SetDeviationCoefficient(aDeflection);
   }
   return aContext;
 }
@@ -846,7 +855,11 @@ void XGUI_Displayer::removeFilters()
 //**************************************************************
 void XGUI_Displayer::showOnly(const QObjectPtrList& theList)
 {
+#ifdef OPTIMIZE_PRS
+  QObjectPtrList aDispList = myResult2AISObjectMap.objects();
+#else
   QObjectPtrList aDispList = myResult2AISObjectMap.keys();
+#endif
   foreach(ObjectPtr aObj, aDispList) {
     if (!theList.contains(aObj))
       erase(aObj, false);
@@ -925,7 +938,11 @@ QColor XGUI_Displayer::setObjectColor(ObjectPtr theObject,
 //**************************************************************
 void XGUI_Displayer::appendResultObject(ObjectPtr theObject, AISObjectPtr theAIS)
 {
+#ifdef OPTIMIZE_PRS
+  myResult2AISObjectMap.add(theObject, theAIS);
+#else
   myResult2AISObjectMap[theObject] = theAIS;
+#endif
 
 #ifdef DEBUG_DISPLAY
   std::ostringstream aPtrStr;
@@ -940,8 +957,13 @@ void XGUI_Displayer::appendResultObject(ObjectPtr theObject, AISObjectPtr theAIS
 std::string XGUI_Displayer::getResult2AISObjectMapInfo() const
 {
   QStringList aContent;
-  foreach (ObjectPtr aObj, myResult2AISObjectMap.keys()) {
+#ifdef OPTIMIZE_PRS
+  foreach(ObjectPtr aObj, myResult2AISObjectMap.objects()) {
+    AISObjectPtr aAISObj = myResult2AISObjectMap.value(aObj);
+#else
+  foreach(ObjectPtr aObj, myResult2AISObjectMap.keys()) {
     AISObjectPtr aAISObj = myResult2AISObjectMap[aObj];
+#endif
     std::ostringstream aPtrStr;
     aPtrStr << "aObj = " << aObj.get() << ":";
     aPtrStr << "anAIS = " << aAISObj.get() << ":";
@@ -964,7 +986,7 @@ void XGUI_Displayer::getPresentations(const ObjectPtr& theObject,
     if (aAISObj.get() == NULL) {
       // if result is a result of a composite feature, it is visualized by visualization of
       // composite children, so we should get one of this presentations
-      ResultCompSolidPtr aCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aResult);
+      ResultBodyPtr aCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aResult);
       if (aCompSolid.get() && aCompSolid->numberOfSubs() > 0) {
         aAISObj = getAISObject(aCompSolid->subResult(0));
       }
@@ -1033,8 +1055,6 @@ void XGUI_Displayer::displayTrihedron(bool theToDisplay) const
     if (getCallBack()) getCallBack()->Remove(aTrihedron);
     #endif
   }
-
-  updateViewer();
 }
 
 //**************************************************************
@@ -1055,12 +1075,12 @@ void XGUI_Displayer::AddOrRemoveSelectedShapes(Handle(AIS_InteractiveContext) th
   /// If count of calls setSelectec is even, the object stays in the previous state
   /// (selected, deselected)
   /// OCCT: to write about the problem that active owners method returns one owner several times
-  QList<long> aSelectedIds; // Remember of selected address in order to avoid duplicates
+  QList<size_t> aSelectedIds; // Remember of selected address in order to avoid duplicates
   for (; anOwnersIt.More(); anOwnersIt.Next()) {
     anOwner = Handle(SelectMgr_EntityOwner)::DownCast (anOwnersIt.Value());
-    if (aSelectedIds.contains((long)anOwner.get()))
+    if (aSelectedIds.contains((size_t)anOwner.get()))
       continue;
-    aSelectedIds.append((long)anOwner.get());
+    aSelectedIds.append((size_t)anOwner.get());
 
     Handle(StdSelect_BRepOwner) BROwnr = Handle(StdSelect_BRepOwner)::DownCast(anOwner);
     if (!BROwnr.IsNull() && BROwnr->HasShape()) {
@@ -1074,17 +1094,21 @@ void XGUI_Displayer::AddOrRemoveSelectedShapes(Handle(AIS_InteractiveContext) th
                                              ::Iterator aShapeIt(theShapesToBeSelected);
       for (; aShapeIt.More(); aShapeIt.Next()) {
         const TopoDS_Shape& aParameterShape = aShapeIt.Key();
-        // isSame should be used here as it does not check orientation of shapes
-        // despite on isEqual of shapes or IsBound for shape in QMap. Orientation is
-        // different for Edges shapes in model shape and owner even if this is the same shape
-        if (aParameterShape.IsSame(aShape)) {
+        // In case of compound we cannot rely on simple comparison method.
+        // If the compound is generated by Group feature then this compound is alwais new.
+        // So, we have to compare content of these compounds
+
+          // isSame should be used here as it does not check orientation of shapes
+          // despite on isEqual of shapes or IsBound for shape in QMap. Orientation is
+          // different for Edges shapes in model shape and owner even if this is the same shape
+        if (ModuleBase_Tools::isSameShape(aParameterShape, aShape)) {
           Handle(AIS_InteractiveObject) anOwnerPresentation =
-                            Handle(AIS_InteractiveObject)::DownCast(anOwner->Selectable());
+            Handle(AIS_InteractiveObject)::DownCast(anOwner->Selectable());
           NCollection_Map<Handle(AIS_InteractiveObject)> aPresentations =
-                                      theShapesToBeSelected.Find(aParameterShape);
+            theShapesToBeSelected.Find(aParameterShape);
           if (aPresentations.Contains(anOwnerPresentation)) {
             theContext->AddOrRemoveSelected(anOwner, Standard_False);
-            anOwner->SetSelected (Standard_True);
+            anOwner->SetSelected(Standard_True);
             // collect selected presentations to do not select them if compsolid is selected
             if (!aSelectedPresentations.Contains(anOwnerPresentation))
               aSelectedPresentations.Add(anOwnerPresentation);
@@ -1117,3 +1141,46 @@ XGUI_SelectionActivate* XGUI_Displayer::selectionActivate() const
 {
   return myWorkshop->selectionActivate();
 }
+
+//**************************************************************
+GeomPlanePtr XGUI_Displayer::getScreenPlane() const
+{
+  GeomPlanePtr aResult;
+  Handle(AIS_InteractiveContext) aContext = AISContext();
+  if (!aContext.IsNull()) {
+    Handle(V3d_Viewer) aViewer = aContext->CurrentViewer();
+    Handle(V3d_View) aView;
+    for (aViewer->InitActiveViews(); aViewer->MoreActiveViews(); aViewer->NextActiveViews()) {
+      aView = aViewer->ActiveView();
+      break;
+    }
+    if (!aView.IsNull()) {
+      double aEyeX, aEyeY, aEyeZ;
+      aView->Eye(aEyeX, aEyeY, aEyeZ);
+
+      double aProjX, aProjY, aProjZ;
+      aView->Proj(aProjX, aProjY, aProjZ);
+
+      GeomPointPtr aPnt = GeomPointPtr(new GeomAPI_Pnt(aEyeX, aEyeY, aEyeZ));
+      GeomDirPtr aDir = GeomDirPtr(new GeomAPI_Dir(aProjX, aProjY, aProjZ));
+
+      aResult = GeomPlanePtr(new GeomAPI_Pln(aPnt, aDir));
+    }
+  }
+  return aResult;
+}
+
+double XGUI_Displayer::getViewScale() const
+{
+  Handle(AIS_InteractiveContext) aContext = AISContext();
+  if (!aContext.IsNull()) {
+    Handle(V3d_Viewer) aViewer = aContext->CurrentViewer();
+    Handle(V3d_View) aView;
+    for (aViewer->InitActiveViews(); aViewer->MoreActiveViews(); aViewer->NextActiveViews()) {
+      aView = aViewer->ActiveView();
+      break;
+    }
+    return aView->Camera()->Scale();
+  }
+  return 1;
+}