]> SALOME platform Git repositories - modules/shaper.git/blob - src/PartSet/PartSet_Module.cpp
Salome HOME
Commit of the current operation if the preselection is activated.
[modules/shaper.git] / src / PartSet / PartSet_Module.cpp
1 #include "PartSet_Module.h"
2 #include <PartSet_OperationSketch.h>
3 #include <PartSet_WidgetSketchLabel.h>
4 #include <PartSet_Validators.h>
5 #include <PartSet_Tools.h>
6 #include <PartSet_WidgetPoint2d.h>
7 #include <PartSet_WidgetPoint2dDistance.h>
8 #include <PartSet_WidgetShapeSelector.h>
9
10 #include <ModuleBase_Operation.h>
11 #include <ModuleBase_IViewer.h>
12 #include <ModuleBase_IViewWindow.h>
13 #include <ModuleBase_IPropertyPanel.h>
14 #include <ModuleBase_WidgetEditor.h>
15 #include <ModuleBase_FilterFactory.h>
16 #include <ModuleBase_FilterLinearEdge.h>
17
18
19 #include <ModelAPI_Object.h>
20 #include <ModelAPI_Events.h>
21 #include <ModelAPI_Validator.h>
22 #include <ModelAPI_Data.h>
23 #include <ModelAPI_Session.h>
24
25 #include <GeomDataAPI_Point2D.h>
26 #include <GeomDataAPI_Point.h>
27 #include <GeomDataAPI_Dir.h>
28
29 #include <XGUI_Displayer.h>
30 #include <XGUI_Workshop.h>
31 #include <XGUI_OperationMgr.h>
32 #include <XGUI_PropertyPanel.h>
33 #include <XGUI_ModuleConnector.h>
34 #include <XGUI_Tools.h>
35
36 #include <SketchPlugin_Line.h>
37 #include <SketchPlugin_Sketch.h>
38 #include <SketchPlugin_Point.h>
39 #include <SketchPlugin_Arc.h>
40 #include <SketchPlugin_Circle.h>
41 #include <SketchPlugin_ConstraintLength.h>
42 #include <SketchPlugin_ConstraintDistance.h>
43 #include <SketchPlugin_ConstraintParallel.h>
44 #include <SketchPlugin_ConstraintPerpendicular.h>
45 #include <SketchPlugin_ConstraintRadius.h>
46 #include <SketchPlugin_ConstraintRigid.h>
47
48 #include <Events_Loop.h>
49
50 #include <StdSelect_TypeOfFace.hxx>
51 #include <TopoDS_Vertex.hxx>
52 #include <TopoDS.hxx>
53 #include <TopoDS_Shape.hxx>
54 #include <BRep_Tool.hxx>
55
56 #include <QObject>
57 #include <QMouseEvent>
58 #include <QString>
59 #include <QTimer>
60 #include <QApplication>
61
62 #include <GeomAlgoAPI_FaceBuilder.h>
63 #include <GeomDataAPI_Dir.h>
64
65 #ifdef _DEBUG
66 #include <QDebug>
67 #endif
68
69
70 /// Returns list of unique objects by sum of objects from List1 and List2
71 QList<ObjectPtr> getSumList(const QList<ModuleBase_ViewerPrs>& theList1,
72                                        const QList<ModuleBase_ViewerPrs>& theList2)
73 {
74   QList<ObjectPtr> aRes;
75   foreach (ModuleBase_ViewerPrs aPrs, theList1) {
76     if (!aRes.contains(aPrs.object()))
77       aRes.append(aPrs.object());
78   }
79   foreach (ModuleBase_ViewerPrs aPrs, theList2) {
80     if (!aRes.contains(aPrs.object()))
81       aRes.append(aPrs.object());
82   }
83   return aRes;
84 }
85
86 /*!Create and return new instance of XGUI_Module*/
87 extern "C" PARTSET_EXPORT ModuleBase_IModule* createModule(ModuleBase_IWorkshop* theWshop)
88 {
89   return new PartSet_Module(theWshop);
90 }
91
92 PartSet_Module::PartSet_Module(ModuleBase_IWorkshop* theWshop)
93   : ModuleBase_IModule(theWshop), 
94   myIsDragging(false), myRestartingMode(RM_None), myDragDone(false)
95 {
96   //myWorkshop = dynamic_cast<XGUI_Workshop*>(theWshop);
97   ModuleBase_IViewer* aViewer = aViewer = theWshop->viewer();
98   connect(aViewer, SIGNAL(mousePress(ModuleBase_IViewWindow*, QMouseEvent*)),
99           this, SLOT(onMousePressed(ModuleBase_IViewWindow*, QMouseEvent*)));
100
101   connect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)),
102           this, SLOT(onMouseReleased(ModuleBase_IViewWindow*, QMouseEvent*)));
103
104   connect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)),
105           this, SLOT(onMouseMoved(ModuleBase_IViewWindow*, QMouseEvent*)));
106
107   connect(aViewer, SIGNAL(mouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*)),
108           this, SLOT(onMouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*)));
109
110   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWshop);
111   XGUI_Workshop* aWorkshop = aConnector->workshop();
112
113   XGUI_OperationMgr* anOpMgr = aWorkshop->operationMgr();
114   connect(anOpMgr, SIGNAL(keyEnterReleased()), this, SLOT(onEnterReleased()));
115   connect(anOpMgr, SIGNAL(operationActivatedByPreselection()),
116           this, SLOT(onOperationActivatedByPreselection()));
117
118   connect(aViewer, SIGNAL(keyRelease(ModuleBase_IViewWindow*, QKeyEvent*)),
119           this, SLOT(onKeyRelease(ModuleBase_IViewWindow*, QKeyEvent*)));
120 }
121
122 PartSet_Module::~PartSet_Module()
123 {
124   if (!myDocumentShapeFilter.IsNull())
125     myDocumentShapeFilter.Nullify();
126   if (!myPlaneFilter.IsNull())
127     myPlaneFilter.Nullify();
128 }
129
130 void PartSet_Module::registerValidators()
131 {
132   //Registering of validators
133   SessionPtr aMgr = ModelAPI_Session::get();
134   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
135   aFactory->registerValidator("PartSet_DistanceValidator", new PartSet_DistanceValidator);
136   aFactory->registerValidator("PartSet_LengthValidator", new PartSet_LengthValidator);
137   aFactory->registerValidator("PartSet_PerpendicularValidator", new PartSet_PerpendicularValidator);
138   aFactory->registerValidator("PartSet_ParallelValidator", new PartSet_ParallelValidator);
139   aFactory->registerValidator("PartSet_RadiusValidator", new PartSet_RadiusValidator);
140   aFactory->registerValidator("PartSet_DifferentObjects", new PartSet_DifferentObjectsValidator);
141 }
142
143 void PartSet_Module::registerFilters()
144 {
145   //Registering of selection filters
146   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(workshop());
147   ModuleBase_FilterFactory* aFactory = aConnector->selectionFilters();
148
149   aFactory->registerFilter("LinearEdgeFilter", new ModuleBase_FilterLinearEdge);
150 }
151
152 void PartSet_Module::onOperationComitted(ModuleBase_Operation* theOperation) 
153 {
154   if (theOperation->isEditOperation())
155     return;
156   /// Restart sketcher operations automatically
157   FeaturePtr aFeature = theOperation->feature();
158   std::shared_ptr<SketchPlugin_Feature> aSPFeature = 
159             std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
160   if (aSPFeature && (myRestartingMode == RM_LastFeatureUsed ||
161                      myRestartingMode == RM_EmptyFeatureUsed)) {
162     myLastOperationId = theOperation->id();
163     myLastFeature = myRestartingMode == RM_LastFeatureUsed ? theOperation->feature() : FeaturePtr();
164     launchOperation(myLastOperationId);
165   }
166   breakOperationSequence();
167 }
168
169 void PartSet_Module::breakOperationSequence()
170 {
171   myLastOperationId = "";
172   myLastFeature = FeaturePtr();
173   myRestartingMode = RM_None;
174 }
175
176 void PartSet_Module::onOperationAborted(ModuleBase_Operation* theOperation)
177 {
178   breakOperationSequence();
179 }
180
181 void PartSet_Module::onOperationStarted(ModuleBase_Operation* theOperation)
182 {
183   if (theOperation->id().toStdString() == SketchPlugin_Sketch::ID()) {
184     // Display all sketcher sub-Objects
185     myCurrentSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theOperation->feature());
186     XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(workshop());
187     XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
188
189     for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {
190       FeaturePtr aFeature = myCurrentSketch->subFeature(i);
191       std::list<ResultPtr> aResults = aFeature->results();
192       std::list<ResultPtr>::const_iterator aIt;
193       for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
194         aDisplayer->display((*aIt), false);
195       }
196       aDisplayer->display(aFeature);
197     }
198     // Hide sketcher result
199     std::list<ResultPtr> aResults = myCurrentSketch->results();
200     std::list<ResultPtr>::const_iterator aIt;
201     for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
202       aDisplayer->erase((*aIt), false);
203     }
204     aDisplayer->erase(myCurrentSketch);
205
206
207     if (myPlaneFilter.IsNull()) 
208       myPlaneFilter = new ModuleBase_ShapeInPlaneFilter();
209     myWorkshop->viewer()->addSelectionFilter(myPlaneFilter);
210     if (theOperation->isEditOperation()) {
211       // If it is editing of sketch then it means that plane is already defined
212       std::shared_ptr<GeomAPI_Pln> aPln = PartSet_Tools::sketchPlane(myCurrentSketch);
213       myPlaneFilter->setPlane(aPln->impl<gp_Pln>());
214     }
215   }
216   if (myDocumentShapeFilter.IsNull())
217     myDocumentShapeFilter = new PartSet_GlobalFilter(myWorkshop);
218   myWorkshop->viewer()->addSelectionFilter(myDocumentShapeFilter);
219 }
220
221 void PartSet_Module::onOperationStopped(ModuleBase_Operation* theOperation)
222 {
223   if (theOperation->id().toStdString() == SketchPlugin_Sketch::ID()) {
224     DataPtr aData = myCurrentSketch->data();
225     if ((!aData) || (!aData->isValid())) {
226       // The sketch was aborted
227       myCurrentSketch = CompositeFeaturePtr();
228       return; 
229     }
230     // Hide all sketcher sub-Objects
231     XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(workshop());
232     XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
233     for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {
234       FeaturePtr aFeature = myCurrentSketch->subFeature(i);
235       std::list<ResultPtr> aResults = aFeature->results();
236       std::list<ResultPtr>::const_iterator aIt;
237       for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
238         aDisplayer->erase((*aIt), false);
239       }
240       aDisplayer->erase(aFeature, false);
241     }
242     // Display sketcher result
243     std::list<ResultPtr> aResults = myCurrentSketch->results();
244     std::list<ResultPtr>::const_iterator aIt;
245     for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
246       aDisplayer->display((*aIt), false);
247     }
248     aDisplayer->display(myCurrentSketch);
249     
250     myCurrentSketch = CompositeFeaturePtr();
251     myWorkshop->viewer()->removeSelectionFilter(myPlaneFilter);
252   }
253   myWorkshop->viewer()->removeSelectionFilter(myDocumentShapeFilter);
254 }
255
256 void PartSet_Module::onPlaneSelected(const std::shared_ptr<GeomAPI_Pln>& thePln)
257 {
258   myPlaneFilter->setPlane(thePln->impl<gp_Pln>());
259 }
260
261
262 void PartSet_Module::propertyPanelDefined(ModuleBase_Operation* theOperation)
263 {
264   ModuleBase_IPropertyPanel* aPanel = theOperation->propertyPanel();
265   if ((theOperation->id().toStdString() == SketchPlugin_Sketch::ID()) && 
266     (theOperation->isEditOperation())) {
267     // we have to manually activate the sketch label in edit mode
268       aPanel->activateWidget(aPanel->modelWidgets().first());
269       return;
270   }
271
272   // Restart last operation type 
273   if ((theOperation->id() == myLastOperationId) && myLastFeature) {
274     ModuleBase_ModelWidget* aWgt = aPanel->activeWidget();
275     if (theOperation->id().toStdString() == SketchPlugin_Line::ID()) {
276       // Initialise new line with first point equal to end of previous
277       PartSet_WidgetPoint2D* aPnt2dWgt = dynamic_cast<PartSet_WidgetPoint2D*>(aWgt);
278       if (aPnt2dWgt) {
279         std::shared_ptr<ModelAPI_Data> aData = myLastFeature->data();
280         std::shared_ptr<GeomDataAPI_Point2D> aPoint = 
281           std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Line::END_ID()));
282         if (aPoint) {
283           aPnt2dWgt->setPoint(aPoint->x(), aPoint->y());
284           PartSet_Tools::setConstraints(myCurrentSketch, theOperation->feature(), 
285             aWgt->attributeID(), aPoint->x(), aPoint->y());
286           theOperation->propertyPanel()->activateNextWidget(aPnt2dWgt);
287         }
288       }
289     }
290   } else {
291     // Start editing constraint
292     if (theOperation->isEditOperation()) {
293       std::string aId = theOperation->id().toStdString();
294       if (sketchOperationIdList().contains(QString(aId.c_str()))) {
295         if ((aId == SketchPlugin_ConstraintRadius::ID()) ||
296             (aId == SketchPlugin_ConstraintLength::ID()) || 
297             (aId == SketchPlugin_ConstraintDistance::ID())) {
298           // Find and activate widget for management of point for dimension line position
299           QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();
300           foreach (ModuleBase_ModelWidget* aWgt, aWidgets) {
301             PartSet_WidgetPoint2D* aPntWgt = dynamic_cast<PartSet_WidgetPoint2D*>(aWgt);
302             if (aPntWgt) {
303               aPanel->activateWidget(aPntWgt);
304               return;
305             }
306           }
307         } 
308       }
309     }
310   }
311 }
312
313
314 void PartSet_Module::onSelectionChanged()
315 {
316   ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
317   bool isSketcherOp = false;
318   // An edit operation is enable only if the current opeation is the sketch operation
319   if (aOperation && myCurrentSketch) {
320     if (PartSet_Tools::sketchPlane(myCurrentSketch))
321       isSketcherOp = (aOperation->id().toStdString() == SketchPlugin_Sketch::ID());
322   }
323   if (!isSketcherOp)
324     return;
325
326   // Editing of constraints can be done on selection
327   ModuleBase_ISelection* aSelect = myWorkshop->selection();
328   QList<ModuleBase_ViewerPrs> aSelected = aSelect->getSelected();
329   if (aSelected.size() == 1) {
330     ModuleBase_ViewerPrs aPrs = aSelected.first();
331     ObjectPtr aObject = aPrs.object();
332     FeaturePtr aFeature = ModelAPI_Feature::feature(aObject);
333     if (aFeature) {
334       std::string aId = aFeature->getKind();
335       if ((aId == SketchPlugin_ConstraintRadius::ID()) ||
336           (aId == SketchPlugin_ConstraintLength::ID()) || 
337           (aId == SketchPlugin_ConstraintDistance::ID())) {
338         editFeature(aFeature);
339       }
340     }
341   }
342 }
343
344 void PartSet_Module::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) 
345 {
346   if (!(theEvent->buttons() & Qt::LeftButton))
347     return;
348
349   ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
350   // Use only for sketch operations
351   if (aOperation && myCurrentSketch) {
352     if (!PartSet_Tools::sketchPlane(myCurrentSketch))
353       return;
354
355     bool isSketcher = (aOperation->id().toStdString() == SketchPlugin_Sketch::ID());
356     bool isSketchOpe = sketchOperationIdList().contains(aOperation->id());
357
358     // Avoid non-sketch operations
359     if ((!isSketchOpe) && (!isSketcher))
360       return;
361
362     bool isEditing = aOperation->isEditOperation();
363
364     // Ignore creation sketch operation
365     if ((!isSketcher) && (!isEditing))
366       return;
367
368     if (theEvent->modifiers()) {
369       // If user performs multiselection
370       if (isSketchOpe && (!isSketcher))
371         if (!aOperation->commit())
372           aOperation->abort();
373       return;
374     }
375     // Remember highlighted objects for editing
376     ModuleBase_ISelection* aSelect = myWorkshop->selection();
377     QList<ModuleBase_ViewerPrs> aHighlighted = aSelect->getHighlighted();
378     QList<ModuleBase_ViewerPrs> aSelected = aSelect->getSelected();
379     myEditingFeatures.clear();
380     myEditingAttr.clear();
381     if ((aHighlighted.size() == 0) && (aSelected.size() == 0)) {
382       if (isSketchOpe && (!isSketcher))
383         // commit previous operation
384         if (!aOperation->commit())
385           aOperation->abort();
386       return;
387     }
388
389     QObjectPtrList aSelObjects = getSumList(aHighlighted, aSelected);
390     if ((aHighlighted.size() == 1) && (aSelected.size() == 0)) {
391       // Move by selected shape (vertex). Can be used only for single selection
392       foreach(ModuleBase_ViewerPrs aPrs, aHighlighted) {
393         FeaturePtr aFeature = ModelAPI_Feature::feature(aHighlighted.first().object());
394         if (aFeature) {
395           myEditingFeatures.append(aFeature);
396           TopoDS_Shape aShape = aPrs.shape();
397           if (!aShape.IsNull()) {
398             if (aShape.ShapeType() == TopAbs_VERTEX) {
399               AttributePtr aAttr = PartSet_Tools::findAttributeBy2dPoint(myEditingFeatures.first(), 
400                                                                          aShape, myCurrentSketch);
401               if (aAttr)
402                 myEditingAttr.append(aAttr);
403             }
404           }
405         }
406       }
407     } else {
408       // Provide multi-selection. Can be used only for features
409       foreach (ObjectPtr aObj, aSelObjects) {
410         FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
411         if (aFeature && (!myEditingFeatures.contains(aFeature)))
412           myEditingFeatures.append(aFeature);
413       }
414
415     }
416     // If nothing highlighted - return
417     if (myEditingFeatures.size() == 0)
418       return;
419
420     if (isSketcher) {
421       myIsDragging = true;
422       get2dPoint(theWnd, theEvent, myCurX, myCurY);
423       myDragDone = false;
424       myWorkshop->viewer()->enableSelection(false);
425       launchEditing();
426
427     } else if (isSketchOpe && isEditing) {
428       // If selected another object
429       aOperation->abort();
430
431       myIsDragging = true;
432       get2dPoint(theWnd, theEvent, myCurX, myCurY);
433       myDragDone = false;
434       myWorkshop->viewer()->enableSelection(false);
435
436       // This is necessary in order to finalize previous operation
437       QApplication::processEvents();
438       launchEditing();
439     }
440   }
441 }
442
443
444 void PartSet_Module::get2dPoint(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent, 
445                                 double& theX, double& theY)
446 {
447   Handle(V3d_View) aView = theWnd->v3dView();
448   gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);
449   PartSet_Tools::convertTo2D(aPoint, myCurrentSketch, aView, theX, theY);
450 }
451
452
453 void PartSet_Module::launchEditing()
454 {
455   if (myEditingFeatures.size() > 0) {
456     FeaturePtr aFeature = myEditingFeatures.first();
457     std::shared_ptr<SketchPlugin_Feature> aSPFeature = 
458               std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
459     if (aSPFeature) {
460       editFeature(aSPFeature);
461     }
462   }
463 }
464
465 /// Returns new instance of operation object (used in createOperation for customization)
466 ModuleBase_Operation* PartSet_Module::getNewOperation(const std::string& theFeatureId)
467 {
468   if (theFeatureId == PartSet_OperationSketch::Type()) {
469     return new PartSet_OperationSketch(theFeatureId.c_str(), this);
470   }
471   return ModuleBase_IModule::getNewOperation(theFeatureId);
472 }
473
474
475 void PartSet_Module::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
476 {
477   myWorkshop->viewer()->enableSelection(true);
478   if (myIsDragging) {
479     myIsDragging = false;
480     if (myDragDone) {
481       myWorkshop->currentOperation()->commit();
482       myEditingFeatures.clear();
483       myEditingAttr.clear();
484     }
485   }
486 }
487
488
489 void PartSet_Module::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
490 {
491   if (myIsDragging) {
492     ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
493     if (aOperation->id().toStdString() == SketchPlugin_Sketch::ID())
494       return; // No edit operation activated
495
496     static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED);
497     Handle(V3d_View) aView = theWnd->v3dView();
498     gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);
499     double aX, aY;
500     PartSet_Tools::convertTo2D(aPoint, myCurrentSketch, aView, aX, aY);
501     double dX =  aX - myCurX;
502     double dY =  aY - myCurY;
503
504     if ((aOperation->id().toStdString() == SketchPlugin_Line::ID()) &&
505         (myEditingAttr.size() == 1) && 
506         myEditingAttr.first()) {
507       // probably we have prehighlighted point
508       AttributePtr aAttr = myEditingAttr.first();
509       std::string aAttrId = aAttr->id();
510       ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
511       QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();
512       // Find corresponded widget to provide dragging
513       foreach (ModuleBase_ModelWidget* aWgt, aWidgets) {
514         if (aWgt->attributeID() == aAttrId) {
515           PartSet_WidgetPoint2D* aWgt2d = dynamic_cast<PartSet_WidgetPoint2D*>(aWgt);
516           if (aWgt2d) {
517             aWgt2d->setPoint(aWgt2d->x() + dX, aWgt2d->y() + dY);
518             break;
519           }
520         }
521       }
522     } else {
523       foreach(FeaturePtr aFeature, myEditingFeatures) {
524         std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
525           std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
526         if (aSketchFeature) { 
527           aSketchFeature->move(dX, dY);
528           ModelAPI_EventCreator::get()->sendUpdated(aSketchFeature, anEvent);
529         }
530       }
531       Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_MOVED));
532       Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
533     }
534     myDragDone = true;
535     myCurX = aX;
536     myCurY = aY;
537   }
538 }
539
540 void PartSet_Module::onMouseDoubleClick(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
541 {
542   ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
543   if (aOperation->isEditOperation()) {
544     std::string aId = aOperation->id().toStdString();
545     if ((aId == SketchPlugin_ConstraintLength::ID()) ||
546       (aId == SketchPlugin_ConstraintDistance::ID()) ||
547       (aId == SketchPlugin_ConstraintRadius::ID())) 
548     {
549       // Activate dimension value editing on double click
550       ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
551       QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();
552       // Find corresponded widget to activate value editing
553       foreach (ModuleBase_ModelWidget* aWgt, aWidgets) {
554         if (aWgt->attributeID() == "ConstraintValue") {
555           aWgt->focusTo();
556           return;
557         }
558       }
559     }
560   }
561 }
562
563 void PartSet_Module::onKeyRelease(ModuleBase_IViewWindow* theWnd, QKeyEvent* theEvent)
564 {
565   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(workshop());
566   XGUI_OperationMgr* anOpMgr = aConnector->workshop()->operationMgr();
567   anOpMgr->onKeyReleased(theEvent);
568 }
569
570 void PartSet_Module::onEnterReleased()
571 {
572   myRestartingMode = RM_EmptyFeatureUsed;
573 }
574
575 void PartSet_Module::onOperationActivatedByPreselection()
576 {
577   ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
578   if (!aOperation)
579     return;
580
581   // Set final definitions if they are necessary
582   //propertyPanelDefined(aOperation);
583
584   /// Commit sketcher operations automatically
585   FeaturePtr aFeature = aOperation->feature();
586   std::shared_ptr<SketchPlugin_Feature> aSPFeature = 
587             std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
588   if (aSPFeature) {
589     aOperation->commit();
590   }
591 }
592
593 void PartSet_Module::onNoMoreWidgets()
594 {
595   ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
596   if (aOperation) {
597     /// Restart sketcher operations automatically
598     FeaturePtr aFeature = aOperation->feature();
599     std::shared_ptr<SketchPlugin_Feature> aSPFeature = 
600               std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
601     if (aSPFeature) {
602       if (myRestartingMode != RM_Forbided)
603         myRestartingMode = RM_LastFeatureUsed;
604       aOperation->commit();
605     }
606   }
607 }
608
609 QStringList PartSet_Module::sketchOperationIdList() const
610 {
611   QStringList aIds;
612   aIds << SketchPlugin_Line::ID().c_str();
613   aIds << SketchPlugin_Point::ID().c_str();
614   aIds << SketchPlugin_Arc::ID().c_str();
615   aIds << SketchPlugin_Circle::ID().c_str();
616   aIds << SketchPlugin_ConstraintLength::ID().c_str();
617   aIds << SketchPlugin_ConstraintDistance::ID().c_str();
618   aIds << SketchPlugin_ConstraintRigid::ID().c_str();
619   aIds << SketchPlugin_ConstraintRadius::ID().c_str();
620   aIds << SketchPlugin_ConstraintPerpendicular::ID().c_str();
621   aIds << SketchPlugin_ConstraintParallel::ID().c_str();
622   return aIds;
623 }
624
625 void PartSet_Module::onVertexSelected(ObjectPtr theObject, const TopoDS_Shape& theShape)
626 {
627   ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
628   if (aOperation->id().toStdString() == SketchPlugin_Line::ID()) {
629     /// If last line finished on vertex the lines creation sequence has to be break
630     ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
631     const QList<ModuleBase_ModelWidget*>& aWidgets = aPanel->modelWidgets();
632     if (aWidgets.last() == aPanel->activeWidget()) {
633       myRestartingMode = RM_Forbided;
634     }
635   }
636 }
637
638 QWidget* PartSet_Module::createWidgetByType(const std::string& theType, QWidget* theParent,
639                                             Config_WidgetAPI* theWidgetApi, std::string theParentId,
640                                             QList<ModuleBase_ModelWidget*>& theModelWidgets)
641 {
642   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(workshop());
643   XGUI_Workshop* aWorkshop = aConnector->workshop();
644   if (theType == "sketch-start-label") {
645     PartSet_WidgetSketchLabel* aWgt = new PartSet_WidgetSketchLabel(theParent, theWidgetApi, theParentId);
646     aWgt->setWorkshop(aWorkshop);
647     connect(aWgt, SIGNAL(planeSelected(const std::shared_ptr<GeomAPI_Pln>&)), 
648       this, SLOT(onPlaneSelected(const std::shared_ptr<GeomAPI_Pln>&)));
649     theModelWidgets.append(aWgt);
650     return aWgt->getControl();
651
652   } else if (theType == "sketch-2dpoint_selector") {
653     PartSet_WidgetPoint2D* aWgt = new PartSet_WidgetPoint2D(theParent, theWidgetApi, theParentId);
654     aWgt->setWorkshop(aWorkshop);
655     aWgt->setSketch(myCurrentSketch);
656
657     connect(aWgt, SIGNAL(vertexSelected(ObjectPtr, const TopoDS_Shape&)), 
658       this, SLOT(onVertexSelected(ObjectPtr, const TopoDS_Shape&)));
659
660     theModelWidgets.append(aWgt);
661     return aWgt->getControl();
662
663   } if (theType == "point2ddistance") {
664     PartSet_WidgetPoint2dDistance* aWgt = new PartSet_WidgetPoint2dDistance(theParent, theWidgetApi, theParentId);
665     aWgt->setWorkshop(aWorkshop);
666     aWgt->setSketch(myCurrentSketch);
667
668     theModelWidgets.append(aWgt);
669     return aWgt->getControl();
670
671   } if (theType == "sketch_shape_selector") {
672     PartSet_WidgetShapeSelector* aWgt = 
673       new PartSet_WidgetShapeSelector(theParent, workshop(), theWidgetApi, theParentId);
674     aWgt->setSketcher(myCurrentSketch);
675
676     theModelWidgets.append(aWgt);
677     return aWgt->getControl();
678
679   } if (theType == "sketch_constraint_shape_selector") {
680     PartSet_WidgetConstraintShapeSelector* aWgt = 
681       new PartSet_WidgetConstraintShapeSelector(theParent, workshop(), theWidgetApi, theParentId);
682     aWgt->setSketcher(myCurrentSketch);
683
684     theModelWidgets.append(aWgt);
685     return aWgt->getControl();
686
687   }else
688     return 0;
689 }
690