]> SALOME platform Git repositories - modules/shaper.git/blob - src/PartSet/PartSet_WidgetBSplinePoints.cpp
Salome HOME
5050b335534b8b465bbf849ad985cde37d41bc7e
[modules/shaper.git] / src / PartSet / PartSet_WidgetBSplinePoints.cpp
1 // Copyright (C) 2019-2020  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include <PartSet_WidgetBSplinePoints.h>
21
22 #include <PartSet_CenterPrs.h>
23 #include <PartSet_ExternalObjectsMgr.h>
24 #include <PartSet_Module.h>
25 #include <PartSet_SketcherReentrantMgr.h>
26 #include <PartSet_WidgetPoint2d.h>
27
28 #include <XGUI_Tools.h>
29 #include <XGUI_Workshop.h>
30 #include <XGUI_Displayer.h>
31
32 #include <ModuleBase_ISelection.h>
33 #include <ModuleBase_IViewer.h>
34 #include <ModuleBase_IViewWindow.h>
35 #include <ModuleBase_LabelValue.h>
36 #include <ModuleBase_Tools.h>
37 #include <ModuleBase_ViewerPrs.h>
38 #include <ModuleBase_WidgetValidator.h>
39 #include <ModuleBase_WidgetValidated.h>
40
41 #include <Config_Keywords.h>
42 #include <Config_WidgetAPI.h>
43
44 #include <Events_Loop.h>
45
46 #include <ModelAPI_Events.h>
47 #include <ModelAPI_AttributeDoubleArray.h>
48 #include <ModelAPI_AttributeRefAttrList.h>
49 #include <ModelAPI_CompositeFeature.h>
50
51 #include <GeomDataAPI_Point2D.h>
52 #include <GeomDataAPI_Point2DArray.h>
53
54 #include <GeomAPI_Pnt2d.h>
55
56 #include <SketchPlugin_ConstraintCoincidence.h>
57
58 #include <QGridLayout>
59 #include <QGroupBox>
60 #include <QMouseEvent>
61
62 static const double MaxCoordinate = 1e12;
63
64 PartSet_WidgetBSplinePoints::PartSet_WidgetBSplinePoints(QWidget* theParent,
65                                              ModuleBase_IWorkshop* theWorkshop,
66                                              const Config_WidgetAPI* theData)
67 : ModuleBase_ModelWidget(theParent, theData), myWorkshop(theWorkshop),
68   myValueIsCashed(false), myIsFeatureVisibleInCash(true),
69   myXValueInCash(0), myYValueInCash(0),
70   myPointIndex(0), myFinished(false)
71 {
72   myRefAttribute = theData->getProperty("reference_attribute");
73
74   // the control should accept the focus, so the boolean flag is corrected to be true
75   myIsObligatory = true;
76   QString aPageName = translate(theData->getProperty(CONTAINER_PAGE_NAME));
77   myGroupBox = new QGroupBox(aPageName, theParent);
78   myGroupBox->setFlat(false);
79
80   bool aAcceptVariables = theData->getBooleanAttribute(DOUBLE_WDG_ACCEPT_EXPRESSIONS, true);
81
82   // B-spline weights attribute
83   myWeightsAttr = theData->getProperty("weights");
84
85   QGridLayout* aGroupLay = new QGridLayout(myGroupBox);
86   ModuleBase_Tools::adjustMargins(aGroupLay);
87   aGroupLay->setSpacing(4);
88   aGroupLay->setColumnStretch(1, 1);
89   createNextPoint();
90
91   QVBoxLayout* aLayout = new QVBoxLayout(this);
92   ModuleBase_Tools::zeroMargins(aLayout);
93   aLayout->addWidget(myGroupBox);
94   setLayout(aLayout);
95
96   myWidgetValidator = new ModuleBase_WidgetValidator(this, myWorkshop);
97   myExternalObjectMgr = new PartSet_ExternalObjectsMgr(theData->getProperty("use_external"),
98                                          theData->getProperty("can_create_external"), true);
99 }
100
101 void PartSet_WidgetBSplinePoints::createNextPoint()
102 {
103   storeCurentValue();
104
105   QGridLayout* aGroupLay = dynamic_cast<QGridLayout*>(myGroupBox->layout());
106   int row = (int)(myXSpin.size() + myWeightSpin.size());
107
108   QString aPoleStr = tr("Pole %1");
109   aPoleStr = aPoleStr.arg(myXSpin.size() + 1);
110
111   QGroupBox* aPoleGroupBox = new QGroupBox(aPoleStr, myGroupBox);
112   QGridLayout* aPoleLay = new QGridLayout(aPoleGroupBox);
113   ModuleBase_Tools::adjustMargins(aPoleLay);
114   aPoleLay->setSpacing(2);
115   aPoleLay->setColumnStretch(1, 1);
116
117   myXSpin.push_back(new ModuleBase_LabelValue(aPoleGroupBox, tr("X")));
118   aPoleLay->addWidget(myXSpin.back(), 0, 1);
119   myYSpin.push_back(new ModuleBase_LabelValue(aPoleGroupBox, tr("Y")));
120   aPoleLay->addWidget(myYSpin.back(), 1, 1);
121
122   aGroupLay->addWidget(aPoleGroupBox, row, 1);
123
124   QString aWeightStr = tr("Weight %1");
125   aWeightStr = aWeightStr.arg(myWeightSpin.size() + 1);
126
127   myWeightSpin.push_back(new ModuleBase_LabelValue(myGroupBox, aWeightStr));
128   aGroupLay->addWidget(myWeightSpin.back(), ++row, 1);
129 }
130
131 void PartSet_WidgetBSplinePoints::removeLastPoint()
132 {
133   QGridLayout* aGroupLay = dynamic_cast<QGridLayout*>(myGroupBox->layout());
134   aGroupLay->removeWidget(myWeightSpin.back());
135   myWeightSpin.pop_back();
136   aGroupLay->removeWidget(myYSpin.back());
137   aGroupLay->removeWidget(myXSpin.back());
138   aGroupLay->removeWidget(myXSpin.back()->parentWidget());
139   myYSpin.pop_back();
140   myXSpin.pop_back();
141
142   // update B-spline feature attributes
143   storeValueCustom();
144 }
145
146 bool PartSet_WidgetBSplinePoints::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr& theValue)
147 {
148   bool aValid = true;
149
150   PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
151   if (aModule->sketchReentranceMgr()->isInternalEditActive())
152     return true; // when internal edit is started a new feature is created. I has not results, AIS
153
154   // the selection is not possible if the current feature has no presentation for the current
155   // attribute not in AIS not in results. If so, no object in current feature where make
156   // coincidence, so selection is not necessary
157   GeomShapePtr anAISShape;
158   GeomPresentablePtr aPrs = std::dynamic_pointer_cast<GeomAPI_IPresentable>(myFeature);
159   if (aPrs.get()) {
160     AISObjectPtr anAIS;
161     anAIS = aPrs->getAISObject(anAIS);
162     if (anAIS.get()) {
163       anAISShape = anAIS->getShape();
164     }
165   }
166   const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = myFeature->results();
167   if (!anAISShape.get() && aResults.empty())
168     return true;
169
170   AttributeRefAttrListPtr aRefAttrList = attributeRefAttrList();
171   if (aRefAttrList)
172     return isValidSelectionForAttribute_(theValue, myFeature->attribute(attributeID()));
173   return true;
174 }
175
176 bool PartSet_WidgetBSplinePoints::isValidSelectionForAttribute_(
177                                             const ModuleBase_ViewerPrsPtr& theValue,
178                                             const AttributePtr& theAttribute)
179 {
180   bool aValid = false;
181
182   // stores the current values of the widget attribute
183   bool isFlushesActived, isAttributeSetInitializedBlocked, isAttributeSendUpdatedBlocked;
184
185   AttributeRefAttrListPtr aRefAttrList = attributeRefAttrList();
186   ModuleBase_WidgetValidated::blockFeatureAttribute(aRefAttrList, myFeature, true,
187       isFlushesActived, isAttributeSetInitializedBlocked, isAttributeSendUpdatedBlocked);
188   myWidgetValidator->storeAttributeValue(aRefAttrList);
189
190   // saves the owner value to the widget attribute
191   aValid = setSelectionCustom(theValue);
192   if (aValid)
193     // checks the attribute validity
194     aValid = myWidgetValidator->isValidAttribute(theAttribute);
195
196   // restores the current values of the widget attribute
197   myWidgetValidator->restoreAttributeValue(aRefAttrList, aValid);
198   myExternalObjectMgr->removeExternal(sketch(), myFeature, myWorkshop, true);
199
200   ModuleBase_WidgetValidated::blockFeatureAttribute(aRefAttrList, myFeature, false,
201       isFlushesActived, isAttributeSetInitializedBlocked, isAttributeSendUpdatedBlocked);
202   return aValid;
203 }
204
205 bool PartSet_WidgetBSplinePoints::setSelectionCustom(const ModuleBase_ViewerPrsPtr& theValue)
206 {
207   bool isDone = false;
208   GeomShapePtr aShape = theValue->shape();
209   if (aShape.get() && !aShape->isNull()) {
210     Handle(V3d_View) aView = myWorkshop->viewer()->activeView();
211     const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();
212     GeomPnt2dPtr aPnt = PartSet_Tools::getPnt2d(aView, aTDShape, mySketch);
213     if (aPnt) {
214       fillRefAttribute(aPnt, theValue);
215       isDone = true;
216     }
217     else if (aTDShape.ShapeType() == TopAbs_EDGE) {
218       fillRefAttribute(theValue);
219       isDone = true;
220     }
221   }
222   return isDone;
223 }
224
225 static void fillLabels(std::vector<ModuleBase_LabelValue*>& theLabels, const double theValue)
226 {
227   for (std::vector<ModuleBase_LabelValue*>::iterator anIt = theLabels.begin();
228        anIt != theLabels.end(); ++anIt)
229     (*anIt)->setValue(theValue);
230 }
231
232 bool PartSet_WidgetBSplinePoints::resetCustom()
233 {
234   bool aDone = false;
235   if (!isUseReset() || isComputedDefault())
236     aDone = false;
237   else {
238     if (myValueIsCashed) {
239       // if the restored value should be hidden, aDone = true to set
240       // reset state for the widget in the parent
241       aDone = restoreCurentValue();
242       emit objectUpdated();
243     }
244     else {
245       // it is important to block the spin box control in order to do not through out the
246       // locking of the validating state.
247       fillLabels(myXSpin, 0.0);
248       fillLabels(myYSpin, 0.0);
249       fillLabels(myWeightSpin, 1.0);
250
251       storeValueCustom();
252       aDone = true;
253     }
254   }
255   return aDone;
256 }
257
258 PartSet_WidgetBSplinePoints::~PartSet_WidgetBSplinePoints()
259 {
260   delete myExternalObjectMgr;
261 }
262
263 bool PartSet_WidgetBSplinePoints::setPoint(double theX, double theY)
264 {
265   if (fabs(theX) >= MaxCoordinate || fabs(theY) >= MaxCoordinate)
266     return false;
267
268   myXSpin.back()->setValue(theX);
269   myYSpin.back()->setValue(theY);
270   myWeightSpin.back()->setValue(1.0);
271
272   storeValue();
273   return true;
274 }
275
276 void PartSet_WidgetBSplinePoints::storePolesAndWeights() const
277 {
278   std::shared_ptr<ModelAPI_Data> aData = myFeature->data();
279   AttributePoint2DArrayPtr aPointArray = std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(
280       aData->attribute(attributeID()));
281   AttributeDoubleArrayPtr aWeightsArray = aData->realArray(myWeightsAttr);
282
283   aPointArray->setSize((int)myXSpin.size());
284   aWeightsArray->setSize((int)myWeightSpin.size());
285
286   std::vector<ModuleBase_LabelValue*>::const_iterator aXIt = myXSpin.begin();
287   std::vector<ModuleBase_LabelValue*>::const_iterator aYIt = myYSpin.begin();
288   for (int anIndex = 0; aXIt != myXSpin.end() && aYIt != myYSpin.end(); ++anIndex, ++aXIt, ++aYIt)
289     aPointArray->setPnt(anIndex, (*aXIt)->value(), (*aYIt)->value());
290
291   std::vector<ModuleBase_LabelValue*>::const_iterator aWIt = myWeightSpin.begin();
292   for (int anIndex = 0; aWIt != myWeightSpin.end(); ++anIndex, ++aWIt)
293     aWeightsArray->setValue(anIndex, (*aWIt)->value());
294 }
295
296 bool PartSet_WidgetBSplinePoints::storeValueCustom()
297 {
298   std::shared_ptr<ModelAPI_Data> aData = myFeature->data();
299   if (!aData || !aData->isValid()) // can be on abort of sketcher element
300     return false;
301   AttributePoint2DArrayPtr aPointArray = std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(
302       aData->attribute(attributeID()));
303   AttributeDoubleArrayPtr aWeightsArray = aData->realArray(myWeightsAttr);
304
305   PartSet_WidgetBSplinePoints* that = (PartSet_WidgetBSplinePoints*) this;
306   bool isBlocked = that->blockSignals(true);
307   bool isImmutable = aPointArray->setImmutable(true);
308
309   if (myFeature->isMacro()) {
310     // Moving points of macro-features has been processed directly (without solver)
311     storePolesAndWeights();
312     updateObject(myFeature);
313
314   } else {
315     if (!aPointArray->isInitialized()) {
316       storePolesAndWeights();
317     }
318
319     std::shared_ptr<ModelAPI_ObjectMovedMessage> aMessage(
320         new ModelAPI_ObjectMovedMessage(this));
321     aMessage->setMovedAttribute(aPointArray, aPointArray->size() - 1);
322     aMessage->setOriginalPosition(aPointArray->pnt(aPointArray->size() - 1));
323     aMessage->setCurrentPosition(myXSpin.back()->value(), myYSpin.back()->value());
324     Events_Loop::loop()->send(aMessage);
325   }
326
327   aPointArray->setImmutable(isImmutable);
328   that->blockSignals(isBlocked);
329
330   return true;
331 }
332
333 bool PartSet_WidgetBSplinePoints::restoreValueCustom()
334 {
335   std::shared_ptr<ModelAPI_Data> aData = myFeature->data();
336   AttributePoint2DArrayPtr aPointArray = std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(
337       aData->attribute(attributeID()));
338   AttributeDoubleArrayPtr aWeightsArray = aData->realArray(myWeightsAttr);
339
340   if (aPointArray->isInitialized()) {
341     while (myXSpin.size() < aPointArray->size())
342       createNextPoint();
343
344     std::vector<ModuleBase_LabelValue*>::iterator aXIt = myXSpin.begin();
345     std::vector<ModuleBase_LabelValue*>::iterator aYIt = myYSpin.begin();
346     for (int anIndex = 0; aXIt != myXSpin.end() && aYIt != myYSpin.end();
347          ++anIndex, ++aXIt, ++aYIt) {
348       GeomPnt2dPtr aPoint = aPointArray->pnt(anIndex);
349       (*aXIt)->setValue(aPoint->x());
350       (*aYIt)->setValue(aPoint->y());
351     }
352
353     std::vector<ModuleBase_LabelValue*>::iterator aWIt = myWeightSpin.begin();
354     for (int anIndex = 0; aWIt != myWeightSpin.end(); ++anIndex, ++aWIt)
355       (*aWIt)->setValue(aWeightsArray->value(anIndex));
356   }
357   else {
358     if (myXSpin.empty())
359       createNextPoint();
360
361     myXSpin.back()->setValue(0.0);
362     myYSpin.back()->setValue(0.0);
363     myWeightSpin.back()->setValue(0.0);
364   }
365
366   return true;
367 }
368
369 static void storeArray(const std::vector<ModuleBase_LabelValue*>& theLabels,
370                        std::vector<double>& theValues)
371 {
372   theValues.clear();
373   theValues.reserve(theLabels.size());
374   for (std::vector<ModuleBase_LabelValue*>::const_iterator anIt = theLabels.begin();
375        anIt != theLabels.end(); ++anIt)
376     theValues.push_back((*anIt)->value());
377 }
378
379 void PartSet_WidgetBSplinePoints::storeCurentValue()
380 {
381   myValueIsCashed = true;
382   myIsFeatureVisibleInCash = XGUI_Displayer::isVisible(
383                        XGUI_Tools::workshop(myWorkshop)->displayer(), myFeature);
384
385   storeArray(myXSpin, myXValueInCash);
386   storeArray(myYSpin, myYValueInCash);
387   storeArray(myWeightSpin, myWeightInCash);
388 }
389
390 static void restoreArray(std::vector<double>& theCacheValues,
391                          std::vector<ModuleBase_LabelValue*>& theLabels)
392 {
393   std::vector<double>::iterator aCIt = theCacheValues.begin();
394   std::vector<ModuleBase_LabelValue*>::iterator anIt = theLabels.begin();
395   for (; anIt != theLabels.end(); ++anIt) {
396     if (aCIt != theCacheValues.end())
397       (*anIt)->setValue(*aCIt++);
398     else
399       (*anIt)->setValue(0.0);
400   }
401   theCacheValues.clear();
402 }
403
404 bool PartSet_WidgetBSplinePoints::restoreCurentValue()
405 {
406   bool aRestoredAndHidden = true;
407
408   bool isVisible = myIsFeatureVisibleInCash;
409
410   myValueIsCashed = false;
411   myIsFeatureVisibleInCash = true;
412   // fill the control widgets by the cashed value
413   restoreArray(myXValueInCash, myXSpin);
414   restoreArray(myYValueInCash, myYSpin);
415   restoreArray(myWeightInCash, myWeightSpin);
416
417   // store value to the model
418   storeValueCustom();
419   if (isVisible) {
420     setValueState(Stored);
421     aRestoredAndHidden = false;
422   }
423   else
424     aRestoredAndHidden = true;
425
426   return aRestoredAndHidden;
427 }
428
429 QList<QWidget*> PartSet_WidgetBSplinePoints::getControls() const
430 {
431   QList<QWidget*> aControls;
432   std::vector<ModuleBase_LabelValue*>::const_iterator aXIt = myXSpin.begin();
433   std::vector<ModuleBase_LabelValue*>::const_iterator aYIt = myYSpin.begin();
434   std::vector<ModuleBase_LabelValue*>::const_iterator aWIt = myWeightSpin.begin();
435   for (; aXIt != myXSpin.end() && aYIt != myYSpin.end() && aWIt != myWeightSpin.end();
436        ++aXIt, ++aYIt, ++aWIt) {
437     aControls.append(*aXIt);
438     aControls.append(*aYIt);
439     aControls.append(*aWIt);
440   }
441   return aControls;
442 }
443
444 void PartSet_WidgetBSplinePoints::selectionModes(int& theModuleSelectionModes, QIntList& theModes)
445 {
446   theModuleSelectionModes = -1;
447   theModes << TopAbs_VERTEX;
448   theModes << TopAbs_EDGE;
449 }
450
451 void PartSet_WidgetBSplinePoints::deactivate()
452 {
453   // the value of the control should be stored to model if it was not
454   // initialized yet. It is important when we leave this control by Tab key.
455   // It should not be performed by the widget activation as the preview
456   // is visualized with default value. Line point is moved to origin.
457   AttributePtr anAttribute = myFeature->data()->attribute(attributeID());
458   if (anAttribute && !anAttribute->isInitialized())
459     storeValue();
460
461   ModuleBase_ModelWidget::deactivate();
462 }
463
464 void PartSet_WidgetBSplinePoints::mouseReleased(ModuleBase_IViewWindow* theWindow, QMouseEvent* theEvent)
465 {
466   // the contex menu release by the right button should not be processed by this widget
467   if (theEvent->button() != Qt::LeftButton)
468     return;
469
470   ModuleBase_ISelection* aSelection = myWorkshop->selection();
471   Handle(V3d_View) aView = theWindow->v3dView();
472
473   QList<ModuleBase_ViewerPrsPtr> aList = aSelection->getSelected(ModuleBase_ISelection::Viewer);
474   ModuleBase_ViewerPrsPtr aFirstValue =
475     aList.size() > 0 ? aList.first() : ModuleBase_ViewerPrsPtr();
476   if (!aFirstValue.get() && myPreSelected.get()) {
477     aFirstValue = myPreSelected;
478   }
479
480   TopoDS_Shape aSelectedShape;
481   ObjectPtr aSelectedObject;
482
483   // if we have selection and use it
484   if (aFirstValue.get() && isValidSelectionCustom(aFirstValue) &&
485       aFirstValue->shape().get()) { // Trihedron Axis may be selected, but shape is empty
486     GeomShapePtr aGeomShape = aFirstValue->shape();
487     aSelectedShape = aGeomShape->impl<TopoDS_Shape>();
488     aSelectedObject = aFirstValue->object();
489
490     FeaturePtr aSelectedFeature = ModelAPI_Feature::feature(aSelectedObject);
491     std::shared_ptr<SketchPlugin_Feature> aSPFeature;
492     if (aSelectedFeature.get())
493       aSPFeature = std::dynamic_pointer_cast<SketchPlugin_Feature>(aSelectedFeature);
494
495     bool isSketchExternalFeature = aSPFeature.get() && aSPFeature->isExternal();
496     if ((!aSPFeature && !aSelectedShape.IsNull()) || isSketchExternalFeature) {
497       ObjectPtr aFixedObject =
498           PartSet_Tools::findFixedObjectByExternal(aSelectedShape, aSelectedObject, mySketch);
499       if (aFixedObject)
500         aSelectedObject = aFixedObject;
501       else if (!isSketchExternalFeature) {
502         FeaturePtr aCreatedFeature;
503         aSelectedObject = PartSet_Tools::createFixedObjectByExternal(
504             aGeomShape, aSelectedObject, mySketch, false, aCreatedFeature);
505       }
506     }
507   }
508   // The selection could be a center of an external circular object
509   else if (aFirstValue.get() && (!aFirstValue->interactive().IsNull())) {
510     Handle(PartSet_CenterPrs) aAIS =
511         Handle(PartSet_CenterPrs)::DownCast(aFirstValue->interactive());
512     if (!aAIS.IsNull()) {
513       gp_Pnt aPntComp = aAIS->Component()->Pnt();
514       GeomVertexPtr aVertPtr(new GeomAPI_Vertex(aPntComp.X(), aPntComp.Y(), aPntComp.Z()));
515       aSelectedShape = aVertPtr->impl<TopoDS_Shape>();
516
517       aSelectedObject =
518           PartSet_Tools::findFixedObjectByExternal(aSelectedShape, aAIS->object(), mySketch);
519       if (!aSelectedObject.get())
520       {
521         FeaturePtr aCreatedFeature;
522         aSelectedObject = PartSet_Tools::createFixedByExternalCenter(aAIS->object(), aAIS->edge(),
523             aAIS->centerType(), mySketch, false, aCreatedFeature);
524       }
525     }
526   }
527
528   GeomPnt2dPtr aSelectedPoint = PartSet_Tools::getPnt2d(aView, aSelectedShape, mySketch);
529   if (aSelectedPoint) {
530     // nullify selected object to add reference to attribute instead of its owner
531     aSelectedObject = ObjectPtr();
532   }
533   else {
534     aSelectedPoint = PartSet_Tools::getPnt2d(theEvent, theWindow, mySketch);
535     setValueState(Stored); // in case of edge selection, Apply state should also be updated
536   }
537   if (aSelectedObject)
538     fillRefAttribute(aSelectedObject);
539   else
540     fillRefAttribute(aSelectedPoint, aFirstValue);
541
542   // next pole of B-spline
543   createNextPoint();
544 }
545
546 void PartSet_WidgetBSplinePoints::mouseMoved(ModuleBase_IViewWindow* theWindow, QMouseEvent* theEvent)
547 {
548   PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
549
550   if (myFinished || isEditingMode() || aModule->sketchReentranceMgr()->isInternalEditActive())
551     return;
552
553   gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView());
554
555   double aX = 0, aY = 0;
556   PartSet_Tools::convertTo2D(aPoint, mySketch, theWindow->v3dView(), aX, aY);
557   if (myState != ModifiedInViewer)
558     storeCurentValue();
559   // we need to block the value state change
560   bool isBlocked = blockValueState(true);
561   setPoint(aX, aY);
562   blockValueState(isBlocked);
563   setValueState(ModifiedInViewer);
564 }
565
566 bool PartSet_WidgetBSplinePoints::processEscape()
567 {
568   bool isProcessed = !isEditingMode();
569   if (isProcessed) {
570     // remove widgets corrsponding to the last pole/weight of B-spline
571     removeLastPoint();
572     myFinished = true;
573
574     emit focusOutWidget(this);
575   }
576   return isProcessed;
577 }
578
579 bool PartSet_WidgetBSplinePoints::useSelectedShapes() const
580 {
581   return true;
582 }
583
584 AttributeRefAttrListPtr PartSet_WidgetBSplinePoints::attributeRefAttrList() const
585 {
586   if (myRefAttribute.empty())
587     return AttributeRefAttrListPtr();
588
589   AttributePtr anAttributeRef = feature()->attribute(myRefAttribute);
590   if (!anAttributeRef.get())
591     return AttributeRefAttrListPtr();
592
593   return std::dynamic_pointer_cast<ModelAPI_AttributeRefAttrList>(anAttributeRef);
594 }
595
596 void PartSet_WidgetBSplinePoints::fillRefAttribute(GeomPnt2dPtr theClickedPoint,
597                               const std::shared_ptr<ModuleBase_ViewerPrs>& theValue)
598 {
599   AttributeRefAttrListPtr aRefAttrList = attributeRefAttrList();
600   if (!aRefAttrList.get())
601     return;
602
603   FeaturePtr aFeature = feature();
604   std::string anAttribute = attributeID();
605
606   if (aFeature.get()) {
607     AttributePoint2DPtr aClickedFeaturePoint =
608         PartSet_WidgetPoint2D::findFirstEqualPointInSketch(mySketch, aFeature, theClickedPoint);
609     if (aClickedFeaturePoint.get())
610       aRefAttrList->append(aClickedFeaturePoint);
611     else
612       fillRefAttribute(theValue);
613   }
614 }
615
616 void PartSet_WidgetBSplinePoints::fillRefAttribute(const ModuleBase_ViewerPrsPtr& theValue)
617 {
618   ObjectPtr anObject;
619   if (theValue)
620     anObject = getGeomSelection(theValue);
621   fillRefAttribute(anObject);
622 }
623
624 void PartSet_WidgetBSplinePoints::fillRefAttribute(const ObjectPtr& theObject)
625 {
626   AttributeRefAttrListPtr aRefAttrList = attributeRefAttrList();
627   if (aRefAttrList.get())
628     aRefAttrList->append(theObject);
629 }
630
631 ObjectPtr PartSet_WidgetBSplinePoints::getGeomSelection(const ModuleBase_ViewerPrsPtr& theValue)
632 {
633   ObjectPtr anObject;
634   GeomShapePtr aShape;
635   ModuleBase_ISelection* aSelection = myWorkshop->selection();
636   anObject = aSelection->getResult(theValue);
637   aShape = aSelection->getShape(theValue);
638   myExternalObjectMgr->getGeomSelection(theValue, anObject, aShape, myWorkshop, sketch(), true);
639
640   return anObject;
641 }