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