Salome HOME
updated copyright message
[modules/shaper.git] / src / PartSet / PartSet_WidgetSketchLabel.cpp
index f4514b92725c02d11920b9dd2e5053a04dc4621f..4a5edfa01266b8b6093f1fb59bbbf450bf1e9feb 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+// Copyright (C) 2014-2023  CEA, EDF
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -38,6 +38,7 @@
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_Tools.h>
 #include <ModelAPI_AttributeString.h>
+#include <ModelAPI_Events.h>
 
 #include <ModuleBase_Operation.h>
 #include <ModuleBase_ViewerPrs.h>
@@ -62,7 +63,6 @@
 #include <gp_Pnt.hxx>
 #include <gp_Dir.hxx>
 #include <AIS_Shape.hxx>
-#include <AIS_DimensionSelectionMode.hxx>
 #include <Bnd_Box.hxx>
 
 #include <Config_WidgetAPI.h>
 #include <QCheckBox>
 #include <QGroupBox>
 #include <QPushButton>
-#include <QStackedWidget>
 #include <QLineEdit>
 #include <QDoubleValidator>
 #include <QDialog>
+#include <QTimer>
+
+#ifdef WIN32
+#pragma warning(disable : 4456) // for nested foreach
+#endif
 
 #ifndef DBL_MAX
 #define DBL_MAX 1.7976931348623158e+308
@@ -157,15 +161,29 @@ myIsSelection(false)
   ModuleBase_Tools::zeroMargins(aLayout);
 
   QGroupBox* aViewBox = new QGroupBox(tr("Sketcher plane"), this);
-  QVBoxLayout* aViewLayout = new QVBoxLayout(aViewBox);
+  QGridLayout* aViewLayout = new QGridLayout(aViewBox);
 
   myViewInverted = new QCheckBox(tr("Reversed"), aViewBox);
-  aViewLayout->addWidget(myViewInverted);
+  aViewLayout->addWidget(myViewInverted, 0, 0);
+
+  // Sketch plane visibility
+  myViewVisible = new QCheckBox(tr("Visible"), aViewBox);
+  PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
+  PartSet_PreviewSketchPlane* aPreviewPlane = aModule->sketchMgr()->previewSketchPlane();
+  if (aPreviewPlane->isPlaneCreated())
+    // init with current state
+    myViewVisible->setChecked(aPreviewPlane->isDisplayed());
+  else
+    // true by default (at start of sketch creation)
+    myViewVisible->setChecked(true);
+
+  aViewLayout->addWidget(myViewVisible, 0, 1, Qt::AlignRight);
+  connect(myViewVisible, SIGNAL(toggled(bool)), this, SLOT(onShowViewPlane(bool)));
 
   QPushButton* aSetViewBtn =
     new QPushButton(QIcon(":icons/plane_view.png"), tr("Set plane view"), aViewBox);
   connect(aSetViewBtn, SIGNAL(clicked(bool)), this, SLOT(onSetPlaneView()));
-  aViewLayout->addWidget(aSetViewBtn);
+  aViewLayout->addWidget(aSetViewBtn, 1, 0, 1, 2);
 
   aLayout->addWidget(aViewBox);
 
@@ -200,9 +218,16 @@ myIsSelection(false)
   connect(aPlaneBtn, SIGNAL(clicked(bool)), SLOT(onChangePlane()));
   aLayout->addWidget(aPlaneBtn);
 
+  aLayout->addSpacing(15);
+
   myDoFLabel = new QLabel("", aSecondWgt);
   aLayout->addWidget(myDoFLabel);
 
+  myShowDOFBtn = new QPushButton(tr("Show remaining DoFs"), aSecondWgt);
+  aLayout->addWidget(myShowDOFBtn);
+  myShowDOFBtn->setEnabled(false);
+  connect(myShowDOFBtn, SIGNAL(clicked(bool)), SLOT(onShowDOF()));
+
   myStackWidget->addWidget(aSecondWgt);
   //setLayout(aLayout);
 
@@ -305,7 +330,7 @@ bool PartSet_WidgetSketchLabel::setSelectionInternal(
   bool aDone = false;
   if (theValues.empty()) {
     // In order to make reselection possible, set empty object and shape should be done
-    setSelectionCustom(std::shared_ptr<ModuleBase_ViewerPrs>(
+    setSelectionCustom(ModuleBase_ViewerPrsPtr(
                               new ModuleBase_ViewerPrs(ObjectPtr(), GeomShapePtr(), NULL)));
     aDone = false;
   }
@@ -324,6 +349,10 @@ bool PartSet_WidgetSketchLabel::setSelectionInternal(
 
 void PartSet_WidgetSketchLabel::updateByPlaneSelected(const ModuleBase_ViewerPrsPtr& thePrs)
 {
+  // Nullify a temporary remembered plane
+  if (myTmpPlane.get())
+    myTmpPlane.reset();
+
   GeomPlanePtr aPlane = plane();
   if (!aPlane.get())
     return;
@@ -334,20 +363,23 @@ void PartSet_WidgetSketchLabel::updateByPlaneSelected(const ModuleBase_ViewerPrs
   // 1. hide main planes if they have been displayed and display sketch preview plane
   myPreviewPlanes->erasePreviewPlanes(myWorkshop);
 
+  QString aSizeOfViewStr = mySizeOfView->text();
+  bool isSetSizeOfView = false;
+  double aSizeOfView = 0;
+  if (!aSizeOfViewStr.isEmpty()) {
+    aSizeOfView = aSizeOfViewStr.toDouble(&isSetSizeOfView);
+    if (isSetSizeOfView && aSizeOfView <= 0) {
+      isSetSizeOfView = false;
+    }
+  }
   PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
   if (aModule) {
     CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
-    bool isSetSizeOfView = false;
-    double aSizeOfView = 0;
-    QString aSizeOfViewStr = mySizeOfView->text();
-    if (!aSizeOfViewStr.isEmpty()) {
-      aSizeOfView = aSizeOfViewStr.toDouble(&isSetSizeOfView);
-      if (isSetSizeOfView && aSizeOfView <= 0) {
-        isSetSizeOfView = false;
-      }
-    }
     aModule->sketchMgr()->previewSketchPlane()->setSizeOfView(aSizeOfView, isSetSizeOfView);
-    aModule->sketchMgr()->previewSketchPlane()->createSketchPlane(aSketch, myWorkshop);
+    if (myViewVisible->isChecked())
+      aModule->sketchMgr()->previewSketchPlane()->createSketchPlane(aSketch, myWorkshop);
+    else
+      aModule->sketchMgr()->previewSketchPlane()->clearPlanePreview();
   }
   // 2. if the planes were displayed, change the view projection
 
@@ -361,18 +393,13 @@ void PartSet_WidgetSketchLabel::updateByPlaneSelected(const ModuleBase_ViewerPrs
   if (aRotate) {
     myWorkshop->viewer()->setViewProjection(aXYZ.X(), aXYZ.Y(), aXYZ.Z(), aTwist);
   }
-  QString aSizeOfViewStr = mySizeOfView->text();
-  if (!aSizeOfViewStr.isEmpty()) {
-    bool isOk;
-    double aSizeOfView = aSizeOfViewStr.toDouble(&isOk);
-    if (isOk && aSizeOfView > 0) {
-      Handle(V3d_View) aView3d = myWorkshop->viewer()->activeView();
-      if (!aView3d.IsNull()) {
-        Bnd_Box aBndBox;
-        double aHalfSize = aSizeOfView/2.0;
-        aBndBox.Update(-aHalfSize, -aHalfSize, -aHalfSize, aHalfSize, aHalfSize, aHalfSize);
-        aView3d->FitAll(aBndBox, 0.01, false);
-      }
+  if (isSetSizeOfView && aSizeOfView > 0) {
+    Handle(V3d_View) aView3d = myWorkshop->viewer()->activeView();
+    if (!aView3d.IsNull()) {
+      Bnd_Box aBndBox;
+      double aHalfSize = aSizeOfView/2.0;
+      aBndBox.Update(-aHalfSize, -aHalfSize, -aHalfSize, aHalfSize, aHalfSize, aHalfSize);
+      aView3d->FitAll(aBndBox, 0.01, false);
     }
   }
   if (myOpenTransaction) {
@@ -397,9 +424,6 @@ void PartSet_WidgetSketchLabel::updateByPlaneSelected(const ModuleBase_ViewerPrs
   if (aModule)
     aModule->onViewTransformed();
 
-  // 6. Update sketcher actions
-  XGUI_ActionsMgr* anActMgr = aWorkshop->actionsMgr();
-
   myWorkshop->updateCommandStatus();
   aWorkshop->selector()->clearSelection();
   myWorkshop->viewer()->update();
@@ -443,6 +467,15 @@ void PartSet_WidgetSketchLabel::restoreAttributeValue(const AttributePtr& theAtt
     GeomShapePtr anEmptyShape;
     aSelAttr->setValue(anEmptyResult, anEmptyShape);
   }
+  std::shared_ptr<GeomDataAPI_Point> anOrigin = std::dynamic_pointer_cast<GeomDataAPI_Point>(
+    aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
+  anOrigin->reset();
+  std::shared_ptr<GeomDataAPI_Dir> aNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+    aData->attribute(SketchPlugin_Sketch::NORM_ID()));
+  aNormal->reset();
+  std::shared_ptr<GeomDataAPI_Dir> aDirX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+    aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
+  aDirX->reset();
 }
 
 bool PartSet_WidgetSketchLabel::setSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs)
@@ -468,8 +501,6 @@ bool PartSet_WidgetSketchLabel::canFillSketch(const ModuleBase_ViewerPrsPtr& the
   }
   // check plane or planar face of any non-sketch object
   if (aCanFillSketch) {
-    std::shared_ptr<GeomAPI_Face> aGeomFace;
-
     GeomShapePtr aGeomShape = thePrs->shape();
     if ((!aGeomShape.get() || aGeomShape->isNull()) && aResult.get()) {
       aGeomShape = aResult->shape();
@@ -522,13 +553,13 @@ bool PartSet_WidgetSketchLabel::fillSketchPlaneBySelection(const ModuleBase_View
       }
       else {
         aSelAttr->setValue(aFeature, GeomShapePtr());
-        GeomShapePtr aShape = aSelAttr->value();
-        if (!aShape.get() && aSelAttr->contextFeature().get() &&
+        GeomShapePtr aSelShape = aSelAttr->value();
+        if (!aSelShape.get() && aSelAttr->contextFeature().get() &&
           aSelAttr->contextFeature()->firstResult().get()) {
-          aShape = aSelAttr->contextFeature()->firstResult()->shape();
+          aSelShape = aSelAttr->contextFeature()->firstResult()->shape();
         }
-        if (aShape.get() && aShape->isPlanar()) {
-          const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();
+        if (aSelShape.get() && aSelShape->isPlanar()) {
+          const TopoDS_Shape& aTDShape = aSelShape->impl<TopoDS_Shape>();
           setSketchPlane(aTDShape);
           isOwnerSet = true;
         }
@@ -540,6 +571,10 @@ bool PartSet_WidgetSketchLabel::fillSketchPlaneBySelection(const ModuleBase_View
 
 void PartSet_WidgetSketchLabel::activateCustom()
 {
+  QWidget* aTopWidget = window();
+  if (aTopWidget)
+    aTopWidget->installEventFilter(this);
+
   PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
   if (aModule) {
     bool isBlocked = myAutoConstraints->blockSignals(true);
@@ -572,21 +607,49 @@ void PartSet_WidgetSketchLabel::activateCustom()
 
 void PartSet_WidgetSketchLabel::showEvent(QShowEvent* theEvent)
 {
-  if (mySizeOfViewWidget->isVisible()) {
+  ModuleBase_WidgetValidated::showEvent(theEvent);
+  QTimer::singleShot(10, this, SLOT(onShowPanel()));
+}
+
+void PartSet_WidgetSketchLabel::hideEvent(QHideEvent* theEvent)
+{
+  ModuleBase_WidgetValidated::hideEvent(theEvent);
+  if (myPartSetMessage->isVisible())
+    myPartSetMessage->hide();
+  if (mySizeMessage->isVisible())
+    mySizeMessage->hide();
+}
+
+
+void PartSet_WidgetSketchLabel::onShowPanel()
+{
+  //if (mySizeOfViewWidget->isVisible()) {
+  if (myStackWidget->currentIndex() == 0) {
     DocumentPtr aDoc = feature()->document();
     DocumentPtr aModDoc = ModelAPI_Session::get()->moduleDocument();
     if (aModDoc == aDoc) {
       myPartSetMessage->move(mapToGlobal(geometry().bottomLeft()));
       myPartSetMessage->show();
     }
-    mySizeMessage->move(mySizeOfView->mapToGlobal(mySizeOfView->geometry().center()));
-    mySizeMessage->show();
+    if (mySizeOfViewWidget->isVisible()) {
+      QPoint aPnt = mySizeOfView->mapToGlobal(mySizeOfView->geometry().center());
+      mySizeMessage->move(aPnt);
+      mySizeMessage->show();
+    }
   }
 }
 
-
 void PartSet_WidgetSketchLabel::deactivate()
 {
+  QWidget* aTopWidget = window();
+  if (aTopWidget)
+    aTopWidget->removeEventFilter(this);
+
+  if (myTmpPlane.get()) {
+    setSketchPlane(myTmpPlane);
+    myTmpPlane.reset();
+  }
+
   ModuleBase_WidgetValidated::deactivate();
   bool aHidePreview = myPreviewPlanes->isPreviewDisplayed();
   myPreviewPlanes->erasePreviewPlanes(myWorkshop);
@@ -689,7 +752,7 @@ void PartSet_WidgetSketchLabel::onSetPlaneView()
 
 
 //******************************************************
-QList<std::shared_ptr<ModuleBase_ViewerPrs>> PartSet_WidgetSketchLabel::findCircularEdgesInPlane()
+QList<ModuleBase_ViewerPrsPtr> PartSet_WidgetSketchLabel::findCircularEdgesInPlane()
 {
   QList<std::shared_ptr<ModuleBase_ViewerPrs>> aResult;
   XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
@@ -711,7 +774,7 @@ QList<std::shared_ptr<ModuleBase_ViewerPrs>> PartSet_WidgetSketchLabel::findCirc
             bool isContains = false;
             // Check that edge is not used.
             // It is possible that the same edge will be taken from different faces
-            foreach(std::shared_ptr<ModuleBase_ViewerPrs> aPrs, aResult) {
+            foreach(ModuleBase_ViewerPrsPtr aPrs, aResult) {
               GeomAPI_Edge aUsedEdge(aPrs->shape());
               if (aUsedEdge.isEqual(aEdgeShape)) {
                 isContains = true;
@@ -719,8 +782,7 @@ QList<std::shared_ptr<ModuleBase_ViewerPrs>> PartSet_WidgetSketchLabel::findCirc
               }
             }
             if (!isContains) {
-              std::shared_ptr<ModuleBase_ViewerPrs>
-                aPrs(new ModuleBase_ViewerPrs(aResObj, aEdgeShape));
+              ModuleBase_ViewerPrsPtr aPrs(new ModuleBase_ViewerPrs(aResObj, aEdgeShape));
               aResult.append(aPrs);
             }
           }
@@ -748,6 +810,7 @@ void PartSet_WidgetSketchLabel::onChangePlane()
     }
 
     CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
+    myTmpPlane = PartSet_Tools::sketchPlane(aSketch);
     PartSet_Tools::nullifySketchPlane(aSketch);
 
     Handle(SelectMgr_Filter) aFilter = aModule->selectionFilter(SF_SketchPlaneFilter);
@@ -789,14 +852,67 @@ bool PartSet_WidgetSketchLabel::restoreValueCustom()
         int aDoF = aVal.toInt();
         if (aDoF == 0) {
           myDoFLabel->setText(tr("Sketch is fully fixed (DoF = 0)"));
+          myShowDOFBtn->setEnabled(false);
         } else {
           myDoFLabel->setText(tr("DoF (degrees of freedom) = ") + aVal);
+          myShowDOFBtn->setEnabled(true);
         }
       }
     }
     else {
       myDoFLabel->setText("");
+      myShowDOFBtn->setEnabled(false);
     }
   }
   return true;
 }
+
+
+void PartSet_WidgetSketchLabel::onShowDOF()
+{
+  CompositeFeaturePtr aCompFeature =
+    std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
+  if (aCompFeature.get()) {
+    static const Events_ID anEvent = Events_Loop::eventByName(EVENT_GET_DOF_OBJECTS);
+    ModelAPI_EventCreator::get()->sendUpdated(aCompFeature, anEvent);
+    Events_Loop::loop()->flush(anEvent);
+
+    // Transfer focus to the current viewport for correct processing of a key event
+    QWidget* aViewPort = myWorkshop->viewer()->activeViewPort();
+    if (aViewPort)
+      aViewPort->setFocus();
+  }
+}
+
+bool PartSet_WidgetSketchLabel::eventFilter(QObject* theObj, QEvent* theEvent)
+{
+  if (theObj == window()) {
+    int aType = theEvent->type();
+    if ((aType == QEvent::Hide) || (aType == QEvent::WindowDeactivate)) {
+      if (myPartSetMessage->isVisible())
+        myPartSetMessage->hide();
+      if (mySizeMessage->isVisible())
+        mySizeMessage->hide();
+    }
+    else if ((aType == QEvent::Show) || (aType == QEvent::WindowActivate))
+      onShowPanel();
+  }
+  return ModuleBase_WidgetValidated::eventFilter(theObj, theEvent);
+}
+
+void PartSet_WidgetSketchLabel::onShowViewPlane(bool toShow)
+{
+  PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
+  PartSet_PreviewSketchPlane* aPreviewPlane = aModule->sketchMgr()->previewSketchPlane();
+  if (toShow) {
+    CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
+    if (aPreviewPlane->isPlaneCreated())
+      aPreviewPlane->displaySketchPlane(myWorkshop);
+    else
+      aPreviewPlane->createSketchPlane(aSketch, myWorkshop);
+  }
+  else {
+    aPreviewPlane->eraseSketchPlane(myWorkshop, false);
+  }
+  myWorkshop->viewer()->update();
+}