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