Salome HOME
Update TestConstraintEqual.py
[modules/shaper.git] / src / PartSet / PartSet_SketcherMgr.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        PartSet_SketcherMgr.cpp
4 // Created:     19 Dec 2014
5 // Author:      Vitaly SMETANNIKOV
6
7 #include "PartSet_SketcherMgr.h"
8 #include "PartSet_SketcherReetntrantMgr.h"
9 #include "PartSet_Module.h"
10 #include "PartSet_WidgetPoint2d.h"
11 #include "PartSet_WidgetPoint2dDistance.h"
12 #include "PartSet_Tools.h"
13 #include "PartSet_WidgetSketchLabel.h"
14 #include "PartSet_WidgetEditor.h"
15
16 #include <XGUI_ModuleConnector.h>
17 #include <XGUI_Displayer.h>
18 #include <XGUI_Workshop.h>
19 #include <XGUI_ContextMenuMgr.h>
20 #include <XGUI_Selection.h>
21 #include <XGUI_SelectionMgr.h>
22 #include <XGUI_ModuleConnector.h>
23 #include <XGUI_PropertyPanel.h>
24 #include <XGUI_ViewerProxy.h>
25 #include <XGUI_OperationMgr.h>
26
27 #include <ModuleBase_IPropertyPanel.h>
28 #include <ModuleBase_ISelection.h>
29 #include <ModuleBase_IViewer.h>
30 #include <ModuleBase_IWorkshop.h>
31 #include <ModuleBase_IViewWindow.h>
32 #include <ModuleBase_ModelWidget.h>
33 #include <ModuleBase_Operation.h>
34 #include <ModuleBase_OperationFeature.h>
35 #include <ModuleBase_Operation.h>
36 #include <ModuleBase_WidgetEditor.h>
37
38 #include <GeomDataAPI_Point2D.h>
39
40 #include <Events_Loop.h>
41
42 #include <SketchPlugin_Line.h>
43 #include <SketchPlugin_Sketch.h>
44 #include <SketchPlugin_Point.h>
45 #include <SketchPlugin_Arc.h>
46 #include <SketchPlugin_Circle.h>
47 #include <SketchPlugin_ConstraintLength.h>
48 #include <SketchPlugin_ConstraintDistance.h>
49 #include <SketchPlugin_ConstraintParallel.h>
50 #include <SketchPlugin_ConstraintPerpendicular.h>
51 #include <SketchPlugin_ConstraintRadius.h>
52 #include <SketchPlugin_ConstraintRigid.h>
53 #include <SketchPlugin_ConstraintHorizontal.h>
54 #include <SketchPlugin_ConstraintVertical.h>
55 #include <SketchPlugin_ConstraintEqual.h>
56 #include <SketchPlugin_ConstraintTangent.h>
57 #include <SketchPlugin_ConstraintCoincidence.h>
58 #include <SketchPlugin_ConstraintFillet.h>
59 #include <SketchPlugin_ConstraintMirror.h>
60 #include <SketchPlugin_ConstraintAngle.h>
61 #include <SketchPlugin_MultiRotation.h>
62 #include <SketchPlugin_MultiTranslation.h>
63
64 #include <SketcherPrs_Tools.h>
65
66 #include <SelectMgr_IndexedMapOfOwner.hxx>
67 #include <StdSelect_BRepOwner.hxx>
68
69 //#include <AIS_DimensionSelectionMode.hxx>
70 #include <AIS_Shape.hxx>
71 #include <AIS_Dimension.hxx>
72
73 #include <ModelAPI_Events.h>
74 #include <ModelAPI_Session.h>
75 #include <ModelAPI_AttributeString.h>
76
77 #include <QMouseEvent>
78 #include <QApplication>
79 #include <QCursor>
80 #include <QMessageBox>
81
82 //#define DEBUG_DO_NOT_BY_ENTER
83
84 //#define DEBUG_CURSOR
85
86 /// Returns list of unique objects by sum of objects from List1 and List2
87 /*QList<ModuleBase_ViewerPrs> getSumList(const QList<ModuleBase_ViewerPrs>& theList1,
88                                        const QList<ModuleBase_ViewerPrs>& theList2)
89 {
90   QList<ModuleBase_ViewerPrs> aRes;
91   foreach (ModuleBase_ViewerPrs aPrs, theList1) {
92     if (!aRes.contains(aPrs))
93       aRes.append(aPrs);
94   }
95   foreach (ModuleBase_ViewerPrs aPrs, theList2) {
96     if (!aRes.contains(aPrs))
97       aRes.append(aPrs);
98   }
99   return aRes;
100 }*/
101
102 // Fills the list of features the list of selected presentations.
103 // \param theList a list of selected presentations
104 // \param theSketch a sketch to project a vertex shape of a presentation to the plane
105 // and find the corresponded attribute
106 // \param theFeatureList  an output list of features
107 void fillFeatureList(const QList<ModuleBase_ViewerPrs>& theList,
108                      const FeaturePtr theSketch,
109                      QList<FeaturePtr>& theFeatureList)
110 {
111   QList<ModuleBase_ViewerPrs> aRes;
112
113   QList<ModuleBase_ViewerPrs>::const_iterator anIt = theList.begin(),
114                                               aLast = theList.end();
115   for (; anIt != aLast; anIt++)
116   {
117     ModuleBase_ViewerPrs aPrs = *anIt;
118     FeaturePtr aFeature = ModelAPI_Feature::feature(aPrs.object());
119     if (aFeature.get()  && !theFeatureList.contains(aFeature))
120       theFeatureList.append(aFeature);
121   }
122 }
123
124 /// Fills attribute and result lists by the selected owner. In case if the attribute is found,
125 /// by the owner shape, it is put to the list. Otherwise if type of owner shape is edge, put the function
126 /// result as is to the list of results.
127 /// \param theOwner a viewer selected owner
128 /// \param theFeature a feature, where the attribute is searched
129 /// \param theSketch a current sketch
130 /// \param theSelectedAttribute an output list of attributes
131 /// \param theSelectedResults an output list of edge results
132 void getAttributesOrResults(const Handle(SelectMgr_EntityOwner)& theOwner,
133                             const FeaturePtr& theFeature, const FeaturePtr& theSketch,
134                             const ResultPtr& theResult,
135                             std::set<AttributePtr>& aSelectedAttributes,
136                             std::set<ResultPtr>& aSelectedResults)
137 {
138   Handle(StdSelect_BRepOwner) aBRepOwner = Handle(StdSelect_BRepOwner)::DownCast(theOwner);
139   if (aBRepOwner.IsNull())
140     return;
141   Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast(
142                                                                     aBRepOwner->Selectable());
143   if (aBRepOwner->HasShape()) {
144     const TopoDS_Shape& aShape = aBRepOwner->Shape();
145     TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
146     if (aShapeType == TopAbs_VERTEX) {
147       AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(theFeature,
148                                                                     aShape, theSketch);
149       if (aPntAttr.get() != NULL)
150         aSelectedAttributes.insert(aPntAttr);
151     }
152     else if (aShapeType == TopAbs_EDGE &&
153              aSelectedResults.find(theResult) == aSelectedResults.end()) {
154       aSelectedResults.insert(theResult);
155     }
156   }
157 }
158
159 PartSet_SketcherMgr::PartSet_SketcherMgr(PartSet_Module* theModule)
160   : QObject(theModule), myModule(theModule), myIsDragging(false), myDragDone(false),
161     myIsMouseOverWindow(false),
162     myIsMouseOverViewProcessed(true), myPreviousUpdateViewerEnabled(true),
163     myIsPopupMenuActive(false)
164 {
165   ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();
166   ModuleBase_IViewer* aViewer = anIWorkshop->viewer();
167
168   myPreviousDrawModeEnabled = true;//aViewer->isSelectionEnabled();
169
170   connect(aViewer, SIGNAL(mousePress(ModuleBase_IViewWindow*, QMouseEvent*)),
171           this, SLOT(onMousePressed(ModuleBase_IViewWindow*, QMouseEvent*)));
172
173   connect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)),
174           this, SLOT(onMouseReleased(ModuleBase_IViewWindow*, QMouseEvent*)));
175
176   connect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)),
177           this, SLOT(onMouseMoved(ModuleBase_IViewWindow*, QMouseEvent*)));
178
179   connect(aViewer, SIGNAL(mouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*)),
180           this, SLOT(onMouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*)));
181
182   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(anIWorkshop);
183   XGUI_Workshop* aWorkshop = aConnector->workshop();
184   connect(aWorkshop, SIGNAL(applicationStarted()), this, SLOT(onApplicationStarted()));
185
186   myIsConstraintsShown[PartSet_Tools::Geometrical] = true;
187   myIsConstraintsShown[PartSet_Tools::Dimensional] = true;
188 }
189
190 PartSet_SketcherMgr::~PartSet_SketcherMgr()
191 {
192   if (!myPlaneFilter.IsNull())
193     myPlaneFilter.Nullify();
194 }
195
196 void PartSet_SketcherMgr::onEnterViewPort()
197 {
198   // 1. if the mouse over window, update the next flag. Do not perform update visibility of
199   // created feature because it should be done in onMouseMove(). Some widgets watch
200   // the mouse move and use the cursor position to update own values. If the presentaion is
201   // redisplayed before this update, the feature presentation jumps from reset value to current.
202   myIsMouseOverWindow = true;
203
204   #ifdef DEBUG_DO_NOT_BY_ENTER
205   return;
206   #endif
207
208   if (canChangeCursor(getCurrentOperation())) {
209     QCursor* aCurrentCursor = QApplication::overrideCursor();
210     if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) {
211       QApplication::setOverrideCursor(QCursor(Qt::CrossCursor));
212 #ifdef DEBUG_CURSOR
213       qDebug("onEnterViewPort() : Qt::CrossCursor");
214 #endif
215     }
216   }
217
218   if (!isNestedCreateOperation(getCurrentOperation()))
219     return;
220
221   operationMgr()->onValidateOperation();
222
223   // we need change displayed state of the current operation feature
224   // if the feature is presentable, e.g. distance construction. It has no results, so workshop does
225   // not accept a signal about the result created. Nothing is shown until mouse is moved out/in view
226   // port. If the isDisplayed flag is true, the presentable feature is displayed as soon as the
227   // presentation becomes valid and redisplay happens
228   //ModuleBase_Operation* aOperation = getCurrentOperation();
229   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
230                                                                            (getCurrentOperation());
231   if (aFOperation) {
232     FeaturePtr aFeature = aFOperation->feature();
233     if (aFeature.get() && aFeature->data()->isValid()) {
234       visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature), false);
235     }
236   }
237 }
238
239 void PartSet_SketcherMgr::onLeaveViewPort()
240 {
241   myIsMouseOverViewProcessed = false;
242   myIsMouseOverWindow = false;
243   // it is important to validate operation here only if sketch entity create operation is active
244   // because at this operation we reacts to the mouse leave/enter view port
245   //operationMgr()->onValidateOperation();
246
247   #ifdef DEBUG_DO_NOT_BY_ENTER
248   return;
249   #endif
250
251   if (canChangeCursor(getCurrentOperation())) {
252     QApplication::restoreOverrideCursor();
253 #ifdef DEBUG_CURSOR
254     qDebug("onLeaveViewPort() : None");
255 #endif
256   }
257
258   if (!isNestedCreateOperation(getCurrentOperation()))
259     return;
260
261   // the method should be performed if the popup menu is called,
262   // the reset of the current widget should not happen
263   if (myIsPopupMenuActive)
264     return;
265
266   operationMgr()->onValidateOperation();
267
268   // 2. if the mouse IS NOT over window, reset the active widget value and hide the presentation
269   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
270   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
271   XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
272   // disable the viewer update in order to avoid visualization of redisplayed feature in viewer
273   // obtained after reset value
274   bool isEnableUpdateViewer = aDisplayer->enableUpdateViewer(false);
275   ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
276   if (anActiveWidget)
277     anActiveWidget->reset();
278
279   // hides the presentation of the current operation feature
280   // the feature is to be erased here, but it is correct to call canDisplayObject because
281   // there can be additional check (e.g. editor widget in distance constraint)
282   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
283                                                                            (getCurrentOperation());
284   if (aFOperation) {
285     FeaturePtr aFeature = aFOperation->feature();
286     visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature));
287   }
288   // we should update viewer after the presentation are hidden in the viewer
289   // otherwise the reset presentation(line) appears in the viewer(by quick move from viewer to PP)
290   aDisplayer->enableUpdateViewer(isEnableUpdateViewer);
291 }
292
293 void PartSet_SketcherMgr::onBeforeValuesChangedInPropertyPanel()
294 {
295   if (!isNestedEditOperation(getCurrentOperation()) ||
296       myModule->sketchReentranceMgr()->isInternalEditActive())
297     return;
298   // it is necessary to save current selection in order to restore it after the values are modifed
299   storeSelection();
300
301   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
302   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
303   XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
304   myPreviousUpdateViewerEnabled = aDisplayer->enableUpdateViewer(false);
305 }
306
307 void PartSet_SketcherMgr::onAfterValuesChangedInPropertyPanel()
308 {
309   if (!isNestedEditOperation(getCurrentOperation()) ||
310       myModule->sketchReentranceMgr()->isInternalEditActive())
311     return;
312   // it is necessary to restore current selection in order to restore it after the values are modified
313   restoreSelection();
314   myCurrentSelection.clear();
315
316   // 3. the flag to disable the update viewer should be set in order to avoid blinking in the 
317   // viewer happens by deselect/select the modified objects. The flag should be restored after
318   // the selection processing. The update viewer should be also called.
319   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
320   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
321   XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
322   aDisplayer->enableUpdateViewer(myPreviousUpdateViewerEnabled);
323   aDisplayer->updateViewer();
324 }
325
326 void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
327 {
328   if (myModule->sketchReentranceMgr()->processMousePressed(theWnd, theEvent))
329     return;
330
331   //get2dPoint(theWnd, theEvent, myClickedPoint);
332
333   if (!(theEvent->buttons() & Qt::LeftButton))
334     return;
335
336   // Clear dragging mode
337   myIsDragging = false;
338
339   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
340   ModuleBase_IViewer* aViewer = aWorkshop->viewer();
341   if (!aViewer->canDragByMouse())
342     return;
343
344   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
345                                                                (getCurrentOperation());
346   if (!aFOperation)
347     return;
348
349   if (aFOperation->isEditOperation()) {
350     // If the current widget is a selector, do nothing, it processes the mouse press
351     ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
352     if(anActiveWidget && anActiveWidget->isViewerSelector()) {
353       return;
354     }
355   }
356
357   // Use only for sketch operations
358   if (myCurrentSketch) {
359     if (!PartSet_Tools::sketchPlane(myCurrentSketch))
360       return;
361
362     bool isSketcher = isSketchOperation(aFOperation);
363     bool isSketchOpe = isNestedSketchOperation(aFOperation);
364
365     // Avoid non-sketch operations
366     if ((!isSketchOpe) && (!isSketcher))
367       return;
368
369     bool isEditing = aFOperation->isEditOperation();
370
371     // Ignore creation sketch operation
372     if ((!isSketcher) && (!isEditing))
373       return;
374
375     Handle(AIS_InteractiveContext) aContext = aViewer->AISContext();
376     if (!aContext.IsNull()) {
377       // MoveTo in order to highlight current object
378       aContext->MoveTo(theEvent->x(), theEvent->y(), theWnd->v3dView());
379     }
380     // Remember highlighted objects for editing
381     ModuleBase_ISelection* aSelect = aWorkshop->selection();
382
383     bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
384     storeSelection(!aHasShift);
385
386     if (myCurrentSelection.empty()) {
387       if (isSketchOpe && (!isSketcher))
388         // commit previous operation
389         if (!aFOperation->commit())
390           aFOperation->abort();
391       return;
392     }
393     // Init flyout point for radius rotation
394     FeaturePtr aFeature = myCurrentSelection.begin().key();
395
396     if (isSketcher) {
397       myIsDragging = true;
398       get2dPoint(theWnd, theEvent, myCurrentPoint);
399       myDragDone = false;
400
401       myPreviousDrawModeEnabled = aViewer->enableDrawMode(false);
402       launchEditing();
403       if (aFeature.get() != NULL) {
404         std::shared_ptr<SketchPlugin_Feature> aSPFeature = 
405                   std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
406       if (aSPFeature.get() && aSPFeature->getKind() == SketchPlugin_ConstraintRadius::ID()) {
407           DataPtr aData = aSPFeature->data();
408           AttributePtr aAttr = aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT());
409           std::shared_ptr<GeomDataAPI_Point2D> aFPAttr = 
410             std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aAttr);
411           aFPAttr->setValue(myCurrentPoint.myCurX, myCurrentPoint.myCurY);
412         }
413       }
414     } else if (isSketchOpe && isEditing) {
415       // If selected another object commit current result
416       aFOperation->commit();
417
418       myIsDragging = true;
419       get2dPoint(theWnd, theEvent, myCurrentPoint);
420       myDragDone = false;
421
422       myPreviousDrawModeEnabled = aViewer->enableDrawMode(false);
423
424       // this is temporary commented in order to avoid the following wrong case:
425       // Distance constraint is under edition, double click on the digit -> nothing happens
426       // because QApplication::processEvents() calls onMouseDoubleClick, which try to show editor
427       // but as the prev edit is commited an new one is not started, editor is not shown.
428       // This is necessary in order to finalize previous operation
429       //QApplication::processEvents();
430       launchEditing();
431     }
432   }
433 }
434
435 void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
436 {
437   if (myModule->sketchReentranceMgr()->processMouseReleased(theWnd, theEvent))
438     return;
439
440   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
441   ModuleBase_IViewer* aViewer = aWorkshop->viewer();
442   if (!aViewer->canDragByMouse())
443     return;
444   ModuleBase_Operation* aOp = getCurrentOperation();
445   if (aOp) {
446     if (isNestedSketchOperation(aOp)) {
447       //get2dPoint(theWnd, theEvent, myClickedPoint);
448
449       // Only for sketcher operations
450       if (myIsDragging) {
451         if (myDragDone) {
452           //aOp->commit();
453           myCurrentSelection.clear();
454           /*Handle(AIS_InteractiveContext) aContext = aViewer->AISContext();
455           if (!aContext.IsNull()) {
456           // Reselect edited object
457           aContext->MoveTo(theEvent->x(), theEvent->y(), theWnd->v3dView());
458           if (theEvent->modifiers() & Qt::ShiftModifier)
459             aContext->ShiftSelect();
460           else
461             aContext->Select();
462           */
463         }
464       }
465     }
466   }
467
468   aWorkshop->viewer()->enableDrawMode(myPreviousDrawModeEnabled);
469   myIsDragging = false;
470 }
471
472 void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
473 {
474   if (myModule->sketchReentranceMgr()->processMouseMoved(theWnd, theEvent))
475     return;
476
477   if (isNestedCreateOperation(getCurrentOperation()) && !myIsMouseOverViewProcessed) {
478     myIsMouseOverViewProcessed = true;
479     // 1. perform the widget mouse move functionality and display the presentation
480     // the mouse move should be processed in the widget, if it can in order to visualize correct
481     // presentation. These widgets correct the feature attribute according to the mouse position
482     ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
483     PartSet_WidgetPoint2D* aPoint2DWdg = dynamic_cast<PartSet_WidgetPoint2D*>(anActiveWidget);
484     if (aPoint2DWdg) {
485       aPoint2DWdg->onMouseMove(theWnd, theEvent);
486     }
487     PartSet_WidgetPoint2dDistance* aDistanceWdg = dynamic_cast<PartSet_WidgetPoint2dDistance*>
488                                                                 (anActiveWidget);
489     if (aDistanceWdg) {
490       aDistanceWdg->onMouseMove(theWnd, theEvent);
491     }
492     // the feature is to be erased here, but it is correct to call canDisplayObject because
493     // there can be additional check (e.g. editor widget in distance constraint)
494     ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
495                                                                              (getCurrentOperation());
496     if (aFOperation) {
497       FeaturePtr aFeature = aFOperation->feature();
498       visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature));
499     }
500   }
501
502   //myClickedPoint.clear();
503
504   if (myIsDragging) {
505     // 1. the current selection is saved in the mouse press method in order to restore it after moving
506     // 2. the enable selection in the viewer should be temporary switched off in order to ignore
507     // mouse press signal in the viewer(it call Select for AIS context and the dragged objects are
508     // deselected). This flag should be restored in the slot, processed the mouse release signal.
509
510     ModuleBase_Operation* aCurrentOperation = getCurrentOperation();
511     if (!aCurrentOperation)
512       return;
513     if (isSketchOperation(aCurrentOperation))
514       return; // No edit operation activated
515
516     Handle(V3d_View) aView = theWnd->v3dView();
517     gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);
518     double aX, aY;
519     PartSet_Tools::convertTo2D(aPoint, myCurrentSketch, aView, aX, aY);
520     double dX =  aX - myCurrentPoint.myCurX;
521     double dY =  aY - myCurrentPoint.myCurY;
522
523     ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
524     XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
525     XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
526     // 3. the flag to disable the update viewer should be set in order to avoid blinking in the 
527     // viewer happens by deselect/select the modified objects. The flag should be restored after
528     // the selection processing. The update viewer should be also called.
529     bool isEnableUpdateViewer = aDisplayer->enableUpdateViewer(false);
530
531     static Events_ID aMoveEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED);
532     //static Events_ID aUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
533     FeatureToSelectionMap::const_iterator anIt = myCurrentSelection.begin(),
534                                           aLast = myCurrentSelection.end();
535     // 4. the features and attributes modification(move)
536     bool isModified = false;
537     for (; anIt != aLast; anIt++) {
538       FeaturePtr aFeature = anIt.key();
539
540       std::set<AttributePtr> anAttributes = anIt.value().first;
541       // Process selection by attribute: the priority to the attribute
542       if (!anAttributes.empty()) {
543         std::set<AttributePtr>::const_iterator anAttIt = anAttributes.begin(),
544                                                anAttLast = anAttributes.end();
545         for (; anAttIt != anAttLast; anAttIt++) {
546           AttributePtr anAttr = *anAttIt;
547           if (anAttr.get() == NULL)
548             continue;
549           std::string aAttrId = anAttr->id();
550           DataPtr aData = aFeature->data();
551           if (aData->isValid()) {
552             std::shared_ptr<GeomDataAPI_Point2D> aPoint = 
553               std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(aAttrId));
554             if (aPoint.get() != NULL) {
555               bool isImmutable = aPoint->setImmutable(true);
556               aPoint->move(dX, dY);
557               isModified = true;
558               ModelAPI_EventCreator::get()->sendUpdated(aFeature, aMoveEvent);
559               aPoint->setImmutable(isImmutable);
560             }
561           }
562         }
563       } else {
564         // Process selection by feature
565         std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
566           std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
567         if (aSketchFeature) {
568           aSketchFeature->move(dX, dY);
569           isModified = true;
570           ModelAPI_EventCreator::get()->sendUpdated(aSketchFeature, aMoveEvent);
571         }
572       }
573     }
574     // the modified state of the current operation should be updated if there are features, which
575     // were changed here
576     if (isModified) {
577       aCurrentOperation->onValuesChanged();
578     }
579     Events_Loop::loop()->flush(aMoveEvent); // up all move events - to be processed in the solver
580     //Events_Loop::loop()->flush(aUpdateEvent); // up update events - to redisplay presentations
581
582     // 5. it is necessary to save current selection in order to restore it after the features moving
583     restoreSelection();
584     // 6. restore the update viewer flag and call this update
585     aDisplayer->enableUpdateViewer(isEnableUpdateViewer);
586     aDisplayer->updateViewer();
587
588     myDragDone = true;
589     myCurrentPoint.setValue(aX, aY);
590   }
591 }
592
593 void PartSet_SketcherMgr::onMouseDoubleClick(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
594 {
595   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
596                                                                (getCurrentOperation());
597   if (aFOperation && aFOperation->isEditOperation()) {
598     std::string aId = aFOperation->id().toStdString();
599     if (isDistanceOperation(aFOperation))
600     {
601       // Activate dimension value editing on double click
602       ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel();
603       QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();
604       // Find corresponded widget to activate value editing
605       foreach (ModuleBase_ModelWidget* aWgt, aWidgets) {
606         if (aWgt->attributeID() == "ConstraintValue") {
607           PartSet_WidgetEditor* anEditor = dynamic_cast<PartSet_WidgetEditor*>(aWgt);
608           if (anEditor)
609             anEditor->showPopupEditor();
610           return;
611         }
612       }
613     }
614   }
615 }
616
617 void PartSet_SketcherMgr::onApplicationStarted()
618 {
619   ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();
620   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(anIWorkshop);
621   XGUI_Workshop* aWorkshop = aConnector->workshop();
622   PartSet_SketcherReetntrantMgr* aReentranceMgr = myModule->sketchReentranceMgr();
623
624   XGUI_PropertyPanel* aPropertyPanel = aWorkshop->propertyPanel();
625   if (aPropertyPanel) {
626     //connect(aPropertyPanel, SIGNAL(beforeWidgetActivated(ModuleBase_ModelWidget*)),
627     //        this, SLOT(onBeforeWidgetActivated(ModuleBase_ModelWidget*)));
628
629     connect(aPropertyPanel, SIGNAL(noMoreWidgets(const std::string&)),
630             aReentranceMgr, SLOT(onNoMoreWidgets(const std::string&)));
631     connect(aPropertyPanel, SIGNAL(widgetActivated(ModuleBase_ModelWidget*)),
632             aReentranceMgr, SLOT(onWidgetActivated()));
633   }
634
635   XGUI_ViewerProxy* aViewerProxy = aWorkshop->viewer();
636   connect(aViewerProxy, SIGNAL(enterViewPort()), this, SLOT(onEnterViewPort()));
637   connect(aViewerProxy, SIGNAL(leaveViewPort()), this, SLOT(onLeaveViewPort()));
638
639   XGUI_ContextMenuMgr* aContextMenuMgr = aWorkshop->contextMenuMgr();
640   connect(aContextMenuMgr, SIGNAL(beforeContextMenu()), this, SLOT(onBeforeContextMenu()));
641   connect(aContextMenuMgr, SIGNAL(afterContextMenu()), this, SLOT(onAfterContextMenu()));
642 }
643
644 //void PartSet_SketcherMgr::onBeforeWidgetActivated(ModuleBase_ModelWidget* theWidget)
645 //{
646   //if (!myClickedPoint.myIsInitialized)
647   //  return;
648
649   //ModuleBase_Operation* aOperation = getCurrentOperation();
650   // the distance constraint feature should not use the clickedd point
651   // this is workaround in order to don't throw down the flyout point value,
652   // set by execute() method of these type of features
653   //if (isDistanceOperation(aOperation))
654   //  return;
655
656   //PartSet_WidgetPoint2D* aPnt2dWgt = dynamic_cast<PartSet_WidgetPoint2D*>(theWidget);
657   //if (aPnt2dWgt) {
658   //  aPnt2dWgt->setPoint(myClickedPoint.myCurX, myClickedPoint.myCurY);
659   //}
660 //}
661
662 void PartSet_SketcherMgr::onBeforeContextMenu()
663 {
664   myIsPopupMenuActive = true;
665 }
666
667 void PartSet_SketcherMgr::onAfterContextMenu()
668 {
669   myIsPopupMenuActive = false;
670 }
671
672 void PartSet_SketcherMgr::get2dPoint(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent, 
673                                      Point& thePoint)
674 {
675   Handle(V3d_View) aView = theWnd->v3dView();
676   gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);
677   double aX, anY;
678   PartSet_Tools::convertTo2D(aPoint, myCurrentSketch, aView, aX, anY);
679   thePoint.setValue(aX, anY);
680 }
681
682 void PartSet_SketcherMgr::launchEditing()
683 {
684   if (!myCurrentSelection.empty()) {
685     FeaturePtr aFeature = myCurrentSelection.begin().key();
686     std::shared_ptr<SketchPlugin_Feature> aSPFeature = 
687               std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
688     if (aSPFeature) {
689       myModule->editFeature(aSPFeature);
690     }
691   }
692 }
693
694 bool PartSet_SketcherMgr::sketchSolverError()
695 {
696   bool anError = false;
697   CompositeFeaturePtr aSketch = activeSketch();
698   if (aSketch.get()) {
699     AttributeStringPtr aAttributeString = aSketch->string(SketchPlugin_Sketch::SOLVER_ERROR());
700     anError = !aAttributeString->value().empty();
701   }
702   return anError;
703 }
704
705 QString PartSet_SketcherMgr::getFeatureError(const FeaturePtr& theFeature)
706 {
707   QString anError = "";
708   if (!theFeature.get() || !theFeature->data()->isValid())
709     return anError;
710
711   CompositeFeaturePtr aSketch = activeSketch();
712   if (aSketch.get() && aSketch == theFeature) {
713     AttributeStringPtr aAttributeString = aSketch->string(SketchPlugin_Sketch::SOLVER_ERROR());
714     anError = aAttributeString->value().c_str();
715   }
716   return anError;
717 }
718
719 void PartSet_SketcherMgr::clearClickedFlags()
720 {
721   //myClickedPoint.clear();
722   myCurrentPoint.clear();
723 }
724
725 const QStringList& PartSet_SketcherMgr::sketchOperationIdList()
726 {
727   static QStringList aIds;
728   if (aIds.size() == 0) {
729     aIds << SketchPlugin_Line::ID().c_str();
730     aIds << SketchPlugin_Point::ID().c_str();
731     aIds << SketchPlugin_Arc::ID().c_str();
732     aIds << SketchPlugin_Circle::ID().c_str();
733     aIds << SketchPlugin_ConstraintFillet::ID().c_str();
734     aIds.append(constraintsIdList());
735   }
736   return aIds;
737 }
738
739 const QStringList& PartSet_SketcherMgr::constraintsIdList()
740 {
741   static QStringList aIds;
742   if (aIds.size() == 0) {
743     aIds << SketchPlugin_ConstraintLength::ID().c_str();
744     aIds << SketchPlugin_ConstraintDistance::ID().c_str();
745     aIds << SketchPlugin_ConstraintRigid::ID().c_str();
746     aIds << SketchPlugin_ConstraintRadius::ID().c_str();
747     aIds << SketchPlugin_ConstraintPerpendicular::ID().c_str();
748     aIds << SketchPlugin_ConstraintParallel::ID().c_str();
749     aIds << SketchPlugin_ConstraintHorizontal::ID().c_str();
750     aIds << SketchPlugin_ConstraintVertical::ID().c_str();
751     aIds << SketchPlugin_ConstraintEqual::ID().c_str();
752     aIds << SketchPlugin_ConstraintTangent::ID().c_str();
753     aIds << SketchPlugin_ConstraintCoincidence::ID().c_str();
754     aIds << SketchPlugin_ConstraintMirror::ID().c_str();
755     aIds << SketchPlugin_ConstraintAngle::ID().c_str();
756     aIds << SketchPlugin_MultiRotation::ID().c_str();
757     aIds << SketchPlugin_MultiTranslation::ID().c_str();
758   }
759   return aIds;
760 }
761
762 void PartSet_SketcherMgr::sketchSelectionModes(QIntList& theModes)
763 {
764   theModes.clear();
765
766   theModes.append(SketcherPrs_Tools::Sel_Dimension_Text);
767   theModes.append(SketcherPrs_Tools::Sel_Dimension_Line);
768   theModes.append(SketcherPrs_Tools::Sel_Constraint);
769   theModes.append(TopAbs_VERTEX);
770   theModes.append(TopAbs_EDGE);
771 }
772
773 bool PartSet_SketcherMgr::isSketchOperation(ModuleBase_Operation* theOperation)
774 {
775   return theOperation && theOperation->id().toStdString() == SketchPlugin_Sketch::ID();
776 }
777
778 bool PartSet_SketcherMgr::isNestedSketchOperation(ModuleBase_Operation* theOperation)
779 {
780   return theOperation &&
781          PartSet_SketcherMgr::sketchOperationIdList().contains(theOperation->id());
782 }
783
784 bool PartSet_SketcherMgr::isNestedCreateOperation(ModuleBase_Operation* theOperation)
785 {
786   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
787                                                                (theOperation);
788   return aFOperation && !aFOperation->isEditOperation() && isNestedSketchOperation(aFOperation);
789 }
790
791 bool PartSet_SketcherMgr::isNestedEditOperation(ModuleBase_Operation* theOperation)
792 {
793   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
794                                                                (theOperation);
795   return aFOperation && aFOperation->isEditOperation() && isNestedSketchOperation(aFOperation);
796 }
797
798 bool PartSet_SketcherMgr::isEntity(const std::string& theId)
799 {
800   return (theId == SketchPlugin_Line::ID()) ||
801          (theId == SketchPlugin_Point::ID()) ||
802          (theId == SketchPlugin_Arc::ID()) ||
803          (theId == SketchPlugin_Circle::ID());
804 }
805
806 bool PartSet_SketcherMgr::isDistanceOperation(ModuleBase_Operation* theOperation)
807 {
808   std::string anId = theOperation ? theOperation->id().toStdString() : "";
809
810   return isDistanceKind(anId);
811 }
812
813 bool PartSet_SketcherMgr::isDistanceKind(std::string& theKind)
814 {
815   return (theKind == SketchPlugin_ConstraintLength::ID()) ||
816          (theKind == SketchPlugin_ConstraintDistance::ID()) ||
817          (theKind == SketchPlugin_ConstraintRadius::ID()) ||
818          (theKind == SketchPlugin_ConstraintAngle::ID());
819 }
820
821 void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
822 {
823   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
824                                                                (getCurrentOperation());
825   if (!aFOperation)
826     return;
827
828   myModule->onViewTransformed();
829
830   // Display all sketcher sub-Objects
831   myCurrentSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFOperation->feature());
832   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
833   aConnector->workshop()->displayer()->activateTrihedron(true);
834
835   // Hide sketcher result
836   std::list<ResultPtr> aResults = myCurrentSketch->results();
837   std::list<ResultPtr>::const_iterator aIt;
838   for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
839     (*aIt)->setDisplayed(false);
840   }
841   myCurrentSketch->setDisplayed(false);
842
843   // Display sketcher objects
844   for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {
845     FeaturePtr aFeature = myCurrentSketch->subFeature(i);
846     std::list<ResultPtr> aResults = aFeature->results();
847     std::list<ResultPtr>::const_iterator aIt;
848     for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
849       (*aIt)->setDisplayed(true);
850     }
851     aFeature->setDisplayed(true);
852   }
853
854   if (myPlaneFilter.IsNull()) 
855     myPlaneFilter = new ModuleBase_ShapeInPlaneFilter();
856
857   myModule->workshop()->viewer()->addSelectionFilter(myPlaneFilter);
858
859   bool aHasPlane = false;
860   std::shared_ptr<GeomAPI_Pln> aPln;
861   if (aFOperation->isEditOperation()) {
862     // If it is editing of sketch then it means that plane is already defined
863     aPln = PartSet_Tools::sketchPlane(myCurrentSketch);
864     if (aPln.get())
865       aHasPlane = true;
866   }
867   myPlaneFilter->setPlane(aPln);
868
869   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
870   // all sketch objects should be activated in the sketch selection modes by edit operation start
871   // in case of creation operation, there is an active widget, which activates own selection mode
872   if (aFOperation->isEditOperation() && aHasPlane)
873     aConnector->activateModuleSelectionModes();
874 }
875
876 void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
877 {
878   myIsMouseOverWindow = false;
879   myIsConstraintsShown[PartSet_Tools::Geometrical] = true;
880   myIsConstraintsShown[PartSet_Tools::Dimensional] = true;
881
882   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
883
884   DataPtr aData = myCurrentSketch->data();
885   if (!aData->isValid()) {
886     XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
887     // The sketch was aborted
888     myCurrentSketch = CompositeFeaturePtr();
889     myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter);
890
891     // Erase all sketcher objects
892     QStringList aSketchIds = sketchOperationIdList();
893     QObjectPtrList aObjects = aDisplayer->displayedObjects();
894     foreach (ObjectPtr aObj, aObjects) {
895       DataPtr aObjData = aObj->data();
896       if (!aObjData->isValid())
897         aObj->setDisplayed(false);
898     }
899   }
900   else {
901     // Hide all sketcher sub-Objects
902     for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {
903       FeaturePtr aFeature = myCurrentSketch->subFeature(i);
904       std::list<ResultPtr> aResults = aFeature->results();
905       std::list<ResultPtr>::const_iterator aIt;
906       for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
907         (*aIt)->setDisplayed(false);
908       }
909       aFeature->setDisplayed(false);
910     }
911     // Display sketcher result
912     std::list<ResultPtr> aResults = myCurrentSketch->results();
913     std::list<ResultPtr>::const_iterator aIt;
914     Events_Loop* aLoop = Events_Loop::loop();
915     static Events_ID aDispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
916
917     ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
918                                                                            (theOperation);
919     for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
920       if (!aFOperation->isDisplayedOnStart(*aIt)) {
921         (*aIt)->setDisplayed(true);
922         // this display event is needed because sketch already may have "displayed" state,
923         // but not displayed while it is still active (issue 613, abort of existing sketch)
924         ModelAPI_EventCreator::get()->sendUpdated(*aIt, aDispEvent);
925       }
926     }
927     if (!aFOperation->isDisplayedOnStart(myCurrentSketch))
928       myCurrentSketch->setDisplayed(true);
929     
930     myCurrentSketch = CompositeFeaturePtr();
931     myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter);
932
933     Events_Loop::loop()->flush(aDispEvent);
934   }
935   // restore the module selection modes, which were changed on startSketch
936   aConnector->activateModuleSelectionModes();
937   aConnector->workshop()->displayer()->activateTrihedron(false);
938 }
939
940 void PartSet_SketcherMgr::startNestedSketch(ModuleBase_Operation* theOperation)
941 {
942   if (canChangeCursor(theOperation) && myIsMouseOverWindow) {
943     QCursor* aCurrentCursor = QApplication::overrideCursor();
944     if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) {
945       QApplication::setOverrideCursor(QCursor(Qt::CrossCursor));
946 #ifdef DEBUG_CURSOR
947       qDebug("startNestedSketch() : Qt::CrossCursor");
948 #endif
949     }
950   }
951 }
952
953 void PartSet_SketcherMgr::stopNestedSketch(ModuleBase_Operation* theOperation)
954 {
955   myIsMouseOverViewProcessed = true;
956   operationMgr()->onValidateOperation();
957   if (canChangeCursor(theOperation)) {
958     QApplication::restoreOverrideCursor();
959 #ifdef DEBUG_CURSOR
960     qDebug("stopNestedSketch() : None");
961 #endif
962   }
963 }
964
965 void PartSet_SketcherMgr::commitNestedSketch(ModuleBase_Operation* theOperation)
966 {
967   if (isNestedCreateOperation(theOperation)) {
968     ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
969                                                                              (theOperation);
970     if (aFOperation) {
971       FeaturePtr aFeature = aFOperation->feature();
972       // it is necessary to check the the feature data validity because
973       // some kind of features are removed by an operation commit(the macro state of a feature)
974       if (aFeature.get() && aFeature->data()->isValid()) {
975         visualizeFeature(aFeature, aFOperation->isEditOperation(), true);
976       }
977     }
978   }
979 }
980
981 void PartSet_SketcherMgr::operationActivatedByPreselection()
982 {
983   ModuleBase_Operation* anOperation = getCurrentOperation();
984   if(anOperation && PartSet_SketcherMgr::isNestedSketchOperation(anOperation)) {
985     // Set final definitions if they are necessary
986     //propertyPanelDefined(aOperation);
987     /// Commit sketcher operations automatically
988     ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
989                                                                             (anOperation);
990     if (aFOperation) {
991       if (PartSet_SketcherMgr::isDistanceOperation(aFOperation)) {
992         FeaturePtr aFeature = aFOperation->feature();
993         // editor is shown only if all attribute references are filled by preseletion
994         bool anAllRefAttrInitialized = true;
995
996         std::list<AttributePtr> aRefAttrs = aFeature->data()->attributes(
997                                                     ModelAPI_AttributeRefAttr::typeId());
998         std::list<AttributePtr>::const_iterator anIt = aRefAttrs.begin(), aLast = aRefAttrs.end();
999         for (; anIt != aLast && anAllRefAttrInitialized; anIt++) {
1000           anAllRefAttrInitialized = (*anIt)->isInitialized();
1001         }
1002         if (anAllRefAttrInitialized) {
1003           // Activate dimension value editing on double click
1004           ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel();
1005           QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();
1006           // Find corresponded widget to activate value editing
1007           foreach (ModuleBase_ModelWidget* aWgt, aWidgets) {
1008             if (aWgt->attributeID() == "ConstraintValue") {
1009               // the featue should be displayed in order to find the AIS text position,
1010               // the place where the editor will be shown
1011               aFeature->setDisplayed(true);
1012               /// the execute is necessary to perform in the feature compute for flyout position
1013               aFeature->execute();
1014
1015               Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
1016               Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
1017
1018               PartSet_WidgetEditor* anEditor = dynamic_cast<PartSet_WidgetEditor*>(aWgt);
1019               if (anEditor) {
1020                 int aX = 0, anY = 0;
1021
1022                 ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
1023                 XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
1024                 XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
1025                 AISObjectPtr anAIS = aDisplayer->getAISObject(aFeature);
1026                 Handle(AIS_InteractiveObject) anAISIO;
1027                 if (anAIS.get() != NULL) {
1028                   anAISIO = anAIS->impl<Handle(AIS_InteractiveObject)>();
1029                 }
1030                 if (anAIS.get() != NULL) {
1031                   Handle(AIS_InteractiveObject) anAISIO = anAIS->impl<Handle(AIS_InteractiveObject)>();
1032
1033                   if (!anAISIO.IsNull()) {
1034                     Handle(AIS_Dimension) aDim = Handle(AIS_Dimension)::DownCast(anAISIO);
1035                     if (!aDim.IsNull()) {
1036                       gp_Pnt aPosition = aDim->GetTextPosition();
1037
1038                       ModuleBase_IViewer* aViewer = aWorkshop->viewer();
1039                       Handle(V3d_View) aView = aViewer->activeView();
1040                       int aCX, aCY;
1041                       aView->Convert(aPosition.X(), aPosition.Y(), aPosition.Z(), aCX, aCY);
1042
1043                       QWidget* aViewPort = aViewer->activeViewPort();
1044                       QPoint aGlPoint = aViewPort->mapToGlobal(QPoint(aCX, aCY));
1045                       aX = aGlPoint.x();
1046                       anY = aGlPoint.y();
1047                     }
1048                   }
1049                   anEditor->setCursorPosition(aX, anY);
1050                   anEditor->showPopupEditor(false);
1051                 }
1052               }
1053             }
1054           }
1055         }
1056       }
1057     }
1058     anOperation->commit();
1059   }
1060 }
1061
1062 bool PartSet_SketcherMgr::canUndo() const
1063 {
1064   return isNestedCreateOperation(getCurrentOperation());
1065 }
1066
1067 bool PartSet_SketcherMgr::canRedo() const
1068 {
1069   return isNestedCreateOperation(getCurrentOperation());
1070 }
1071
1072 bool PartSet_SketcherMgr::canEraseObject(const ObjectPtr& theObject) const
1073 {
1074   bool aCanErase = true;
1075   // when the sketch operation is active, results of sketch sub-feature can not be hidden
1076   if (myCurrentSketch.get()) {
1077     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
1078     if (aResult.get()) {
1079       // Display sketcher objects
1080       for (int i = 0; i < myCurrentSketch->numberOfSubs() && aCanErase; i++) {
1081
1082         FeaturePtr aFeature = myCurrentSketch->subFeature(i);
1083         std::list<ResultPtr> aResults = aFeature->results();
1084         std::list<ResultPtr>::const_iterator anIt;
1085         for (anIt = aResults.begin(); anIt != aResults.end() && aCanErase; ++anIt) {
1086           aCanErase = *anIt != aResult;
1087         }
1088       }
1089     }
1090   }
1091   return aCanErase;
1092 }
1093
1094 bool PartSet_SketcherMgr::canDisplayObject(const ObjectPtr& theObject) const
1095 {
1096   bool aCanDisplay = true;
1097
1098   bool aHasActiveSketch = activeSketch().get() != NULL;
1099   if (aHasActiveSketch) {
1100     // 1. the sketch feature should not be displayed during the sketch active operation
1101     // it is hidden by a sketch operation start and shown by a sketch stop, just the sketch 
1102     // nested features can be visualized
1103     FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
1104     if (aFeature.get() != NULL && aFeature == activeSketch()) {
1105       aCanDisplay = false;
1106     }
1107   }
1108   else { // there are no an active sketch
1109     // 2. sketch sub-features should not be visualized if the sketch operation is not active
1110     FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
1111     if (aFeature.get() != NULL) {
1112       std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
1113                               std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
1114       if (aSketchFeature.get()) {
1115         aCanDisplay = false;
1116       }
1117     }
1118   }
1119
1120   // 3. the method should not filter the objects, which are not related to the current operation.
1121   // The object is filtered just if it is a current operation feature or this feature result
1122   bool isObjectFound = false;
1123   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
1124                                                                (getCurrentOperation());
1125   if (aFOperation) {
1126     FeaturePtr aFeature = aFOperation->feature();
1127     if (aFeature.get()) {
1128       std::list<ResultPtr> aResults = aFeature->results();
1129       if (theObject == aFeature)
1130         isObjectFound = true;
1131       else {
1132         std::list<ResultPtr>::const_iterator anIt = aResults.begin(), aLast = aResults.end();
1133         for (; anIt != aLast && !isObjectFound; anIt++) {
1134           isObjectFound = *anIt == theObject;
1135         }
1136       }
1137     }
1138   }
1139   if (!isObjectFound) 
1140     return aCanDisplay;
1141   
1142   // 4. For created nested feature operation do not display the created feature if
1143   // the mouse curstor leaves the OCC window.
1144   // The correction cases, which ignores this condition:
1145   // a. the property panel values modification
1146   // b. the popup menu activated
1147   // c. widget editor control
1148   #ifndef DEBUG_DO_NOT_BY_ENTER
1149   if (aCanDisplay && isNestedCreateOperation(getCurrentOperation())) {
1150     ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
1151     ModuleBase_WidgetEditor* anEditorWdg = anActiveWidget ? dynamic_cast<ModuleBase_WidgetEditor*>(anActiveWidget) : 0;
1152     // the active widget editor should not influence here. The presentation should be visible always
1153     // when this widget is active.
1154     if (!anEditorWdg && !myIsPopupMenuActive) {
1155       // during a nested create operation, the feature is redisplayed only if the mouse over view
1156       // of there was a value modified in the property panel after the mouse left the view
1157       aCanDisplay = canDisplayCurrentCreatedFeature();
1158     }
1159   }
1160   #endif
1161   return aCanDisplay;
1162 }
1163
1164 void PartSet_SketcherMgr::processHiddenObject(const std::list<ObjectPtr>& theObjects)
1165 {
1166   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
1167                                                                            (getCurrentOperation());
1168   if (aFOperation && myCurrentSketch.get()) {
1169     // find results of the current operation
1170     // these results should not be proposed to be deleted
1171     FeaturePtr anOperationFeature = aFOperation->feature();
1172     std::list<ResultPtr> anOperationResultList = anOperationFeature->results();
1173     std::set<ResultPtr> anOperationResults;
1174     std::list<ResultPtr>::const_iterator aRIt = anOperationResultList.begin(),
1175                                         aRLast = anOperationResultList.end();
1176     for (; aRIt != aRLast; aRIt++)
1177       anOperationResults.insert(*aRIt);
1178
1179     std::set<FeaturePtr> anObjectsToBeDeleted;
1180     QStringList anObjectsToBeDeletedNames;
1181     std::list<ObjectPtr>::const_iterator anIt = theObjects.begin(), aLast = theObjects.end();
1182     for (; anIt != aLast; anIt++) {
1183       ObjectPtr anObject = *anIt;
1184       bool aCanErase = true;
1185       // when the sketch operation is active, results of sketch sub-feature can not be hidden
1186       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
1187       // the result is found between current feature results
1188       if (anOperationResults.find(aResult) != anOperationResults.end())
1189         continue;
1190
1191       if (aResult.get()) {
1192         // Display sketcher objects
1193         for (int i = 0; i < myCurrentSketch->numberOfSubs() && aCanErase; i++) {
1194           FeaturePtr aFeature = myCurrentSketch->subFeature(i);
1195           std::list<ResultPtr> aResults = aFeature->results();
1196           std::list<ResultPtr>::const_iterator anIt;
1197           for (anIt = aResults.begin(); anIt != aResults.end() && aCanErase; ++anIt) {
1198             aCanErase = *anIt != aResult;
1199           }
1200         }
1201       }
1202       if (!aCanErase) {
1203         FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
1204         if (aFeature.get() && anObjectsToBeDeleted.find(aFeature) == anObjectsToBeDeleted.end()) {
1205           anObjectsToBeDeleted.insert(aFeature);
1206           anObjectsToBeDeletedNames.append(aFeature->name().c_str());
1207         }
1208       }
1209     }
1210     if (!anObjectsToBeDeleted.empty()) {
1211       QString aFeatureNames = anObjectsToBeDeletedNames.join(", ");
1212       QString aMessage = tr("The following features have incorrect presentation and \
1213 will be hidden: %1. Would you like to delete them?")
1214                          .arg(aFeatureNames);
1215       int anAnswer = QMessageBox::question(qApp->activeWindow(), tr("Features hide"),
1216                                            aMessage, QMessageBox::Ok | QMessageBox::Cancel,
1217                                            QMessageBox::Cancel);
1218       if (anAnswer == QMessageBox::Ok) {
1219         QObjectPtrList anObjects;
1220         std::set<FeaturePtr>::const_iterator anIt = anObjectsToBeDeleted.begin(),
1221                                              aLast = anObjectsToBeDeleted.end();
1222         for (; anIt != aLast; anIt++)
1223           anObjects.append(*anIt);
1224         SessionPtr aMgr = ModelAPI_Session::get();
1225         DocumentPtr aDoc = aMgr->activeDocument();
1226         bool aIsOp = aMgr->isOperation();
1227         if (!aIsOp)
1228           aMgr->startOperation();
1229         workshop()->deleteFeatures(anObjects);
1230         //static Events_ID aDeletedEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
1231         //static Events_ID aRedispEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
1232         //Events_Loop::loop()->flush(aDeletedEvent);
1233         //Events_Loop::loop()->flush(aRedispEvent);
1234
1235         if (!aIsOp)
1236           aMgr->finishOperation();
1237       }
1238     }
1239   }
1240 }
1241
1242 bool PartSet_SketcherMgr::canDisplayCurrentCreatedFeature() const
1243 {
1244   bool aCanDisplay = myIsMouseOverWindow;
1245   if (!aCanDisplay) {
1246     ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
1247     if (anActiveWidget)
1248       aCanDisplay = anActiveWidget->getValueState() == ModuleBase_ModelWidget::Stored;
1249   }
1250   return aCanDisplay;
1251 }
1252
1253 bool PartSet_SketcherMgr::canChangeCursor(ModuleBase_Operation* theOperation) const
1254 {
1255   return isNestedCreateOperation(theOperation) ||
1256          myModule->sketchReentranceMgr()->isInternalEditActive();
1257 }
1258
1259 const QMap<PartSet_Tools::ConstraintVisibleState, bool>& PartSet_SketcherMgr::showConstraintStates()
1260 {
1261   return myIsConstraintsShown;
1262 }
1263
1264 bool PartSet_SketcherMgr::isObjectOfSketch(const ObjectPtr& theObject) const
1265 {
1266   bool isFoundObject = false;
1267
1268   FeaturePtr anObjectFeature = ModelAPI_Feature::feature(theObject);
1269   if (anObjectFeature.get()) {
1270     int aSize = myCurrentSketch->numberOfSubs();
1271     for (int i = 0; i < myCurrentSketch->numberOfSubs() && !isFoundObject; i++) {
1272       FeaturePtr aCurrentFeature = myCurrentSketch->subFeature(i);
1273       isFoundObject = myCurrentSketch->subFeature(i) == anObjectFeature;
1274     }
1275   }
1276   return isFoundObject;
1277 }
1278
1279 void PartSet_SketcherMgr::onPlaneSelected(const std::shared_ptr<GeomAPI_Pln>& thePln)
1280 {
1281   if (myPlaneFilter.IsNull()) 
1282    myPlaneFilter = new ModuleBase_ShapeInPlaneFilter();
1283
1284   myPlaneFilter->setPlane(thePln);
1285 }
1286
1287 void PartSet_SketcherMgr::getCurrentSelection(const FeaturePtr& theFeature,
1288                                               const FeaturePtr& theSketch,
1289                                               ModuleBase_IWorkshop* theWorkshop,
1290                                               FeatureToSelectionMap& theSelection)
1291 {
1292   if (theFeature.get() == NULL)
1293     return;
1294
1295   std::set<AttributePtr> aSelectedAttributes;
1296   std::set<ResultPtr> aSelectedResults;
1297
1298   ModuleBase_IViewer* aViewer = theWorkshop->viewer();
1299   Handle(AIS_InteractiveContext) aContext = aViewer->AISContext();
1300   if (!aContext.IsNull()) {
1301     XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWorkshop);
1302     XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
1303
1304     std::list<ResultPtr> aResults = theFeature->results();
1305     std::list<ResultPtr>::const_iterator aIt;
1306     for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt)
1307     {
1308       ResultPtr aResult = *aIt;
1309       AISObjectPtr aAISObj = aDisplayer->getAISObject(aResult);
1310       if (aAISObj.get() == NULL)
1311         continue;
1312       Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
1313       for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected())
1314       {
1315         Handle(SelectMgr_EntityOwner) anOwner = aContext->SelectedOwner();
1316         if (anOwner->Selectable() != anAISIO)
1317           continue;
1318         getAttributesOrResults(anOwner, theFeature, theSketch, aResult,
1319                                aSelectedAttributes, aSelectedResults);
1320       }
1321       for (aContext->InitDetected(); aContext->MoreDetected(); aContext->NextDetected()) {
1322         Handle(SelectMgr_EntityOwner) anOwner = aContext->DetectedOwner();
1323         if (anOwner.IsNull())
1324           continue;
1325         if (anOwner->Selectable() != anAISIO)
1326           continue;
1327         getAttributesOrResults(anOwner, theFeature, theSketch, aResult,
1328                                aSelectedAttributes, aSelectedResults);
1329       }
1330     }
1331   }
1332   theSelection[theFeature] = std::make_pair(aSelectedAttributes, aSelectedResults);
1333 }
1334
1335 void PartSet_SketcherMgr::getSelectionOwners(const FeaturePtr& theFeature,
1336                                              const FeaturePtr& theSketch,
1337                                              ModuleBase_IWorkshop* theWorkshop,
1338                                              const FeatureToSelectionMap& theSelection,
1339                                              SelectMgr_IndexedMapOfOwner& theOwnersToSelect)
1340 {
1341   if (theFeature.get() == NULL)
1342     return;
1343
1344   FeatureToSelectionMap::const_iterator anIt = theSelection.find(theFeature);
1345   std::set<AttributePtr> aSelectedAttributes = anIt.value().first;
1346   std::set<ResultPtr> aSelectedResults = anIt.value().second;
1347
1348   ModuleBase_IViewer* aViewer = theWorkshop->viewer();
1349
1350   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWorkshop);
1351   XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
1352
1353   // 1. found the feature's owners. Check the AIS objects of the constructions
1354   AISObjectPtr aAISObj = aDisplayer->getAISObject(theFeature);
1355   if (aAISObj.get() != NULL && aSelectedAttributes.empty() && aSelectedResults.empty()) {
1356     Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
1357
1358     SelectMgr_IndexedMapOfOwner aSelectedOwners;
1359     aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners);
1360     for  (Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++) {
1361       Handle(SelectMgr_EntityOwner) anOwner = aSelectedOwners(i);
1362       if (!anOwner.IsNull())
1363         theOwnersToSelect.Add(anOwner);
1364     }
1365   }
1366
1367   // 2. found the feature results's owners
1368   std::list<ResultPtr> aResults = theFeature->results();
1369   std::list<ResultPtr>::const_iterator aIt;
1370   for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt)
1371   {
1372     ResultPtr aResult = *aIt;
1373     AISObjectPtr aAISObj = aDisplayer->getAISObject(aResult);
1374     if (aAISObj.get() == NULL)
1375       continue; 
1376     Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
1377
1378     SelectMgr_IndexedMapOfOwner aSelectedOwners;  
1379     aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners);
1380     for  ( Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++ ) {
1381       Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast(aSelectedOwners(i));
1382       if ( anOwner.IsNull() || !anOwner->HasShape() )
1383         continue;
1384       const TopoDS_Shape& aShape = anOwner->Shape();
1385       TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
1386       if (aShapeType == TopAbs_VERTEX) {
1387         AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(theFeature, aShape, theSketch);
1388         if (aPntAttr.get() != NULL &&
1389             aSelectedAttributes.find(aPntAttr) != aSelectedAttributes.end()) {
1390           theOwnersToSelect.Add(anOwner);
1391         }
1392       }
1393       else if (aShapeType == TopAbs_EDGE) {
1394         bool aFound = aSelectedResults.find(aResult) != aSelectedResults.end();
1395         if (aSelectedResults.find(aResult) != aSelectedResults.end() &&
1396             theOwnersToSelect.FindIndex(anOwner) <= 0)
1397           theOwnersToSelect.Add(anOwner);
1398       }
1399     }
1400   }
1401 }
1402
1403 void PartSet_SketcherMgr::connectToPropertyPanel(ModuleBase_ModelWidget* theWidget, const bool isToConnect)
1404 {
1405   if (isToConnect) {
1406     connect(theWidget, SIGNAL(beforeValuesChanged()),
1407             this, SLOT(onBeforeValuesChangedInPropertyPanel()));
1408     connect(theWidget, SIGNAL(afterValuesChanged()),
1409             this, SLOT(onAfterValuesChangedInPropertyPanel()));
1410   }
1411   else {
1412     disconnect(theWidget, SIGNAL(beforeValuesChanged()),
1413                 this, SLOT(onBeforeValuesChangedInPropertyPanel()));
1414     disconnect(theWidget, SIGNAL(afterValuesChanged()),
1415                 this, SLOT(onAfterValuesChangedInPropertyPanel()));
1416   }
1417 }
1418
1419 void PartSet_SketcherMgr::widgetStateChanged(int thePreviousState)
1420 {
1421   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
1422                                                                            (getCurrentOperation());
1423   if (aFOperation) {
1424     if (PartSet_SketcherMgr::isSketchOperation(aFOperation) ||
1425         PartSet_SketcherMgr::isNestedSketchOperation(aFOperation) &&
1426         thePreviousState == ModuleBase_ModelWidget::ModifiedInPP) {
1427       FeaturePtr aFeature = aFOperation->feature();
1428       visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature));
1429     }
1430   }
1431 }
1432
1433 ModuleBase_Operation* PartSet_SketcherMgr::getCurrentOperation() const
1434 {
1435   return myModule->workshop()->currentOperation();
1436 }
1437
1438 //**************************************************************
1439 ModuleBase_ModelWidget* PartSet_SketcherMgr::getActiveWidget() const
1440 {
1441   ModuleBase_ModelWidget* aWidget = 0;
1442   ModuleBase_Operation* anOperation = getCurrentOperation();
1443   if (anOperation) {
1444     ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel();
1445     if (aPanel)
1446       aWidget = aPanel->activeWidget();
1447   }
1448   return aWidget;
1449 }
1450
1451 void PartSet_SketcherMgr::visualizeFeature(const FeaturePtr& theFeature,
1452                                            const bool isEditOperation,
1453                                            const bool isToDisplay,
1454                                            const bool isFlushRedisplay)
1455 {
1456   #ifdef DEBUG_DO_NOT_BY_ENTER
1457   return;
1458   #endif
1459
1460   if (isEditOperation || !theFeature.get())
1461     return;
1462
1463   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
1464   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
1465
1466   // 1. change visibility of the object itself, here the presentable object is processed,
1467   // e.g. constraints features
1468   //FeaturePtr aFeature = aFOperation->feature();
1469   std::list<ResultPtr> aResults = theFeature->results();
1470   if (isToDisplay)
1471     theFeature->setDisplayed(true);
1472   else
1473     theFeature->setDisplayed(false);
1474
1475   // change visibility of the object results, e.g. non-constraint features
1476   std::list<ResultPtr>::const_iterator aIt;
1477   for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
1478     if (isToDisplay) {
1479       (*aIt)->setDisplayed(true);
1480     }
1481     else {
1482       (*aIt)->setDisplayed(false);
1483     }
1484   }
1485   if (isFlushRedisplay)
1486     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
1487 }
1488
1489 void PartSet_SketcherMgr::storeSelection(const bool theHighlightedOnly)
1490 {
1491   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
1492   ModuleBase_ISelection* aSelect = aWorkshop->selection();
1493   QList<ModuleBase_ViewerPrs> aHighlighted = aSelect->getHighlighted();
1494
1495   QList<FeaturePtr> aFeatureList;
1496   if (theHighlightedOnly) {
1497     fillFeatureList(aHighlighted, myCurrentSketch, aFeatureList);
1498   }
1499   else {
1500     fillFeatureList(aHighlighted, myCurrentSketch, aFeatureList);
1501
1502     QList<ModuleBase_ViewerPrs> aSelected = aSelect->getSelected(ModuleBase_ISelection::AllControls);
1503     fillFeatureList(aSelected, myCurrentSketch, aFeatureList);
1504   }
1505
1506   // 1. it is necessary to save current selection in order to restore it after the features moving
1507   myCurrentSelection.clear();
1508   QList<FeaturePtr>::const_iterator anIt = aFeatureList.begin(), aLast = aFeatureList.end();
1509   for (; anIt != aLast; anIt++) {
1510     getCurrentSelection(*anIt, myCurrentSketch, aWorkshop, myCurrentSelection);
1511   }
1512   //qDebug(QString("  storeSelection: %1").arg(myCurrentSelection.size()).toStdString().c_str());
1513 }
1514
1515 void PartSet_SketcherMgr::restoreSelection()
1516 {
1517   //qDebug(QString("restoreSelection: %1").arg(myCurrentSelection.size()).toStdString().c_str());
1518   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
1519   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
1520   FeatureToSelectionMap::const_iterator aSIt = myCurrentSelection.begin(),
1521                                         aSLast = myCurrentSelection.end();
1522   SelectMgr_IndexedMapOfOwner anOwnersToSelect;
1523   for (; aSIt != aSLast; aSIt++) {
1524     anOwnersToSelect.Clear();
1525     getSelectionOwners(aSIt.key(), myCurrentSketch, aWorkshop, myCurrentSelection,
1526                         anOwnersToSelect);
1527     aConnector->workshop()->selector()->setSelectedOwners(anOwnersToSelect, false);
1528   }
1529 }
1530
1531 void PartSet_SketcherMgr::onShowConstraintsToggle(bool theState, int theType)
1532 {
1533   PartSet_Tools::ConstraintVisibleState aType = (PartSet_Tools::ConstraintVisibleState)theType;
1534   if (myIsConstraintsShown.contains(aType) && myIsConstraintsShown[aType] == theState)
1535     return;
1536   if (myCurrentSketch.get() == NULL)
1537     return;
1538
1539   myIsConstraintsShown[aType] = theState;
1540
1541   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
1542   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
1543
1544   const QStringList& aConstrIds = constraintsIdList();
1545   for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {
1546     FeaturePtr aSubFeature = myCurrentSketch->subFeature(i);
1547     std::string aKind = aSubFeature->getKind();
1548     if (aConstrIds.contains(QString(aKind.c_str()))) {
1549       bool isTypedConstraint = false;
1550       if (aType == PartSet_Tools::Dimensional) {
1551         isTypedConstraint = isDistanceKind(aKind);
1552       }
1553       else
1554         isTypedConstraint = !isDistanceKind(aKind);
1555
1556       if (isTypedConstraint) {
1557         if (theState)
1558           aSubFeature->setDisplayed(true);
1559         else
1560           aSubFeature->setDisplayed(false);
1561       }
1562     }
1563   }
1564   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
1565 }
1566
1567 XGUI_Workshop* PartSet_SketcherMgr::workshop() const
1568 {
1569   ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();
1570   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(anIWorkshop);
1571   return aConnector->workshop();
1572 }
1573
1574 XGUI_OperationMgr* PartSet_SketcherMgr::operationMgr() const
1575 {
1576   return workshop()->operationMgr();
1577 }
1578