Salome HOME
Merge branch 'master' of newgeom:newgeom
[modules/shaper.git] / src / PartSet / PartSet_OperationFeatureEdit.cpp
1 // File:        PartSet_OperationFeatureEdit.h
2 // Created:     05 May 2014
3 // Author:      Natalia ERMOLAEVA
4
5 #include <PartSet_OperationFeatureEdit.h>
6 #include <PartSet_Tools.h>
7 #include <PartSet_OperationSketch.h>
8 #include <PartSet_OperationFeatureEditMulti.h>
9
10 #include <SketchPlugin_Constraint.h>
11
12 #include <ModuleBase_OperationDescription.h>
13 #include <ModuleBase_WidgetEditor.h>
14 #include <ModuleBase_ViewerPrs.h>
15 #include <ModuleBase_IPropertyPanel.h>
16 #include <ModuleBase_ISelection.h>
17 #include <ModuleBase_IViewer.h>
18
19 #include <ModelAPI_Events.h>
20
21 #include <SketchPlugin_Feature.h>
22 #include <GeomDataAPI_Point2D.h>
23
24 #include <ModelAPI_Data.h>
25 #include <ModelAPI_Document.h>
26 #include <ModelAPI_Events.h>
27
28 #include <Events_Loop.h>
29
30 #include <SketchPlugin_Line.h>
31
32 #include <V3d_View.hxx>
33 #include <TopoDS_Vertex.hxx>
34 #include <TopoDS.hxx>
35 #include <BRep_Tool.hxx>
36 #include <AIS_DimensionOwner.hxx>
37 #include <AIS_DimensionSelectionMode.hxx>
38
39 #ifdef _DEBUG
40 #include <QDebug>
41 #endif
42
43 #include <QMouseEvent>
44
45 using namespace std;
46
47 PartSet_OperationFeatureEdit::PartSet_OperationFeatureEdit(const QString& theId,
48                                                            QObject* theParent,
49                                                            CompositeFeaturePtr theFeature)
50     : PartSet_OperationFeatureBase(theId, theParent, theFeature),
51       myIsBlockedSelection(false)
52 {
53   myIsEditing = true;
54 }
55
56 PartSet_OperationFeatureEdit::~PartSet_OperationFeatureEdit()
57 {
58 }
59
60 void PartSet_OperationFeatureEdit::initSelection(ModuleBase_ISelection* theSelection,
61                                                       ModuleBase_IViewer* theViewer)
62 {
63   PartSet_OperationFeatureBase::initSelection(theSelection, theViewer);
64   // 1. unite selected and hightlighted objects in order to have an opportunity to drag
65   // by the highlighted object
66   QList<ModuleBase_ViewerPrs> aFeatures = theSelection->getSelected();
67   QList<ModuleBase_ViewerPrs> aHighlighted = theSelection->getHighlighted();
68   // add highlighted elements if they are not selected
69   foreach (ModuleBase_ViewerPrs aPrs, aHighlighted) {
70     if (!PartSet_Tools::isContainPresentation(aFeatures, aPrs))
71       aFeatures.append(aPrs);
72   }
73
74   // 1. find all features with skipping features with selected vertex shapes
75   myFeature2Attribute.clear();
76   // firstly, collect the features without local selection
77   /*foreach (ModuleBase_ViewerPrs aPrs, aFeatures) {
78     const TopoDS_Shape& aShape = aPrs.shape();
79     if (!aShape.IsNull() && aShape.ShapeType() == TopAbs_VERTEX) { // a point is selected
80       const TopoDS_Vertex& aVertex = TopoDS::Vertex(aShape);
81       if (!aVertex.IsNull()) {
82         continue;
83       }
84     }
85     else {
86       ObjectPtr aObject = aPrs.object();
87       if (!aObject)
88         continue;
89       FeaturePtr aFeature = ModelAPI_Feature::feature(aObject);
90       if (aFeature && myFeature2Attribute.find(aFeature) == myFeature2Attribute.end()) {
91         std::list<std::string> aList;
92         // using an empty list as a sign, that this feature should be moved itself
93         myFeature2Attribute[aFeature] = aList;
94       }
95     }
96   }*/
97   // 2. collect the features with a local selection on them.
98   // if the list already has this feature, the local selection is skipped
99   // that means that if the selection contains a feature and a feature with local selected point,
100   // the edit is performed for a full feature
101   Handle(V3d_View) aView = theViewer->activeView();
102   foreach (ModuleBase_ViewerPrs aPrs, aFeatures) {
103     const TopoDS_Shape& aShape = aPrs.shape();
104     if (!aShape.IsNull() && aShape.ShapeType() == TopAbs_VERTEX) { // a point is selected
105       const TopoDS_Vertex& aVertex = TopoDS::Vertex(aShape);
106       if (aVertex.IsNull())
107         continue;
108       ObjectPtr aObject = aPrs.object();
109       if (!aObject)
110         continue;
111       FeaturePtr aFeature = ModelAPI_Feature::feature(aObject);
112       if (!aFeature)
113         continue;
114       // if the feature is already moved, do nothing for this feature local selection
115       if (myFeature2Attribute.find(aFeature) != myFeature2Attribute.end())
116         continue;
117
118       // append the attribute of the vertex if it is found on the current feature
119       gp_Pnt aPoint = BRep_Tool::Pnt(aVertex);
120       double aVX, aVY;
121       PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aVX, aVY);
122       boost::shared_ptr<GeomDataAPI_Point2D> aPoint2D = PartSet_Tools::getFeaturePoint(
123                                                                     aFeature, aVX, aVY);
124       std::string anAttribute = aFeature->data()->id(aPoint2D);
125       std::list<std::string> aList;
126       if (myFeature2Attribute.find(aFeature) != myFeature2Attribute.end())
127         aList = myFeature2Attribute[aFeature];
128
129       aList.push_back(anAttribute);
130       myFeature2Attribute[aFeature] = aList;
131     }
132   }
133 }
134
135 void PartSet_OperationFeatureEdit::mousePressed(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, ModuleBase_ISelection* theSelection)
136 {
137   ModuleBase_ModelWidget* aActiveWgt = myPropertyPanel->activeWidget();
138   if(aActiveWgt && aActiveWgt->isViewerSelector()) {
139     // Almost do nothing, all stuff in on PartSet_OperationFeatureBase::mouseReleased
140     PartSet_OperationFeatureBase::mousePressed(theEvent, theViewer, theSelection);
141     return;
142   }
143   QList<ModuleBase_ViewerPrs> aSelected = theSelection->getSelected();
144   QList<ModuleBase_ViewerPrs> aHighlighted = theSelection->getHighlighted();
145   bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
146   if (aHasShift && !aHighlighted.empty()) {
147     foreach (ModuleBase_ViewerPrs aPrs, aHighlighted) {
148       aSelected.append(aPrs);
149     }
150   }
151   ObjectPtr aObject;
152   if (!aSelected.empty()) {
153     aObject = aSelected.first().object();
154   } else {   
155     if (!aHighlighted.empty())
156       aObject = aHighlighted.first().object();
157   }
158   //if (!theHighlighted.empty())
159   //  aObject = theHighlighted.front().object();
160   //if (!aObject && !theSelected.empty())  // changed for a constrain
161   //  aObject = theSelected.front().object();
162
163   FeaturePtr aFeature = ModelAPI_Feature::feature(aObject);
164   if (!aFeature || aFeature != feature() || (aSelected.size() > 1)) {
165     if (commit()) {
166       theViewer->enableSelection(true);
167       emit featureConstructed(feature(), FM_Deactivation);
168
169       // If we have selection and prehilighting with shift pressed 
170       // Then we have to select all these objects and restart as multi edit operfation
171       //bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
172       //if (aHasShift && !theHighlighted.empty()) {
173       //  QList<ObjectPtr> aSelected;
174       //  std::list<ModuleBase_ViewerPrs>::const_iterator aIt;
175       //  for (aIt = theSelected.cbegin(); aIt != theSelected.cend(); ++aIt)
176       //    aSelected.append((*aIt).object());
177
178       //  for (aIt = theHighlighted.cbegin(); aIt != theHighlighted.cend(); ++aIt) {
179       //    if (!aSelected.contains((*aIt).object()))
180       //      aSelected.append((*aIt).object());
181       //  }
182       //  emit setSelection(aSelected);
183       //} else 
184       if (aFeature) {
185         std::string anOperationType =
186             (aSelected.size() > 1) ?
187                 PartSet_OperationFeatureEditMulti::Type() : PartSet_OperationFeatureEdit::Type();
188         restartOperation(anOperationType, aFeature);
189       }
190       //}
191     }
192   }
193 }
194
195 void PartSet_OperationFeatureEdit::mouseMoved(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer)
196 {
197   if (!(theEvent->buttons() & Qt::LeftButton))
198     return;
199   Handle(V3d_View) aView = theViewer->activeView();
200   gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);
201
202   theViewer->enableSelection(false);
203
204   //blockSelection(true);
205   if (myCurPoint.myIsInitialized) {
206     double aCurX, aCurY;
207     PartSet_Tools::convertTo2D(myCurPoint.myPoint, sketch(), aView, aCurX, aCurY);
208
209     double aX, anY;
210     PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aX, anY);
211
212     double aDeltaX = aX - aCurX;
213     double aDeltaY = anY - aCurY;
214
215     boost::shared_ptr<SketchPlugin_Feature> aSketchFeature = boost::dynamic_pointer_cast<
216         SketchPlugin_Feature>(feature());
217
218     bool isMoved = false;
219     // the functionality to move the feature attribute if it exists in the internal map
220     std::map<FeaturePtr, std::list<std::string>>::iterator aFeatIter = myFeature2Attribute.begin();
221     while (aFeatIter != myFeature2Attribute.end()) {
222       FeaturePtr aFeature = aFeatIter->first;
223       std::list<std::string> anAttributes = aFeatIter->second;
224       // perform edit for the feature
225       /*if (anAttributes.empty()) {
226         boost::shared_ptr<SketchPlugin_Feature> aSketchFeature =
227                                        boost::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
228         if (aSketchFeature) {
229           aSketchFeature->move(aDeltaX, aDeltaY);
230         }
231       }*/
232       // perform edit for the feature's attribute
233       //else {
234       if (!anAttributes.empty()) {
235         std::list<std::string>::const_iterator anAttrIter = anAttributes.begin(),
236                                                anAttrEnd = anAttributes.end();
237         for (; anAttrIter != anAttrEnd; anAttrIter++) {
238           boost::shared_ptr<GeomDataAPI_Point2D> aPointAttr = boost::dynamic_pointer_cast<
239                            GeomDataAPI_Point2D>(aFeature->data()->attribute(*anAttrIter));
240           if (aPointAttr) {
241             aPointAttr->move(aDeltaX, aDeltaY);
242             isMoved = true;
243           }
244         }      
245       }
246       aFeatIter++;
247     }
248
249     // the feature is moved only if there is no a local selection on this feature
250     if (!isMoved) {
251       // MPV: added condition because it could be external edge of some object, not sketch
252       if (aSketchFeature && aSketchFeature->sketch() == sketch().get()) {
253         aSketchFeature->move(aDeltaX, aDeltaY);
254         static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
255         ModelAPI_EventCreator::get()->sendUpdated(feature(), anEvent);
256       }
257     }
258   }
259   sendFeatures();
260
261   myCurPoint.setPoint(aPoint);
262 }
263
264 void PartSet_OperationFeatureEdit::mouseReleased(
265     QMouseEvent* theEvent, ModuleBase_IViewer* theViewer,
266     ModuleBase_ISelection* theSelection)
267 {
268   theViewer->enableSelection(true);
269   ModuleBase_ModelWidget* aActiveWgt = 0;
270   if (myPropertyPanel)
271     aActiveWgt = myPropertyPanel->activeWidget();
272   if(aActiveWgt && aActiveWgt->isViewerSelector()) {
273     // Almost do nothing, all stuff in on PartSet_OperationFeatureBase::mouseReleased
274     PartSet_OperationFeatureBase::mouseReleased(theEvent, theViewer, theSelection);
275   }// else {
276     //blockSelection(false);
277   //}
278 }
279
280 void PartSet_OperationFeatureEdit::mouseDoubleClick(
281     QMouseEvent* theEvent, Handle_V3d_View theView,
282     ModuleBase_ISelection* theSelection)
283 {
284   // TODO the functionality is important only for constraint feature. Should be moved in another place
285   QList<ModuleBase_ViewerPrs> aSelected = theSelection->getSelected();
286   if (!aSelected.empty()) {
287     ModuleBase_ViewerPrs aFeaturePrs = aSelected.first();
288     if (!aFeaturePrs.owner().IsNull()) {
289       Handle(AIS_DimensionOwner) anOwner = Handle(AIS_DimensionOwner)::DownCast(
290           aFeaturePrs.owner());
291       if (!anOwner.IsNull() && anOwner->SelectionMode() == AIS_DSM_Text) {
292         bool isValid;
293         double aValue = PartSet_Tools::featureValue(feature(), SketchPlugin_Constraint::VALUE(),
294                                                     isValid);
295         if (isValid) {
296           ModuleBase_WidgetEditor::editFeatureValue(feature(), SketchPlugin_Constraint::VALUE());
297           flushUpdated();
298         }
299       }
300     }
301   }
302 }
303
304 void PartSet_OperationFeatureEdit::startOperation()
305 {
306   PartSet_OperationSketchBase::startOperation();
307   //emit multiSelectionEnabled(false);
308
309   myCurPoint.clear();
310 }
311
312 void PartSet_OperationFeatureEdit::stopOperation()
313 {
314   //emit multiSelectionEnabled(true);
315
316   //blockSelection(false, false);
317 }
318
319 //void PartSet_OperationFeatureEdit::blockSelection(bool isBlocked, const bool isRestoreSelection)
320 //{
321 //  if (myIsBlockedSelection == isBlocked)
322 //    return;
323 //
324 //  myIsBlockedSelection = isBlocked;
325 //  QList<ObjectPtr> aFeatureList;
326 //  aFeatureList.append(feature());
327 //
328 //  //if (isBlocked) {
329 //  //  emit setSelection(QList<ObjectPtr>());
330 //  //  emit stopSelection(aFeatureList, true);
331 //  //} else {
332 //  //  emit stopSelection(aFeatureList, false);
333 //  //  if (isRestoreSelection)
334 //  //    emit setSelection(aFeatureList);
335 //  //}
336 //}
337
338 FeaturePtr PartSet_OperationFeatureEdit::createFeature(const bool theFlushMessage,
339   CompositeFeaturePtr theCompositeFeature)
340 {
341   // do nothing in order to do not create a new feature
342   return FeaturePtr();
343 }
344
345 void PartSet_OperationFeatureEdit::sendFeatures()
346 {
347   static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED);
348
349   FeaturePtr aFeature = feature();
350   ModelAPI_EventCreator::get()->sendUpdated(aFeature, anEvent);
351
352   Events_Loop::loop()->flush(anEvent);
353   flushUpdated();
354 }
355