Salome HOME
Provide editing on multi-selection
[modules/shaper.git] / src / PartSet / PartSet_SketcherMgr.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        PartSet_SketcherMgr.cpp
4 // Created:     19 Dec 2014
5 // Author:      Vitaly SMETANNIKOV
6
7 #include "PartSet_SketcherMgr.h"
8 #include "PartSet_Module.h"
9 #include "PartSet_WidgetPoint2D.h"
10 #include "PartSet_Tools.h"
11
12 #include <XGUI_ModuleConnector.h>
13 #include <XGUI_Displayer.h>
14 #include <XGUI_Workshop.h>
15 #include <XGUI_Selection.h>
16 #include <XGUI_SelectionMgr.h>
17
18 #include <ModuleBase_IViewer.h>
19 #include <ModuleBase_IWorkshop.h>
20 #include <ModuleBase_IViewWindow.h>
21 #include <ModuleBase_Operation.h>
22 #include <ModuleBase_ISelection.h>
23 #include <ModuleBase_IPropertyPanel.h>
24 #include <ModuleBase_Operation.h>
25
26 #include <GeomDataAPI_Point2D.h>
27
28 #include <Events_Loop.h>
29
30 #include <SketchPlugin_Line.h>
31 #include <SketchPlugin_Sketch.h>
32 #include <SketchPlugin_Point.h>
33 #include <SketchPlugin_Arc.h>
34 #include <SketchPlugin_Circle.h>
35 #include <SketchPlugin_ConstraintLength.h>
36 #include <SketchPlugin_ConstraintDistance.h>
37 #include <SketchPlugin_ConstraintParallel.h>
38 #include <SketchPlugin_ConstraintPerpendicular.h>
39 #include <SketchPlugin_ConstraintRadius.h>
40 #include <SketchPlugin_ConstraintRigid.h>
41
42 #include <SelectMgr_IndexedMapOfOwner.hxx>
43 #include <StdSelect_BRepOwner.hxx>
44
45 #include <ModelAPI_Events.h>
46
47 #include <QMouseEvent>
48 #include <QApplication>
49
50
51
52
53 /// Returns list of unique objects by sum of objects from List1 and List2
54 QList<ModuleBase_ViewerPrs> getSumList(const QList<ModuleBase_ViewerPrs>& theList1,
55                                        const QList<ModuleBase_ViewerPrs>& theList2)
56 {
57   QList<ModuleBase_ViewerPrs> aRes;
58   foreach (ModuleBase_ViewerPrs aPrs, theList1) {
59     if (!aRes.contains(aPrs))
60       aRes.append(aPrs);
61   }
62   foreach (ModuleBase_ViewerPrs aPrs, theList2) {
63     if (!aRes.contains(aPrs))
64       aRes.append(aPrs);
65   }
66   return aRes;
67 }
68
69
70
71
72 PartSet_SketcherMgr::PartSet_SketcherMgr(PartSet_Module* theModule)
73   : QObject(theModule), myModule(theModule), myIsDragging(false), myDragDone(false)
74 {
75   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
76   ModuleBase_IViewer* aViewer = aWorkshop->viewer();
77
78   connect(aViewer, SIGNAL(mousePress(ModuleBase_IViewWindow*, QMouseEvent*)),
79           this, SLOT(onMousePressed(ModuleBase_IViewWindow*, QMouseEvent*)));
80
81   connect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)),
82           this, SLOT(onMouseReleased(ModuleBase_IViewWindow*, QMouseEvent*)));
83
84   connect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)),
85           this, SLOT(onMouseMoved(ModuleBase_IViewWindow*, QMouseEvent*)));
86
87   connect(aViewer, SIGNAL(mouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*)),
88           this, SLOT(onMouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*)));
89 }
90
91 PartSet_SketcherMgr::~PartSet_SketcherMgr()
92 {
93   if (!myPlaneFilter.IsNull())
94     myPlaneFilter.Nullify();
95 }
96
97 void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
98 {
99   // 
100   if (!(theEvent->buttons() & Qt::LeftButton))
101     return;
102
103   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
104   ModuleBase_Operation* aOperation = aWorkshop->currentOperation();
105   // Use only for sketch operations
106   if (aOperation && myCurrentSketch) {
107     if (!PartSet_Tools::sketchPlane(myCurrentSketch))
108       return;
109
110     bool isSketcher = (aOperation->id().toStdString() == SketchPlugin_Sketch::ID());
111     bool isSketchOpe = sketchOperationIdList().contains(aOperation->id());
112
113     // Avoid non-sketch operations
114     if ((!isSketchOpe) && (!isSketcher))
115       return;
116
117     bool isEditing = aOperation->isEditOperation();
118
119     // Ignore creation sketch operation
120     if ((!isSketcher) && (!isEditing))
121       return;
122
123     // MoveTo in order to highlight current object
124     ModuleBase_IViewer* aViewer = aWorkshop->viewer();
125     aViewer->AISContext()->MoveTo(theEvent->x(), theEvent->y(), theWnd->v3dView());
126
127     // Remember highlighted objects for editing
128     ModuleBase_ISelection* aSelect = aWorkshop->selection();
129     QList<ModuleBase_ViewerPrs> aHighlighted = aSelect->getHighlighted();
130     QList<ModuleBase_ViewerPrs> aSelected = aSelect->getSelected();
131     myEditingFeatures.clear();
132     myEditingAttr.clear();
133
134     bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
135     QList<ModuleBase_ViewerPrs> aSelObjects;
136     if (aHasShift)
137       aSelObjects = getSumList(aHighlighted, aSelected);
138     else {
139       foreach (ModuleBase_ViewerPrs aPrs, aHighlighted) {
140         aSelObjects.append(aPrs);
141       }
142     }
143     if ((aSelObjects.size() == 0)) {
144       if (isSketchOpe && (!isSketcher))
145         // commit previous operation
146         if (!aOperation->commit())
147           aOperation->abort();
148       return;
149     }
150
151     foreach(ModuleBase_ViewerPrs aPrs, aSelObjects) {
152       FeaturePtr aFeature = ModelAPI_Feature::feature(aPrs.object());
153       if (aFeature) {
154         myEditingFeatures.append(aFeature);
155         AttributePtr aAttr;
156         TopoDS_Shape aShape = aPrs.shape();
157         if (!aShape.IsNull()) {
158           if (aShape.ShapeType() == TopAbs_VERTEX) {
159             aAttr = PartSet_Tools::findAttributeBy2dPoint(aFeature, aShape, myCurrentSketch);
160           }
161         }
162         myEditingAttr.append(aAttr);
163       }
164     }
165
166     // If nothing highlighted - return
167     if (myEditingFeatures.size() == 0)
168       return;
169
170     if (isSketcher) {
171       myIsDragging = true;
172       get2dPoint(theWnd, theEvent, myCurX, myCurY);
173       myDragDone = false;
174       aWorkshop->viewer()->enableMultiselection(false);
175       launchEditing();
176
177     } else if (isSketchOpe && isEditing) {
178       // If selected another object commit current result
179       aOperation->commit();
180
181       myIsDragging = true;
182       get2dPoint(theWnd, theEvent, myCurX, myCurY);
183       myDragDone = false;
184       aWorkshop->viewer()->enableMultiselection(false);
185
186       // This is necessary in order to finalize previous operation
187       QApplication::processEvents();
188       launchEditing();
189     }
190   }
191 }
192
193 void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
194 {
195   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
196   ModuleBase_Operation* aOp = aWorkshop->currentOperation();
197   if (!aOp)
198     return;
199   if (!sketchOperationIdList().contains(aOp->id()))
200     return;
201
202   // Only for sketcher operations
203   ModuleBase_IViewer* aViewer = aWorkshop->viewer();
204   if (myIsDragging) {
205     myIsDragging = false;
206     if (myDragDone) {
207       aViewer->enableMultiselection(true);
208       //aOp->commit();
209       myEditingFeatures.clear();
210       myEditingAttr.clear();
211
212       // Reselect edited object
213       aViewer->AISContext()->MoveTo(theEvent->x(), theEvent->y(), theWnd->v3dView());
214       if (theEvent->modifiers() & Qt::ShiftModifier)
215         aViewer->AISContext()->ShiftSelect();
216       else
217         aViewer->AISContext()->Select();
218       return;
219     }
220   }
221   if (!aViewer->isMultiSelectionEnabled()) {
222     aViewer->enableMultiselection(true);
223   }
224 }
225
226 void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
227 {
228   if (myIsDragging) {
229     ModuleBase_Operation* aOperation = myModule->workshop()->currentOperation();
230     if (aOperation->id().toStdString() == SketchPlugin_Sketch::ID())
231       return; // No edit operation activated
232
233     Handle(V3d_View) aView = theWnd->v3dView();
234     gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);
235     double aX, aY;
236     PartSet_Tools::convertTo2D(aPoint, myCurrentSketch, aView, aX, aY);
237     double dX =  aX - myCurX;
238     double dY =  aY - myCurY;
239
240     ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
241     XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
242     XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
243     bool isEnableUpdateViewer = aDisplayer->enableUpdateViewer(false);
244
245     static Events_ID aMoveEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED);
246     static Events_ID aUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
247
248     for (int i = 0; i < myEditingFeatures.size(); i++) {
249       AttributePtr aAttr = myEditingAttr.at(i);
250       FeaturePtr aFeature = myEditingFeatures.at(i);
251       // save the previous selection
252       std::set<AttributePtr> aSelectedAttributes;
253       std::set<ResultPtr> aSelectedResults;
254       getCurrentSelection(aFeature, myCurrentSketch, aWorkshop, aSelectedAttributes,
255                           aSelectedResults);
256       // save the previous selection: end
257
258       // Process selection by attribute
259       if (aAttr.get() != NULL) {
260         std::string aAttrId = aAttr->id();
261         DataPtr aData = aFeature->data();
262         if (aData.get() != NULL) {
263           std::shared_ptr<GeomDataAPI_Point2D> aPoint = 
264             std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(aAttrId));
265           if (aPoint.get() != NULL) {
266             bool isImmutable = aPoint->setImmutable(true);
267             aPoint->move(dX, dY);
268             ModelAPI_EventCreator::get()->sendUpdated(aFeature, aMoveEvent);
269             aPoint->setImmutable(isImmutable);
270           }
271         }
272       } else {
273         // Process selection by feature
274         std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
275           std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
276         if (aSketchFeature) {
277           aSketchFeature->move(dX, dY);
278           ModelAPI_EventCreator::get()->sendUpdated(aSketchFeature, aMoveEvent);
279           // TODO: the selection restore should be after the AIS presentation is rebuilt
280         }
281       }
282       Events_Loop::loop()->flush(aMoveEvent);
283       Events_Loop::loop()->flush(aUpdateEvent);
284       // restore the previous selection
285       SelectMgr_IndexedMapOfOwner anOwnersToSelect;
286       getSelectionOwners(aFeature, myCurrentSketch, aWorkshop, aSelectedAttributes,
287                          aSelectedResults, anOwnersToSelect);
288       aConnector->workshop()->selector()->setSelectedOwners(anOwnersToSelect, false);
289       // restore the previous selection
290       ModelAPI_EventCreator::get()->sendUpdated(aFeature, aMoveEvent, true);
291     }
292     Events_Loop::loop()->flush(aUpdateEvent);
293     aDisplayer->enableUpdateViewer(isEnableUpdateViewer);
294     aDisplayer->updateViewer();
295     myDragDone = true;
296     myCurX = aX;
297     myCurY = aY;
298   }
299 }
300     //if ((myEditingAttr.size() == 1) && myEditingAttr.first()) {
301     //  // probably we have prehighlighted point
302     //  AttributePtr aAttr = myEditingAttr.first();
303     //  std::string aAttrId = aAttr->id();
304     //  ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
305     //  QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();
306     //  // Find corresponded widget to provide dragging
307     //  foreach (ModuleBase_ModelWidget* aWgt, aWidgets) {
308     //    if (aWgt->attributeID() == aAttrId) {
309     //      PartSet_WidgetPoint2D* aWgt2d = dynamic_cast<PartSet_WidgetPoint2D*>(aWgt);
310     //      if (aWgt2d) {
311     //        aWgt2d->setPoint(aWgt2d->x() + dX, aWgt2d->y() + dY);
312     //        break;
313     //      }
314     //    }
315     //  }
316     //} else {
317     //  ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
318     //  XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
319     //  XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
320     //  bool isEnableUpdateViewer = aDisplayer->enableUpdateViewer(false);
321
322     //  foreach(FeaturePtr aFeature, myEditingFeatures) {
323     //    std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
324     //      std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
325     //    if (aSketchFeature) {
326     //      // save the previous selection
327
328     //      std::set<AttributePtr> aSelectedAttributes;
329     //      std::set<ResultPtr> aSelectedResults;
330     //      getCurrentSelection(aSketchFeature, myCurrentSketch, aWorkshop, aSelectedAttributes,
331     //                          aSelectedResults);
332     //      // save the previous selection: end
333
334     //      aSketchFeature->move(dX, dY);
335     //      // TODO: the selection restore should be after the AIS presentation is rebuilt
336     //      Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_MOVED));
337     //      Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
338
339     //      // restore the previous selection
340     //      SelectMgr_IndexedMapOfOwner anOwnersToSelect;
341     //      getSelectionOwners(aSketchFeature, myCurrentSketch, aWorkshop, aSelectedAttributes,
342     //                         aSelectedResults, anOwnersToSelect);
343     //      aConnector->workshop()->selector()->setSelectedOwners(anOwnersToSelect, false);
344     //      // restore the previous selection
345     //    }
346     //    ModelAPI_EventCreator::get()->sendUpdated(aSketchFeature, anEvent, true);
347     //    Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
348     //  }
349     //  // TODO: set here
350     //  //Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_MOVED));
351     //  //Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
352
353     //  //Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
354     //  aDisplayer->enableUpdateViewer(isEnableUpdateViewer);
355     //  aDisplayer->updateViewer();
356     //}
357
358 void PartSet_SketcherMgr::onMouseDoubleClick(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
359 {
360   ModuleBase_Operation* aOperation = myModule->workshop()->currentOperation();
361   if (aOperation && aOperation->isEditOperation()) {
362     std::string aId = aOperation->id().toStdString();
363     if ((aId == SketchPlugin_ConstraintLength::ID()) ||
364       (aId == SketchPlugin_ConstraintDistance::ID()) ||
365       (aId == SketchPlugin_ConstraintRadius::ID())) 
366     {
367       // Activate dimension value editing on double click
368       ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
369       QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();
370       // Find corresponded widget to activate value editing
371       foreach (ModuleBase_ModelWidget* aWgt, aWidgets) {
372         if (aWgt->attributeID() == "ConstraintValue") {
373           aWgt->focusTo();
374           return;
375         }
376       }
377     }
378   }
379 }
380
381 void PartSet_SketcherMgr::get2dPoint(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent, 
382                                 double& theX, double& theY)
383 {
384   Handle(V3d_View) aView = theWnd->v3dView();
385   gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);
386   PartSet_Tools::convertTo2D(aPoint, myCurrentSketch, aView, theX, theY);
387 }
388
389 void PartSet_SketcherMgr::launchEditing()
390 {
391   if (myEditingFeatures.size() > 0) {
392     FeaturePtr aFeature = myEditingFeatures.first();
393     std::shared_ptr<SketchPlugin_Feature> aSPFeature = 
394               std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
395     if (aSPFeature) {
396       myModule->editFeature(aSPFeature);
397     }
398   }
399 }
400
401
402 QStringList PartSet_SketcherMgr::sketchOperationIdList()
403 {
404   static QStringList aIds;
405   if (aIds.size() == 0) {
406     aIds << SketchPlugin_Line::ID().c_str();
407     aIds << SketchPlugin_Point::ID().c_str();
408     aIds << SketchPlugin_Arc::ID().c_str();
409     aIds << SketchPlugin_Circle::ID().c_str();
410     aIds << SketchPlugin_ConstraintLength::ID().c_str();
411     aIds << SketchPlugin_ConstraintDistance::ID().c_str();
412     aIds << SketchPlugin_ConstraintRigid::ID().c_str();
413     aIds << SketchPlugin_ConstraintRadius::ID().c_str();
414     aIds << SketchPlugin_ConstraintPerpendicular::ID().c_str();
415     aIds << SketchPlugin_ConstraintParallel::ID().c_str();
416   }
417   return aIds;
418 }
419
420 void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
421 {
422   // Display all sketcher sub-Objects
423   myCurrentSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theOperation->feature());
424   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
425   XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
426
427   // Hide sketcher result
428   std::list<ResultPtr> aResults = myCurrentSketch->results();
429   std::list<ResultPtr>::const_iterator aIt;
430   for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
431     aDisplayer->erase((*aIt), false);
432   }
433   aDisplayer->erase(myCurrentSketch, false);
434
435   // Display sketcher objects
436   for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {
437     FeaturePtr aFeature = myCurrentSketch->subFeature(i);
438     std::list<ResultPtr> aResults = aFeature->results();
439     std::list<ResultPtr>::const_iterator aIt;
440     for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
441       aDisplayer->display((*aIt), false);
442     }
443     aDisplayer->display(aFeature, false);
444   }
445
446   if (myPlaneFilter.IsNull()) 
447     myPlaneFilter = new ModuleBase_ShapeInPlaneFilter();
448
449   myModule->workshop()->viewer()->addSelectionFilter(myPlaneFilter);
450   if (theOperation->isEditOperation()) {
451     // If it is editing of sketch then it means that plane is already defined
452     std::shared_ptr<GeomAPI_Pln> aPln = PartSet_Tools::sketchPlane(myCurrentSketch);
453     myPlaneFilter->setPlane(aPln->impl<gp_Pln>());
454   }
455   aDisplayer->updateViewer();
456 }
457
458 void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
459 {
460   DataPtr aData = myCurrentSketch->data();
461   if ((!aData) || (!aData->isValid())) {
462     // The sketch was aborted
463     myCurrentSketch = CompositeFeaturePtr();
464     myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter);
465     return; 
466   }
467   // Hide all sketcher sub-Objects
468   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
469   XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
470   for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {
471     FeaturePtr aFeature = myCurrentSketch->subFeature(i);
472     std::list<ResultPtr> aResults = aFeature->results();
473     std::list<ResultPtr>::const_iterator aIt;
474     for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
475       aDisplayer->erase((*aIt), false);
476     }
477     aDisplayer->erase(aFeature, false);
478   }
479   // Display sketcher result
480   std::list<ResultPtr> aResults = myCurrentSketch->results();
481   std::list<ResultPtr>::const_iterator aIt;
482   for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
483     aDisplayer->display((*aIt), false);
484   }
485   aDisplayer->display(myCurrentSketch);
486     
487   myCurrentSketch = CompositeFeaturePtr();
488   myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter);
489   aDisplayer->updateViewer();
490 }
491
492
493 void PartSet_SketcherMgr::onPlaneSelected(const std::shared_ptr<GeomAPI_Pln>& thePln)
494 {
495   myPlaneFilter->setPlane(thePln->impl<gp_Pln>());
496 }
497
498 void PartSet_SketcherMgr::getCurrentSelection(const ObjectPtr& theObject,
499                                               const FeaturePtr& theSketch,
500                                               ModuleBase_IWorkshop* theWorkshop,
501                                               std::set<AttributePtr>& theSelectedAttributes,
502                                               std::set<ResultPtr>& theSelectedResults)
503 {
504   FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
505   if (aFeature.get() == NULL)
506     return;
507
508   ModuleBase_IViewer* aViewer = theWorkshop->viewer();
509   Handle(AIS_InteractiveContext) aContext = aViewer->AISContext();
510   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWorkshop);
511   XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
512
513   std::list<ResultPtr> aResults = aFeature->results();
514   std::list<ResultPtr>::const_iterator aIt;
515   for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt)
516   {
517     ResultPtr aResult = *aIt;
518     AISObjectPtr aAISObj = aDisplayer->getAISObject(aResult);
519     if (aAISObj.get() == NULL)
520       continue;
521     Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
522     for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected())
523     {
524       Handle(StdSelect_BRepOwner) aBRepOwner = Handle(StdSelect_BRepOwner)::DownCast(
525                                                                       aContext->SelectedOwner());
526       if (aBRepOwner.IsNull())
527         continue;
528       Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast(
529                                                                         aBRepOwner->Selectable());
530       if (aBRepOwner->HasShape()) {
531         const TopoDS_Shape& aShape = aBRepOwner->Shape();
532         TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
533         if (aShapeType == TopAbs_VERTEX) {
534           AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(theObject,
535                                                                         aShape, theSketch);
536           if (aPntAttr.get() != NULL)
537             theSelectedAttributes.insert(aPntAttr);
538         }
539         else if (aShapeType == TopAbs_EDGE &&
540                  theSelectedResults.find(aResult) == theSelectedResults.end()) {
541           theSelectedResults.insert(aResult);
542         }
543       }
544     }
545   }
546 }
547
548 void PartSet_SketcherMgr::getSelectionOwners(const ObjectPtr& theObject,
549                                              const FeaturePtr& theSketch,
550                                              ModuleBase_IWorkshop* theWorkshop,
551                                              const std::set<AttributePtr>& theSelectedAttributes,
552                                              const std::set<ResultPtr>& theSelectedResults,
553                                              SelectMgr_IndexedMapOfOwner& anOwnersToSelect)
554 {
555   FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
556   if (aFeature.get() == NULL)
557     return;
558
559   ModuleBase_IViewer* aViewer = theWorkshop->viewer();
560   Handle(AIS_InteractiveContext) aContext = aViewer->AISContext();
561   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWorkshop);
562   XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
563
564   std::list<ResultPtr> aResults = aFeature->results();
565   std::list<ResultPtr>::const_iterator aIt;
566   for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt)
567   {
568     ResultPtr aResult = *aIt;
569     AISObjectPtr aAISObj = aDisplayer->getAISObject(aResult);
570     if (aAISObj.get() == NULL)
571       continue; 
572     Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
573
574     SelectMgr_IndexedMapOfOwner aSelectedOwners;  
575     aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners);
576     for  ( Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++ ) {
577       Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast(aSelectedOwners(i));
578       if ( anOwner.IsNull() || !anOwner->HasShape() )
579         continue;
580       const TopoDS_Shape& aShape = anOwner->Shape();
581       TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
582       if (aShapeType == TopAbs_VERTEX) {
583         AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(aFeature, aShape, theSketch);
584         if (aPntAttr.get() != NULL &&
585             theSelectedAttributes.find(aPntAttr) != theSelectedAttributes.end()) {
586           anOwnersToSelect.Add(anOwner);
587         }
588       }
589       else if (aShapeType == TopAbs_EDGE) {
590         bool aFound = theSelectedResults.find(aResult) != theSelectedResults.end();
591         int anIndex = anOwnersToSelect.FindIndex(anOwner);
592         if (theSelectedResults.find(aResult) != theSelectedResults.end()/* &&
593             anOwnersToSelect.FindIndex(anOwner) < 0*/)
594           anOwnersToSelect.Add(anOwner);
595       }
596     }
597   }
598 }