Salome HOME
Issue #2927: Show/Hide markers on free points
[modules/shaper.git] / src / PartSet / PartSet_SketcherMgr.cpp
1 // Copyright (C) 2014-2019  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "PartSet_SketcherMgr.h"
21
22 #include "PartSet_Filters.h"
23 #include "PartSet_SketcherReentrantMgr.h"
24 #include "PartSet_Module.h"
25 #include "PartSet_MouseProcessor.h"
26 #include "PartSet_Tools.h"
27 #include "PartSet_WidgetSketchLabel.h"
28 #include "PartSet_WidgetEditor.h"
29 #include "PartSet_ResultSketchPrs.h"
30 #include "PartSet_ExternalPointsMgr.h"
31 #include "PartSet_PreviewSketchPlane.h"
32
33 #include <XGUI_ModuleConnector.h>
34 #include <XGUI_Displayer.h>
35 #include <XGUI_Workshop.h>
36 #include <XGUI_ContextMenuMgr.h>
37 #include <XGUI_Selection.h>
38 #include <XGUI_SelectionActivate.h>
39 #include <XGUI_SelectionMgr.h>
40 #include <XGUI_ModuleConnector.h>
41 #include <XGUI_PropertyPanel.h>
42 #include <XGUI_ViewerProxy.h>
43 #include <XGUI_OperationMgr.h>
44 #include <XGUI_ErrorMgr.h>
45 #include <XGUI_Tools.h>
46
47 #include <ModuleBase_IPropertyPanel.h>
48 #include <ModuleBase_ISelection.h>
49 #include <ModuleBase_IViewer.h>
50 #include <ModuleBase_IWorkshop.h>
51 #include <ModuleBase_IViewWindow.h>
52 #include <ModuleBase_ModelWidget.h>
53 #include <ModuleBase_Operation.h>
54 #include <ModuleBase_OperationFeature.h>
55 #include <ModuleBase_Operation.h>
56 #include <ModuleBase_WidgetEditor.h>
57 #include <ModuleBase_ViewerPrs.h>
58 #include <ModuleBase_Tools.h>
59 #include <ModuleBase_ResultPrs.h>
60 #include <ModuleBase_ViewerFilters.h>
61
62 #include <GeomDataAPI_Point2D.h>
63
64 #include <GeomAPI_Shape.h>
65
66 #include <Events_Loop.h>
67
68 #include <SketchPlugin_Line.h>
69 #include <SketchPlugin_Sketch.h>
70 #include <SketchPlugin_Point.h>
71 #include <SketchPlugin_Arc.h>
72 #include <SketchPlugin_Circle.h>
73 #include <SketchPlugin_ConstraintLength.h>
74 #include <SketchPlugin_ConstraintDistance.h>
75 #include <SketchPlugin_ConstraintParallel.h>
76 #include <SketchPlugin_ConstraintPerpendicular.h>
77 #include <SketchPlugin_ConstraintRadius.h>
78 #include <SketchPlugin_ConstraintRigid.h>
79 #include <SketchPlugin_ConstraintHorizontal.h>
80 #include <SketchPlugin_ConstraintVertical.h>
81 #include <SketchPlugin_ConstraintEqual.h>
82 #include <SketchPlugin_ConstraintTangent.h>
83 #include <SketchPlugin_ConstraintCoincidence.h>
84 #include <SketchPlugin_Fillet.h>
85 #include <SketchPlugin_ConstraintMirror.h>
86 #include <SketchPlugin_ConstraintAngle.h>
87 #include <SketchPlugin_ConstraintCollinear.h>
88 #include <SketchPlugin_ConstraintMiddle.h>
89 #include <SketchPlugin_MultiRotation.h>
90 #include <SketchPlugin_MultiTranslation.h>
91 #include <SketchPlugin_IntersectionPoint.h>
92 #include <SketchPlugin_Projection.h>
93 #include <SketchPlugin_ConstraintDistanceAlongDir.h>
94 #include <SketchPlugin_ConstraintDistanceHorizontal.h>
95 #include <SketchPlugin_ConstraintDistanceVertical.h>
96
97 #include <SketcherPrs_Tools.h>
98
99 #include <SelectMgr_IndexedMapOfOwner.hxx>
100 #include <StdSelect_BRepOwner.hxx>
101
102 //#include <AIS_DimensionSelectionMode.hxx>
103 #include <AIS_Shape.hxx>
104 #include <AIS_Dimension.hxx>
105
106 #include <ModelAPI_Events.h>
107 #include <ModelAPI_Session.h>
108 #include <ModelAPI_AttributeString.h>
109
110 #include <ModelAPI_Validator.h>
111 #include <ModelAPI_Tools.h>
112
113 #include <QMouseEvent>
114 #include <QApplication>
115 #include <QCursor>
116 #include <QMessageBox>
117 #include <QMainWindow>
118
119 //#define DEBUG_DO_NOT_BY_ENTER
120 //#define DEBUG_SKETCHER_ENTITIES
121 //#define DEBUG_SKETCH_ENTITIES_ON_MOVE
122
123 //#define DEBUG_CURSOR
124
125 /// Fills attribute and result lists by the selected owner. In case if the attribute is found,
126 /// by the owner shape, it is put to the list. Otherwise if type of owner shape is edge,
127 /// put the function result as is to the list of results.
128 /// \param theOwner a viewer selected owner
129 /// \param theFeature a feature, where the attribute is searched
130 /// \param theSketch a current sketch
131 /// \param theSelectedAttribute an output list of attributes
132 /// \param theSelectedResults an output list of edge results
133 void getAttributesOrResults(const Handle(SelectMgr_EntityOwner)& theOwner,
134                             const FeaturePtr& theFeature, const FeaturePtr& theSketch,
135                             const ResultPtr& theResult,
136                             std::set<AttributePtr>& theSelectedAttributes,
137                             std::set<ResultPtr>& theSelectedResults,
138                             TopTools_MapOfShape& theShapes)
139 {
140   Handle(StdSelect_BRepOwner) aBRepOwner = Handle(StdSelect_BRepOwner)::DownCast(theOwner);
141   if (aBRepOwner.IsNull())
142     return;
143   Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast(
144                                                                     aBRepOwner->Selectable());
145   if (aBRepOwner->HasShape()) {
146     const TopoDS_Shape& aShape = aBRepOwner->Shape();
147     theShapes.Add(aShape);
148     TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
149     if (aShapeType == TopAbs_VERTEX) {
150       AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(theFeature,
151                                                                     aShape, theSketch);
152       if (aPntAttr.get() != NULL)
153         theSelectedAttributes.insert(aPntAttr);
154     }
155     else if (aShapeType == TopAbs_EDGE &&
156              theSelectedResults.find(theResult) == theSelectedResults.end()) {
157       theSelectedResults.insert(theResult);
158     }
159   }
160 }
161
162 PartSet_SketcherMgr::PartSet_SketcherMgr(PartSet_Module* theModule)
163   : QObject(theModule), myModule(theModule), myIsEditLaunching(false), myIsDragging(false),
164     myDragDone(false), myIsMouseOverWindow(false),
165     myIsMouseOverViewProcessed(true), myPreviousUpdateViewerEnabled(true),
166     myIsPopupMenuActive(false), myExternalPointsMgr(0)
167 {
168   ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();
169   ModuleBase_IViewer* aViewer = anIWorkshop->viewer();
170
171   myPreviousDrawModeEnabled = true;//aViewer->isSelectionEnabled();
172
173   connect(aViewer, SIGNAL(mousePress(ModuleBase_IViewWindow*, QMouseEvent*)),
174           this, SLOT(onMousePressed(ModuleBase_IViewWindow*, QMouseEvent*)));
175
176   connect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)),
177           this, SLOT(onMouseReleased(ModuleBase_IViewWindow*, QMouseEvent*)));
178
179   connect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)),
180           this, SLOT(onMouseMoved(ModuleBase_IViewWindow*, QMouseEvent*)));
181
182   connect(aViewer, SIGNAL(mouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*)),
183           this, SLOT(onMouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*)));
184
185   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(anIWorkshop);
186   XGUI_Workshop* aWorkshop = aConnector->workshop();
187   connect(aWorkshop, SIGNAL(applicationStarted()), this, SLOT(onApplicationStarted()));
188
189   myIsConstraintsShown[PartSet_Tools::Geometrical] = true;
190   myIsConstraintsShown[PartSet_Tools::Dimensional] = true;
191   myIsConstraintsShown[PartSet_Tools::Expressions] = false;
192
193   mySketchPlane = new PartSet_PreviewSketchPlane();
194
195   registerSelectionFilter(SF_SketchCirclePointFilter, new PartSet_CirclePointFilter(anIWorkshop));
196   registerSelectionFilter(SF_SketchPlaneFilter, new ModuleBase_ShapeInPlaneFilter());
197 }
198
199 PartSet_SketcherMgr::~PartSet_SketcherMgr()
200 {
201   delete mySketchPlane;
202 }
203
204 void PartSet_SketcherMgr::onEnterViewPort()
205 {
206   // 1. if the mouse over window, update the next flag. Do not perform update visibility of
207   // created feature because it should be done in onMouseMove(). Some widgets watch
208   // the mouse move and use the cursor position to update own values. If the presentaion is
209   // redisplayed before this update, the feature presentation jumps from reset value to current.
210   myIsMouseOverWindow = true;
211
212   #ifdef DEBUG_DO_NOT_BY_ENTER
213   return;
214   #endif
215
216   if (canChangeCursor(getCurrentOperation())) {
217     QCursor* aCurrentCursor = QApplication::overrideCursor();
218     if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) {
219       QApplication::setOverrideCursor(QCursor(Qt::CrossCursor));
220 #ifdef DEBUG_CURSOR
221       qDebug("onEnterViewPort() : Qt::CrossCursor");
222 #endif
223     }
224   }
225
226   if (!isNestedCreateOperation(getCurrentOperation(), activeSketch()))
227     return;
228
229   operationMgr()->onValidateOperation();
230
231   // we need change displayed state of the current operation feature
232   // if the feature is presentable, e.g. distance construction. It has no results, so workshop does
233   // not accept a signal about the result created. Nothing is shown until mouse is moved out/in view
234   // port. If the isDisplayed flag is true, the presentable feature is displayed as soon as the
235   // presentation becomes valid and redisplay happens
236   //ModuleBase_Operation* aOperation = getCurrentOperation();
237   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
238                                                                            (getCurrentOperation());
239   if (aFOperation) {
240     FeaturePtr aFeature = aFOperation->feature();
241     if (aFeature.get() && aFeature->data()->isValid()) {
242       visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature), false);
243     }
244   }
245 }
246
247 void PartSet_SketcherMgr::onLeaveViewPort()
248 {
249   myIsMouseOverViewProcessed = false;
250   myIsMouseOverWindow = false;
251
252   #ifdef DEBUG_DO_NOT_BY_ENTER
253   return;
254   #endif
255
256   if (canChangeCursor(getCurrentOperation())) {
257     QApplication::restoreOverrideCursor();
258 #ifdef DEBUG_CURSOR
259     qDebug("onLeaveViewPort() : None");
260 #endif
261   }
262
263   if (!isNestedCreateOperation(getCurrentOperation(), activeSketch()))
264     return;
265
266   // the method should be performed if the popup menu is called,
267   // the reset of the current widget should not happen
268   if (myIsPopupMenuActive)
269     return;
270
271   // it is important to validate operation here only if sketch entity create operation is active
272   // because at this operation we reacts to the mouse leave/enter view port
273   operationMgr()->onValidateOperation();
274
275   // 2. if the mouse IS NOT over window, reset the active widget value and hide the presentation
276   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
277   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
278   XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
279   // disable the viewer update in order to avoid visualization of redisplayed feature in viewer
280   // obtained after reset value
281   bool isEnableUpdateViewer = aDisplayer->enableUpdateViewer(false);
282   ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
283   if (anActiveWidget)
284     anActiveWidget->reset();
285
286   // hides the presentation of the current operation feature
287   // the feature is to be erased here, but it is correct to call canDisplayObject because
288   // there can be additional check (e.g. editor widget in distance constraint)
289   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
290                                                                            (getCurrentOperation());
291   if (aFOperation) {
292     FeaturePtr aFeature = aFOperation->feature();
293     visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature));
294   }
295   // we should update viewer after the presentation are hidden in the viewer
296   // otherwise the reset presentation(line) appears in the viewer(by quick move from viewer to PP)
297   aDisplayer->enableUpdateViewer(isEnableUpdateViewer);
298 }
299
300 /*
301 //Temporary commented as we do not modify values in property panel
302 void PartSet_SketcherMgr::onBeforeValuesChangedInPropertyPanel()
303 {
304   if (!isNestedEditOperation(getCurrentOperation(), myModule->sketchMgr()->activeSketch()) ||
305       myModule->sketchReentranceMgr()->isInternalEditActive())
306     return;
307   // it is necessary to save current selection in order to restore it after the values are modifed
308   storeSelection(ST_SelectAndHighlightType);
309
310   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
311   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
312   XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
313   myPreviousUpdateViewerEnabled = aDisplayer->enableUpdateViewer(false);
314 }
315
316 void PartSet_SketcherMgr::onAfterValuesChangedInPropertyPanel()
317 {
318   if (!isNestedEditOperation(getCurrentOperation(), myModule->sketchMgr()->activeSketch()) ||
319       myModule->sketchReentranceMgr()->isInternalEditActive()) {
320     myModule->sketchReentranceMgr()->updateInternalEditActiveState();
321     return;
322   }
323   // it is necessary to restore current selection in order to restore it after values are modified
324   restoreSelection();
325   myCurrentSelection.clear();
326
327   // 3. the flag to disable the update viewer should be set in order to avoid blinking in the
328   // viewer happens by deselect/select the modified objects. The flag should be restored after
329   // the selection processing. The update viewer should be also called.
330   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
331   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
332   XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
333   aDisplayer->enableUpdateViewer(myPreviousUpdateViewerEnabled);
334   aDisplayer->updateViewer();
335 }
336 */
337
338 void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
339 {
340   // Clear dragging mode
341   myIsDragging = false;
342
343   if (myModule->sketchReentranceMgr()->processMousePressed(theWnd, theEvent))
344     return;
345   //get2dPoint(theWnd, theEvent, myClickedPoint);
346   if (!(theEvent->buttons() & Qt::LeftButton))
347     return;
348
349   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
350   ModuleBase_IViewer* aViewer = aWorkshop->viewer();
351   if (!aViewer->canDragByMouse())
352     return;
353
354   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
355                                                                (getCurrentOperation());
356   if (!aFOperation)
357     return;
358
359   if (aFOperation->isEditOperation()) {
360     // If the current widget is a selector, do nothing, it processes the mouse press
361     ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
362     if(anActiveWidget && anActiveWidget->isViewerSelector()) {
363       return;
364     }
365   }
366
367   // Use only for sketch operations
368   if (myCurrentSketch) {
369     if (!PartSet_Tools::sketchPlane(myCurrentSketch))
370       return;
371
372     bool isSketcher = isSketchOperation(aFOperation);
373     bool isSketchOpe = isNestedSketchOperation(aFOperation);
374
375     // Avoid non-sketch operations
376     if ((!isSketchOpe) && (!isSketcher))
377       return;
378
379     bool isEditing = aFOperation->isEditOperation();
380
381     // Ignore creation sketch operation
382     if ((!isSketcher) && (!isEditing))
383       return;
384
385     Handle(AIS_InteractiveContext) aContext = aViewer->AISContext();
386     // Remember highlighted objects for editing
387     ModuleBase_ISelection* aSelect = aWorkshop->selection();
388
389     bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
390     storeSelection(aHasShift ? ST_SelectAndHighlightType : ST_HighlightType, myCurrentSelection);
391
392     if (myCurrentSelection.empty()) {
393       if (isSketchOpe && (!isSketcher))
394         // commit previous operation
395         if (!aFOperation->commit())
396           aFOperation->abort();
397       return;
398     }
399     // Init flyout point for radius rotation
400     FeaturePtr aFeature = myCurrentSelection.begin().key();
401
402     get2dPoint(theWnd, theEvent, myCurrentPoint);
403     if (isSketcher) {
404       myIsDragging = true;
405       myDragDone = false;
406
407       myPreviousDrawModeEnabled = aViewer->enableDrawMode(false);
408       launchEditing();
409       if (aFeature.get() != NULL) {
410         std::shared_ptr<SketchPlugin_Feature> aSPFeature =
411                   std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
412         if (aSPFeature.get() &&
413           (aSPFeature->getKind() == SketchPlugin_ConstraintRadius::ID() ||
414            aSPFeature->getKind() == SketchPlugin_ConstraintAngle::ID())) {
415           DataPtr aData = aSPFeature->data();
416           AttributePtr aAttr = aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT());
417           std::shared_ptr<GeomDataAPI_Point2D> aFPAttr =
418             std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aAttr);
419           aFPAttr->setValue(myCurrentPoint.myCurX, myCurrentPoint.myCurY);
420         }
421       }
422     } else if (isSketchOpe && isEditing) {
423       // If selected another object commit current result
424       bool aPrevLaunchingState = myIsEditLaunching;
425       /// store editing state for Edit operation in order to do not clear highlight by restart
426       /// of edit operation.
427       /// Internal edit should not be stored as editing operation as the result will be a
428       /// creation operation, where previous selection should not be used(and will be cleared)
429       myIsEditLaunching = !myModule->sketchReentranceMgr()->isInternalEditActive();
430       aFOperation->commit();
431
432       myIsDragging = true;
433       myDragDone = false;
434
435       myPreviousDrawModeEnabled = aViewer->enableDrawMode(false);
436       launchEditing();
437       myIsEditLaunching = aPrevLaunchingState;
438       if (aFeature.get() != NULL) {
439         std::shared_ptr<SketchPlugin_Feature> aSPFeature =
440                   std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
441         if (aSPFeature.get() &&
442           (aSPFeature->getKind() == SketchPlugin_ConstraintRadius::ID() ||
443            aSPFeature->getKind() == SketchPlugin_ConstraintAngle::ID())) {
444           DataPtr aData = aSPFeature->data();
445           AttributePtr aAttr = aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT());
446           std::shared_ptr<GeomDataAPI_Point2D> aFPAttr =
447             std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aAttr);
448           aFPAttr->setValue(myCurrentPoint.myCurX, myCurrentPoint.myCurY);
449         }
450       }
451     }
452   }
453 }
454
455 void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
456 {
457   bool aWasDragging = myIsDragging;
458   myIsDragging = false;
459
460   if (myModule->sketchReentranceMgr()->processMouseReleased(theWnd, theEvent))
461     return;
462
463   // if mouse is pressed when it was over view and at release the mouse is out of view, do nothing
464   if (!myIsMouseOverViewProcessed)
465     return;
466
467   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
468   ModuleBase_IViewer* aViewer = aWorkshop->viewer();
469   if (!aViewer->canDragByMouse())
470     return;
471   ModuleBase_Operation* aOp = getCurrentOperation();
472   if (aOp) {
473     if (isNestedSketchOperation(aOp)) {
474       // Only for sketcher operations
475       if (aWasDragging) {
476         if (myDragDone) {
477           /// the previous selection is lost by mouse release in the viewer(Select method), but
478           /// it is still stored in myCurrentSelection. So, it is possible to restore selection
479           /// It is important for drag(edit with mouse) of sketch entities.
480           restoreSelection(myCurrentSelection);
481           myCurrentSelection.clear();
482         }
483       }
484     }
485   }
486
487   aWorkshop->viewer()->enableDrawMode(myPreviousDrawModeEnabled);
488
489   ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
490   PartSet_MouseProcessor* aProcessor = dynamic_cast<PartSet_MouseProcessor*>(anActiveWidget);
491   if (aProcessor)
492     aProcessor->mouseReleased(theWnd, theEvent);
493 }
494
495 void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
496 {
497 #ifdef DEBUG_SKETCH_ENTITIES_ON_MOVE
498   CompositeFeaturePtr aSketch = activeSketch();
499   if (aSketch.get()) {
500     std::cout << "mouse move SKETCH FEATURES [" << aSketch->numberOfSubs() << "]:" << std::endl;
501     QStringList anInfo;
502     for (int i = 0, aNbSubs = aSketch->numberOfSubs(); i < aNbSubs; i++) {
503       //std::cout << getFeatureInfo(aSketch->subFeature(i), false) << std::endl;
504       anInfo.append(ModuleBase_Tools::objectInfo(aSketch->subFeature(i)));
505     }
506     QString anInfoStr = anInfo.join("\n");
507     qDebug(QString("%1").arg(anInfo.size()).arg(anInfoStr).toStdString().c_str());
508   }
509 #endif
510
511   if (myModule->sketchReentranceMgr()->processMouseMoved(theWnd, theEvent))
512     return;
513
514   if (isNestedCreateOperation(getCurrentOperation(), activeSketch())) {
515     // 1. perform the widget mouse move functionality and display the presentation
516     // the mouse move should be processed in the widget, if it can in order to visualize correct
517     // presentation. These widgets correct the feature attribute according to the mouse position
518     ModuleBase_ModelWidget* anActiveWidget = myModule->activeWidget();
519     PartSet_MouseProcessor* aProcessor = dynamic_cast<PartSet_MouseProcessor*>(anActiveWidget);
520     if (aProcessor)
521       aProcessor->mouseMoved(theWnd, theEvent);
522     if (!myIsMouseOverViewProcessed) {
523       myIsMouseOverViewProcessed = true;
524
525       // the feature is to be erased here, but it is correct to call canDisplayObject because
526       // there can be additional check (e.g. editor widget in distance constraint)
527       ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
528                                                  (getCurrentOperation());
529       if (aFOperation) {
530         FeaturePtr aFeature = aFOperation->feature();
531         visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature));
532       }
533     }
534   }
535   //myClickedPoint.clear();
536
537   if (myIsDragging) {
538     // 1. the current selection is saved in the mouse press method in order to restore it after
539     //    moving
540     // 2. the enable selection in the viewer should be temporary switched off in order to ignore
541     // mouse press signal in the viewer(it call Select for AIS context and the dragged objects are
542     // deselected). This flag should be restored in the slot, processed the mouse release signal.
543
544     ModuleBase_Operation* aCurrentOperation = getCurrentOperation();
545     if (!aCurrentOperation)
546       return;
547     if (isSketchOperation(aCurrentOperation))
548       return; // No edit operation activated
549
550     Handle(V3d_View) aView = theWnd->v3dView();
551     gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);
552     Point aMousePnt;
553     get2dPoint(theWnd, theEvent, aMousePnt);
554
555     std::shared_ptr<GeomAPI_Pnt2d> anOriginalPosition = std::shared_ptr<GeomAPI_Pnt2d>(
556                             new GeomAPI_Pnt2d(myCurrentPoint.myCurX, myCurrentPoint.myCurY));
557     std::shared_ptr<GeomAPI_Pnt2d> aCurrentPosition = std::shared_ptr<GeomAPI_Pnt2d>(
558                             new GeomAPI_Pnt2d(aMousePnt.myCurX, aMousePnt.myCurY));
559
560     ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
561     XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
562     XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
563     // 3. the flag to disable the update viewer should be set in order to avoid blinking in the
564     // viewer happens by deselect/select the modified objects. The flag should be restored after
565     // the selection processing. The update viewer should be also called.
566     bool isEnableUpdateViewer = aDisplayer->enableUpdateViewer(false);
567
568     static Events_ID aMoveEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED);
569     //static Events_ID aUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
570     FeatureToSelectionMap::const_iterator anIt = myCurrentSelection.begin(),
571                                           aLast = myCurrentSelection.end();
572     // 4. the features and attributes modification(move)
573     bool isModified = false;
574     for (; anIt != aLast; anIt++) {
575       FeaturePtr aFeature = anIt.key();
576
577       std::set<AttributePtr> anAttributes = anIt.value().myAttributes;
578       // Process selection by attribute: the priority to the attribute
579       if (!anAttributes.empty()) {
580         std::set<AttributePtr>::const_iterator anAttIt = anAttributes.begin(),
581                                                anAttLast = anAttributes.end();
582         for (; anAttIt != anAttLast; anAttIt++) {
583           AttributePtr anAttr = *anAttIt;
584           if (anAttr.get() == NULL)
585             continue;
586           std::string aAttrId = anAttr->id();
587           DataPtr aData = aFeature->data();
588           if (aData->isValid()) {
589             std::shared_ptr<GeomDataAPI_Point2D> aPoint =
590               std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(aAttrId));
591             if (aPoint.get() != NULL) {
592               bool isImmutable = aPoint->setImmutable(true);
593
594               std::shared_ptr<ModelAPI_ObjectMovedMessage> aMessage = std::shared_ptr
595                        <ModelAPI_ObjectMovedMessage>(new ModelAPI_ObjectMovedMessage(this));
596               aMessage->setMovedAttribute(aPoint);
597               aMessage->setOriginalPosition(anOriginalPosition);
598               aMessage->setCurrentPosition(aCurrentPosition);
599               Events_Loop::loop()->send(aMessage);
600
601               isModified = true;
602               aPoint->setImmutable(isImmutable);
603             }
604           }
605         }
606       } else {
607         // Process selection by feature
608         std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
609           std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
610         if (aSketchFeature) {
611           std::shared_ptr<ModelAPI_ObjectMovedMessage> aMessage = std::shared_ptr
612                     <ModelAPI_ObjectMovedMessage>(new ModelAPI_ObjectMovedMessage(this));
613           aMessage->setMovedObject(aFeature);
614           aMessage->setOriginalPosition(anOriginalPosition);
615           aMessage->setCurrentPosition(aCurrentPosition);
616           Events_Loop::loop()->send(aMessage);
617           isModified = true;
618         }
619       }
620     }
621     // the modified state of the current operation should be updated if there are features, which
622     // were changed here
623     if (isModified) {
624       aCurrentOperation->onValuesChanged();
625       Events_Loop::loop()->flush(aMoveEvent); // up all move events - to be processed in the solver
626     }
627     //Events_Loop::loop()->flush(aUpdateEvent); // up update events - to redisplay presentations
628
629     // 5. it is necessary to save current selection in order to restore it after the features moving
630     restoreSelection(myCurrentSelection);
631     // 6. restore the update viewer flag and call this update
632     aDisplayer->enableUpdateViewer(isEnableUpdateViewer);
633     aDisplayer->updateViewer();
634
635     myDragDone = true;
636     myCurrentPoint = aMousePnt;
637   }
638 }
639
640 void PartSet_SketcherMgr::onMouseDoubleClick(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
641 {
642   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
643                                                                (getCurrentOperation());
644   if (aFOperation && aFOperation->isEditOperation()) {
645     std::string aId = aFOperation->id().toStdString();
646     if (isDistanceOperation(aFOperation))
647     {
648       // Activate dimension value editing on double click
649       ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel();
650       QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();
651       // Find corresponded widget to activate value editing
652       foreach (ModuleBase_ModelWidget* aWgt, aWidgets) {
653         std::string anId = aWgt->attributeID();
654         if (anId == SketchPlugin_Constraint::VALUE() ||
655           anId == SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID() ||
656           anId == SketchPlugin_ConstraintDistanceAlongDir::DISTANCE_VALUE_ID()) {
657           PartSet_WidgetEditor* anEditor = dynamic_cast<PartSet_WidgetEditor*>(aWgt);
658           if (anEditor)
659             anEditor->showPopupEditor();
660           return;
661         }
662       }
663     }
664   }
665 }
666
667 void PartSet_SketcherMgr::onApplicationStarted()
668 {
669   ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();
670   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(anIWorkshop);
671   XGUI_Workshop* aWorkshop = aConnector->workshop();
672   PartSet_SketcherReentrantMgr* aReentranceMgr = myModule->sketchReentranceMgr();
673
674   XGUI_PropertyPanel* aPropertyPanel = aWorkshop->propertyPanel();
675   if (aPropertyPanel) {
676     //connect(aPropertyPanel, SIGNAL(beforeWidgetActivated(ModuleBase_ModelWidget*)),
677     //        this, SLOT(onBeforeWidgetActivated(ModuleBase_ModelWidget*)));
678
679     connect(aPropertyPanel, SIGNAL(noMoreWidgets(const std::string&)),
680             aReentranceMgr, SLOT(onNoMoreWidgets(const std::string&)));
681     //connect(aPropertyPanel, SIGNAL(widgetActivated(ModuleBase_ModelWidget*)),
682     //        aReentranceMgr, SLOT(onWidgetActivated()));
683   }
684
685   XGUI_ViewerProxy* aViewerProxy = aWorkshop->viewer();
686   connect(aViewerProxy, SIGNAL(enterViewPort()), this, SLOT(onEnterViewPort()));
687   connect(aViewerProxy, SIGNAL(leaveViewPort()), this, SLOT(onLeaveViewPort()));
688
689   XGUI_ContextMenuMgr* aContextMenuMgr = aWorkshop->contextMenuMgr();
690   connect(aContextMenuMgr, SIGNAL(beforeContextMenu()), this, SLOT(onBeforeContextMenu()));
691   connect(aContextMenuMgr, SIGNAL(afterContextMenu()), this, SLOT(onAfterContextMenu()));
692 }
693
694 //void PartSet_SketcherMgr::onBeforeWidgetActivated(ModuleBase_ModelWidget* theWidget)
695 //{
696   //if (!myClickedPoint.myIsInitialized)
697   //  return;
698
699   //ModuleBase_Operation* aOperation = getCurrentOperation();
700   // the distance constraint feature should not use the clickedd point
701   // this is workaround in order to don't throw down the flyout point value,
702   // set by execute() method of these type of features
703   //if (isDistanceOperation(aOperation))
704   //  return;
705
706   //PartSet_WidgetPoint2D* aPnt2dWgt = dynamic_cast<PartSet_WidgetPoint2D*>(theWidget);
707   //if (aPnt2dWgt) {
708   //  aPnt2dWgt->setPoint(myClickedPoint.myCurX, myClickedPoint.myCurY);
709   //}
710 //}
711
712 void PartSet_SketcherMgr::onBeforeContextMenu()
713 {
714   myIsPopupMenuActive = true;
715 }
716
717 void PartSet_SketcherMgr::onAfterContextMenu()
718 {
719   myIsPopupMenuActive = false;
720 }
721
722 void PartSet_SketcherMgr::get2dPoint(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent,
723                                      Point& thePoint)
724 {
725   Handle(V3d_View) aView = theWnd->v3dView();
726   gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);
727   double aX, anY;
728   PartSet_Tools::convertTo2D(aPoint, myCurrentSketch, aView, aX, anY);
729   thePoint.setValue(aX, anY);
730 }
731
732 void PartSet_SketcherMgr::launchEditing()
733 {
734   if (!myCurrentSelection.empty()) {
735     FeaturePtr aFeature = myCurrentSelection.begin().key();
736     std::shared_ptr<SketchPlugin_Feature> aSPFeature =
737               std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
738     if (aSPFeature) {
739       if (!aSPFeature->isExternal())
740         myModule->editFeature(aSPFeature);
741       else {
742         // need to edit a feature (Projection/IntersectionPoint),
743         // which produces current External feature
744         FeaturePtr aProducerFeature = PartSet_Tools::findRefsToMeFeature(aFeature,
745                                                         SketchPlugin_Projection::ID());
746         if (!aProducerFeature.get())
747           aProducerFeature = PartSet_Tools::findRefsToMeFeature(aFeature,
748                                                         SketchPlugin_IntersectionPoint::ID());
749         if (aProducerFeature.get())
750           myModule->editFeature(aProducerFeature);
751       }
752     }
753   }
754 }
755
756 bool PartSet_SketcherMgr::sketchSolverError()
757 {
758   bool anError = false;
759   CompositeFeaturePtr aSketch = activeSketch();
760   if (aSketch.get()) {
761     AttributeStringPtr aAttributeString = aSketch->string(SketchPlugin_Sketch::SOLVER_ERROR());
762     anError = !aAttributeString->value().empty();
763   }
764   return anError;
765 }
766
767 QString PartSet_SketcherMgr::getFeatureError(const FeaturePtr& theFeature)
768 {
769   QString anError;
770   if (!theFeature.get() || !theFeature->data()->isValid())
771     return anError;
772
773   CompositeFeaturePtr aSketch = activeSketch();
774   if (aSketch.get() && aSketch == theFeature) {
775     std::string aSolverError = aSketch->string(SketchPlugin_Sketch::SOLVER_ERROR())->value();
776     anError = ModuleBase_Tools::translate(aSketch->getKind(), aSolverError);
777   }
778   return anError;
779 }
780
781 void PartSet_SketcherMgr::clearClickedFlags()
782 {
783   //myClickedPoint.clear();
784   myCurrentPoint.clear();
785 }
786
787 const QStringList& PartSet_SketcherMgr::replicationsIdList()
788 {
789   static QStringList aReplicationIds;
790   if (aReplicationIds.size() == 0) {
791     aReplicationIds << SketchPlugin_ConstraintMirror::ID().c_str();
792     aReplicationIds << SketchPlugin_MultiRotation::ID().c_str();
793     aReplicationIds << SketchPlugin_MultiTranslation::ID().c_str();
794   }
795   return aReplicationIds;
796 }
797
798 const QStringList& PartSet_SketcherMgr::constraintsIdList()
799 {
800   static QStringList aConstraintIds;
801   if (aConstraintIds.size() == 0) {
802     aConstraintIds << SketchPlugin_ConstraintLength::ID().c_str();
803     aConstraintIds << SketchPlugin_ConstraintDistance::ID().c_str();
804     aConstraintIds << SketchPlugin_ConstraintRigid::ID().c_str();
805     aConstraintIds << SketchPlugin_ConstraintRadius::ID().c_str();
806     aConstraintIds << SketchPlugin_ConstraintPerpendicular::ID().c_str();
807     aConstraintIds << SketchPlugin_ConstraintParallel::ID().c_str();
808     aConstraintIds << SketchPlugin_ConstraintHorizontal::ID().c_str();
809     aConstraintIds << SketchPlugin_ConstraintVertical::ID().c_str();
810     aConstraintIds << SketchPlugin_ConstraintEqual::ID().c_str();
811     aConstraintIds << SketchPlugin_ConstraintTangent::ID().c_str();
812     aConstraintIds << SketchPlugin_ConstraintCoincidence::ID().c_str();
813     aConstraintIds << SketchPlugin_ConstraintAngle::ID().c_str();
814     aConstraintIds << SketchPlugin_ConstraintCollinear::ID().c_str();
815     aConstraintIds << SketchPlugin_ConstraintMiddle::ID().c_str();
816     aConstraintIds << SketchPlugin_ConstraintMirror::ID().c_str();
817     aConstraintIds << SketchPlugin_MultiTranslation::ID().c_str();
818     aConstraintIds << SketchPlugin_MultiRotation::ID().c_str();
819     aConstraintIds << SketchPlugin_ConstraintDistanceAlongDir::ID().c_str();
820     aConstraintIds << SketchPlugin_ConstraintDistanceHorizontal::ID().c_str();
821     aConstraintIds << SketchPlugin_ConstraintDistanceVertical::ID().c_str();
822   }
823   return aConstraintIds;
824 }
825
826 void PartSet_SketcherMgr::sketchSelectionModes(const CompositeFeaturePtr& theSketch,
827                                                QIntList& theModes)
828 {
829   if (!theSketch.get() || !PartSet_Tools::sketchPlane(theSketch).get())
830     return;
831
832   theModes.append(SketcherPrs_Tools::Sel_Dimension_Text);
833   theModes.append(SketcherPrs_Tools::Sel_Dimension_Line);
834   theModes.append(SketcherPrs_Tools::Sel_Constraint);
835   theModes.append(TopAbs_VERTEX);
836   theModes.append(TopAbs_EDGE);
837 }
838
839 Handle(AIS_InteractiveObject) PartSet_SketcherMgr::createPresentation(const ResultPtr& theResult)
840 {
841   Handle(AIS_InteractiveObject) aPrs;
842
843   FeaturePtr aFeature = ModelAPI_Feature::feature(theResult);
844   if (aFeature.get() && aFeature->getKind() == SketchPlugin_Sketch::ID()) {
845     aPrs = new PartSet_ResultSketchPrs(theResult);
846   }
847   return aPrs;
848 }
849
850 bool PartSet_SketcherMgr::isSketchOperation(ModuleBase_Operation* theOperation)
851 {
852   return theOperation && theOperation->id().toStdString() == SketchPlugin_Sketch::ID();
853 }
854
855 bool PartSet_SketcherMgr::isNestedSketchOperation(ModuleBase_Operation* theOperation) const
856 {
857   bool aNestedSketch = false;
858
859   FeaturePtr anActiveSketch = activeSketch();
860   if (anActiveSketch.get() && theOperation) {
861     ModuleBase_Operation* aSketchOperation = operationMgr()->findOperation(
862                                                               anActiveSketch->getKind().c_str());
863     ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
864                                                                                   (theOperation);
865     if (aSketchOperation && aFOperation) {
866       FeaturePtr aFeature = aFOperation->feature();
867       if (aFeature.get()) {
868         QStringList aGrantedOpIds = aSketchOperation->grantedOperationIds();
869         aNestedSketch = aGrantedOpIds.contains(aFeature->getKind().c_str());
870       }
871     }
872   }
873   return aNestedSketch;
874 }
875
876 bool PartSet_SketcherMgr::isNestedSketchFeature(const QString& theFeatureKind) const
877 {
878   bool aNestedSketch = false;
879
880   FeaturePtr anActiveSketch = activeSketch();
881   if (anActiveSketch.get()) {
882     ModuleBase_Operation* aSketchOperation = operationMgr()->findOperation(
883                                                               anActiveSketch->getKind().c_str());
884     if (aSketchOperation) {
885       QStringList aGrantedOpIds = aSketchOperation->grantedOperationIds();
886       aNestedSketch = aGrantedOpIds.contains(theFeatureKind);
887     }
888   }
889   return aNestedSketch;
890 }
891
892 bool PartSet_SketcherMgr::isNestedCreateOperation(ModuleBase_Operation* theOperation,
893                                                   const CompositeFeaturePtr& theSketch) const
894 {
895   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
896                                                                (theOperation);
897   return aFOperation && !aFOperation->isEditOperation() &&
898          isNestedSketchOperation(aFOperation);
899 }
900
901 bool PartSet_SketcherMgr::isNestedEditOperation(ModuleBase_Operation* theOperation,
902                                                 const CompositeFeaturePtr& theSketch) const
903 {
904   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
905                                                                (theOperation);
906   return aFOperation && aFOperation->isEditOperation() &&
907     isNestedSketchOperation(aFOperation);
908 }
909
910 bool PartSet_SketcherMgr::isEntity(const std::string& theId)
911 {
912   return (theId == SketchPlugin_Line::ID()) ||
913          (theId == SketchPlugin_Point::ID()) ||
914          (theId == SketchPlugin_Arc::ID()) ||
915          (theId == SketchPlugin_Circle::ID());
916 }
917
918 bool PartSet_SketcherMgr::isExternalFeature(const FeaturePtr& theFeature)
919 {
920   std::shared_ptr<SketchPlugin_Feature> aSPFeature =
921           std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
922   return aSPFeature.get() && aSPFeature->isExternal();
923 }
924
925 bool PartSet_SketcherMgr::isDistanceOperation(ModuleBase_Operation* theOperation)
926 {
927   std::string anId = theOperation ? theOperation->id().toStdString() : "";
928
929   return isDistanceKind(anId);
930 }
931
932 bool PartSet_SketcherMgr::isDistanceKind(std::string& theKind)
933 {
934   return (theKind == SketchPlugin_ConstraintLength::ID()) ||
935          (theKind == SketchPlugin_ConstraintDistance::ID()) ||
936          (theKind == SketchPlugin_ConstraintRadius::ID()) ||
937          (theKind == SketchPlugin_ConstraintAngle::ID()) ||
938          (theKind == SketchPlugin_ConstraintDistanceHorizontal::ID()) ||
939          (theKind == SketchPlugin_ConstraintDistanceVertical::ID()) ||
940          (theKind == SketchPlugin_ConstraintDistanceAlongDir::ID());
941 }
942
943 void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
944 {
945   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
946                                                                (getCurrentOperation());
947   if (!aFOperation)
948     return;
949
950   myModule->onViewTransformed();
951
952   // Display all sketcher sub-Objects
953   myCurrentSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFOperation->feature());
954   double aSizeOfView = 0;
955   std::shared_ptr<GeomAPI_Pnt> aCentralPoint;
956   if (aFOperation->isEditOperation() &&
957       mySketchPlane->getDefaultSizeOfView(myCurrentSketch, aSizeOfView, aCentralPoint)) {
958     mySketchPlane->setSizeOfView(aSizeOfView, true, aCentralPoint);
959   }
960
961   mySketchPlane->createSketchPlane(myCurrentSketch, myModule->workshop());
962   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
963
964   // Hide sketcher result
965   std::list<ResultPtr> aResults = myCurrentSketch->results();
966   std::list<ResultPtr>::const_iterator aIt;
967   for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
968     (*aIt)->setDisplayed(false);
969   }
970   myCurrentSketch->setDisplayed(false);
971
972   // Remove invalid sketch entities
973   std::set<FeaturePtr> anInvalidFeatures;
974   ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
975   int aNumberOfSubs = myCurrentSketch->numberOfSubs();
976   for (int i = 0; i < aNumberOfSubs; i++) {
977     FeaturePtr aFeature = myCurrentSketch->subFeature(i);
978     if (aFeature.get()) {
979       if (!aFactory->validate(aFeature))
980         anInvalidFeatures.insert(aFeature);
981     }
982   }
983   if (!anInvalidFeatures.empty()) {
984     std::map<FeaturePtr, std::set<FeaturePtr> > aReferences;
985     ModelAPI_Tools::findAllReferences(anInvalidFeatures, aReferences, false);
986
987     std::set<FeaturePtr>::const_iterator anIt = anInvalidFeatures.begin(),
988                                          aLast = anInvalidFeatures.end();
989     // separate features to references to parameter features and references to others
990     QStringList anInvalidFeatureNames;
991     for (; anIt != aLast; anIt++) {
992       FeaturePtr aFeature = *anIt;
993       if (aFeature.get())
994         anInvalidFeatureNames.append(aFeature->name().c_str());
995     }
996     std::string aPrefixInfo = QString("Invalid features of the sketch will be deleted: %1.\n\n").
997                                   arg(anInvalidFeatureNames.join(", ")).toStdString().c_str();
998     std::set<FeaturePtr> aFeatureRefsToDelete;
999     if (ModuleBase_Tools::askToDelete(anInvalidFeatures, aReferences, aConnector->desktop(),
1000                                       aFeatureRefsToDelete, aPrefixInfo)) {
1001       if (!aFeatureRefsToDelete.empty())
1002         anInvalidFeatures.insert(aFeatureRefsToDelete.begin(), aFeatureRefsToDelete.end());
1003       ModelAPI_Tools::removeFeatures(anInvalidFeatures, true);
1004       Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
1005       // TODO: call the next method in the XGUI_OperationMgr::onOperationStarted().
1006       workshop()->errorMgr()->updateAcceptAllAction(myCurrentSketch);
1007     }
1008   }
1009
1010   // update state of overconstraint listener should be done before sketch features/results
1011   // display (as the display will ask custom color from the listener)
1012   myModule->overconstraintListener()->setActive(true);
1013   // Display sketcher objects
1014   QStringList anInfo;
1015   Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
1016   const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
1017   aNumberOfSubs = myCurrentSketch->numberOfSubs();
1018   for (int i = 0; i < aNumberOfSubs; i++) {
1019     FeaturePtr aFeature = myCurrentSketch->subFeature(i);
1020 #ifdef DEBUG_SKETCHER_ENTITIES
1021     anInfo.append(ModuleBase_Tools::objectInfo(aFeature));
1022 #endif
1023     std::list<ResultPtr> aResults = aFeature->results();
1024     std::list<ResultPtr>::const_iterator aIt;
1025     for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
1026       if ((*aIt)->isDisplayed())
1027         // Display object if it was created outside of GUI
1028         aECreator->sendUpdated((*aIt), EVENT_DISP);
1029       else
1030         (*aIt)->setDisplayed(true);
1031     }
1032     if (aFeature->isDisplayed())
1033       aECreator->sendUpdated(aFeature, EVENT_DISP);
1034     else
1035       aFeature->setDisplayed(true);
1036   }
1037 #ifdef DEBUG_SKETCHER_ENTITIES
1038   QString anInfoStr = anInfo.join(";\t");
1039   qDebug(QString("startSketch: %1, %2").arg(anInfo.size()).arg(anInfoStr).toStdString().c_str());
1040 #endif
1041
1042   bool aHasPlane = false;
1043   std::shared_ptr<GeomAPI_Pln> aPln;
1044   aPln = PartSet_Tools::sketchPlane(myCurrentSketch);
1045   Handle(SelectMgr_Filter) aFilter = myModule->selectionFilter(SF_SketchPlaneFilter);
1046   if (!aFilter.IsNull())
1047     Handle(ModuleBase_ShapeInPlaneFilter)::DownCast(aFilter)->setPlane(aPln);
1048
1049   workshop()->selectionActivate()->updateSelectionFilters();
1050   workshop()->selectionActivate()->updateSelectionModes();
1051
1052   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
1053
1054   myExternalPointsMgr = new PartSet_ExternalPointsMgr(myModule->workshop(), myCurrentSketch);
1055
1056   workshop()->viewer()->set2dMode(true);
1057 }
1058
1059 void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
1060 {
1061   myIsMouseOverWindow = false;
1062   myIsConstraintsShown[PartSet_Tools::Geometrical] = true;
1063   myIsConstraintsShown[PartSet_Tools::Dimensional] = true;
1064   myIsConstraintsShown[PartSet_Tools::Expressions] = false;
1065
1066   if (myExternalPointsMgr) {
1067     delete myExternalPointsMgr;
1068     myExternalPointsMgr = 0;
1069   }
1070   onShowPoints(false);
1071
1072   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
1073
1074   DataPtr aData = myCurrentSketch->data();
1075   if (!aData->isValid()) {
1076     XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
1077     // The sketch was aborted
1078     myCurrentSketch = CompositeFeaturePtr();
1079     mySketchPlane->eraseSketchPlane(myModule->workshop());
1080
1081     // Erase all sketcher objects
1082     QObjectPtrList aObjects = aDisplayer->displayedObjects();
1083     foreach (ObjectPtr aObj, aObjects) {
1084       DataPtr aObjData = aObj->data();
1085       if (!aObjData->isValid())
1086         aObj->setDisplayed(false);
1087     }
1088   }
1089   else {
1090     // Hide all sketcher sub-Objects
1091     int aNumberOfSubs = myCurrentSketch->numberOfSubs();
1092     for (int i = 0; i < aNumberOfSubs; i++) {
1093       FeaturePtr aFeature = myCurrentSketch->subFeature(i);
1094       std::list<ResultPtr> aResults = aFeature->results();
1095       std::list<ResultPtr>::const_iterator aIt;
1096       for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
1097         (*aIt)->setDisplayed(false);
1098       }
1099       aFeature->setDisplayed(false);
1100     }
1101     // Display sketcher result
1102     std::list<ResultPtr> aResults = myCurrentSketch->results();
1103     std::list<ResultPtr>::const_iterator aIt;
1104     Events_Loop* aLoop = Events_Loop::loop();
1105     static Events_ID aDispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
1106
1107     ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
1108                                                                            (theOperation);
1109     for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
1110       if (!aFOperation->isDisplayedOnStart(*aIt)) {
1111         (*aIt)->setDisplayed(true);
1112         // this display event is needed because sketch already may have "displayed" state,
1113         // but not displayed while it is still active (issue 613, abort of existing sketch)
1114         ModelAPI_EventCreator::get()->sendUpdated(*aIt, aDispEvent);
1115       }
1116     }
1117     if (!aFOperation->isDisplayedOnStart(myCurrentSketch))
1118       myCurrentSketch->setDisplayed(true);
1119
1120     myCurrentSketch = CompositeFeaturePtr();
1121     mySketchPlane->eraseSketchPlane(myModule->workshop());
1122
1123     Events_Loop::loop()->flush(aDispEvent);
1124   }
1125   workshop()->selectionActivate()->updateSelectionFilters();
1126   workshop()->selectionActivate()->updateSelectionModes();
1127   workshop()->viewer()->set2dMode(false);
1128 }
1129
1130 void PartSet_SketcherMgr::startNestedSketch(ModuleBase_Operation* theOperation)
1131 {
1132   if (canChangeCursor(theOperation) && myIsMouseOverWindow) {
1133     QCursor* aCurrentCursor = QApplication::overrideCursor();
1134     if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) {
1135       QApplication::setOverrideCursor(QCursor(Qt::CrossCursor));
1136 #ifdef DEBUG_CURSOR
1137       qDebug("startNestedSketch() : Qt::CrossCursor");
1138 #endif
1139     }
1140   }
1141 }
1142
1143 void PartSet_SketcherMgr::stopNestedSketch(ModuleBase_Operation* theOperation)
1144 {
1145   myIsMouseOverViewProcessed = true;
1146   operationMgr()->onValidateOperation();
1147   // when sketch nested operation is stopped the cursor should be restored unconditionally
1148   //if (canChangeCursor(theOperation)) {
1149     QApplication::restoreOverrideCursor();
1150 #ifdef DEBUG_CURSOR
1151     qDebug("stopNestedSketch() : None");
1152 #endif
1153   //}
1154   /// improvement to deselect automatically all eventual selected objects, when
1155   // returning to the neutral point of the Sketcher
1156   bool isClearSelectionPossible = true;
1157   if (myIsEditLaunching) {
1158     ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
1159                                                                           (theOperation);
1160     if (aFOperation) {
1161       FeaturePtr aFeature = aFOperation->feature();
1162       if (aFeature.get() && PartSet_SketcherMgr::isEntity(aFeature->getKind())) {
1163         isClearSelectionPossible = false;
1164       }
1165     }
1166   }
1167   if (isClearSelectionPossible)
1168     workshop()->selector()->clearSelection();
1169   if (myPointsHighlight.size())
1170     onShowPoints(true);
1171 }
1172
1173 void PartSet_SketcherMgr::commitNestedSketch(ModuleBase_Operation* theOperation)
1174 {
1175   if (isNestedCreateOperation(theOperation, activeSketch())) {
1176     ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
1177                                                                              (theOperation);
1178     if (aFOperation) {
1179       FeaturePtr aFeature = aFOperation->feature();
1180       // it is necessary to check the the feature data validity because
1181       // some kind of features are removed by an operation commit(the macro state of a feature)
1182       if (aFeature.get() && aFeature->data()->isValid()) {
1183         visualizeFeature(aFeature, aFOperation->isEditOperation(), true);
1184       }
1185     }
1186   }
1187 }
1188
1189 bool PartSet_SketcherMgr::sketchSelectionFilter(const XGUI_SelectionFilterType theFilterType)
1190 {
1191   return mySelectionFilterTypes.find(theFilterType) != mySelectionFilterTypes.end();
1192 }
1193
1194 void PartSet_SketcherMgr::registerSelectionFilter(const XGUI_SelectionFilterType theFilterType,
1195                                                   const Handle(SelectMgr_Filter)& theFilter)
1196 {
1197   mySelectionFilterTypes.insert(theFilterType);
1198   myModule->registerSelectionFilter(theFilterType, theFilter);
1199 }
1200
1201 bool PartSet_SketcherMgr::operationActivatedByPreselection()
1202 {
1203   bool isOperationStopped = false;
1204   ModuleBase_Operation* anOperation = getCurrentOperation();
1205   if(anOperation && isNestedSketchOperation(anOperation)) {
1206     // Set final definitions if they are necessary
1207     //propertyPanelDefined(aOperation);
1208     /// Commit sketcher operations automatically
1209     /// distance operation are able to show popup editor to modify the distance value
1210     /// after entering the value, the operation should be committed/aborted(by Esc key)
1211     bool aCanCommitOperation = true;
1212     ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
1213                                                                             (anOperation);
1214     if (aFOperation && PartSet_SketcherMgr::isDistanceOperation(aFOperation)) {
1215       bool aValueAccepted = setDistanceValueByPreselection(anOperation, myModule->workshop(),
1216                                                            aCanCommitOperation);
1217       if (!aValueAccepted)
1218         return isOperationStopped;
1219     }
1220
1221     if (aCanCommitOperation)
1222       isOperationStopped = anOperation->commit();
1223     else {
1224       anOperation->abort();
1225       isOperationStopped = true;
1226     }
1227   }
1228   return isOperationStopped;
1229 }
1230
1231 bool PartSet_SketcherMgr::canUndo() const
1232 {
1233   return isNestedCreateOperation(getCurrentOperation(), activeSketch());
1234 }
1235
1236 bool PartSet_SketcherMgr::canRedo() const
1237 {
1238   return isNestedCreateOperation(getCurrentOperation(), activeSketch());
1239 }
1240
1241 bool PartSet_SketcherMgr::canEraseObject(const ObjectPtr& theObject) const
1242 {
1243   bool aCanErase = true;
1244   // when the sketch operation is active, results of sketch sub-feature can not be hidden
1245   if (myCurrentSketch.get()) {
1246     return !isObjectOfSketch(theObject);
1247   }
1248   return aCanErase;
1249 }
1250
1251 bool PartSet_SketcherMgr::canDisplayObject(const ObjectPtr& theObject) const
1252 {
1253   bool aCanDisplay = true;
1254
1255   bool aHasActiveSketch = activeSketch().get() != NULL;
1256   if (aHasActiveSketch) {
1257     // 1. the sketch feature should not be displayed during the sketch active operation
1258     // it is hidden by a sketch operation start and shown by a sketch stop, just the sketch
1259     // nested features can be visualized
1260     FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
1261     if (aFeature.get() != NULL && aFeature == activeSketch()) {
1262       aCanDisplay = false;
1263     }
1264     std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
1265                             std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
1266     /// some sketch entities should be never shown, e.g. projection feature
1267     if (aSketchFeature.get())
1268       aCanDisplay = aSketchFeature->canBeDisplayed();
1269   }
1270   else { // there are no an active sketch
1271     // 2. sketch sub-features should not be visualized if the sketch operation is not active
1272     FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
1273     if (aFeature.get() != NULL) {
1274       std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
1275                               std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
1276       if (aSketchFeature.get()) {
1277         aCanDisplay = false;
1278       }
1279     }
1280   }
1281
1282   // 3. the method should not filter the objects, which are not related to the current operation.
1283   // The object is filtered just if it is a current operation feature or this feature result
1284   if (aCanDisplay) {
1285     bool isObjectFound = false;
1286     ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
1287                                                                  (getCurrentOperation());
1288     if (aFOperation) {
1289       FeaturePtr aFeature = aFOperation->feature();
1290       if (aFeature.get()) {
1291         std::list<ResultPtr> aResults = aFeature->results();
1292         if (theObject == aFeature)
1293           isObjectFound = true;
1294         else {
1295           std::list<ResultPtr>::const_iterator anIt = aResults.begin(), aLast = aResults.end();
1296           for (; anIt != aLast && !isObjectFound; anIt++) {
1297             isObjectFound = *anIt == theObject;
1298           }
1299         }
1300       }
1301     }
1302     if (isObjectFound) {
1303       // 4. For created nested feature operation do not display the created feature if
1304       // the mouse curstor leaves the OCC window.
1305       // The correction cases, which ignores this condition:
1306       // a. the property panel values modification
1307       // b. the popup menu activated
1308       // c. widget editor control
1309       #ifndef DEBUG_DO_NOT_BY_ENTER
1310       if (isNestedCreateOperation(getCurrentOperation(), activeSketch())) {
1311         ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
1312         ModuleBase_WidgetEditor* anEditorWdg =
1313           anActiveWidget ? dynamic_cast<ModuleBase_WidgetEditor*>(anActiveWidget) : 0;
1314         // the active widget editor should not influence here. The presentation should be visible
1315         // always when this widget is active.
1316         if (!anEditorWdg && !myIsPopupMenuActive) {
1317           // during a nested create operation, the feature is redisplayed only
1318           // if the mouse over view
1319           // of there was a value modified in the property panel after the mouse left the view
1320           aCanDisplay = canDisplayCurrentCreatedFeature();
1321         }
1322       }
1323       #endif
1324     }
1325   }
1326
1327   // checks the sketcher constraints visibility according to active sketch check box states
1328   if (aCanDisplay) {
1329     bool aProcessed = false;
1330     FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
1331     if (aFeature.get()) {
1332       bool aConstraintDisplayed = canDisplayConstraint(aFeature, PartSet_Tools::Any, aProcessed);
1333       if (aProcessed)
1334         aCanDisplay = aConstraintDisplayed;
1335     }
1336   }
1337
1338   return aCanDisplay;
1339 }
1340
1341 bool PartSet_SketcherMgr::canDisplayConstraint(const FeaturePtr& theFeature,
1342                                              const PartSet_Tools::ConstraintVisibleState& theState,
1343                                              bool& isProcessed) const
1344 {
1345   bool aSwitchedOn = true;
1346
1347   const QStringList& aConstrIds = constraintsIdList();
1348
1349   std::string aKind = theFeature->getKind();
1350   if (aConstrIds.contains(QString(aKind.c_str()))) {
1351     bool isTypedConstraint = false;
1352
1353     switch (theState) {
1354       case PartSet_Tools::Dimensional: {
1355         bool isDistance = isDistanceKind(aKind);
1356         if (isDistance) {
1357           isProcessed = true;
1358           aSwitchedOn = myIsConstraintsShown[theState];
1359         }
1360       }
1361       break;
1362       case PartSet_Tools::Geometrical: {
1363         bool isGeometrical = !isDistanceKind(aKind);
1364         if (isGeometrical) {
1365           isProcessed = true;
1366           aSwitchedOn = myIsConstraintsShown[theState];
1367         }
1368       }
1369       break;
1370       case PartSet_Tools::Any: {
1371         isProcessed = true;
1372         bool isDistance = isDistanceKind(aKind);
1373         if (isDistance)
1374           aSwitchedOn = myIsConstraintsShown[PartSet_Tools::Dimensional];
1375         else
1376           aSwitchedOn = myIsConstraintsShown[PartSet_Tools::Geometrical];
1377       }
1378       break;
1379     default:
1380       break;
1381     }
1382   }
1383   return aSwitchedOn;
1384 }
1385
1386 /*void PartSet_SketcherMgr::processHiddenObject(const std::list<ObjectPtr>& theObjects)
1387 {
1388   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
1389                                                                            (getCurrentOperation());
1390   if (aFOperation && myCurrentSketch.get()) {
1391     // find results of the current operation
1392     // these results should not be proposed to be deleted
1393     FeaturePtr anOperationFeature = aFOperation->feature();
1394     std::list<ResultPtr> anOperationResultList = anOperationFeature->results();
1395     std::set<ResultPtr> anOperationResults;
1396     std::list<ResultPtr>::const_iterator aRIt = anOperationResultList.begin(),
1397                                         aRLast = anOperationResultList.end();
1398     for (; aRIt != aRLast; aRIt++)
1399       anOperationResults.insert(*aRIt);
1400
1401     std::set<FeaturePtr> anObjectsToBeDeleted;
1402     QStringList anObjectsToBeDeletedNames;
1403     std::list<ObjectPtr>::const_iterator anIt = theObjects.begin(), aLast = theObjects.end();
1404     for (; anIt != aLast; anIt++) {
1405       ObjectPtr anObject = *anIt;
1406       bool aCanErase = true;
1407       // when the sketch operation is active, results of sketch sub-feature can not be hidden
1408       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
1409       // the result is found between current feature results
1410       if (anOperationResults.find(aResult) != anOperationResults.end())
1411         continue;
1412
1413       if (aResult.get()) {
1414         // Display sketcher objects
1415         for (int i = 0; i < myCurrentSketch->numberOfSubs() && aCanErase; i++) {
1416           FeaturePtr aFeature = myCurrentSketch->subFeature(i);
1417           std::list<ResultPtr> aResults = aFeature->results();
1418           std::list<ResultPtr>::const_iterator anIt;
1419           for (anIt = aResults.begin(); anIt != aResults.end() && aCanErase; ++anIt) {
1420             aCanErase = *anIt != aResult;
1421           }
1422         }
1423       }
1424       if (!aCanErase) {
1425         FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
1426         if (aFeature.get() && anObjectsToBeDeleted.find(aFeature) == anObjectsToBeDeleted.end()) {
1427           anObjectsToBeDeleted.insert(aFeature);
1428           anObjectsToBeDeletedNames.append(aFeature->name().c_str());
1429         }
1430       }
1431     }
1432     if (!anObjectsToBeDeleted.empty()) {
1433       QString aFeatureNames = anObjectsToBeDeletedNames.join(", ");
1434       QString aMessage = tr("The following features have incorrect presentation and \
1435 will be hidden: %1. Would you like to delete them?")
1436                          .arg(aFeatureNames);
1437       int anAnswer = QMessageBox::question(qApp->activeWindow(), tr("Features hide"),
1438                                            aMessage, QMessageBox::Ok | QMessageBox::Cancel,
1439                                            QMessageBox::Cancel);
1440       if (anAnswer == QMessageBox::Ok) {
1441         QObjectPtrList anObjects;
1442         std::set<FeaturePtr>::const_iterator anIt = anObjectsToBeDeleted.begin(),
1443                                              aLast = anObjectsToBeDeleted.end();
1444         for (; anIt != aLast; anIt++)
1445           anObjects.append(*anIt);
1446         SessionPtr aMgr = ModelAPI_Session::get();
1447         DocumentPtr aDoc = aMgr->activeDocument();
1448         bool aIsOp = aMgr->isOperation();
1449         if (!aIsOp)
1450           aMgr->startOperation();
1451         workshop()->deleteFeatures(anObjects);
1452         //static Events_ID aDeletedEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
1453         //static Events_ID aRedispEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
1454         //Events_Loop::loop()->flush(aDeletedEvent);
1455         //Events_Loop::loop()->flush(aRedispEvent);
1456
1457         if (!aIsOp)
1458           aMgr->finishOperation();
1459       }
1460     }
1461   }
1462 }*/
1463
1464 bool PartSet_SketcherMgr::canDisplayCurrentCreatedFeature() const
1465 {
1466   bool aCanDisplay = myIsMouseOverWindow;
1467   if (!aCanDisplay) {
1468     ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
1469     if (anActiveWidget)
1470       aCanDisplay = anActiveWidget->getValueState() == ModuleBase_ModelWidget::Stored;
1471   }
1472   return aCanDisplay;
1473 }
1474
1475 bool PartSet_SketcherMgr::canChangeCursor(ModuleBase_Operation* theOperation) const
1476 {
1477   return isNestedCreateOperation(theOperation, activeSketch()) ||
1478          myModule->sketchReentranceMgr()->isInternalEditActive();
1479 }
1480
1481 const QMap<PartSet_Tools::ConstraintVisibleState, bool>& PartSet_SketcherMgr::showConstraintStates()
1482 {
1483   return myIsConstraintsShown;
1484 }
1485
1486 bool PartSet_SketcherMgr::isObjectOfSketch(const ObjectPtr& theObject) const
1487 {
1488   bool isFoundObject = false;
1489
1490   FeaturePtr anObjectFeature = ModelAPI_Feature::feature(theObject);
1491   if (anObjectFeature.get()) {
1492     int aSize = myCurrentSketch->numberOfSubs();
1493     for (int i = 0; i < aSize && !isFoundObject; i++) {
1494       FeaturePtr aCurrentFeature = myCurrentSketch->subFeature(i);
1495       isFoundObject = myCurrentSketch->subFeature(i) == anObjectFeature;
1496     }
1497   }
1498   return isFoundObject;
1499 }
1500
1501 void PartSet_SketcherMgr::onPlaneSelected(const std::shared_ptr<GeomAPI_Pln>& thePlane)
1502 {
1503   Handle(SelectMgr_Filter) aFilter = myModule->selectionFilter(SF_SketchPlaneFilter);
1504   if (!aFilter.IsNull())
1505     Handle(ModuleBase_ShapeInPlaneFilter)::DownCast(aFilter)->setPlane(thePlane);
1506
1507   workshop()->selectionActivate()->updateSelectionModes();
1508 }
1509
1510 bool PartSet_SketcherMgr::setDistanceValueByPreselection(ModuleBase_Operation* theOperation,
1511                                                          ModuleBase_IWorkshop* theWorkshop,
1512                                                          bool& theCanCommitOperation)
1513 {
1514   bool isValueAccepted = false;
1515   theCanCommitOperation = false;
1516
1517   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
1518                                                                               (theOperation);
1519   FeaturePtr aFeature = aFOperation->feature();
1520   // editor is shown only if all attribute references are filled by preseletion
1521   bool anAllRefAttrInitialized = true;
1522
1523   std::list<AttributePtr> aRefAttrs = aFeature->data()->attributes(
1524                                               ModelAPI_AttributeRefAttr::typeId());
1525   std::list<AttributePtr>::const_iterator anIt = aRefAttrs.begin(), aLast = aRefAttrs.end();
1526   for (; anIt != aLast && anAllRefAttrInitialized; anIt++) {
1527     anAllRefAttrInitialized = (*anIt)->isInitialized();
1528   }
1529   if (anAllRefAttrInitialized) {
1530     // Activate dimension value editing on double click
1531     ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel();
1532     QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();
1533     // Find corresponded widget to activate value editing
1534     foreach (ModuleBase_ModelWidget* aWgt, aWidgets) {
1535       if (aWgt->attributeID() == "ConstraintValue") {
1536         // the featue should be displayed in order to find the AIS text position,
1537         // the place where the editor will be shown
1538         aFeature->setDisplayed(true);
1539         /// the execute is necessary to perform in the feature compute for flyout position
1540         aFeature->execute();
1541
1542         Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
1543         Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
1544
1545         PartSet_WidgetEditor* anEditor = dynamic_cast<PartSet_WidgetEditor*>(aWgt);
1546         if (anEditor) {
1547           int aX = 0, anY = 0;
1548
1549           XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(theWorkshop);
1550           XGUI_Displayer* aDisplayer = aWorkshop->displayer();
1551           AISObjectPtr anAIS = aDisplayer->getAISObject(aFeature);
1552           Handle(AIS_InteractiveObject) anAISIO;
1553           if (anAIS.get() != NULL) {
1554             anAISIO = anAIS->impl<Handle(AIS_InteractiveObject)>();
1555           }
1556           if (anAIS.get() != NULL) {
1557             Handle(AIS_InteractiveObject) anAISIO = anAIS->impl<Handle(AIS_InteractiveObject)>();
1558
1559             if (!anAISIO.IsNull()) {
1560               Handle(AIS_Dimension) aDim = Handle(AIS_Dimension)::DownCast(anAISIO);
1561               if (!aDim.IsNull()) {
1562                 gp_Pnt aPosition = aDim->GetTextPosition();
1563
1564                 ModuleBase_IViewer* aViewer = aWorkshop->viewer();
1565                 Handle(V3d_View) aView = aViewer->activeView();
1566                 int aCX, aCY;
1567                 aView->Convert(aPosition.X(), aPosition.Y(), aPosition.Z(), aCX, aCY);
1568
1569                 QWidget* aViewPort = aViewer->activeViewPort();
1570                 QPoint aGlPoint = aViewPort->mapToGlobal(QPoint(aCX, aCY));
1571                 aX = aGlPoint.x();
1572                 anY = aGlPoint.y();
1573               }
1574             }
1575             anEditor->setCursorPosition(aX, anY);
1576             isValueAccepted = anEditor->showPopupEditor(false);
1577             theCanCommitOperation = true;
1578           }
1579         }
1580       }
1581     }
1582   }
1583   return isValueAccepted;
1584 }
1585
1586 void PartSet_SketcherMgr::getSelectionOwners(const FeaturePtr& theFeature,
1587                                              const FeaturePtr& theSketch,
1588                                              ModuleBase_IWorkshop* theWorkshop,
1589                                              const FeatureToSelectionMap& theSelection,
1590                                              SelectMgr_IndexedMapOfOwner& theOwnersToSelect)
1591 {
1592   if (theFeature.get() == NULL)
1593     return;
1594
1595   FeatureToSelectionMap::const_iterator anIt = theSelection.find(theFeature);
1596   SelectionInfo anInfo = anIt.value();
1597   std::set<AttributePtr> aSelectedAttributes = anInfo.myAttributes;
1598   std::set<ResultPtr> aSelectedResults = anInfo.myResults;
1599
1600   ModuleBase_IViewer* aViewer = theWorkshop->viewer();
1601
1602   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWorkshop);
1603   XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
1604
1605   // 1. found the feature's owners. Check the AIS objects of the constructions
1606   AISObjectPtr aAISObj = aDisplayer->getAISObject(theFeature);
1607   if (aAISObj.get() != NULL && aSelectedAttributes.empty() && aSelectedResults.empty()) {
1608     Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
1609
1610     SelectMgr_IndexedMapOfOwner aSelectedOwners;
1611     aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners);
1612     for  (Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++) {
1613       Handle(SelectMgr_EntityOwner) anOwner = aSelectedOwners(i);
1614       if (!anOwner.IsNull())
1615         theOwnersToSelect.Add(anOwner);
1616     }
1617   }
1618
1619   // 2. found the feature results's owners
1620   std::list<ResultPtr> aResults = theFeature->results();
1621   std::list<ResultPtr>::const_iterator aIt;
1622
1623   bool isSameShape = false;
1624   if (aResults.size() > 0) {
1625     ResultPtr aFirstResult = theFeature->firstResult();
1626     if (aFirstResult.get() && aFirstResult->shape().get()) {
1627       TopoDS_Shape aFirstShape = aFirstResult->shape()->impl<TopoDS_Shape>();
1628       isSameShape = aFirstShape.IsEqual(anInfo.myFirstResultShape);
1629     }
1630   }
1631   for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
1632     ResultPtr aResult = *aIt;
1633     AISObjectPtr aAISObj = aDisplayer->getAISObject(aResult);
1634     if (aAISObj.get() == NULL)
1635       continue;
1636     Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
1637
1638     SelectMgr_IndexedMapOfOwner aSelectedOwners;
1639     aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners);
1640     bool aFoundLocalShape = false;
1641     for  ( Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++ ) {
1642       Handle(StdSelect_BRepOwner) anOwner =
1643         Handle(StdSelect_BRepOwner)::DownCast(aSelectedOwners(i));
1644       if ( anOwner.IsNull() || !anOwner->HasShape() || theOwnersToSelect.FindIndex(anOwner))
1645         continue;
1646       const TopoDS_Shape& aShape = anOwner->Shape();
1647       TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
1648       if (aShapeType == TopAbs_VERTEX) {
1649         AttributePtr aPntAttr =
1650           PartSet_Tools::findAttributeBy2dPoint(theFeature, aShape, theSketch);
1651         if (aPntAttr.get() != NULL &&
1652             aSelectedAttributes.find(aPntAttr) != aSelectedAttributes.end())
1653           theOwnersToSelect.Add(anOwner);
1654         else if (isSameShape && anInfo.myLocalSelectedShapes.Contains(aShape)) {
1655           theOwnersToSelect.Add(anOwner);
1656         }
1657       }
1658       else if (aShapeType == TopAbs_EDGE) {
1659         if (isSameShape && anInfo.myLocalSelectedShapes.Contains(aShape)) {
1660           // try to restore local selection on Shape result
1661           // we can do this only if the shape was not changed
1662           theOwnersToSelect.Add(anOwner);
1663           aFoundLocalShape = true;
1664           break;
1665         }
1666       }
1667     }
1668     if (!aFoundLocalShape) {
1669       // result owners are put in the list of selection only if local selected shapes were not
1670       // found
1671       if (aSelectedResults.find(aResult) != aSelectedResults.end()) {
1672         for  ( Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++ ) {
1673           Handle(StdSelect_BRepOwner) anOwner =
1674             Handle(StdSelect_BRepOwner)::DownCast(aSelectedOwners(i));
1675           if ( anOwner.IsNull() || !anOwner->HasShape() || theOwnersToSelect.FindIndex(anOwner))
1676             continue;
1677             // select whole result
1678             theOwnersToSelect.Add(anOwner);
1679         }
1680       }
1681     }
1682   }
1683 }
1684
1685 void PartSet_SketcherMgr::connectToPropertyPanel(ModuleBase_ModelWidget* theWidget,
1686                                                  const bool isToConnect)
1687 {
1688   //Temporary commented as we do not modify values in property panel
1689   if (isToConnect) {
1690     //connect(theWidget, SIGNAL(beforeValuesChanged()),
1691     //        this, SLOT(onBeforeValuesChangedInPropertyPanel()));
1692     //connect(theWidget, SIGNAL(afterValuesChanged()),
1693     //        this, SLOT(onAfterValuesChangedInPropertyPanel()));
1694     connect(theWidget, SIGNAL(afterValuesChanged()),
1695             myModule->sketchReentranceMgr(), SLOT(onAfterValuesChangedInPropertyPanel()));
1696   }
1697   else {
1698     //disconnect(theWidget, SIGNAL(beforeValuesChanged()),
1699     //            this, SLOT(onBeforeValuesChangedInPropertyPanel()));
1700     //disconnect(theWidget, SIGNAL(afterValuesChanged()),
1701     //            this, SLOT(onAfterValuesChangedInPropertyPanel()));
1702     disconnect(theWidget, SIGNAL(afterValuesChanged()),
1703                myModule->sketchReentranceMgr(), SLOT(onAfterValuesChangedInPropertyPanel()));
1704   }
1705 }
1706
1707 void PartSet_SketcherMgr::widgetStateChanged(int thePreviousState)
1708 {
1709   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
1710                                                                            (getCurrentOperation());
1711   if (aFOperation) {
1712     if (PartSet_SketcherMgr::isSketchOperation(aFOperation) ||
1713         isNestedSketchOperation(aFOperation) &&
1714         thePreviousState == ModuleBase_ModelWidget::ModifiedInPP) {
1715       FeaturePtr aFeature = aFOperation->feature();
1716       visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature));
1717     }
1718   }
1719 }
1720
1721 void PartSet_SketcherMgr::customizePresentation(const ObjectPtr& theObject)
1722 {
1723   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
1724                                                                            (getCurrentOperation());
1725   if (aFOperation && (PartSet_SketcherMgr::isSketchOperation(aFOperation) ||
1726                       isNestedSketchOperation(aFOperation)))
1727     SketcherPrs_Tools::sendExpressionShownEvent(myIsConstraintsShown[PartSet_Tools::Expressions]);
1728
1729   // update entities selection priorities
1730   FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
1731   if (aFeature.get() && PartSet_SketcherMgr::isEntity(aFeature->getKind())) {
1732     // update priority for feature
1733     updateSelectionPriority(aFeature, aFeature);
1734     // update priority for results of the feature
1735     std::list<ResultPtr> aResults = aFeature->results();
1736     std::list<ResultPtr>::const_iterator anIt = aResults.begin(), aLastIt = aResults.end();
1737     for (; anIt != aLastIt; anIt++)
1738       updateSelectionPriority(*anIt, aFeature);
1739   }
1740 }
1741
1742 ModuleBase_Operation* PartSet_SketcherMgr::getCurrentOperation() const
1743 {
1744   return myModule->workshop()->currentOperation();
1745 }
1746
1747 //**************************************************************
1748 ModuleBase_ModelWidget* PartSet_SketcherMgr::getActiveWidget() const
1749 {
1750   ModuleBase_ModelWidget* aWidget = 0;
1751   ModuleBase_Operation* anOperation = getCurrentOperation();
1752   if (anOperation) {
1753     ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel();
1754     if (aPanel)
1755       aWidget = aPanel->activeWidget();
1756   }
1757   return aWidget;
1758 }
1759
1760 void PartSet_SketcherMgr::visualizeFeature(const FeaturePtr& theFeature,
1761                                            const bool isEditOperation,
1762                                            const bool isToDisplay,
1763                                            const bool isFlushRedisplay)
1764 {
1765   #ifdef DEBUG_DO_NOT_BY_ENTER
1766   return;
1767   #endif
1768
1769   if (isEditOperation || !theFeature.get())
1770     return;
1771
1772   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
1773   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
1774
1775   // 1. change visibility of the object itself, here the presentable object is processed,
1776   // e.g. constraints features
1777   //FeaturePtr aFeature = aFOperation->feature();
1778   std::list<ResultPtr> aResults = theFeature->results();
1779   if (isToDisplay)
1780     theFeature->setDisplayed(true);
1781   else
1782     theFeature->setDisplayed(false);
1783
1784   // change visibility of the object results, e.g. non-constraint features
1785   std::list<ResultPtr>::const_iterator aIt;
1786   for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
1787     if (isToDisplay) {
1788       (*aIt)->setDisplayed(true);
1789     }
1790     else {
1791       (*aIt)->setDisplayed(false);
1792     }
1793   }
1794   if (isFlushRedisplay)
1795     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
1796 }
1797
1798 void PartSet_SketcherMgr::storeSelection(const SelectionType theType,
1799                         PartSet_SketcherMgr::FeatureToSelectionMap& theCurrentSelection)
1800 {
1801   if (!myCurrentSketch.get())
1802     return;
1803
1804   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
1805   ModuleBase_ISelection* aSelect = aWorkshop->selection();
1806   QList<ModuleBase_ViewerPrsPtr> aStoredPrs;
1807
1808   if (theType == ST_HighlightType || theType == ST_SelectAndHighlightType)
1809     aStoredPrs = aSelect->getHighlighted();
1810
1811   QList<FeaturePtr> aFeatureList;
1812   if (theType == ST_SelectAndHighlightType || theType == ST_SelectType) {
1813     QList<ModuleBase_ViewerPrsPtr> aSelected = aSelect->getSelected(
1814                                                               ModuleBase_ISelection::AllControls);
1815     aStoredPrs.append(aSelected);
1816   }
1817
1818   // 1. it is necessary to save current selection in order to restore it after the features moving
1819   theCurrentSelection.clear();
1820
1821   QList<ModuleBase_ViewerPrsPtr>::const_iterator anIt = aStoredPrs.begin(),
1822                                                 aLast = aStoredPrs.end();
1823
1824   CompositeFeaturePtr aSketch = activeSketch();
1825   for (; anIt != aLast; anIt++) {
1826     ModuleBase_ViewerPrsPtr aPrs = *anIt;
1827     ObjectPtr anObject = aPrs->object();
1828     if (!anObject.get())
1829       continue;
1830
1831     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
1832     FeaturePtr aFeature;
1833     if (aResult.get())
1834       aFeature = ModelAPI_Feature::feature(aResult);
1835     else
1836       aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
1837
1838     if (!aFeature.get())
1839       continue;
1840
1841     std::set<AttributePtr> aSelectedAttributes;
1842     std::set<ResultPtr> aSelectedResults;
1843     SelectionInfo anInfo;
1844     if (theCurrentSelection.find(aFeature) != theCurrentSelection.end())
1845       anInfo = theCurrentSelection.find(aFeature).value();
1846
1847     TopoDS_Shape aFirstShape;
1848     ResultPtr aFirstResult = aFeature->firstResult();
1849     if (aFirstResult.get() && aFirstResult->shape().get())
1850       aFirstShape = aFirstResult->shape()->impl<TopoDS_Shape>();
1851     anInfo.myFirstResultShape = aFirstShape;
1852     Handle(SelectMgr_EntityOwner) anOwner = aPrs->owner();
1853     if (aResult.get()) {
1854       getAttributesOrResults(anOwner, aFeature, aSketch, aResult,
1855           anInfo.myAttributes, anInfo.myResults, anInfo.myLocalSelectedShapes);
1856     }
1857     else {
1858       std::list<ResultPtr> aResults = aFeature->results();
1859       std::list<ResultPtr>::const_iterator aIt;
1860       for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
1861         ResultPtr aResult = *aIt;
1862         getAttributesOrResults(anOwner, aFeature, aSketch, aResult,
1863           anInfo.myAttributes, anInfo.myResults, anInfo.myLocalSelectedShapes);
1864       }
1865     }
1866     theCurrentSelection[aFeature] = anInfo;
1867   }
1868   //qDebug(QString("  storeSelection: %1").arg(theCurrentSelection.size()).toStdString().c_str());
1869 }
1870
1871 void PartSet_SketcherMgr::restoreSelection(
1872                                 PartSet_SketcherMgr::FeatureToSelectionMap& theCurrentSelection)
1873 {
1874   if (!myCurrentSketch.get())
1875     return;
1876
1877   //qDebug(QString("restoreSelection: %1").arg(theCurrentSelection.size()).toStdString().c_str());
1878   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
1879   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
1880   FeatureToSelectionMap::const_iterator aSIt = theCurrentSelection.begin(),
1881                                         aSLast = theCurrentSelection.end();
1882   SelectMgr_IndexedMapOfOwner anOwnersToSelect;
1883   anOwnersToSelect.Clear();
1884   for (; aSIt != aSLast; aSIt++) {
1885     getSelectionOwners(aSIt.key(), myCurrentSketch, aWorkshop, theCurrentSelection,
1886                        anOwnersToSelect);
1887   }
1888   aConnector->workshop()->selector()->setSelectedOwners(anOwnersToSelect, false);
1889 }
1890
1891 void PartSet_SketcherMgr::onShowConstraintsToggle(int theType, bool theState)
1892 {
1893   PartSet_Tools::ConstraintVisibleState aType = (PartSet_Tools::ConstraintVisibleState)theType;
1894
1895   updateBySketchParameters(aType, theState);
1896 }
1897
1898 void PartSet_SketcherMgr::updateBySketchParameters(
1899                                    const PartSet_Tools::ConstraintVisibleState& theType,
1900                                    bool theState)
1901 {
1902   if (myCurrentSketch.get() == NULL)
1903     return;
1904
1905   bool aPrevState = myIsConstraintsShown[theType];
1906   myIsConstraintsShown[theType] = theState;
1907
1908   switch (theType) {
1909     case PartSet_Tools::Geometrical:
1910     case PartSet_Tools::Dimensional: {
1911       if (aPrevState != theState) {
1912         ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
1913         XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
1914         int aNumberOfSubs = myCurrentSketch->numberOfSubs();
1915         for (int i = 0; i < aNumberOfSubs; i++) {
1916           FeaturePtr aSubFeature = myCurrentSketch->subFeature(i);
1917           bool aProcessed = false;
1918           bool aConstraintDisplayed = canDisplayConstraint(aSubFeature, theType, aProcessed);
1919           if (aProcessed)
1920             aSubFeature->setDisplayed(aConstraintDisplayed);
1921         }
1922         Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
1923       }
1924     }
1925     break;
1926     case PartSet_Tools::Expressions: {
1927       if (aPrevState != theState) {
1928         /// call all sketch features redisplay, the expression state will be corrected in customize
1929         /// of distance presentation
1930         Events_ID anEventId = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
1931         PartSet_Tools::sendSubFeaturesEvent(myCurrentSketch, anEventId);
1932       }
1933     }
1934     break;
1935   }
1936 }
1937
1938 void PartSet_SketcherMgr::updateSelectionPriority(ObjectPtr theObject,
1939                                                   FeaturePtr theFeature)
1940 {
1941   if (!theObject.get() || !theFeature.get())
1942     return;
1943
1944   AISObjectPtr anAIS = workshop()->displayer()->getAISObject(theObject);
1945   Handle(AIS_InteractiveObject) anAISIO;
1946   if (anAIS.get() != NULL) {
1947     anAISIO = anAIS->impl<Handle(AIS_InteractiveObject)>();
1948   }
1949
1950   if (!anAISIO.IsNull()) { // the presentation for the object is visualized
1951     int anAdditionalPriority = 0;
1952     // current feature
1953     std::shared_ptr<SketchPlugin_Feature> aSPFeature =
1954             std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
1955     if (aSPFeature.get() != NULL) {
1956       // 1. Vertices
1957       // 2. Simple segments
1958       // 3. External objects (violet color)
1959       // 4. Auxiliary segments (dotted)
1960       // StdSelect_BRepSelectionTool::Load uses priority calculating:
1961       // Standard_Integer aPriority =
1962       // (thePriority == -1) ? GetStandardPriority (theShape, theType) : thePriority;
1963       // Priority of Vertex is 8, edge(segment) is 7.
1964       // It might be not corrected as provides the condition above.
1965       bool isExternal = aSPFeature->isExternal();
1966       bool isAuxiliary = PartSet_Tools::isAuxiliarySketchEntity(aSPFeature);
1967       // current feature
1968       if (!isExternal && !isAuxiliary)
1969         anAdditionalPriority = 30;
1970       // external feature
1971       if (isExternal)
1972         anAdditionalPriority = 20;
1973       // auxiliary feature
1974       if (isAuxiliary) {
1975         anAdditionalPriority = 10; /// auxiliary objects should have less priority that
1976         // edges/vertices of local selection on not-sketch objects
1977       }
1978       Handle(ModuleBase_ResultPrs) aResult = Handle(ModuleBase_ResultPrs)::DownCast(anAISIO);
1979       if (!aResult.IsNull()) {
1980         aResult->setAdditionalSelectionPriority(anAdditionalPriority);
1981       }
1982     }
1983   }
1984 }
1985
1986 XGUI_Workshop* PartSet_SketcherMgr::workshop() const
1987 {
1988   ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();
1989   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(anIWorkshop);
1990   return aConnector->workshop();
1991 }
1992
1993 XGUI_OperationMgr* PartSet_SketcherMgr::operationMgr() const
1994 {
1995   return workshop()->operationMgr();
1996 }
1997
1998 void PartSet_SketcherMgr::onShowPoints(bool toShow)
1999 {
2000   if (!myCurrentSketch.get())
2001     return;
2002   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
2003   ModuleBase_IViewer* aViewer = aWorkshop->viewer();
2004   Handle(AIS_InteractiveContext) aContext = aViewer->AISContext();
2005
2006   bool aToUpdate = false;
2007   if (toShow) {
2008     std::list<ResultPtr> aFreePoints = SketcherPrs_Tools::getFreePoints(myCurrentSketch);
2009
2010     // Delete obsolete presentations
2011     std::list<ResultPtr> aDelList;
2012     foreach(ResultPtr aObj, myPointsHighlight.keys()) {
2013       bool aFound = (std::find(aFreePoints.begin(), aFreePoints.end(), aObj) != aFreePoints.end());
2014       if (!aFound)
2015         aDelList.push_back(aObj);
2016     }
2017     foreach(ResultPtr aObj, aDelList) {
2018       aContext->Remove(myPointsHighlight[aObj], false);
2019       aToUpdate = true;
2020       myPointsHighlight.remove(aObj);
2021     }
2022
2023     // Display new objects
2024     QList<ResultPtr> aKeysList = myPointsHighlight.keys();
2025     std::list<ResultPtr>::const_iterator aIt;
2026     for (aIt = aFreePoints.cbegin(); aIt != aFreePoints.cend(); aIt++) {
2027       if (!aKeysList.contains(*aIt)) {
2028         GeomShapePtr aShapePtr = (*aIt)->shape();
2029         TopoDS_Shape aShape = aShapePtr->impl<TopoDS_Shape>();
2030         Handle(AIS_Shape) aShapePrs = new AIS_Shape(aShape);
2031         aShapePrs->SetColor(Quantity_NOC_BLUE1);
2032         aShapePrs->SetZLayer(Graphic3d_ZLayerId_Top);
2033         Handle(Prs3d_Drawer) aDrawer = aShapePrs->Attributes();
2034         if (aDrawer->HasOwnPointAspect()) {
2035           aDrawer->PointAspect()->SetTypeOfMarker(Aspect_TOM_O_STAR);
2036           aDrawer->PointAspect()->SetColor(Quantity_NOC_BLUE1);
2037           aDrawer->PointAspect()->SetScale(2);
2038         }
2039         else
2040           aDrawer->SetPointAspect(new Prs3d_PointAspect(Aspect_TOM_O_STAR, Quantity_NOC_BLUE1, 2));
2041         aContext->Display(aShapePrs, false);
2042         aContext->Deactivate(aShapePrs);
2043         myPointsHighlight[*aIt] = aShapePrs;
2044         aToUpdate = true;
2045       }
2046     }
2047   }
2048   else {
2049     foreach(Handle(AIS_Shape) aPrs, myPointsHighlight.values()) {
2050       aContext->Remove(aPrs, false);
2051       aToUpdate = true;
2052     }
2053     myPointsHighlight.clear();
2054   }
2055   if (aToUpdate)
2056     aViewer->update();
2057 }