]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Merge remote-tracking branch 'remotes/origin/master' into CEA_2019
authorazv <azv@opencascade.com>
Fri, 6 Sep 2019 11:20:21 +0000 (14:20 +0300)
committerazv <azv@opencascade.com>
Fri, 6 Sep 2019 11:20:21 +0000 (14:20 +0300)
# Conflicts:
# src/PartSet/PartSet_SketcherMgr.cpp

13 files changed:
1  2 
src/ModuleBase/ModuleBase_Tools.cpp
src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp
src/PartSet/PartSet_Module.cpp
src/PartSet/PartSet_SketcherMgr.cpp
src/PartSet/PartSet_SketcherMgr.h
src/PartSet/PartSet_SketcherReentrantMgr.cpp
src/PartSet/PartSet_WidgetSketchLabel.cpp
src/SketchAPI/SketchAPI_Sketch.cpp
src/SketchAPI/SketchAPI_Sketch.h
src/SketchPlugin/plugin-Sketch.xml
src/XGUI/XGUI_ContextMenuMgr.cpp
src/XGUI/XGUI_PropertyPanel.cpp
src/XGUI/XGUI_Workshop.cpp

index eb66062e82e26fbb0d6736af81e64fbedfdf31e8,a3c4d0ebdbf3c7c874d2abc25315c6594763d22d..83d25c2ad8093b04cf335a8a458b206c748a9b7d
@@@ -82,6 -82,8 +82,8 @@@
  #include <QMessageBox>
  #include <QAction>
  #include <QTextCodec>
+ #include <QWindow>
+ #include <QScreen>
  
  #include <sstream>
  #include <string>
@@@ -152,10 -154,9 +154,9 @@@ void activateWindow(QWidget* theWidget
  
  void setFocus(QWidget* theWidget, const QString& theInfo)
  {
-   activateWindow(theWidget);
    theWidget->setFocus();
    // rectangle of focus is not visible on tool button widgets
 -  theWidget->repaint();
 +  theWidget->update();
  #ifdef DEBUG_SET_FOCUS
    qDebug(QString("setFocus: %1").arg(theInfo).toStdString().c_str());
  #endif
@@@ -1320,6 -1321,14 +1321,14 @@@ bool isSameShape(const TopoDS_Shape& th
    return true;
  }
  
+ qreal currentPixelRatio()
+ {
+   QWindowList aWnds = qApp->topLevelWindows();
+   if (aWnds.size() > 0)
+     return aWnds.first()->devicePixelRatio();
+   return qApp->primaryScreen()->devicePixelRatio();
+ }
  
  } // namespace ModuleBase_Tools
  
index 4e458fa7bd5bf0f0349b893cfd07cef9a7132d83,1740c62ffd732e623fd73c1bc67091195791889b..f338f8eaa8c6c7f8f33e09e911cf354f55b09893
@@@ -116,20 -116,26 +116,26 @@@ ModuleBase_WidgetMultiSelector::ModuleB
    myIsSetSelectionBlocked(false), myCurrentHistoryIndex(-1),
    myIsFirst(true), myFiltersWgt(0)
  {
-   std::string aPropertyTypes = theData->getProperty("type_choice");
+   std::string aPropertyTypes = theData->getProperty("shape_types");
    QString aTypesStr = aPropertyTypes.c_str();
    myShapeTypes = aTypesStr.split(' ', QString::SkipEmptyParts);
    myIsUseChoice = theData->getBooleanAttribute("use_choice", false);
  
+   QString aAllowedList(theData->getProperty("allow_objects").c_str());
+   if (!aAllowedList.isEmpty())
+     myAllowedObjects = aAllowedList.split(' ', QString::SkipEmptyParts);
    QVBoxLayout* aMainLay = new QVBoxLayout(this);
    ModuleBase_Tools::adjustMargins(aMainLay);
  
    QStringList aIconsList = getIconsList(myShapeTypes);
    myTypeCtrl = new ModuleBase_ChoiceCtrl(this, myShapeTypes, aIconsList);
    myTypeCtrl->setLabel(tr("Type"));
-   myTypeCtrl->setValue(0);
+   if (!myShapeTypes.empty()) {
+     myTypeCtrl->setValue(0);
+     myDefMode = myShapeTypes.first().toStdString();
+   }
    aMainLay->addWidget(myTypeCtrl);
-   myDefMode = myShapeTypes.first().toStdString();
  
    // There is no sense to parameterize list of types while we can not parameterize selection mode
    // if the xml definition contains one type, the controls to select a type should not be shown
@@@ -215,9 -221,26 +221,26 @@@ void ModuleBase_WidgetMultiSelector::ac
  {
    ModuleBase_WidgetSelector::activateCustom();
  
-   myWorkshop->module()->activateCustomPrs(myFeature,
+   ModuleBase_IModule* aModule = myWorkshop->module();
+   aModule->activateCustomPrs(myFeature,
                              ModuleBase_IModule::CustomizeHighlightedObjects, true);
    clearSelectedHistory();
+   if (myAllowedObjects.length() > 0) {
+     Handle(SelectMgr_Filter) aFilter = aModule->selectionFilter(SF_GlobalFilter);
+     if (!aFilter.IsNull()) {
+       Handle(ModuleBase_ShapeDocumentFilter) aDocFilter =
+         Handle(ModuleBase_ShapeDocumentFilter)::DownCast(aFilter);
+       if (!aDocFilter.IsNull()) {
+         QStringList aSelFilters = aDocFilter->nonSelectableTypes();
+         foreach(QString aType, aSelFilters) {
+           if (aSelFilters.contains(aType)) {
+             aDocFilter->removeNonSelectableType(aType);
+             myTmpAllowed.append(aType);
+           }
+         }
+       }
+     }
+   }
  }
  
  //********************************************************************
@@@ -231,6 -254,20 +254,20 @@@ void ModuleBase_WidgetMultiSelector::de
  
    myWorkshop->module()->deactivateCustomPrs(ModuleBase_IModule::CustomizeHighlightedObjects, true);
    clearSelectedHistory();
+   if (myTmpAllowed.length() > 0) {
+     ModuleBase_IModule* aModule = myWorkshop->module();
+     Handle(SelectMgr_Filter) aFilter = aModule->selectionFilter(SF_GlobalFilter);
+     if (!aFilter.IsNull()) {
+       Handle(ModuleBase_ShapeDocumentFilter) aDocFilter =
+         Handle(ModuleBase_ShapeDocumentFilter)::DownCast(aFilter);
+       if (!aDocFilter.IsNull()) {
+         foreach(QString aType, myTmpAllowed) {
+           aDocFilter->addNonSelectableType(aType);
+         }
+       }
+     }
+     myTmpAllowed.clear();
+   }
  }
  
  //********************************************************************
@@@ -259,12 -296,23 +296,23 @@@ bool ModuleBase_WidgetMultiSelector::st
    std::string aType = anAttribute->attributeType();
    if (aType == ModelAPI_AttributeSelectionList::typeId()) {
      AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID());
-     std::string aMode = myTypeCtrl->textValue().toStdString();
-     if (myTypeCtrl->isVisible() && myIsFirst && (!myDefMode.empty()))
-       aMode = myDefMode;
-     aSelectionListAttr->setSelectionType(aMode);
-     myIsFirst = false;
+     if (myTypeCtrl->isVisible()) {
+       std::string aMode = myTypeCtrl->textValue().toStdString();
+       if (myIsFirst && (!myDefMode.empty()))
+         aMode = myDefMode;
+       aSelectionListAttr->setSelectionType(aMode);
+       myIsFirst = false;
+     } else { // no type, set the type as a first element of the list shape type when it is appeared
+       if (aSelectionListAttr->size()) {
+         AttributeSelectionPtr aSel = aSelectionListAttr->value(0);
+         GeomShapePtr aFirstVal = aSel->value();
+         if (!aFirstVal.get() && aSel->context().get())
+           aFirstVal = aSel->context()->shape();
+         if (aFirstVal.get() && !aFirstVal->isNull())
+           aSelectionListAttr->setSelectionType(aFirstVal->shapeTypeStr());
+       }
+     }
    }
    return true;
  }
@@@ -761,7 -809,7 +809,7 @@@ void ModuleBase_WidgetMultiSelector::up
    }
  
    // We have to call repaint because sometimes the List control is not updated
 -  myListView->getControl()->repaint();
 +  myListView->getControl()->update();
  }
  
  //********************************************************************
index db790beb92cb34adc6190d22105a3a10d6879379,7859a701c54d767aa784f40617a6538a50141bf4..3a8d9643e1594961cdac490f48336f7166d6ce09
@@@ -233,13 -233,6 +233,6 @@@ PartSet_Module::PartSet_Module(ModuleBa
  //******************************************************
  PartSet_Module::~PartSet_Module()
  {
-   std::map<XGUI_SelectionFilterType, Handle(SelectMgr_Filter)>::const_iterator aFiltersIt =
-     mySelectionFilters.begin();
-   for (; aFiltersIt != mySelectionFilters.end(); aFiltersIt++) {
-     Handle(SelectMgr_Filter) aFilter = aFiltersIt->second;
-     if (!aFilter.IsNull())
-       aFilter.Nullify();
-   }
    delete myCustomPrs;
    delete myOverconstraintListener;
    delete myRoot;
@@@ -659,7 -652,7 +652,7 @@@ void PartSet_Module::moduleSelectionFil
  {
    bool isSketchActive = mySketchMgr->activeSketch().get();
  
-   std::map<XGUI_SelectionFilterType, Handle(SelectMgr_Filter)>::const_iterator aFiltersIt =
+   std::map<ModuleBase_SelectionFilterType, Handle(SelectMgr_Filter)>::const_iterator aFiltersIt =
      mySelectionFilters.begin();
    for (; aFiltersIt != mySelectionFilters.end(); aFiltersIt++) {
      int aFilterType = aFiltersIt->first;
  
      // using sketch filters only if sketch operation is active
      if (!isSketchActive &&
-         mySketchMgr->sketchSelectionFilter((XGUI_SelectionFilterType)aFilterType))
+         mySketchMgr->sketchSelectionFilter((ModuleBase_SelectionFilterType)aFilterType))
        continue;
  
      // using filtering of construction results only from faces panel
    }
  }
  
- //******************************************************
- QIntList PartSet_Module::selectionFilters()
- {
-   QIntList aTypes;
-   std::map<XGUI_SelectionFilterType, Handle(SelectMgr_Filter)>::const_iterator aFiltersIt =
-     mySelectionFilters.begin();
-   for (; aFiltersIt != mySelectionFilters.end(); aFiltersIt++)
-     aTypes.append(aFiltersIt->first);
-   return aTypes;
- }
- //******************************************************
- void PartSet_Module::registerSelectionFilter(const XGUI_SelectionFilterType theFilterType,
-                                              const Handle(SelectMgr_Filter)& theFilter)
- {
-   mySelectionFilters[theFilterType] = theFilter;
- }
- //******************************************************
- Handle(SelectMgr_Filter) PartSet_Module::selectionFilter(const int theType)
- {
-   XGUI_SelectionFilterType aType = (XGUI_SelectionFilterType)theType;
-   if (mySelectionFilters.find(aType) != mySelectionFilters.end())
-     return mySelectionFilters[aType];
-   else
-     return Handle(SelectMgr_Filter)();
- }
  //******************************************************
  void PartSet_Module::customSubShapesSelectionModes(QIntList& theModes)
  {
@@@ -895,8 -857,6 +857,8 @@@ ModuleBase_ModelWidget* PartSet_Module:
      connect(aLabelWgt, SIGNAL(showConstraintToggled(int, bool)),
        mySketchMgr, SLOT(onShowConstraintsToggle(int, bool)));
      connect(aLabelWgt, SIGNAL(showFreePoints(bool)), mySketchMgr, SLOT(onShowPoints(bool)));
 +    connect(aLabelWgt, SIGNAL(autoConstraints(bool)),
 +      sketchReentranceMgr(), SLOT(onAutoConstraints(bool)));
      aLabelWgt->setShowPointsState(mySketchMgr->isShowFreePointsShown());
      aWgt = aLabelWgt;
    } else if (theType == "sketch-2dpoint_selector") {
@@@ -1493,7 -1453,7 +1455,7 @@@ void PartSet_Module::processEvent(cons
      aDisplayer->updateViewer();
      // Update tree items if they are expanded
      if (needUpdate) {
 -      aTreeView->viewport()->repaint(aTreeView->viewport()->rect());
 +      aTreeView->viewport()->update(aTreeView->viewport()->rect());
      }
    } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
      std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
index 669e8ee95b27033438efc183368d96f1174621a6,e936d729bdd6952ba32ada7763f5cb52f6bf48df..1c4c03e07ac37eda0a63e73411c862524ba05dbe
@@@ -168,7 -168,7 +168,7 @@@ PartSet_SketcherMgr::PartSet_SketcherMg
    : QObject(theModule), myModule(theModule), myIsEditLaunching(false), myIsDragging(false),
      myDragDone(false), myIsMouseOverWindow(false),
      myIsMouseOverViewProcessed(true), myPreviousUpdateViewerEnabled(true),
 -    myIsPopupMenuActive(false), myExternalPointsMgr(0)
 +    myIsPopupMenuActive(false), myExternalPointsMgr(0), myNoDragMoving(false)
  {
    ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();
    ModuleBase_IViewer* aViewer = anIWorkshop->viewer();
@@@ -353,23 -353,15 +353,23 @@@ void PartSet_SketcherMgr::onMousePresse
  
    ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
    ModuleBase_IViewer* aViewer = aWorkshop->viewer();
 -  if (!aViewer->canDragByMouse())
 -    return;
 +  //if (!aViewer->canDragByMouse())
 +  //  return;
  
    ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
                                                                 (getCurrentOperation());
    if (!aFOperation)
      return;
  
 -  if (aFOperation->isEditOperation()) {
 +  bool isEditing = aFOperation->isEditOperation();
 +  bool aCanDrag = aViewer->canDragByMouse();
 +
 +  //if (!aViewer->canDragByMouse() && isEditing) {
 +  //  // Do not edit by dragging
 +  //  return;
 +  //}
 +
 +  if (isEditing) {
      // If the current widget is a selector, do nothing, it processes the mouse press
      ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
      if(anActiveWidget && anActiveWidget->isViewerSelector()) {
      if ((!isSketchOpe) && (!isSketcher))
        return;
  
 -    bool isEditing = aFOperation->isEditOperation();
 -
      // Ignore creation sketch operation
      if ((!isSketcher) && (!isEditing))
        return;
  
 -    Handle(AIS_InteractiveContext) aContext = aViewer->AISContext();
 -    // Remember highlighted objects for editing
 -    ModuleBase_ISelection* aSelect = aWorkshop->selection();
 -
      bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
      storeSelection(aHasShift ? ST_SelectAndHighlightType : ST_HighlightType, myCurrentSelection);
  
  
      get2dPoint(theWnd, theEvent, myCurrentPoint);
      if (isSketcher) {
 -      myIsDragging = true;
 -      myDragDone = false;
 -
 +      if (aCanDrag) {
 +        myIsDragging = true;
 +        myDragDone = false;
 +      }
        myPreviousDrawModeEnabled = aViewer->enableDrawMode(false);
        launchEditing();
        if (aFeature.get() != NULL) {
        myIsEditLaunching = !myModule->sketchReentranceMgr()->isInternalEditActive();
        aFOperation->commit();
  
 -      myIsDragging = true;
 -      myDragDone = false;
 -
 +      if (aCanDrag) {
 +        myIsDragging = true;
 +        myDragDone = false;
 +      }
        myPreviousDrawModeEnabled = aViewer->enableDrawMode(false);
        launchEditing();
        myIsEditLaunching = aPrevLaunchingState;
  
  void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
  {
+   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
+   if (myIsDragging)
+     aWorkshop->viewer()->enableDrawMode(myPreviousDrawModeEnabled);
    bool aWasDragging = myIsDragging;
    myIsDragging = false;
  
 -  if (myModule->sketchReentranceMgr()->processMouseReleased(theWnd, theEvent))
 +  if (myModule->sketchReentranceMgr()->processMouseReleased(theWnd, theEvent)) {
      return;
 -
 +  }
    // if mouse is pressed when it was over view and at release the mouse is out of view, do nothing
 -  if (!myIsMouseOverViewProcessed)
 +  if (!myIsMouseOverViewProcessed) {
      return;
 -
 +  }
-   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
    ModuleBase_IViewer* aViewer = aWorkshop->viewer();
 -  if (!aViewer->canDragByMouse())
 -    return;
 -  ModuleBase_Operation* aOp = getCurrentOperation();
 +  //if (!aViewer->canDragByMouse())
 +  //  return;
 +  ModuleBase_OperationFeature* aOp =
 +      dynamic_cast<ModuleBase_OperationFeature*>(getCurrentOperation());
    if (aOp) {
 -    if (isNestedSketchOperation(aOp)) {
 -      // Only for sketcher operations
 -      if (aWasDragging) {
 -        if (myDragDone) {
 -          /// the previous selection is lost by mouse release in the viewer(Select method), but
 -          /// it is still stored in myCurrentSelection. So, it is possible to restore selection
 -          /// It is important for drag(edit with mouse) of sketch entities.
 -          restoreSelection(myCurrentSelection);
 -          myCurrentSelection.clear();
 +    bool aStartNoDragOperation = !aViewer->canDragByMouse() && aOp->isEditOperation();
 +    if (aStartNoDragOperation || myNoDragMoving) {
 +      // Process edit operation without dragging
 +      if (myCurrentSelection.size() > 0)
 +        myNoDragMoving = !myNoDragMoving;
 +      else
 +        myNoDragMoving = false;
 +      if (myNoDragMoving)
 +        return;
 +      else {
 +        restoreSelection(myCurrentSelection);
 +        myCurrentSelection.clear();
 +      }
 +    }
 +    else {
 +      if (isNestedSketchOperation(aOp)) {
 +        // Only for sketcher operations
 +        if (aWasDragging) {
 +          if (myDragDone) {
 +            /// the previous selection is lost by mouse release in the viewer(Select method), but
 +            /// it is still stored in myCurrentSelection. So, it is possible to restore selection
 +            /// It is important for drag(edit with mouse) of sketch entities.
 +            restoreSelection(myCurrentSelection);
 +            myCurrentSelection.clear();
 +          }
          }
        }
      }
    }
  
-   aWorkshop->viewer()->enableDrawMode(myPreviousDrawModeEnabled);
  
    ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
    PartSet_MouseProcessor* aProcessor = dynamic_cast<PartSet_MouseProcessor*>(anActiveWidget);
@@@ -533,6 -514,7 +535,6 @@@ void PartSet_SketcherMgr::onMouseMoved(
      qDebug(QString("%1").arg(anInfo.size()).arg(anInfoStr).toStdString().c_str());
    }
  #endif
 -
    if (myModule->sketchReentranceMgr()->processMouseMoved(theWnd, theEvent))
      return;
  
        // the feature is to be erased here, but it is correct to call canDisplayObject because
        // there can be additional check (e.g. editor widget in distance constraint)
        ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
 -                                                 (getCurrentOperation());
 +        (getCurrentOperation());
        if (aFOperation) {
          FeaturePtr aFeature = aFOperation->feature();
          visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature));
    }
    //myClickedPoint.clear();
  
 -  if (myIsDragging) {
 +  if (myIsDragging || myNoDragMoving) {
      // 1. the current selection is saved in the mouse press method in order to restore it after
      //    moving
      // 2. the enable selection in the viewer should be temporary switched off in order to ignore
      // mouse press signal in the viewer(it call Select for AIS context and the dragged objects are
      // deselected). This flag should be restored in the slot, processed the mouse release signal.
 -
      ModuleBase_Operation* aCurrentOperation = getCurrentOperation();
      if (!aCurrentOperation)
        return;
      if (isSketchOperation(aCurrentOperation))
        return; // No edit operation activated
  
 +#ifdef DRAGGING_DEBUG
 +    QTime t;
 +    t.start();
 +#endif
 +
      Handle(V3d_View) aView = theWnd->v3dView();
      gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);
      Point aMousePnt;
      get2dPoint(theWnd, theEvent, aMousePnt);
  
      std::shared_ptr<GeomAPI_Pnt2d> anOriginalPosition = std::shared_ptr<GeomAPI_Pnt2d>(
 -                            new GeomAPI_Pnt2d(myCurrentPoint.myCurX, myCurrentPoint.myCurY));
 +      new GeomAPI_Pnt2d(myCurrentPoint.myCurX, myCurrentPoint.myCurY));
      std::shared_ptr<GeomAPI_Pnt2d> aCurrentPosition = std::shared_ptr<GeomAPI_Pnt2d>(
 -                            new GeomAPI_Pnt2d(aMousePnt.myCurX, aMousePnt.myCurY));
 +      new GeomAPI_Pnt2d(aMousePnt.myCurX, aMousePnt.myCurY));
  
      ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
      XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
      static Events_ID aMoveEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED);
      //static Events_ID aUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
      FeatureToSelectionMap::const_iterator anIt = myCurrentSelection.begin(),
 -                                          aLast = myCurrentSelection.end();
 +      aLast = myCurrentSelection.end();
      // 4. the features and attributes modification(move)
      bool isModified = false;
      for (; anIt != aLast; anIt++) {
        // Process selection by attribute: the priority to the attribute
        if (!anAttributes.empty()) {
          std::set<AttributePtr>::const_iterator anAttIt = anAttributes.begin(),
 -                                               anAttLast = anAttributes.end();
 +          anAttLast = anAttributes.end();
          for (; anAttIt != anAttLast; anAttIt++) {
            AttributePtr anAttr = *anAttIt;
            if (anAttr.get() == NULL)
                bool isImmutable = aPoint->setImmutable(true);
  
                std::shared_ptr<ModelAPI_ObjectMovedMessage> aMessage = std::shared_ptr
 -                       <ModelAPI_ObjectMovedMessage>(new ModelAPI_ObjectMovedMessage(this));
 +                <ModelAPI_ObjectMovedMessage>(new ModelAPI_ObjectMovedMessage(this));
                aMessage->setMovedAttribute(aPoint);
                aMessage->setOriginalPosition(anOriginalPosition);
                aMessage->setCurrentPosition(aCurrentPosition);
              }
            }
          }
 -      } else {
 +      }
 +      else {
          // Process selection by feature
          std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
            std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
          if (aSketchFeature) {
            std::shared_ptr<ModelAPI_ObjectMovedMessage> aMessage = std::shared_ptr
 -                    <ModelAPI_ObjectMovedMessage>(new ModelAPI_ObjectMovedMessage(this));
 +            <ModelAPI_ObjectMovedMessage>(new ModelAPI_ObjectMovedMessage(this));
            aMessage->setMovedObject(aFeature);
            aMessage->setOriginalPosition(anOriginalPosition);
            aMessage->setCurrentPosition(aCurrentPosition);
      aDisplayer->enableUpdateViewer(isEnableUpdateViewer);
      aDisplayer->updateViewer();
  
 +#ifdef DRAGGING_DEBUG
 +    cout << "Mouse move processing " << t.elapsed() << endl;
 +#endif
 +
      myDragDone = true;
      myCurrentPoint = aMousePnt;
    }
@@@ -988,6 -961,8 +990,8 @@@ void PartSet_SketcherMgr::startSketch(M
    if (!aFOperation)
      return;
  
+   SketcherPrs_Tools::setPixelRatio(ModuleBase_Tools::currentPixelRatio());
    myModule->onViewTransformed();
  
    // Display all sketcher sub-Objects
@@@ -1227,13 -1202,13 +1231,13 @@@ void PartSet_SketcherMgr::commitNestedS
    }
  }
  
- bool PartSet_SketcherMgr::sketchSelectionFilter(const XGUI_SelectionFilterType theFilterType)
+ bool PartSet_SketcherMgr::sketchSelectionFilter(const ModuleBase_SelectionFilterType theFilterType)
  {
    return mySelectionFilterTypes.find(theFilterType) != mySelectionFilterTypes.end();
  }
  
- void PartSet_SketcherMgr::registerSelectionFilter(const XGUI_SelectionFilterType theFilterType,
-                                                   const Handle(SelectMgr_Filter)& theFilter)
+ void PartSet_SketcherMgr::registerSelectionFilter(
+   const ModuleBase_SelectionFilterType theFilterType, const Handle(SelectMgr_Filter)& theFilter)
  {
    mySelectionFilterTypes.insert(theFilterType);
    myModule->registerSelectionFilter(theFilterType, theFilter);
index db0d0f915c04b7701d666afb599c0c77ce5fdccb,c036615b5ee29855a4495cceedd625903b47b521..6dfe03cc25f850ba5aa564678d4b4aa82d6e008c
  #include "PartSet.h"
  
  #include "PartSet_PreviewSketchPlane.h"
- #include "XGUI_SelectionFilterType.h"
  #include "PartSet_Tools.h"
  
  #include <ModelAPI_Feature.h>
  #include <ModelAPI_Attribute.h>
  #include <ModelAPI_CompositeFeature.h>
  #include <ModelAPI_Result.h>
+ #include <ModuleBase_SelectionFilterType.h>
  
  #include <ModuleBase_Definitions.h>
  #include <ModuleBase_ModelWidget.h>
@@@ -201,12 -201,12 +201,12 @@@ public
    /// Returns true if the filter is created by the sketch manager
    /// \param theFilterType a checked type
    /// \return boolean value
-   bool sketchSelectionFilter(const XGUI_SelectionFilterType theFilterType);
+   bool sketchSelectionFilter(const ModuleBase_SelectionFilterType theFilterType);
  
    /// Append selection filter into the module and type of the filter in internal container
    /// \param theFilterType selection filter type
    /// \param theFilter added filter
-   void registerSelectionFilter(const XGUI_SelectionFilterType theFilterType,
+   void registerSelectionFilter(const ModuleBase_SelectionFilterType theFilterType,
                                 const Handle(SelectMgr_Filter)& theFilter);
  
    /// Commit the operation if it is possible. If the operation is dimention constraint,
@@@ -344,8 -344,6 +344,8 @@@ public slots
    /// Process sketch plane selected event
    void onPlaneSelected(const std::shared_ptr<GeomAPI_Pln>& thePln);
  
 +  /// The slot is called when user checks "Show free points" button
 +  /// \param toShow a state of the check box
    void onShowPoints(bool toShow);
  
  private slots:
@@@ -453,7 -451,7 +453,7 @@@ private
  
    CompositeFeaturePtr myCurrentSketch;
  
-   std::set<XGUI_SelectionFilterType> mySelectionFilterTypes;
+   std::set<ModuleBase_SelectionFilterType> mySelectionFilterTypes;
  
    FeatureToSelectionMap myCurrentSelection;
    bool myPreviousUpdateViewerEnabled;
    PartSet_ExternalPointsMgr* myExternalPointsMgr;
  
    QMap<ResultPtr, Handle(AIS_Shape)> myPointsHighlight;
 +
 +  bool myNoDragMoving;
  };
  
  
index 3a003a708396e376f5547075dc0e8b0b8aad871f,60134597f37250120035825e71ac8e5ecc405b64..5ae47888989d7855d7ec04174d6044d4c5fa3794
@@@ -31,9 -31,6 +31,9 @@@
  
  #include "GeomDataAPI_Point2D.h"
  
 +#include "GeomAPI_Lin2d.h"
 +#include "GeomAPI_Dir2d.h"
 +
  #include <ModuleBase_IPropertyPanel.h>
  #include <ModuleBase_ISelectionActivate.h>
  #include <ModuleBase_OperationFeature.h>
@@@ -54,8 -51,6 +54,8 @@@
  #include <SketchPlugin_Point.h>
  #include <SketchPlugin_Trim.h>
  #include <SketchPlugin_Split.h>
 +#include <SketchPlugin_ConstraintHorizontal.h>
 +#include <SketchPlugin_ConstraintVertical.h>
  
  #include <XGUI_Workshop.h>
  #include <XGUI_ModuleConnector.h>
@@@ -74,8 -69,7 +74,8 @@@ PartSet_SketcherReentrantMgr::PartSet_S
    myRestartingMode(RM_None),
    myIsFlagsBlocked(false),
    myIsInternalEditOperation(false),
 -  myNoMoreWidgetsAttribute("")
 +  myNoMoreWidgetsAttribute(""),
 +  myIsAutoConstraints(true)
  {
  }
  
@@@ -177,8 -171,6 +177,8 @@@ bool PartSet_SketcherReentrantMgr::proc
          workshop()->selector()->clearSelection();
  
          myPreviousFeature = aFOperation->feature();
 +        if (myIsAutoConstraints)
 +          addConstraints(myPreviousFeature);
          restartOperation();
          myPreviousFeature = FeaturePtr();
  
@@@ -405,7 -397,9 +405,9 @@@ bool PartSet_SketcherReentrantMgr::proc
  
    if (!isSketchSolverError) {
      myRestartingMode = RM_EmptyFeatureUsed;
-     isDone = startInternalEdit(thePreviousAttributeID);
+     // It seems that the call is obsolete for Enter key processing
+     // It prevent finalysing of the current operation by Enter key
+     //isDone = startInternalEdit(thePreviousAttributeID);
    }
  
    return isDone;
@@@ -829,47 -823,3 +831,47 @@@ void PartSet_SketcherReentrantMgr::setI
        aPropertyPanel->setInternalActiveWidget(theWidget);
    }
  }
 +
 +void PartSet_SketcherReentrantMgr::onAutoConstraints(bool isOn)
 +{
 +  myIsAutoConstraints = isOn;
 +}
 +
 +void PartSet_SketcherReentrantMgr::addConstraints(const FeaturePtr& theFeature)
 +{
 +  static GeomDir2dPtr myHorDir(new GeomAPI_Dir2d(1, 0));
 +  static GeomDir2dPtr myVertDir(new GeomAPI_Dir2d(0, 1));
 +
 +  if (theFeature->getKind() == SketchPlugin_Line::ID()) {
 +    std::shared_ptr<ModelAPI_Data> aData = theFeature->data();
 +    std::shared_ptr<GeomDataAPI_Point2D> aPoint1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
 +        aData->attribute(SketchPlugin_Line::START_ID()));
 +    std::shared_ptr<GeomDataAPI_Point2D> aPoint2 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
 +        aData->attribute(SketchPlugin_Line::END_ID()));
 +    if (aPoint1.get() && aPoint2.get()) {
 +      GeomLine2dPtr aLine(new GeomAPI_Lin2d(aPoint1->pnt(), aPoint2->pnt()));
 +      GeomDir2dPtr aDir = aLine->direction();
 +      double aHorAngle = fabs(myHorDir->angle(aDir));
 +      double aVertAngle = fabs(myVertDir->angle(aDir));
 +      if (aHorAngle > M_PI/2.)
 +        aHorAngle = M_PI - aHorAngle;
 +      if (aVertAngle > M_PI/2.)
 +        aVertAngle = M_PI - aVertAngle;
 +
 +      double aTolerance = Config_PropManager::real(SKETCH_TAB_NAME, "angular_tolerance");
 +      CompositeFeaturePtr aSketch = module()->sketchMgr()->activeSketch();
 +      FeaturePtr aFeature;
 +      if (aHorAngle < aTolerance)
 +        // Add horizontal constraint
 +        aFeature = aSketch->addFeature(SketchPlugin_ConstraintHorizontal::ID());
 +      else if (aVertAngle < aTolerance)
 +        // Add vertical constraint
 +        aFeature = aSketch->addFeature(SketchPlugin_ConstraintVertical::ID());
 +
 +      if (aFeature.get()) {
 +        aFeature->refattr(SketchPlugin_Constraint::ENTITY_A())->setObject(
 +            theFeature->firstResult());
 +      }
 +    }
 +  }
 +}
index 3f4c8d82990cdffa479015483714a616858e2a38,221207f9d910ebb8b42d124d0f4ef273ca30a160..dafd2526ff3e44a57c511dcf38c9b1100d148f8f
@@@ -21,7 -21,6 +21,7 @@@
  #include "PartSet_Tools.h"
  #include "PartSet_Module.h"
  #include "PartSet_PreviewPlanes.h"
 +#include "PartSet_SketcherReentrantMgr.h"
  
  #include "SketchPlugin_SketchEntity.h"
  
@@@ -172,10 -171,6 +172,10 @@@ myIsSelection(false
    connect(myShowPoints, SIGNAL(toggled(bool)), this, SIGNAL(showFreePoints(bool)));
    aLayout->addWidget(myShowPoints);
  
 +  myAutoConstraints = new QCheckBox(tr("Automatic constraints"), this);
 +  connect(myAutoConstraints, SIGNAL(toggled(bool)), this, SIGNAL(autoConstraints(bool)));
 +  aLayout->addWidget(myAutoConstraints);
 +
    QPushButton* aPlaneBtn = new QPushButton(tr("Change sketch plane"), aSecondWgt);
    connect(aPlaneBtn, SIGNAL(clicked(bool)), SLOT(onChangePlane()));
    aLayout->addWidget(aPlaneBtn);
@@@ -513,13 -508,6 +513,13 @@@ bool PartSet_WidgetSketchLabel::fillSke
  
  void PartSet_WidgetSketchLabel::activateCustom()
  {
 +  PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
 +  if (aModule) {
 +    bool isBlocked = myAutoConstraints->blockSignals(true);
 +    myAutoConstraints->setChecked(aModule->sketchReentranceMgr()->isAutoConstraints());
 +    myAutoConstraints->blockSignals(isBlocked);
 +  }
 +
    std::shared_ptr<GeomAPI_Pln> aPlane = plane();
    if (aPlane.get()) {
      myStackWidget->setCurrentIndex(1);
@@@ -551,6 -539,12 +551,12 @@@ void PartSet_WidgetSketchLabel::deactiv
  
    if (aHidePreview)
      myWorkshop->viewer()->update();
+   if (myOpenTransaction) {
+     SessionPtr aMgr = ModelAPI_Session::get();
+     aMgr->finishOperation();
+     myOpenTransaction = false;
+   }
  }
  
  void PartSet_WidgetSketchLabel::selectionModes(int& theModuleSelectionModes, QIntList& theModes)
@@@ -692,6 -686,13 +698,13 @@@ void PartSet_WidgetSketchLabel::onChang
      myRemoveExternal->setVisible(true);
      myStackWidget->setCurrentIndex(0);
  
+     bool aBodyIsVisualized = myPreviewPlanes->hasVisualizedBodies(myWorkshop);
+     if (!aBodyIsVisualized) {
+       // We have to select a plane before any operation
+       myPreviewPlanes->showPreviewPlanes(myWorkshop);
+     }
      CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
      PartSet_Tools::nullifySketchPlane(aSketch);
  
index b4b43cbb389a565e6bd866455bdef2cd5bb71630,722cbbaa77e40782003c6940d9f14d61f867801a..e1aabba8adf3eac43c6e913336d0c696425389bc
  #include "SketchAPI_Rotation.h"
  #include "SketchAPI_Translation.h"
  //--------------------------------------------------------------------------------------
+ #include <GeomAPI_Curve.h>
  #include <GeomAPI_Dir2d.h>
+ #include <GeomAPI_PlanarEdges.h>
+ #include <GeomAPI_ShapeExplorer.h>
  #include <GeomAPI_XY.h>
+ #include <GeomAlgoAPI_SketchBuilder.h>
  #include <cmath>
  //--------------------------------------------------------------------------------------
  SketchAPI_Sketch::SketchAPI_Sketch(
@@@ -235,6 -239,65 +239,65 @@@ std::list< std::shared_ptr<SketchAPI_Po
    return aFreePoints;
  }
  
+ //--------------------------------------------------------------------------------------
+ static GeomCurvePtr untrimmedCurve(GeomShapePtr theShape)
+ {
+   GeomCurvePtr aCurve(new GeomAPI_Curve(theShape));
+   if (aCurve->isTrimmed())
+     aCurve = aCurve->basisCurve();
+   return aCurve;
+ }
+ void SketchAPI_Sketch::changeFacesOrder(
+     const std::list<std::list<ModelHighAPI_Selection> >& theFaces)
+ {
+   // collect faces of the sketch
+   ResultConstructionPtr aSketchResult =
+       std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(feature()->lastResult());
+   if (!aSketchResult) {
+     // sketch is nested to a boolean operation, thus, it has no result yet.
+     feature()->execute();
+     aSketchResult =
+         std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(feature()->lastResult());
+   }
+   std::list<GeomFacePtr> aFaces;
+   int aFacesNum = aSketchResult->facesNum();
+   for (int i = 0; i < aFacesNum; ++i)
+     aFaces.push_back(aSketchResult->face(i));
+   // find new faces order according to the given lists of edges
+   std::list<GeomFacePtr> aNewFacesOrder;
+   std::list<std::list<ModelHighAPI_Selection> >::const_iterator anIt = theFaces.begin();
+   for (; anIt != theFaces.end(); ++anIt) {
+     // find the appropriate face
+     std::list<GeomFacePtr>::iterator aFIt = aFaces.begin();
+     for (; aFIt != aFaces.end(); ++aFIt) {
+       std::list<ModelHighAPI_Selection>::const_iterator aEdgeIt = anIt->begin();
+       GeomAPI_ShapeExplorer aFExp(*aFIt, GeomAPI_Shape::EDGE);
+       for (; aEdgeIt != anIt->end() && aFExp.more(); ++aEdgeIt, aFExp.next()) {
+         ResultPtr aCurRes = aEdgeIt->resultSubShapePair().first;
+         if (!aCurRes)
+           break;
+         GeomCurvePtr aCurve1 = untrimmedCurve(aCurRes->shape());
+         GeomCurvePtr aCurve2 = untrimmedCurve(aFExp.current());
+         if (!aCurve1->isEqual(aCurve2))
+           break;
+       }
+       if (aEdgeIt == anIt->end() && !aFExp.more()) {
+         // face is found
+         aNewFacesOrder.push_back(*aFIt);
+         aFaces.erase(aFIt);
+         break;
+       }
+     }
+   }
+   // place the rest faces at the end of new faces list
+   if (!aFaces.empty())
+     aNewFacesOrder.insert(aNewFacesOrder.end(), aFaces.begin(), aFaces.end());
+   // update the result of the sketch with the new order of faces
+   aSketchResult->setFacesOrder(aNewFacesOrder);
+ }
  //--------------------------------------------------------------------------------------
  std::shared_ptr<SketchAPI_Point> SketchAPI_Sketch::addPoint(
      double theX, double theY)
@@@ -460,33 -523,22 +523,33 @@@ std::shared_ptr<SketchAPI_MacroArc> Ske
  std::shared_ptr<SketchAPI_MacroArc> SketchAPI_Sketch::addArc(
                                                  const ModelHighAPI_RefAttr& theTangentPoint,
                                                  double theEndX, double theEndY,
 -                                                bool theInversed)
 +                                                bool theInversed,
 +                                                bool theTransversal)
  {
    std::shared_ptr<ModelAPI_Feature> aFeature =
      compositeFeature()->addFeature(SketchPlugin_MacroArc::ID());
 -  return MacroArcPtr(new SketchAPI_MacroArc(
 -    aFeature, theTangentPoint, theEndX, theEndY, theInversed));
 +  MacroArcPtr aMacroArc(new SketchAPI_MacroArc(aFeature));
 +  if (theTransversal)
 +    aMacroArc->setByTransversal(theTangentPoint, theEndX, theEndY, theInversed);
 +  else
 +    aMacroArc->setByTangent(theTangentPoint, theEndX, theEndY, theInversed);
 +  return aMacroArc;
  }
  
  std::shared_ptr<SketchAPI_MacroArc> SketchAPI_Sketch::addArc(
                                                const ModelHighAPI_RefAttr& theTangentPoint,
                                                const std::shared_ptr<GeomAPI_Pnt2d>& theEnd,
 -                                              bool theInversed)
 +                                              bool theInversed,
 +                                              bool theTransversal)
  {
    std::shared_ptr<ModelAPI_Feature> aFeature =
      compositeFeature()->addFeature(SketchPlugin_MacroArc::ID());
 -  return MacroArcPtr(new SketchAPI_MacroArc(aFeature, theTangentPoint, theEnd, theInversed));
 +  MacroArcPtr aMacroArc(new SketchAPI_MacroArc(aFeature));
 +  if (theTransversal)
 +    aMacroArc->setByTransversal(theTangentPoint, theEnd, theInversed);
 +  else
 +    aMacroArc->setByTangent(theTangentPoint, theEnd, theInversed);
 +  return aMacroArc;
  }
  
  std::shared_ptr<SketchAPI_Arc> SketchAPI_Sketch::addArc(const ModelHighAPI_Selection & theExternal)
@@@ -1019,6 -1071,99 +1082,99 @@@ std::shared_ptr<GeomAPI_Pnt2d> SketchAP
  
  //--------------------------------------------------------------------------------------
  
+ static bool isDifferent(GeomFacePtr theFace1, GeomFacePtr theFace2)
+ {
+   // collect edges of the first face
+   std::list<GeomShapePtr> anEdges1;
+   for (GeomAPI_ShapeExplorer anExp(theFace1, GeomAPI_Shape::EDGE); anExp.more(); anExp.next())
+     anEdges1.push_back(anExp.current());
+   // compare edges of faces
+   for (GeomAPI_ShapeExplorer anExp(theFace2, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
+     GeomShapePtr aCurrent = anExp.current();
+     bool isFound = false;
+     std::list<GeomShapePtr>::iterator anIt1 = anEdges1.begin();
+     for (; anIt1 != anEdges1.end(); ++anIt1)
+       if (aCurrent->isSameGeometry(*anIt1)) {
+         isFound = true;
+         anEdges1.erase(anIt1);
+         break;
+       }
+     if (!isFound)
+       return true;
+   }
+   return !anEdges1.empty();
+ }
+ static bool isCustomFacesOrder(CompositeFeaturePtr theSketch)
+ {
+   ResultConstructionPtr aSketchResult =
+       std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theSketch->lastResult());
+   if (!aSketchResult)
+     return false;
+   std::shared_ptr<GeomAPI_PlanarEdges> aWires =
+       std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aSketchResult->shape());
+   if (!aWires)
+     return false;
+   // collect faces constructed by SketchBuilder algorithm
+   GeomAlgoAPI_SketchBuilder aSketchBuilder(aWires->origin(), aWires->dirX(),
+                                            aWires->norm(), aWires);
+   const ListOfShape& aFaces = aSketchBuilder.faces();
+   // compare faces stored in sketch with faces generated by SketchBuilder
+   int aNbSketchFaces = aSketchResult->facesNum();
+   int aFaceIndex = 0;
+   for (ListOfShape::const_iterator aFIt = aFaces.begin();
+        aFIt != aFaces.end() && aFaceIndex < aNbSketchFaces;
+        ++aFIt, ++aFaceIndex) {
+     GeomFacePtr aSketchFace = aSketchResult->face(aFaceIndex);
+     GeomFacePtr aCurFace = (*aFIt)->face();
+     if (isDifferent(aSketchFace, aCurFace))
+       return true;
+   }
+   return false;
+ }
+ static void edgesOfSketchFaces(CompositeFeaturePtr theSketch,
+                                std::list<std::list<ResultPtr> >& theEdges)
+ {
+   ResultConstructionPtr aSketchResult =
+       std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theSketch->lastResult());
+   if (!aSketchResult)
+     return;
+   // collect curves of the sketch
+   std::map<GeomCurvePtr, ResultPtr, GeomAPI_Curve::Comparator> aCurves;
+   int aSubNum = theSketch->numberOfSubs();
+   for (int a = 0; a < aSubNum; ++a) {
+     FeaturePtr aSub = theSketch->subFeature(a);
+     const std::list<ResultPtr>& aResults = aSub->results();
+     std::list<ResultPtr>::const_iterator aRes = aResults.cbegin();
+     for (; aRes != aResults.cend(); aRes++) {
+       GeomShapePtr aCurShape = (*aRes)->shape();
+       if (aCurShape && aCurShape->isEdge())
+         aCurves[untrimmedCurve(aCurShape)] = *aRes;
+     }
+   }
+   // convert each face to the list of results of its edges
+   int aFacesNum = aSketchResult->facesNum();
+   for (int a = 0; a < aFacesNum; ++a) {
+     theEdges.push_back(std::list<ResultPtr>());
+     std::list<ResultPtr>& aCurEdges = theEdges.back();
+     GeomFacePtr aFace = aSketchResult->face(a);
+     for (GeomAPI_ShapeExplorer anExp(aFace, GeomAPI_Shape::EDGE);
+          anExp.more(); anExp.next()) {
+       GeomCurvePtr aCurrent = untrimmedCurve(anExp.current());
+       aCurEdges.push_back(aCurves[aCurrent]);
+     }
+   }
+ }
+ //--------------------------------------------------------------------------------------
  void SketchAPI_Sketch::dump(ModelHighAPI_Dumper& theDumper) const
  {
    FeaturePtr aBase = feature();
    // dump sketch's subfeatures
    CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aBase);
    theDumper.processSubs(aCompFeat, true);
+   // if face order differs to the order generated by SketchBuilder,
+   // dump the list of faces for correct execution of the script
+   if (isCustomFacesOrder(aCompFeat)) {
+     std::list<std::list<ResultPtr> > aFaces;
+     edgesOfSketchFaces(aCompFeat, aFaces);
+     const std::string& aSketchName = theDumper.name(aBase);
+     std::string aMethodName(".changeFacesOrder");
+     std::string aSpaceShift(aSketchName.size() + aMethodName.size(), ' ');
+     theDumper << aSketchName << aMethodName << "([";
+     for (std::list<std::list<ResultPtr> >::iterator aFIt = aFaces.begin();
+          aFIt != aFaces.end(); ++aFIt) {
+       if (aFIt != aFaces.begin())
+         theDumper << ",\n" << aSpaceShift << "  ";
+       theDumper << *aFIt;
+     }
+     theDumper << "\n" << aSpaceShift << " ])" << std::endl;
+   }
  }
index 27a5c543d8ebe21b780bbe1b1932f464f6aa87f3,c32c88d9daf73dc0980d559d2988f126f56a2f10..180ea15bb7f2f7a7ac6d8e394e712bb28234c6a3
@@@ -111,6 -111,10 +111,10 @@@ public
    SKETCHAPI_EXPORT
    void setExternal(std::shared_ptr<ModelAPI_Object> thePlaneObject);
  
+   /// Change order of sketch results (faces)
+   SKETCHAPI_EXPORT
+   void changeFacesOrder(const std::list<std::list<ModelHighAPI_Selection> >& theFaces);
    /// List points not connected by constraints with other sketch entitites
    SKETCHAPI_EXPORT
    std::list< std::shared_ptr<SketchAPI_Point> > getFreePoints();
        const std::shared_ptr<GeomAPI_Pnt2d>& theEnd,
        const std::shared_ptr<GeomAPI_Pnt2d>& thePassed);
  
 -  /// Add arc
 +  /// Add transversal/tangent arc
    SKETCHAPI_EXPORT
    std::shared_ptr<SketchAPI_MacroArc> addArc(
 -      const ModelHighAPI_RefAttr& theTangentPoint,
 +      const ModelHighAPI_RefAttr& theConnectedPoint,
        double theEndX, double theEndY,
 -      bool theInversed);
 +      bool theInversed,
 +      bool theTransversal = false);
  
 -  /// Add arc
 +  /// Add transversal/tangent arc
    SKETCHAPI_EXPORT
    std::shared_ptr<SketchAPI_MacroArc> addArc(
 -      const ModelHighAPI_RefAttr& theTangentPoint,
 +      const ModelHighAPI_RefAttr& theConnectedPoint,
        const std::shared_ptr<GeomAPI_Pnt2d>& theEnd,
 -      bool theInversed);
 +      bool theInversed,
 +      bool theTransversal = false);
  
    /// Add arc
    SKETCHAPI_EXPORT
index 35a8e7a76107fda527e6900103fe66d767980579,118bec3ac059912f37d713c125f5f615b27bac1d..89f8ddea1ee4948fdde866a75e75db11cd609bf9
                <validator id="SketchPlugin_ArcEndPointValidator" parameters="end_point_ref"/>
              </sketch-2dpoint_selector>
            </box>
 +          <box id="by_transversal_line"
 +               icon="icons/Sketch/arc_perp_32x32.png"
 +               title="Perpendicular to line">
 +            <sketch_shape_selector id="tangent_point"
 +                                   label="Transversal point"
 +                                   tooltip="Select point on line"
 +                                   shape_types="vertex">
 +              <validator id="SketchPlugin_ArcTransversalPoint"/>
 +            </sketch_shape_selector>
 +            <sketch-2dpoint_selector id="end_point_3"
 +                                     reference_attribute="end_point_ref"
 +                                     title="End point"
 +                                     tooltip="End point"
 +                                     accept_expressions="0"
 +                                     enable_value="enable_by_preferences">
 +              <validator id="SketchPlugin_ArcEndPointValidator" parameters="end_point_ref"/>
 +            </sketch-2dpoint_selector>
 +          </box>
          </toolbox>
          <labelvalue id="radius"
                      icon="icons/Sketch/radius.png"
        <!--  SketchFillet  -->
        <feature id="SketchFillet"
                 title="Fillet"
-                tooltip="Create constraint defining fillet between two objects"
+                tooltip="Create constraint defining fillet between two connected segments"
                 icon="icons/Sketch/fillet.png"
                 helpfile="filletFeature.html">
          <sketch_shape_selector id="fillet_point"
          <sketch_multi_selector id="ConstraintMirrorList"
              label="Segments:"
              tooltip="Select list of objects to be mirrored"
-             type_choice="Edges"
+             shape_types="Edges"
              use_external="true"
              greed ="true">
            <validator id="SketchPlugin_MirrorAttr" />
          <sketch_multi_selector id="MultiTranslationList"
              label="Segments:"
              tooltip="Select list of objects to be translated"
-             type_choice="Edges"
+             shape_types="Edges"
              use_external="true"
              greed ="true">
            <validator id="SketchPlugin_CopyValidator" />
          <sketch_multi_selector id="MultiRotationList"
              label="Segments:"
              tooltip="Select list of objects to be rotated"
-             type_choice="Edges"
+             shape_types="Edges"
              use_external="true"
              greed ="true">
            <validator id="SketchPlugin_CopyValidator" />
      </group>
  
      <group id="Dimensional constraints">
 -    <!--  SketchConstraintDistance  -->
 +      <!--  SketchConstraintDistance  -->
        <feature
          id="SketchConstraintDistance"
          title="Distance"
          <validator id="PartSet_ParallelSelection"/>
        </feature>
  
 -    <!--  SketchConstraintPerpendicular  -->
 +      <!--  SketchConstraintPerpendicular  -->
        <feature id="SketchConstraintPerpendicular" title="Perpendicular"
 -               tooltip="Create constraint defining two perpendicular lines"
 +               tooltip="Create constraint defining two orthogonal objects"
                 icon="icons/Sketch/perpendicular.png"
                 helpfile="perpendicularFeature.html">
          <sketch_shape_selector id="ConstraintEntityA"
 -            label="First line" tooltip="Select a line"
 +            label="First object" tooltip="Select line or arc"
              shape_types="edge">
            <validator id="PartSet_DifferentObjects"/>
            <validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityB"/>
 -            <validator id="GeomValidators_ShapeType" parameters="line"/>
 +          <validator id="SketchPlugin_PerpendicularAttr" parameters="ConstraintEntityB"/>
 +          <validator id="GeomValidators_ShapeType" parameters="line,circle"/>
          </sketch_shape_selector>
  
          <sketch_shape_selector id="ConstraintEntityB"
 -            label="Second line" tooltip="Select a line"
 +            label="Second object" tooltip="Select line or arc"
              shape_types="edge">
 -            <validator id="PartSet_DifferentObjects"/>
 +          <validator id="PartSet_DifferentObjects"/>
            <validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityA"/>
 -            <validator id="GeomValidators_ShapeType" parameters="line"/>
 +          <validator id="SketchPlugin_PerpendicularAttr" parameters="ConstraintEntityA"/>
 +          <validator id="GeomValidators_ShapeType" parameters="line,circle"/>
          </sketch_shape_selector>
          <validator id="PartSet_PerpendicularSelection"/>
        </feature>
  
        <!--  SketchConstraintTangent  -->
-       <feature id="SketchConstraintTangent" title="Tangent" tooltip="Create constraint defining tangency of two objects with common coincident point" icon="icons/Sketch/tangent.png"
+       <feature id="SketchConstraintTangent" title="Tangent" tooltip="Create constraint defining tangency of two segments with common coincident point" icon="icons/Sketch/tangent.png"
                 helpfile="tangentFeature.html">
          <sketch_shape_selector id="ConstraintEntityA"
              label="First object" tooltip="Select line or arc" shape_types="edge">
          <validator id="PartSet_EqualSelection"/>
        </feature>
  
 -    <!--  SketchConstraintCollinear  -->
 +      <!--  SketchConstraintCollinear  -->
        <feature id="SketchConstraintCollinear" title="Collinear" tooltip="Create constraint defining collinearity of two lines"
                 icon="icons/Sketch/collinear.png"
                 helpfile="collinearFeature.html">
index b1fadf67129ea2d66fb6b1571a25d16c88ff4c46,226aa30dda252dfedcba4bca6b533df7f10a1a5d..51f9fbec2bfd19da8cf104322a3fb1ca58862315
@@@ -293,6 -293,7 +293,7 @@@ void XGUI_ContextMenuMgr::updateObjectB
      bool hasCompositeOwner = false;
      bool hasResultInHistory = false;
      bool hasFolder = false;
+     bool canBeDeleted = true;
      ModuleBase_Tools::checkObjects(aObjects, hasResult, hasFeature, hasParameter,
                                     hasCompositeOwner, hasResultInHistory, hasFolder);
      //Process Feature
          if( aMgr->activeDocument() == aObject->document() )
          {
            action("RENAME_CMD")->setEnabled(true);
-           action("DELETE_CMD")->setEnabled(!hasCompositeOwner);
+           if (aObject->groupName() == ModelAPI_ResultConstruction::group()) {
+             FeaturePtr aFeature = ModelAPI_Feature::feature(aObject);
+             canBeDeleted = aFeature->isInHistory();
+             action("DELETE_CMD")->setEnabled(canBeDeleted);
+           }
+           else
+             action("DELETE_CMD")->setEnabled(!hasCompositeOwner);
            action("CLEAN_HISTORY_CMD")->setEnabled(!hasCompositeOwner &&
                                                    (hasFeature || hasParameter));
          }
          action("SHOW_ONLY_CMD")->setEnabled(true);
          action("SHADING_CMD")->setEnabled(true);
          action("WIREFRAME_CMD")->setEnabled(true);
+         foreach(ObjectPtr aObj, aObjects) {
+           FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
+           if (!aFeature->isInHistory()) {
+             canBeDeleted = false;
+             break;
+           }
+         }
+         action("DELETE_CMD")->setEnabled(canBeDeleted);
        }
 +      if (hasFeature && myWorkshop->canMoveFeature())
 +        action("MOVE_CMD")->setEnabled(true);
      } // end multi-selection
  
      // Check folder management commands state if only features are selected
          break;
        }
      if (!hasCompositeOwner && allActive ) {
-       if (hasResult || hasFeature || hasParameter) // #2924 results can be erased
-         action("DELETE_CMD")->setEnabled(true);
+       if (hasResult || hasFeature || hasParameter)  // #2924 results can be erased
+         action("DELETE_CMD")->setEnabled(canBeDeleted);
      }
      if (!hasCompositeOwner && allActive && (hasFeature|| hasParameter))
        action("CLEAN_HISTORY_CMD")->setEnabled(true);
@@@ -508,6 -522,8 +524,8 @@@ void XGUI_ContextMenuMgr::updateViewerM
      ObjectPtr aObject;
      foreach(ModuleBase_ViewerPrsPtr aPrs, aPrsList) {
        aObject = aPrs->object();
+       if (!aObject.get())
+         continue;
        GeomShapePtr aShape = aPrs->shape();
        if (aObject->isDisplayed()) {
          isVisible = true;
    if (myWorkshop->canChangeProperty("TRANSPARENCY_CMD"))
      action("TRANSPARENCY_CMD")->setEnabled(true);
  
-   action("DELETE_CMD")->setEnabled(true);
+   // Delete command is not used in viewer pop-up menu
+   action("DELETE_CMD")->setEnabled(false);
  }
  
  void XGUI_ContextMenuMgr::connectObjectBrowser()
@@@ -767,7 -784,7 +786,7 @@@ void XGUI_ContextMenuMgr::addObjBrowser
        aActions.append(action("ADD_OUT_FOLDER_BEFORE_CMD"));
        aActions.append(action("ADD_OUT_FOLDER_AFTER_CMD"));
        aActions.append(mySeparator3);
 -      //aActions.append(action("MOVE_CMD"));
 +      aActions.append(action("MOVE_CMD"));
        aActions.append(action("COLOR_CMD"));
        aActions.append(action("DEFLECTION_CMD"));
        aActions.append(action("TRANSPARENCY_CMD"));
index e2ce9216021cf44986c648308bcafc7a64a1bb15,8b5ccaf65b408673ae09be020965f1dddbbdd80b..4138cc25cdc39eddadbbe8021d49755e7e715dbd
@@@ -207,7 -207,7 +207,7 @@@ void XGUI_PropertyPanel::updateContentW
      eachWidget->restoreValue();
    }
    // the repaint is used here to immediately react in GUI to the values change.
 -  repaint();
 +  update();
  }
  
  void XGUI_PropertyPanel::createContentPanel(FeaturePtr theFeature)
@@@ -295,7 -295,6 +295,6 @@@ void XGUI_PropertyPanel::activateNextWi
  
    QList<ModuleBase_ModelWidget*>::const_iterator anIt = myWidgets.begin(), aLast = myWidgets.end();
    bool isFoundWidget = false;
-   ModuleBase_Tools::activateWindow(this, "XGUI_PropertyPanel::activateNextWidget()");
    for (; anIt != aLast; anIt++) {
      ModuleBase_ModelWidget* aCurrentWidget = *anIt;
      if (isFoundWidget || !theWidget) {
index deddb444fae226ce2829a4f34885ea31f1656a1d,df5c48cb13c153a11760d59bac5b59329ef848f6..d5e5bf833fefc51da14c82b6e8e3083e6d626c9c
@@@ -174,13 -174,13 +174,13 @@@ QString XGUI_Workshop::MOVE_TO_END_COMM
  //#define DEBUG_CLEAN_HISTORY
  
  #ifdef HAVE_SALOME
- static QString MyFilter(QObject::tr("SHAPER files (*.shaper *.opp)"));
+ static QString MyFilter(QObject::tr("SHAPER files (*.shaper *.cadbld)"));
  static QString MyFilter2(QObject::tr("SHAPER files (*.shaper)"));
  static QString MyExtension(".shaper");
  #else
- static QString MyFilter(QObject::tr("CAD Builder files (*.opp);;All files (*.*)"));
- static QString MyFilter2(QObject::tr("CAD Builder files (*.opp)"));
- static QString MyExtension(".opp");
+ static QString MyFilter(QObject::tr("CAD Builder files (*.cadbld);;All files (*.*)"));
+ static QString MyFilter2(QObject::tr("CAD Builder files (*.cadbld)"));
+ static QString MyExtension(".cadbld");
  #endif
  
  
@@@ -939,7 -939,11 +939,11 @@@ void XGUI_Workshop::onOpen(
    }
  
    //show file dialog, check if readable and open
-   QString aFile = QFileDialog::getOpenFileName(desktop(), tr("Open file"), QString(), MyFilter);
+   qreal aRatio = ModuleBase_Tools::currentPixelRatio();
+   // If the ratio is > 1 (HD screen) then QT has a bug in
+   // displaying of system open file dialog (too small)
+   QString aFile = QFileDialog::getOpenFileName(desktop(), tr("Open file"), QString(), MyFilter,
+     Q_NULLPTR, ((aRatio > 1)? QFileDialog::DontUseNativeDialog : QFileDialog::Options()));
    if (!aFile.isNull())
      openFile(aFile);
  }
@@@ -1106,8 -1110,10 +1110,10 @@@ bool XGUI_Workshop::onSaveAs(
  {
    if(!myOperationMgr->abortAllOperations(XGUI_OperationMgr::XGUI_InformationMessage))
      return false;
+   qreal aRatio = ModuleBase_Tools::currentPixelRatio();
    myCurrentFile = QFileDialog::getSaveFileName(desktop(), tr("Select name to save file..."),
-     QString(), MyFilter2);
+     QString(), MyFilter2,
+     Q_NULLPTR, ((aRatio > 1) ? QFileDialog::DontUseNativeDialog : QFileDialog::Options()));
    if (!myCurrentFile.isNull()) {
      if (!myCurrentFile.endsWith(MyExtension)) {
        myCurrentFile += MyExtension;
@@@ -2011,10 -2017,6 +2017,10 @@@ void XGUI_Workshop::cleanHistory(
  }
  
  //**************************************************************
 +bool compareFeature(const FeaturePtr& theF1, const FeaturePtr& theF2) {
 +  DocumentPtr aDoc = theF1->document();
 +  return aDoc->index(theF1) < aDoc->index(theF2);
 +}
  void XGUI_Workshop::moveObjects()
  {
    if (!abortAllOperations())
    if (!XGUI_Tools::canRemoveOrRename(desktop(), aFeatures))
      return;
  
 +  // Sort features by index in document
 +  std::list<FeaturePtr> aFList(aFeatures.begin(), aFeatures.end());
 +  aFList.sort(compareFeature);
 +
    DocumentPtr anActiveDocument = aMgr->activeDocument();
    FeaturePtr aCurrentFeature = anActiveDocument->currentFeature(true);
 -  std::set<FeaturePtr>::const_iterator anIt = aFeatures.begin(), aLast = aFeatures.end();
 +  std::list<FeaturePtr>::const_iterator anIt = aFList.begin(), aLast = aFList.end();
    for (; anIt != aLast; anIt++) {
      FeaturePtr aFeature = *anIt;
      if (!aFeature.get() || !myModule->canApplyAction(aFeature, anActionId))
@@@ -2468,14 -2466,16 +2474,16 @@@ void XGUI_Workshop::changeTransparency(
    QString aDescription = contextMenuMgr()->action("TRANSPARENCY_CMD")->text();
    aMgr->startOperation(aDescription.toStdString());
  
-   if (aDlg->exec() != QDialog::Accepted)
-     return;
-   // 4. set the value to all results
-   aCurrentValue = aTransparencyWidget->getValue();
-   setTransparency(aCurrentValue, theObjects);
+   if (aDlg->exec() == QDialog::Accepted) {
+     // 4. set the value to all results
+     aCurrentValue = aTransparencyWidget->getValue();
+     setTransparency(aCurrentValue, theObjects);
+     aMgr->finishOperation();
+   } else {
+     aMgr->abortOperation();
+     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+   }
  
-   aMgr->finishOperation();
    updateCommandStatus();
  }
  
@@@ -2799,8 -2799,12 +2807,12 @@@ void XGUI_Workshop::synchronizeResultTr
        if (aRes.get())
          synchronizeResultTree(aRes, theUpdateViewer);
      }
-   else
-     myDisplayer->display(theRes, theUpdateViewer);
+   else {
+     if (theRes->isDisplayed())
+       myDisplayer->display(theRes, theUpdateViewer);
+     else
+       myDisplayer->erase(theRes, theUpdateViewer);
+   }
  }
  #endif