Salome HOME
Merge branch 'SketchSolver'
[modules/shaper.git] / src / PartSet / PartSet_OperationEditFeature.cpp
1 // File:        PartSet_OperationEditFeature.h
2 // Created:     05 May 2014
3 // Author:      Natalia ERMOLAEVA
4
5 #include <PartSet_OperationEditFeature.h>
6 #include <PartSet_Tools.h>
7 #include <PartSet_OperationSketch.h>
8
9 #include <ModuleBase_OperationDescription.h>
10 #include <Model_Events.h>
11
12 #include <XGUI_ViewerPrs.h>
13
14 #include <SketchPlugin_Feature.h>
15 #include <GeomDataAPI_Point2D.h>
16 #include <ModelAPI_Data.h>
17 #include <ModelAPI_Document.h>
18
19 #include <Model_Events.h>
20
21 #include <Events_Loop.h>
22
23 #include <SketchPlugin_Line.h>
24
25 #include <V3d_View.hxx>
26
27 #ifdef _DEBUG
28 #include <QDebug>
29 #endif
30
31 #include <QMouseEvent>
32
33 using namespace std;
34
35 PartSet_OperationEditFeature::PartSet_OperationEditFeature(const QString& theId,
36                                                   QObject* theParent,
37                                               FeaturePtr theFeature)
38 : PartSet_OperationSketchBase(theId, theParent), mySketch(theFeature), myIsBlockedSelection(false)
39 {
40 }
41
42 PartSet_OperationEditFeature::~PartSet_OperationEditFeature()
43 {
44 }
45
46 bool PartSet_OperationEditFeature::isGranted(ModuleBase_IOperation* theOperation) const
47 {
48   return theOperation->getDescription()->operationId().toStdString() == PartSet_OperationSketch::Type();
49 }
50
51 std::list<int> PartSet_OperationEditFeature::getSelectionModes(FeaturePtr theFeature) const
52 {
53   return PartSet_OperationSketchBase::getSelectionModes(theFeature);
54 }
55
56 void PartSet_OperationEditFeature::init(FeaturePtr theFeature,
57                                      const std::list<XGUI_ViewerPrs>& theSelected,
58                                      const std::list<XGUI_ViewerPrs>& theHighlighted)
59 {
60   setFeature(theFeature);
61
62   if (!theHighlighted.empty()) {
63     // if there is highlighted object, we check whether it is in the list of selected objects
64     // in that case this object is a handle of the moved lines. If there no such object in the selection,
65     // the hightlighted object should moved and the selection is skipped. The skipped selection will be
66     // deselected in the viewer by blockSelection signal in the startOperation method.
67     bool isSelected = false;
68     std::list<XGUI_ViewerPrs>::const_iterator anIt = theSelected.begin(), aLast = theSelected.end();
69     for (; anIt != aLast && !isSelected; anIt++) {
70       isSelected = (*anIt).feature() == feature();
71     }
72     if (!isSelected)
73       myFeatures = theHighlighted;
74     else
75       myFeatures = theSelected;
76   }
77   else
78     myFeatures = theSelected;
79 }
80
81 FeaturePtr PartSet_OperationEditFeature::sketch() const
82 {
83   return mySketch;
84 }
85
86 void PartSet_OperationEditFeature::mousePressed(QMouseEvent* theEvent, Handle(V3d_View) theView,
87                                              const std::list<XGUI_ViewerPrs>& /*theSelected*/,
88                                              const std::list<XGUI_ViewerPrs>& theHighlighted)
89 {
90   if (myFeatures.size() == 1)
91   {
92     FeaturePtr aFeature;
93     if (!theHighlighted.empty())
94       aFeature = theHighlighted.front().feature();
95
96     if (aFeature && aFeature == feature()) { // continue the feature edit
97     }
98     else {
99       XGUI_ViewerPrs aFeaturePrs = myFeatures.front();
100       commit();
101       emit featureConstructed(feature(), FM_Deactivation);
102
103       bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
104       if(aHasShift && !theHighlighted.empty()) {
105         std::list<XGUI_ViewerPrs> aSelected;
106         aSelected.push_back(aFeaturePrs);
107         aSelected.push_back(theHighlighted.front());
108         emit setSelection(aSelected);
109       }
110       else if (aFeature) {
111         restartOperation(PartSet_OperationEditFeature::Type(), aFeature);
112       }
113     }
114   }
115 }
116
117 void PartSet_OperationEditFeature::mouseMoved(QMouseEvent* theEvent, Handle(V3d_View) theView)
118 {
119   if (!(theEvent->buttons() &  Qt::LeftButton))
120     return;
121
122   gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theView);
123
124   blockSelection(true);
125   if (myCurPoint.myIsInitialized) {
126     double aCurX, aCurY;
127     PartSet_Tools::convertTo2D(myCurPoint.myPoint, sketch(), theView, aCurX, aCurY);
128
129     double aX, anY;
130     PartSet_Tools::convertTo2D(aPoint, sketch(), theView, aX, anY);
131
132     double aDeltaX = aX - aCurX;
133     double aDeltaY = anY - aCurY;
134
135     PartSet_Tools::moveFeature(feature(), aDeltaX, aDeltaY);
136
137     std::list<XGUI_ViewerPrs>::const_iterator anIt = myFeatures.begin(), aLast = myFeatures.end();
138     for (; anIt != aLast; anIt++) {
139       FeaturePtr aFeature = (*anIt).feature();
140       if (!aFeature || aFeature == feature())
141         continue;
142       PartSet_Tools::moveFeature(aFeature, aDeltaX, aDeltaY);
143     }
144   }
145   sendFeatures();
146
147   myCurPoint.setPoint(aPoint);
148 }
149
150 void PartSet_OperationEditFeature::mouseReleased(QMouseEvent* theEvent, Handle(V3d_View) theView,
151                                               const std::list<XGUI_ViewerPrs>& /*theSelected*/,
152                                               const std::list<XGUI_ViewerPrs>& /*theHighlighted*/)
153 {
154   std::list<XGUI_ViewerPrs> aFeatures = myFeatures;
155   if (myFeatures.size() == 1) {
156     blockSelection(false);
157   }
158   else {
159     commit();
160     std::list<XGUI_ViewerPrs>::const_iterator anIt = aFeatures.begin(), aLast = aFeatures.end();
161     for (; anIt != aLast; anIt++) {
162       FeaturePtr aFeature = (*anIt).feature();
163       if (aFeature)
164         emit featureConstructed(aFeature, FM_Deactivation);
165     }
166   }
167 }
168
169 void PartSet_OperationEditFeature::startOperation()
170 {
171   // do nothing in order to do not create a new feature
172   emit multiSelectionEnabled(false);
173
174   if (myFeatures.size() > 1)
175     blockSelection(true);
176
177   myCurPoint.clear();
178 }
179
180 void PartSet_OperationEditFeature::stopOperation()
181 {
182   emit multiSelectionEnabled(true);
183
184   blockSelection(false, myFeatures.size() > 1);
185
186   myFeatures.clear();
187 }
188
189 void PartSet_OperationEditFeature::blockSelection(bool isBlocked, const bool isRestoreSelection)
190 {
191   if (myIsBlockedSelection == isBlocked)
192     return;
193
194   myIsBlockedSelection = isBlocked;
195   if (isBlocked) {
196     emit setSelection(std::list<XGUI_ViewerPrs>());
197     emit stopSelection(myFeatures, true);
198   }
199   else {
200     emit stopSelection(myFeatures, false);
201     if (isRestoreSelection)
202       emit setSelection(myFeatures);
203   }
204 }
205
206 FeaturePtr PartSet_OperationEditFeature::createFeature(const bool /*theFlushMessage*/)
207 {
208   // do nothing in order to do not create a new feature
209   return FeaturePtr();
210 }
211
212 void PartSet_OperationEditFeature::sendFeatures()
213 {
214   static Events_ID anEvent = Events_Loop::eventByName(EVENT_FEATURE_MOVED);
215
216   std::list<FeaturePtr > aFeatures;
217   std::list<XGUI_ViewerPrs>::const_iterator anIt = myFeatures.begin(), aLast = myFeatures.end();
218   for (; anIt != aLast; anIt++) {
219     FeaturePtr aFeature = (*anIt).feature();
220     if (!aFeature)
221       continue;
222
223     Model_FeatureUpdatedMessage aMessage(aFeature, anEvent);
224     Events_Loop::loop()->send(aMessage);
225   }
226   Events_Loop::loop()->flush(anEvent);
227   flushUpdated();
228 }
229