]> SALOME platform Git repositories - modules/shaper.git/blob - src/PartSet/PartSet_WidgetPoint2d.cpp
Salome HOME
Issue #1393 Angle constraint : incorrect angle displayed. solution: do not select...
[modules/shaper.git] / src / PartSet / PartSet_WidgetPoint2d.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        PartSet_WidgetPoint2D.cpp
4 // Created:     25 Apr 2014
5 // Author:      Natalia ERMOLAEVA
6
7 #include "PartSet_WidgetPoint2d.h"
8 #include <PartSet_Tools.h>
9 #include <PartSet_Module.h>
10
11 #include <XGUI_Tools.h>
12 #include <XGUI_Workshop.h>
13 #include <XGUI_Displayer.h>
14
15 #include <ModuleBase_ParamSpinBox.h>
16 #include <ModuleBase_Tools.h>
17 #include <ModuleBase_IViewer.h>
18 #include <ModuleBase_IViewWindow.h>
19 #include <ModuleBase_ISelection.h>
20 #include <ModuleBase_ViewerPrs.h>
21 #include <ModuleBase_WidgetValidator.h>
22
23 #include <Config_Keywords.h>
24 #include <Config_WidgetAPI.h>
25
26 #include <Events_Loop.h>
27 #include <ModelAPI_Events.h>
28 #include <ModelAPI_AttributeBoolean.h>
29
30 #include <ModelAPI_Feature.h>
31 #include <ModelAPI_Data.h>
32 #include <ModelAPI_Object.h>
33 #include <GeomDataAPI_Point2D.h>
34 #include <GeomAPI_Pnt2d.h>
35
36 #include <SketchPlugin_Feature.h>
37 #include <SketchPlugin_ConstraintCoincidence.h>
38 #include <SketchPlugin_Line.h>
39 #include <SketchPlugin_Arc.h>
40 #include <SketchPlugin_Circle.h>
41 #include <SketchPlugin_Point.h>
42
43 #include <QGroupBox>
44 #include <QGridLayout>
45 #include <QLabel>
46 #include <QEvent>
47 #include <QMouseEvent>
48 #include <QApplication>
49
50 #include <TopoDS.hxx>
51 #include <TopoDS_Vertex.hxx>
52 #include <BRep_Tool.hxx>
53
54 #include <cfloat>
55 #include <climits>
56
57 const double MaxCoordinate = 1e12;
58
59 static QStringList MyFeaturesForCoincedence;
60
61 PartSet_WidgetPoint2D::PartSet_WidgetPoint2D(QWidget* theParent, 
62                                              ModuleBase_IWorkshop* theWorkshop,
63                                              const Config_WidgetAPI* theData)
64 : ModuleBase_ModelWidget(theParent, theData), myWorkshop(theWorkshop),
65   myValueIsCashed(false), myIsFeatureVisibleInCash(true),
66   myXValueInCash(0), myYValueInCash(0)
67 {
68   if (MyFeaturesForCoincedence.isEmpty()) {
69     MyFeaturesForCoincedence << SketchPlugin_Line::ID().c_str()
70       << SketchPlugin_Arc::ID().c_str()
71       << SketchPlugin_Point::ID().c_str()
72       << SketchPlugin_Circle::ID().c_str();
73   }
74
75   // the control should accept the focus, so the boolean flag is corrected to be true
76   myIsObligatory = true;
77   //myOptionParam = theData->getProperty(PREVIOUS_FEATURE_PARAM);
78   QString aPageName = QString::fromStdString(theData->getProperty(CONTAINER_PAGE_NAME));
79   myGroupBox = new QGroupBox(aPageName, theParent);
80   myGroupBox->setFlat(false);
81
82   bool aAcceptVariables = theData->getBooleanAttribute(DOUBLE_WDG_ACCEPT_EXPRESSIONS, true);
83
84   QGridLayout* aGroupLay = new QGridLayout(myGroupBox);
85   ModuleBase_Tools::adjustMargins(aGroupLay);
86   aGroupLay->setSpacing(2);
87   aGroupLay->setColumnStretch(1, 1);
88   {
89     QLabel* aLabel = new QLabel(myGroupBox);
90     aLabel->setText(tr("X "));
91     aGroupLay->addWidget(aLabel, 0, 0);
92
93     myXSpin = new ModuleBase_ParamSpinBox(myGroupBox);
94     myXSpin->setAcceptVariables(aAcceptVariables);
95     myXSpin->setMinimum(-DBL_MAX);
96     myXSpin->setMaximum(DBL_MAX);
97     myXSpin->setToolTip(tr("X"));
98     aGroupLay->addWidget(myXSpin, 0, 1);
99
100     connect(myXSpin, SIGNAL(valueChanged(const QString&)), this, SIGNAL(valuesModified()));
101   }
102   {
103     QLabel* aLabel = new QLabel(myGroupBox);
104     aLabel->setText(tr("Y "));
105     aGroupLay->addWidget(aLabel, 1, 0);
106
107     myYSpin = new ModuleBase_ParamSpinBox(myGroupBox);
108     myYSpin->setAcceptVariables(aAcceptVariables);
109     myYSpin->setMinimum(-DBL_MAX);
110     myYSpin->setMaximum(DBL_MAX);
111     myYSpin->setToolTip(tr("Y"));
112     aGroupLay->addWidget(myYSpin, 1, 1);
113
114     connect(myYSpin, SIGNAL(valueChanged(const QString&)), this, SIGNAL(valuesModified()));
115   }
116   QVBoxLayout* aLayout = new QVBoxLayout(this);
117   ModuleBase_Tools::zeroMargins(aLayout);
118   aLayout->addWidget(myGroupBox);
119   setLayout(aLayout);
120
121   myWidgetValidator = new ModuleBase_WidgetValidator(this, myWorkshop);
122 }
123
124 bool PartSet_WidgetPoint2D::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr& theValue)
125 {
126   bool aValid = true;
127   /*if (getValidState(theValue, aValid)) {
128     return aValid;
129   }
130   aValid = isValidSelectionCustom(theValue);
131   if (aValid)
132     aValid = isValidSelectionForAttribute(theValue, attribute());
133
134   storeValidState(theValue, aValid);
135   */return aValid;
136 }
137
138 bool PartSet_WidgetPoint2D::resetCustom()
139 {
140   bool aDone = false;
141   if (!isUseReset() || isComputedDefault() || myXSpin->hasVariable() || myYSpin->hasVariable()) {
142     aDone = false;
143   }
144   else {
145     if (myValueIsCashed) {
146       // if the restored value should be hidden, aDone = true to set
147       // reset state for the widget in the parent
148       aDone = restoreCurentValue();
149     }
150     else {
151       bool isOk;
152       double aDefValue = QString::fromStdString(getDefaultValue()).toDouble(&isOk);
153       // it is important to block the spin box control in order to do not through out the
154       // locking of the validating state.
155       ModuleBase_Tools::setSpinValue(myXSpin, isOk ? aDefValue : 0.0);
156       ModuleBase_Tools::setSpinValue(myYSpin, isOk ? aDefValue : 0.0);
157       storeValueCustom();
158       aDone = true;
159     }
160   }
161   return aDone;
162 }
163
164 PartSet_WidgetPoint2D::~PartSet_WidgetPoint2D()
165 {
166 }
167
168 bool PartSet_WidgetPoint2D::setSelection(QList<ModuleBase_ViewerPrsPtr>& theValues,
169                                          const bool theToValidate)
170 {
171   bool isDone = false;
172   if (theValues.empty())
173     return isDone;
174
175   ModuleBase_ViewerPrsPtr aValue = theValues.takeFirst();
176   GeomShapePtr aShape = aValue->shape();
177   if (aShape.get() && !aShape->isNull()) {
178     Handle(V3d_View) aView = myWorkshop->viewer()->activeView();
179     double aX, aY;
180     const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();
181     if (getPoint2d(aView, aTDShape, aX, aY)) {
182       isDone = setPoint(aX, aY);
183       PartSet_Tools::setConstraints(mySketch, feature(), attributeID(), aX, aY);
184     }
185   }
186   else if (canBeActivatedByMove()) {
187     if (feature()->getKind() == SketchPlugin_Line::ID()) {
188       FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aValue->object());
189       // Initialize new line with first point equal to end of previous
190       if (aFeature.get()) {
191         std::shared_ptr<ModelAPI_Data> aData = aFeature->data();
192         std::shared_ptr<GeomDataAPI_Point2D> aPoint = 
193           std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
194                                        aData->attribute(SketchPlugin_Line::END_ID()));
195         if (aPoint) {
196           setPoint(aPoint->x(), aPoint->y());
197           PartSet_Tools::setConstraints(mySketch, feature(), attributeID(), aPoint->x(),
198                                         aPoint->y());
199           isDone = true;
200         }
201       }
202     }
203   }
204   return isDone;
205 }
206
207 void PartSet_WidgetPoint2D::selectContent()
208 {
209   myXSpin->selectAll();
210 }
211
212 bool PartSet_WidgetPoint2D::setPoint(double theX, double theY)
213 {
214   if (fabs(theX) >= MaxCoordinate)
215     return false;
216   if (fabs(theY) >= MaxCoordinate)
217     return false;
218
219   ModuleBase_Tools::setSpinValue(myXSpin, theX);
220   ModuleBase_Tools::setSpinValue(myYSpin, theY);
221
222   storeValue();
223   return true;
224 }
225
226 bool PartSet_WidgetPoint2D::storeValueCustom() const
227 {
228   std::shared_ptr<ModelAPI_Data> aData = myFeature->data();
229   if (!aData) // can be on abort of sketcher element
230     return false;
231   std::shared_ptr<GeomDataAPI_Point2D> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
232       aData->attribute(attributeID()));
233
234   PartSet_WidgetPoint2D* that = (PartSet_WidgetPoint2D*) this;
235   bool isBlocked = that->blockSignals(true);
236   bool isImmutable = aPoint->setImmutable(true);
237
238   // if text is not empty then setValue will be ignored
239   // so we should set the text at first
240   aPoint->setText(myXSpin->hasVariable() ? myXSpin->text().toStdString() : "",
241                   myYSpin->hasVariable() ? myYSpin->text().toStdString() : "");
242   aPoint->setValue(!myXSpin->hasVariable() ? myXSpin->value() : aPoint->x(),
243                    !myYSpin->hasVariable() ? myYSpin->value() : aPoint->y());
244
245   // after movement the solver will call the update event: optimization
246   moveObject(myFeature);
247   aPoint->setImmutable(isImmutable);
248   that->blockSignals(isBlocked);
249
250   return true;
251 }
252
253 bool PartSet_WidgetPoint2D::restoreValueCustom()
254 {
255   std::shared_ptr<ModelAPI_Data> aData = myFeature->data();
256   std::shared_ptr<GeomDataAPI_Point2D> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
257       aData->attribute(attributeID()));
258   QString aTextX = QString::fromStdString(aPoint->textX());
259   QString aTextY = QString::fromStdString(aPoint->textY());
260
261   bool isDouble = false;
262   double aVal = 0;
263   if (aTextX.isEmpty()) {
264     ModuleBase_Tools::setSpinValue(myXSpin, aPoint->x());
265   } else {
266     aVal = aTextX.toDouble(&isDouble);
267     if (isDouble)
268       ModuleBase_Tools::setSpinValue(myXSpin, aVal);
269     else
270       ModuleBase_Tools::setSpinText(myXSpin, aTextX);
271   }
272   if (aTextY.isEmpty()) {
273     ModuleBase_Tools::setSpinValue(myYSpin, aPoint->y());
274   } else {
275     aVal = aTextY.toDouble(&isDouble);
276     if (isDouble)
277       ModuleBase_Tools::setSpinValue(myYSpin, aVal);
278     else
279       ModuleBase_Tools::setSpinText(myYSpin, aTextY);
280   }
281   //if (aTextX.empty() || aTextY.empty()) {
282   //  ModuleBase_Tools::setSpinValue(myXSpin, aPoint->x());
283   //  ModuleBase_Tools::setSpinValue(myYSpin, aPoint->y());
284   //} else {
285   //  ModuleBase_Tools::setSpinText(myXSpin, QString::fromStdString(aTextX));
286   //  ModuleBase_Tools::setSpinText(myYSpin, QString::fromStdString(aTextY));
287   //}
288   return true;
289 }
290
291 void PartSet_WidgetPoint2D::storeCurentValue()
292 {
293   // do not use cash if a variable is used
294   if (myXSpin->hasVariable() || myYSpin->hasVariable())
295     return;
296
297   myValueIsCashed = true;
298   myIsFeatureVisibleInCash = XGUI_Displayer::isVisible(
299                        XGUI_Tools::workshop(myWorkshop)->displayer(), myFeature);
300   myXValueInCash = myXSpin->value();
301   myYValueInCash = myYSpin->value();
302 }
303
304 bool PartSet_WidgetPoint2D::restoreCurentValue()
305 {
306   bool aRestoredAndHidden = true;
307
308   bool isVisible = myIsFeatureVisibleInCash;
309   // fill the control widgets by the cashed value
310
311   myValueIsCashed = false;
312   myIsFeatureVisibleInCash = true;
313   ModuleBase_Tools::setSpinValue(myXSpin, myXValueInCash);
314   ModuleBase_Tools::setSpinValue(myYSpin, myYValueInCash);
315
316   // store value to the model
317   storeValueCustom();
318   if (isVisible) {
319     setValueState(Stored);
320     aRestoredAndHidden = false;
321   }
322   else
323     aRestoredAndHidden = true;
324
325   return aRestoredAndHidden;
326 }
327
328 QList<QWidget*> PartSet_WidgetPoint2D::getControls() const
329 {
330   QList<QWidget*> aControls;
331   aControls.append(myXSpin);
332   aControls.append(myYSpin);
333   return aControls;
334 }
335
336
337 void PartSet_WidgetPoint2D::activateCustom()
338 {
339   ModuleBase_IViewer* aViewer = myWorkshop->viewer();
340   connect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)), 
341           this, SLOT(onMouseMove(ModuleBase_IViewWindow*, QMouseEvent*)));
342   connect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)), 
343           this, SLOT(onMouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)));
344
345   QIntList aModes;
346   aModes << TopAbs_VERTEX;
347   aModes << TopAbs_EDGE;
348   myWorkshop->activateSubShapesSelection(aModes);
349
350   if (!isEditingMode()) {
351     FeaturePtr aFeature = feature();
352     if (aFeature.get() && aFeature->getKind() == SketchPlugin_Point::ID())
353       storeValue();
354   }
355 }
356
357 bool PartSet_WidgetPoint2D::canBeActivatedByMove()
358 {
359   bool aCanBeActivated = false;
360   if (feature()->getKind() == SketchPlugin_Line::ID() &&
361       attributeID() == SketchPlugin_Line::START_ID())
362     aCanBeActivated = true;
363
364   return aCanBeActivated;
365 }
366
367 void PartSet_WidgetPoint2D::deactivate()
368 {
369   // the value of the control should be stored to model if it was not
370   // initialized yet. It is important when we leave this control by Tab key.
371   // It should not be performed by the widget activation as the preview
372   // is visualized with default value. Line point is moved to origin.
373   AttributePtr anAttribute = myFeature->data()->attribute(attributeID());
374   if (anAttribute && !anAttribute->isInitialized())
375     storeValue();
376
377   ModuleBase_ModelWidget::deactivate();
378   ModuleBase_IViewer* aViewer = myWorkshop->viewer();
379   disconnect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)),
380              this, SLOT(onMouseMove(ModuleBase_IViewWindow*, QMouseEvent*)));
381   disconnect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)), 
382              this, SLOT(onMouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)));
383
384   myWorkshop->deactivateSubShapesSelection();
385 }
386
387 bool PartSet_WidgetPoint2D::getPoint2d(const Handle(V3d_View)& theView, 
388                                        const TopoDS_Shape& theShape, 
389                                        double& theX, double& theY) const
390 {
391   if (!theShape.IsNull()) {
392     if (theShape.ShapeType() == TopAbs_VERTEX) {
393       const TopoDS_Vertex& aVertex = TopoDS::Vertex(theShape);
394       if (!aVertex.IsNull()) {
395         // A case when point is taken from existing vertex
396         gp_Pnt aPoint = BRep_Tool::Pnt(aVertex);
397         PartSet_Tools::convertTo2D(aPoint, mySketch, theView, theX, theY);
398         return true;
399       }
400     }
401   }
402   return false;
403 }
404
405 bool PartSet_WidgetPoint2D::setConstraintWith(const ObjectPtr& theObject)
406 {
407   std::shared_ptr<GeomDataAPI_Point2D> aFeaturePoint;
408   if (feature()->isMacro()) {
409     AttributePtr aThisAttr = feature()->data()->attribute(attributeID());
410     std::shared_ptr<GeomDataAPI_Point2D> anAttrPoint =
411                                std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aThisAttr);
412     if (anAttrPoint.get()) {
413       // the macro feature will be removed after the operation is stopped, so we need to build
414       // coicidence to possible sub-features
415       aFeaturePoint = PartSet_Tools::findFirstEqualPointInArgumentFeatures(feature(),
416                                                                  anAttrPoint->pnt());
417     }
418   }
419   else {
420     AttributePtr aThisAttr = feature()->data()->attribute(attributeID());
421     aFeaturePoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aThisAttr);
422   }
423   if (!aFeaturePoint.get())
424     return false;
425
426   // Create point-edge coincedence
427   FeaturePtr aFeature = mySketch->addFeature(SketchPlugin_ConstraintCoincidence::ID());
428   std::shared_ptr<ModelAPI_Data> aData = aFeature->data();
429
430   std::shared_ptr<ModelAPI_AttributeRefAttr> aRef1 = std::dynamic_pointer_cast<
431       ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
432
433   aRef1->setAttr(aFeaturePoint);
434
435   std::shared_ptr<ModelAPI_AttributeRefAttr> aRef2 = std::dynamic_pointer_cast<
436       ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
437   aRef2->setObject(theObject);
438
439   // we need to flush created signal in order to coincidence is processed by solver
440   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
441
442   return true;
443 }
444
445 void PartSet_WidgetPoint2D::onMouseRelease(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
446 {
447   // the contex menu release by the right button should not be processed by this widget
448   if (theEvent->button() != Qt::LeftButton)
449     return;
450
451   ModuleBase_ISelection* aSelection = myWorkshop->selection();
452   Handle(V3d_View) aView = theWnd->v3dView();
453   // TODO: This fragment doesn't work because bug in OCC Viewer. It can be used after fixing.
454   NCollection_List<TopoDS_Shape> aShapes;
455   std::list<ObjectPtr> aObjects;
456   aSelection->selectedShapes(aShapes, aObjects);
457   // if we have selection and use it
458   if (aShapes.Extent() > 0 && useSelectedShapes()) {
459     TopoDS_Shape aShape = aShapes.First();
460     ObjectPtr aObject = aObjects.front();
461     FeaturePtr aSelectedFeature = ModelAPI_Feature::feature(aObject);
462     bool anExternal = false;
463     std::shared_ptr<SketchPlugin_Feature> aSPFeature;
464     if (aSelectedFeature.get() != NULL)
465       aSPFeature = std::dynamic_pointer_cast<SketchPlugin_Feature>(aSelectedFeature);
466       if ((!aSPFeature && !aShape.IsNull()) ||
467           (aSPFeature.get() && aSPFeature->isExternal())) {
468         ResultPtr aFixedObject;
469         anExternal = true;
470         aFixedObject = PartSet_Tools::findFixedObjectByExternal(aShape, aObject, mySketch);
471         if (!aFixedObject.get())
472           aFixedObject = PartSet_Tools::createFixedObjectByExternal(aShape, aObject, mySketch);
473         double aX, aY;
474         if (getPoint2d(aView, aShape, aX, aY) && isFeatureContainsPoint(myFeature, aX, aY)) {
475           // do not create a constraint to the point, which already used by the feature
476           // if the feature contains the point, focus is not switched
477           setPoint(aX, aY);
478         }
479         else {
480           if (getPoint2d(aView, aShape, aX, aY))
481             setPoint(aX, aY);
482           else
483             setValueState(Stored); // in case of edge selection, Apply state should also be updated
484           bool anOrphanPoint = aShape.ShapeType() == TopAbs_VERTEX ||
485                                isOrphanPoint(aSelectedFeature, mySketch, aX, aY);
486           if (anExternal) {
487             anOrphanPoint = true; // we should not stop reentrant operation on external objects because
488             // they are not participate in the contour creation excepting external vertices
489             if (aShape.ShapeType() == TopAbs_VERTEX) {
490               FeaturePtr aFixedFeature = ModelAPI_Feature::feature(aFixedObject);
491               if (aFixedFeature.get() && aFixedFeature->getKind() == SketchPlugin_Point::ID()) {
492                 anOrphanPoint = isOrphanPoint(aFixedFeature, mySketch, aX, aY);
493               }
494             }
495           }
496           if (aFixedObject.get())
497             setConstraintWith(aFixedObject);
498           // fignal updated should be flushed in order to visualize possible created external objects
499           // e.g. selection of trihedron axis when input end arc point
500           updateObject(feature());
501
502           if (!anOrphanPoint)
503             emit vertexSelected(); // it stops the reentrant operation
504
505           emit focusOutWidget(this);
506         }
507       }
508     if (!anExternal) {
509       double aX, aY;
510       bool isProcessed = false;
511       if (getPoint2d(aView, aShape, aX, aY) && isFeatureContainsPoint(myFeature, aX, aY)) {
512         // when the point is selected, the coordinates of the point should be set into the attribute
513         // if the feature contains the point, focus is not switched
514         setPoint(aX, aY);
515       }
516       else {
517         bool anOrphanPoint = isOrphanPoint(aSelectedFeature, mySketch, aX, aY);
518         // do not set a coincidence constraint in the attribute if the feature contains a point
519         // with the same coordinates. It is important for line creation in order to do not set
520         // the same constraints for the same points, oterwise the result line has zero length.
521         bool isAuxiliaryFeature = false;
522         if (getPoint2d(aView, aShape, aX, aY)) {
523           setPoint(aX, aY);
524           feature()->execute();
525           PartSet_Tools::setConstraints(mySketch, feature(), attributeID(), aX, aY);
526         }
527         else if (aShape.ShapeType() == TopAbs_EDGE) {
528           if (!setConstraintWith(aObject)) {
529             gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWnd->v3dView());
530             PartSet_Tools::convertTo2D(aPoint, mySketch, aView, aX, aY);
531             setPoint(aX, aY);
532           }
533           setValueState(Stored); // in case of edge selection, Apply state should also be updated
534           isAuxiliaryFeature = PartSet_Tools::isAuxiliarySketchEntity(aObject);
535         }
536         // it is important to perform updateObject() in order to the current value is 
537         // processed by Sketch Solver. Test case: line is created from a previous point
538         // to some distance, but in the area of the highlighting of the point. Constraint
539         // coincidence is created, after the solver is performed, the distance between the
540         // points of the line becomes less than the tolerance. Validator of the line returns
541         // false, the line will be aborted, but sketch stays valid.
542         updateObject(feature());
543         if (!anOrphanPoint && !anExternal && !isAuxiliaryFeature)
544           emit vertexSelected();
545         emit focusOutWidget(this);
546       }
547     }
548   }
549   // End of Bug dependent fragment
550   else {
551     // A case when point is taken from mouse event
552     gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWnd->v3dView());
553     double aX, anY;
554     PartSet_Tools::convertTo2D(aPoint, mySketch, aView, aX, anY);
555
556     // if the feature contains the point, focus is not switched
557     if (!setPoint(aX, anY) || isFeatureContainsPoint(myFeature, aX, anY))
558       return;
559
560     /// Start alternative code
561     //std::shared_ptr<GeomDataAPI_Point2D> aFeaturePoint = std::dynamic_pointer_cast<
562     //    GeomDataAPI_Point2D>(feature()->data()->attribute(attributeID()));
563     //QList<FeaturePtr> aIgnore;
564     //aIgnore.append(feature());
565
566     //double aTolerance = aView->Convert(7);
567     //std::shared_ptr<GeomDataAPI_Point2D> aAttrPnt = 
568     //  PartSet_Tools::findAttributePoint(mySketch, aX, anY, aTolerance, aIgnore);
569     //if (aAttrPnt.get() != NULL) {
570     //  aFeaturePoint->setValue(aAttrPnt->pnt());
571     //  PartSet_Tools::createConstraint(mySketch, aAttrPnt, aFeaturePoint);
572     //  emit vertexSelected();
573     //}
574     /// End alternative code
575     emit focusOutWidget(this);
576   }
577 }
578
579
580 void PartSet_WidgetPoint2D::onMouseMove(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
581 {
582   if (isEditingMode())
583     return;
584
585   gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWnd->v3dView());
586
587   double aX, anY;
588   PartSet_Tools::convertTo2D(aPoint, mySketch, theWnd->v3dView(), aX, anY);
589   if (myState != ModifiedInViewer)
590     storeCurentValue();
591   // we need to block the value state change 
592   bool isBlocked = blockValueState(true);
593   setPoint(aX, anY);
594   blockValueState(isBlocked);
595   setValueState(ModifiedInViewer);
596 }
597
598 double PartSet_WidgetPoint2D::x() const
599 {
600   return myXSpin->value();
601 }
602
603 double PartSet_WidgetPoint2D::y() const
604 {
605   return myYSpin->value();
606 }
607
608
609 bool PartSet_WidgetPoint2D::isFeatureContainsPoint(const FeaturePtr& theFeature,
610                                                    double theX, double theY)
611 {
612   bool aPointIsFound = false;
613
614   if (feature()->getKind() != SketchPlugin_Line::ID())
615     return aPointIsFound;
616
617   AttributePtr aWidgetAttribute = myFeature->attribute(attributeID());
618
619   std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = 
620                                     std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(theX, theY));
621   std::list<AttributePtr> anAttributes =
622                                 myFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
623   std::list<AttributePtr>::iterator anIter = anAttributes.begin();
624   for(; anIter != anAttributes.end() && !aPointIsFound; anIter++) {
625     AttributePoint2DPtr aPoint2DAttribute =
626       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIter);
627     if (aPoint2DAttribute == aWidgetAttribute)
628       continue;
629     if (aPoint2DAttribute.get() && aPoint2DAttribute->isInitialized()) {
630       aPointIsFound = aPoint2DAttribute->pnt()->isEqual(aPnt2d);
631     }
632   }
633   return aPointIsFound;
634 }
635
636 void PartSet_WidgetPoint2D::initializeValueByActivate()
637 {
638 }
639
640 /*void PartSet_WidgetPoint2D::onValuesChanged()
641 {
642   emit valuesChanged();
643 }*/
644
645 bool PartSet_WidgetPoint2D::processEnter()
646 {
647   bool isModified = getValueState() == ModifiedInPP;
648   if (isModified) {
649     bool isXModified = myXSpin->hasFocus();
650     emit valuesChanged();
651     if (isXModified)
652       myXSpin->selectAll();
653     else
654       myYSpin->selectAll();
655   }
656   return isModified;
657 }
658
659 bool PartSet_WidgetPoint2D::useSelectedShapes() const
660 {
661   return true;
662 }
663
664 bool PartSet_WidgetPoint2D::isOrphanPoint(const FeaturePtr& theFeature,
665                                           const CompositeFeaturePtr& theSketch,
666                                           double theX, double theY)
667 {
668   bool anOrphanPoint = false;
669   if (theFeature.get()) {
670     std::shared_ptr<GeomDataAPI_Point2D> aPointAttr;
671     std::string aFeatureKind = theFeature->getKind();
672     if (aFeatureKind == SketchPlugin_Point::ID())
673       aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
674                                        theFeature->attribute(SketchPlugin_Point::COORD_ID()));
675     else if (aFeatureKind == SketchPlugin_Circle::ID())
676       aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
677                                        theFeature->attribute(SketchPlugin_Circle::CENTER_ID()));
678
679     else if (aFeatureKind == SketchPlugin_Arc::ID())
680       aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
681                                        theFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
682
683     /// check that the geometry point with the given coordinates is the checked point
684     /// e.g. in arc the (x,y) point can not coicide to the center point and it automatically
685     /// means that this point is not an orphant one.
686     if (aPointAttr.get()) {
687       std::shared_ptr<GeomAPI_Pnt2d> aCheckedPoint = std::shared_ptr<GeomAPI_Pnt2d>(
688                                                     new GeomAPI_Pnt2d(theX, theY));
689       if (!aCheckedPoint->isEqual(aPointAttr->pnt()))
690         return anOrphanPoint;
691     }
692
693     if (aPointAttr.get()) {
694       std::shared_ptr<GeomAPI_Pnt2d> aPoint = aPointAttr->pnt();
695       // we need to find coincidence features in results also, because external object(point)
696       // uses refs to me in another feature.
697       FeaturePtr aCoincidence = PartSet_Tools::findFirstCoincidence(theFeature, aPoint);
698       anOrphanPoint = true;
699       // if there is at least one concident line to the point, the point is not an orphant
700       if (aCoincidence.get()) {
701         QList<FeaturePtr> aCoinsideLines;
702         QList<FeaturePtr> aCoins;
703         PartSet_Tools::findCoincidences(aCoincidence, aCoinsideLines, aCoins,
704                                         SketchPlugin_ConstraintCoincidence::ENTITY_A());
705         PartSet_Tools::findCoincidences(aCoincidence, aCoinsideLines, aCoins,
706                                         SketchPlugin_ConstraintCoincidence::ENTITY_B());
707         QList<FeaturePtr>::const_iterator anIt = aCoinsideLines.begin(),
708                                           aLast = aCoinsideLines.end();
709         for (; anIt != aLast && anOrphanPoint; anIt++) {
710           anOrphanPoint = (*anIt)->getKind() != SketchPlugin_Line::ID();
711         }
712       }
713     }
714   }
715   return anOrphanPoint;
716 }