Salome HOME
Provide selection only in plane of sketcher
[modules/shaper.git] / src / XGUI / XGUI_Displayer.cpp
1 // File:        XGUI_Displayer.cpp
2 // Created:     20 Apr 2014
3 // Author:      Natalia ERMOLAEVA
4
5 #include "XGUI_Displayer.h"
6 #include "XGUI_Viewer.h"
7 #include "XGUI_Workshop.h"
8 #include "XGUI_ViewerProxy.h"
9
10 #include <ModelAPI_Document.h>
11 #include <ModelAPI_Data.h>
12 #include <ModelAPI_Object.h>
13 #include <ModelAPI_Tools.h>
14
15 #include <ModuleBase_ResultPrs.h>
16
17 #include <GeomAPI_Shape.h>
18 #include <GeomAPI_IPresentable.h>
19
20 #include <AIS_InteractiveContext.hxx>
21 #include <AIS_LocalContext.hxx>
22 #include <AIS_ListOfInteractive.hxx>
23 #include <AIS_ListIteratorOfListOfInteractive.hxx>
24 #include <AIS_DimensionSelectionMode.hxx>
25 #include <AIS_Shape.hxx>
26 #include <AIS_Dimension.hxx>
27 #include <TColStd_ListIteratorOfListOfInteger.hxx>
28 #include <SelectMgr_ListOfFilter.hxx>
29 #include <SelectMgr_ListIteratorOfListOfFilter.hxx>
30
31 #include <set>
32
33 const int MOUSE_SENSITIVITY_IN_PIXEL = 10;  ///< defines the local context mouse selection sensitivity
34
35 XGUI_Displayer::XGUI_Displayer(XGUI_Workshop* theWorkshop)
36   : myUseExternalObjects(false), myWorkshop(theWorkshop)
37 {
38 }
39
40 XGUI_Displayer::~XGUI_Displayer()
41 {
42 }
43
44 bool XGUI_Displayer::isVisible(ObjectPtr theObject) const
45 {
46   return myResult2AISObjectMap.contains(theObject);
47 }
48
49 void XGUI_Displayer::display(ObjectPtr theObject, bool isUpdateViewer)
50 {
51   if (isVisible(theObject)) {
52     redisplay(theObject, isUpdateViewer);
53   } else {
54     AISObjectPtr anAIS;
55
56     GeomPresentablePtr aPrs = std::dynamic_pointer_cast<GeomAPI_IPresentable>(theObject);
57     bool isShading = false;
58     if (aPrs) {
59       anAIS = aPrs->getAISObject(AISObjectPtr());
60     } else {
61       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
62       if (aResult) {
63         std::shared_ptr<GeomAPI_Shape> aShapePtr = ModelAPI_Tools::shape(aResult);
64         if (aShapePtr) {
65           anAIS = AISObjectPtr(new GeomAPI_AISObject());
66           anAIS->setImpl(new Handle(AIS_InteractiveObject)(new ModuleBase_ResultPrs(aResult)));
67           //anAIS->createShape(aShapePtr);
68           isShading = true;
69         }
70       }
71     }
72     if (anAIS)
73       display(theObject, anAIS, isShading, isUpdateViewer);
74   }
75 }
76
77 void XGUI_Displayer::display(ObjectPtr theObject, AISObjectPtr theAIS, 
78                              bool isShading, bool isUpdateViewer)
79 {
80   Handle(AIS_InteractiveContext) aContext = AISContext();
81   if (aContext.IsNull())
82     return;
83
84   Handle(AIS_InteractiveObject) anAISIO = theAIS->impl<Handle(AIS_InteractiveObject)>();
85   if (!anAISIO.IsNull()) {
86     myResult2AISObjectMap[theObject] = theAIS;
87     aContext->Display(anAISIO, false);
88     aContext->SetDisplayMode(anAISIO, isShading? Shading : Wireframe, isUpdateViewer);
89     if (aContext->HasOpenedContext()) {
90       if (myUseExternalObjects) {
91         if (myActiveSelectionModes.size() == 0)
92           aContext->Activate(anAISIO);
93         else {
94           foreach(int aMode, myActiveSelectionModes) {
95             aContext->Activate(anAISIO, aMode);
96           }
97         }
98       }
99     }
100   }
101 }
102
103 void XGUI_Displayer::erase(ObjectPtr theObject, const bool isUpdateViewer)
104 {
105   if (!isVisible(theObject))
106     return;
107
108   Handle(AIS_InteractiveContext) aContext = AISContext();
109   if (aContext.IsNull())
110     return;
111   AISObjectPtr anObject = myResult2AISObjectMap[theObject];
112   if (anObject) {
113     Handle(AIS_InteractiveObject) anAIS = anObject->impl<Handle(AIS_InteractiveObject)>();
114     if (!anAIS.IsNull()) {
115       aContext->Remove(anAIS, isUpdateViewer);
116     }
117   }
118   myResult2AISObjectMap.remove(theObject);
119 }
120
121 void XGUI_Displayer::redisplay(ObjectPtr theObject, bool isUpdateViewer)
122 {
123   if (!isVisible(theObject))
124     return;
125
126   AISObjectPtr aAISObj = getAISObject(theObject);
127   Handle(AIS_InteractiveObject) aAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
128
129   GeomPresentablePtr aPrs = std::dynamic_pointer_cast<GeomAPI_IPresentable>(theObject);
130   if (aPrs) {
131     AISObjectPtr aAIS_Obj = aPrs->getAISObject(aAISObj);
132     if (!aAIS_Obj) {
133       erase(theObject, isUpdateViewer);
134       return;
135     }
136     if (aAIS_Obj != aAISObj) {
137       myResult2AISObjectMap[theObject] = aAIS_Obj;
138     }
139     aAISIO = aAIS_Obj->impl<Handle(AIS_InteractiveObject)>();
140   }
141
142   if (!aAISIO.IsNull()) {
143     Handle(AIS_InteractiveContext) aContext = AISContext();
144     if (aContext.IsNull())
145       return;
146     aContext->Redisplay(aAISIO, isUpdateViewer);
147   }
148 }
149
150 void XGUI_Displayer::deactivate(ObjectPtr theObject)
151 {
152   if (isVisible(theObject)) {
153     Handle(AIS_InteractiveContext) aContext = AISContext();
154     if (aContext.IsNull())
155       return;
156
157     AISObjectPtr anObj = myResult2AISObjectMap[theObject];
158     Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
159     aContext->Deactivate(anAIS);
160   }
161 }
162
163 void XGUI_Displayer::activate(ObjectPtr theFeature)
164 {
165   QIntList aModes;
166   activate(theFeature, aModes);
167 }
168
169 void XGUI_Displayer::activate(ObjectPtr theObject, const QIntList& theModes)
170 {
171   if (isVisible(theObject)) {
172     Handle(AIS_InteractiveContext) aContext = AISContext();
173     if (aContext.IsNull())
174       return;
175
176     AISObjectPtr anObj = myResult2AISObjectMap[theObject];
177     Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
178     if (aContext->HasOpenedContext()) {
179       aContext->Load(anAIS, -1, true);
180     }
181     if (theModes.size() > 0) {
182       foreach(int aMode, theModes) {
183         aContext->Activate(anAIS, aMode);
184       }
185     } else 
186       aContext->Activate(anAIS);
187   }
188 }
189
190 bool XGUI_Displayer::isActive(ObjectPtr theObject) const
191 {
192   Handle(AIS_InteractiveContext) aContext = AISContext();
193   if (aContext.IsNull())
194     return false;
195   if (!isVisible(theObject))
196     return false;
197     
198   AISObjectPtr anObj = myResult2AISObjectMap[theObject];
199   Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
200
201   TColStd_ListOfInteger aModes;
202   aContext->ActivatedModes(anAIS, aModes);
203   return aModes.Extent() > 0;
204 }
205
206 void XGUI_Displayer::stopSelection(const QObjectPtrList& theResults, const bool isStop,
207                                    const bool isUpdateViewer)
208 {
209   Handle(AIS_InteractiveContext) aContext = AISContext();
210   if (aContext.IsNull())
211     return;
212
213   Handle(AIS_Shape) anAIS;
214   QObjectPtrList::const_iterator anIt = theResults.begin(), aLast = theResults.end();
215   ObjectPtr aFeature;
216   for (; anIt != aLast; anIt++) {
217     aFeature = *anIt;
218     if (isVisible(aFeature))
219       anAIS = Handle(AIS_Shape)::DownCast(
220           myResult2AISObjectMap[aFeature]->impl<Handle(AIS_InteractiveObject)>());
221     if (anAIS.IsNull())
222       continue;
223
224     if (isStop) {
225       QColor aColor(Qt::white);
226       anAIS->SetColor(
227           Quantity_Color(aColor.red() / 255., aColor.green() / 255., aColor.blue() / 255.,
228                          Quantity_TOC_RGB));
229       anAIS->Redisplay();
230     } else {
231       QColor aColor(Qt::red);
232       anAIS->SetColor(
233           Quantity_Color(aColor.red() / 255., aColor.green() / 255., aColor.blue() / 255.,
234                          Quantity_TOC_RGB));
235       anAIS->Redisplay();
236     }
237   }
238   if (isUpdateViewer)
239     updateViewer();
240 }
241
242 void XGUI_Displayer::setSelected(const QObjectPtrList& theResults, const bool isUpdateViewer)
243 {
244   Handle(AIS_InteractiveContext) aContext = AISContext();
245   // we need to unhighligth objects manually in the current local context
246   // in couple with the selection clear (TODO)
247   Handle(AIS_LocalContext) aLocalContext = aContext->LocalContext();
248   if (!aLocalContext.IsNull())
249     aLocalContext->UnhilightLastDetected(myWorkshop->viewer()->activeView());
250
251   aContext->ClearSelected();
252   foreach(ObjectPtr aResult, theResults)
253   {
254     if (isVisible(aResult)) {
255       AISObjectPtr anObj = myResult2AISObjectMap[aResult];
256       Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
257       if (!anAIS.IsNull())
258         aContext->SetSelected(anAIS, false);
259     }
260   }
261   if (isUpdateViewer)
262     updateViewer();
263 }
264
265
266 void XGUI_Displayer::clearSelected()
267 {
268   Handle(AIS_InteractiveContext) aContext = AISContext();
269   if (aContext) {
270     aContext->UnhilightCurrents(false);
271     aContext->ClearSelected();
272   }
273 }
274
275 void XGUI_Displayer::eraseAll(const bool isUpdateViewer)
276 {
277   Handle(AIS_InteractiveContext) ic = AISContext();
278   if (ic.IsNull())
279     return;
280
281    foreach (AISObjectPtr aAISObj, myResult2AISObjectMap) {
282      // erase an object
283      Handle(AIS_InteractiveObject) anIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
284      if (!anIO.IsNull())
285        ic->Remove(anIO, false);
286    }
287    myResult2AISObjectMap.clear();
288    if (isUpdateViewer)
289      updateViewer();
290  }
291
292 void XGUI_Displayer::eraseDeletedResults(const bool isUpdateViewer)
293 {
294   Handle(AIS_InteractiveContext) aContext = AISContext();
295   if (aContext.IsNull())
296     return;
297
298   QObjectPtrList aRemoved;
299   foreach (ObjectPtr aFeature, myResult2AISObjectMap.keys()) {
300     if (!aFeature || !aFeature->data() || !aFeature->data()->isValid()) {
301       AISObjectPtr anObj = myResult2AISObjectMap[aFeature];
302       if (!anObj)
303         continue;
304       Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
305       if (!anAIS.IsNull()) {
306         aContext->Remove(anAIS, false);
307         aRemoved.append(aFeature);
308       }
309     }
310   }
311   foreach(ObjectPtr aObj, aRemoved) {
312     myResult2AISObjectMap.remove(aObj);
313   }
314
315   if (isUpdateViewer)
316     updateViewer();
317 }
318
319 void XGUI_Displayer::openLocalContext()
320 {
321   Handle(AIS_InteractiveContext) aContext = AISContext();
322   if (aContext.IsNull())
323     return;
324   // Open local context if there is no one
325   if (!aContext->HasOpenedContext()) {
326     // Preserve selected objects
327     //AIS_ListOfInteractive aAisList;
328     //for (aContext->InitCurrent(); aContext->MoreCurrent(); aContext->NextCurrent())
329     //  aAisList.Append(aContext->Current());
330
331     SelectMgr_ListOfFilter aFilters;
332     aFilters.Assign(aContext->Filters());
333
334     aContext->ClearCurrents();
335     aContext->OpenLocalContext();
336     aContext->NotUseDisplayedObjects();
337
338     myUseExternalObjects = false;
339     myActiveSelectionModes.clear();
340
341     SelectMgr_ListIteratorOfListOfFilter aIt(aFilters);
342     for (;aIt.More(); aIt.Next()) {
343       aContext->AddFilter(aIt.Value());
344     }
345     // Restore selection
346     //AIS_ListIteratorOfListOfInteractive aIt(aAisList);
347     //for(; aIt.More(); aIt.Next()) {
348     //  if (aContext->IsDisplayed(aIt.Value()))
349     //    aContext->SetSelected(aIt.Value(), false);
350     //}
351   }
352 }
353
354 void XGUI_Displayer::closeLocalContexts(const bool isUpdateViewer)
355 {
356   Handle(AIS_InteractiveContext) ic = AISContext();
357   if ( (!ic.IsNull()) && (ic->HasOpenedContext()) ) {
358     // Preserve selected objects
359     //AIS_ListOfInteractive aAisList;
360     //for (ic->InitSelected(); ic->MoreSelected(); ic->NextSelected())
361     //  aAisList.Append(ic->SelectedInteractive());
362
363     ic->ClearSelected();
364     ic->CloseAllContexts(false);
365
366     // Redisplay all object if they were displayed in localContext
367     Handle(AIS_InteractiveObject) aAISIO;
368     foreach (AISObjectPtr aAIS, myResult2AISObjectMap) {
369       aAISIO = aAIS->impl<Handle(AIS_InteractiveObject)>();
370       if (ic->DisplayStatus(aAISIO) != AIS_DS_Displayed) {
371         ic->Display(aAISIO, false);
372         ic->SetDisplayMode(aAISIO, Shading, false);
373       }
374     }
375     if (isUpdateViewer)
376       updateViewer();
377     myUseExternalObjects = false;
378     myActiveSelectionModes.clear();
379
380     // Restore selection
381     //AIS_ListIteratorOfListOfInteractive aIt(aAisList);
382     //for(; aIt.More(); aIt.Next()) {
383     //  if (ic->IsDisplayed(aIt.Value()))
384     //    ic->SetCurrentObject(aIt.Value(), false);
385     //}
386   }
387 }
388
389 AISObjectPtr XGUI_Displayer::getAISObject(ObjectPtr theObject) const
390 {
391   AISObjectPtr anIO;
392   if (myResult2AISObjectMap.contains(theObject))
393     anIO = myResult2AISObjectMap[theObject];
394   return anIO;
395 }
396
397 ObjectPtr XGUI_Displayer::getObject(const AISObjectPtr& theIO) const
398 {
399   Handle(AIS_InteractiveObject) aRefAIS = theIO->impl<Handle(AIS_InteractiveObject)>();
400   return getObject(aRefAIS);
401 }
402
403 ObjectPtr XGUI_Displayer::getObject(const Handle(AIS_InteractiveObject)& theIO) const
404 {
405   ObjectPtr aFeature;
406   foreach (ObjectPtr anObj, myResult2AISObjectMap.keys()) {
407     AISObjectPtr aAIS = myResult2AISObjectMap[anObj];
408     Handle(AIS_InteractiveObject) anAIS = aAIS->impl<Handle(AIS_InteractiveObject)>();
409     if (anAIS == theIO)
410       return anObj;
411   }
412   return aFeature;
413 }
414
415 void XGUI_Displayer::updateViewer()
416 {
417   Handle(AIS_InteractiveContext) ic = AISContext();
418   if (!ic.IsNull())
419     ic->UpdateCurrentViewer();
420 }
421
422 Handle(AIS_InteractiveContext) XGUI_Displayer::AISContext() const
423 {
424   return myWorkshop->viewer()->AISContext();
425 }
426
427 void XGUI_Displayer::displayAIS(AISObjectPtr theAIS, bool isUpdate)
428 {
429   Handle(AIS_InteractiveContext) aContext = AISContext();
430   Handle(AIS_InteractiveObject) anAISIO = theAIS->impl<Handle(AIS_InteractiveObject)>();
431   if (!anAISIO.IsNull()) {
432     aContext->Display(anAISIO, isUpdate);
433     if (aContext->HasOpenedContext()) {
434       if (myUseExternalObjects) {
435         if (myActiveSelectionModes.size() == 0)
436           aContext->Activate(anAISIO);
437         else {
438           foreach(int aMode, myActiveSelectionModes) {
439             aContext->Activate(anAISIO, aMode);
440           }
441         }
442       }
443     }
444   }
445 }
446
447 void XGUI_Displayer::eraseAIS(AISObjectPtr theAIS, const bool isUpdate)
448 {
449   Handle(AIS_InteractiveContext) aContext = AISContext();
450   Handle(AIS_InteractiveObject) anAISIO = theAIS->impl<Handle(AIS_InteractiveObject)>();
451   if (!anAISIO.IsNull()) {
452     aContext->Remove(anAISIO, isUpdate);
453   }
454 }
455
456 void XGUI_Displayer::activateObjectsOutOfContext(const QIntList& theModes)
457 {
458   Handle(AIS_InteractiveContext) aContext = AISContext();
459   // Open local context if there is no one
460   if (!aContext->HasOpenedContext()) 
461     return;
462
463   aContext->UseDisplayedObjects();
464   myUseExternalObjects = true;
465   myActiveSelectionModes = theModes;
466
467   //Deactivate trihedron which can be activated in local selector
468   AIS_ListOfInteractive aPrsList;
469   aContext->DisplayedObjects(aPrsList, true);
470
471   Handle(AIS_Trihedron) aTrihedron;
472   AIS_ListIteratorOfListOfInteractive aLIt(aPrsList);
473   for(; aLIt.More(); aLIt.Next()){
474     aTrihedron = Handle(AIS_Trihedron)::DownCast(aLIt.Value());
475     if (!aTrihedron.IsNull()) {
476       aContext->Deactivate(aTrihedron);
477       break;
478     }
479   }
480
481   Handle(AIS_InteractiveObject) anAISIO;
482   foreach (AISObjectPtr aAIS, myResult2AISObjectMap) {
483   anAISIO = aAIS->impl<Handle(AIS_InteractiveObject)>();
484     aContext->Load(anAISIO, -1, true);
485     if (theModes.size() == 0)
486       aContext->Activate(anAISIO);
487     else {
488       foreach(int aMode, theModes) {
489         aContext->Activate(anAISIO, aMode);
490       }
491     }
492   }
493 }
494
495
496 void XGUI_Displayer::deactivateObjectsOutOfContext()
497 {
498   Handle(AIS_InteractiveContext) aContext = AISContext();
499   // Open local context if there is no one
500   if (!aContext->HasOpenedContext()) 
501     return;
502
503   aContext->NotUseDisplayedObjects();
504 }
505
506
507 void XGUI_Displayer::setDisplayMode(ObjectPtr theObject, DisplayMode theMode, bool toUpdate)
508 {
509   if (theMode == NoMode)
510     return;
511
512   Handle(AIS_InteractiveContext) aContext = AISContext();
513   if (aContext.IsNull())
514     return;
515
516   AISObjectPtr aAISObj = getAISObject(theObject);
517   if (!aAISObj)
518     return;
519
520   Handle(AIS_InteractiveObject) aAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
521   aContext->SetDisplayMode(aAISIO, theMode, toUpdate);
522 }
523
524 void XGUI_Displayer::setSelectionModes(const QIntList& theModes)
525 {
526   Handle(AIS_InteractiveContext) aContext = AISContext();
527   if (aContext.IsNull())
528     return;
529   if (!aContext->HasOpenedContext())
530     return;
531   // Clear previous mode
532   const TColStd_ListOfInteger& aModes = aContext->ActivatedStandardModes();
533   if (!aModes.IsEmpty()) {
534     TColStd_ListOfInteger aMModes;
535     aMModes.Assign(aModes);
536     TColStd_ListIteratorOfListOfInteger it(aMModes);
537     for(; it.More(); it.Next()) {
538       aContext->DeactivateStandardMode((TopAbs_ShapeEnum)it.Value());
539     }
540   }
541   foreach(int aMode, theModes) {
542     aContext->ActivateStandardMode((TopAbs_ShapeEnum)aMode);
543   }
544 }
545
546 XGUI_Displayer::DisplayMode XGUI_Displayer::displayMode(ObjectPtr theObject) const
547 {
548   Handle(AIS_InteractiveContext) aContext = AISContext();
549   if (aContext.IsNull())
550     return NoMode;
551
552   AISObjectPtr aAISObj = getAISObject(theObject);
553   if (!aAISObj)
554     return NoMode;
555
556   Handle(AIS_InteractiveObject) aAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
557   return (XGUI_Displayer::DisplayMode) aAISIO->DisplayMode();
558 }
559
560 void XGUI_Displayer::addSelectionFilter(const Handle(SelectMgr_Filter)& theFilter)
561 {
562   Handle(AIS_InteractiveContext) aContext = AISContext();
563   if (aContext.IsNull())
564     return;
565   const SelectMgr_ListOfFilter& aFilters = aContext->Filters();
566   SelectMgr_ListIteratorOfListOfFilter aIt(aFilters);
567   for (; aIt.More(); aIt.Next()) {
568     if (theFilter.Access() == aIt.Value().Access())
569       return;
570   }
571   aContext->AddFilter(theFilter);
572 }
573
574 void XGUI_Displayer::removeSelectionFilter(const Handle(SelectMgr_Filter)& theFilter)
575 {
576   Handle(AIS_InteractiveContext) aContext = AISContext();
577   if (aContext.IsNull())
578     return;
579   aContext->RemoveFilter(theFilter);
580 }