0024965: Problem in local selection mode with selected objects staying in the viewer
authorapl <apl@opencascade.com>
Thu, 23 Oct 2014 10:13:46 +0000 (14:13 +0400)
committerbugmaster <bugmaster@opencascade.com>
Thu, 23 Oct 2014 12:20:38 +0000 (16:20 +0400)
Added method to clear outdated selection of entity owners on recompute (update) of selection.
Added test case to check selection behavior in local context.

Cosmetic corrections

src/AIS/AIS_InteractiveContext.cxx
src/AIS/AIS_LocalContext.cdl
src/AIS/AIS_LocalContext.cxx
src/AIS/AIS_LocalContext_1.cxx
tests/bugs/vis/bug24965 [new file with mode: 0644]

index e8e408a..a39f44c 100644 (file)
@@ -1241,26 +1241,36 @@ void AIS_InteractiveContext::RecomputePrsOnly(const Handle(AIS_InteractiveObject
 //function : RecomputeSelectionOnly
 //purpose  : 
 //=======================================================================
-void AIS_InteractiveContext::RecomputeSelectionOnly(const Handle(AIS_InteractiveObject)& anIObj)
+void AIS_InteractiveContext::RecomputeSelectionOnly (const Handle(AIS_InteractiveObject)& theIO)
 {
-  if(anIObj.IsNull()) return;
-  mgrSelector->RecomputeSelection(anIObj);
-
+  if (theIO.IsNull())
+  {
+    return;
+  }
 
+  mgrSelector->RecomputeSelection (theIO);
 
-  TColStd_ListOfInteger LI;
-  TColStd_ListIteratorOfListOfInteger Lit;
-  ActivatedModes(anIObj,LI);
-  if(!HasOpenedContext()){
-    if(!myObjects.IsBound(anIObj)) return;
-
-    if (myObjects(anIObj)->GraphicStatus() == AIS_DS_Displayed)
+  if (HasOpenedContext())
+  {
+    for (Standard_Integer aContextIdx = 1; aContextIdx <= myLocalContexts.Extent(); aContextIdx++)
     {
-      for(Lit.Initialize(LI);Lit.More();Lit.Next())
-      {
-        mgrSelector->Activate(anIObj,Lit.Value(),myMainSel);
-      }
+      myLocalContexts (aContextIdx)->ClearOutdatedSelection (theIO, Standard_False);
     }
+    return;
+  }
+
+  if (!myObjects.IsBound (theIO) ||
+      myObjects (theIO)->GraphicStatus() != AIS_DS_Displayed)
+  {
+    return;
+  }
+
+  TColStd_ListOfInteger aModes;
+  ActivatedModes (theIO, aModes);
+  TColStd_ListIteratorOfListOfInteger aModesIter (aModes);
+  for (; aModesIter.More(); aModesIter.Next())
+  {
+    mgrSelector->Activate (theIO, aModesIter.Value(), myMainSel);
   }
 }
 
@@ -1287,6 +1297,11 @@ void AIS_InteractiveContext::Update (const Handle(AIS_InteractiveObject)& theIOb
 
   mgrSelector->Update(theIObj);
 
+  for (Standard_Integer aContextIdx = 1; aContextIdx <= myLocalContexts.Extent(); aContextIdx++)
+  {
+    myLocalContexts (aContextIdx)->ClearOutdatedSelection (theIObj, Standard_False);
+  }
+
   if (theUpdateViewer)
   {
     if (!myObjects.IsBound (theIObj))
index 977ffee..ec645e4 100644 (file)
@@ -332,13 +332,17 @@ is
     ---Purpose: Clears local context selection.
     --          @param toUpdateViewer [in] if TRUE the viewer will be updated.
 
-    ClearSelected (me                            : mutable;
-                   theIO                         : InteractiveObject from AIS;
-                   toUpdateViewer                : Boolean from Standard = Standard_True);
-    ---Purpose: Removes an interactive object from the local context selection.
-    --          Method deselects all associated entity owners.
+    ClearOutdatedSelection (me                 : mutable;
+                            theIO              : InteractiveObject from AIS;
+                            toClearDeactivated : Boolean from Standard);
+    ---Purpose: Clears outdated selection and detection of owners for the
+    --          interactive object. Use this method if selection structures
+    --          of the interactive object have changed. The method unhilights
+    --          and removes outdated entity owners from lists of selected
+    --          and detected owners.
     --          @param theIO [in] the interactive object.
-    --          @param toUpdateViewer [in] if TRUE the viewer will be updated.
+    --          @param toClearDeactivated [in] pass TRUE to treat deactivated
+    --                 entity owners as 'outdated' when clearing the selection.
 
                     ---Category: GET THE DETECTED
 
index 230606c..aee453f 100644 (file)
@@ -333,8 +333,7 @@ Erase(const Handle(AIS_InteractiveObject)& anInteractive)
 
   UpdateSort();
 
-  // Remove object from current selection of local context
-  ClearSelected (anInteractive, Standard_False);
+  ClearOutdatedSelection (anInteractive, Standard_True);
 
   return status;
 }
@@ -503,8 +502,7 @@ Standard_Boolean AIS_LocalContext::Remove(const Handle(AIS_InteractiveObject)& a
 
   UpdateSort();
 
-  // Remove object from current selection of local context
-  ClearSelected (aSelectable, Standard_False);
+  ClearOutdatedSelection (aSelectable, Standard_True);
 
   return Standard_True;
 }
index cc826ec..3bbeb80 100644 (file)
@@ -72,6 +72,8 @@
 
 #include <AIS_LocalContext.jxx>
 #include <StdSelect_BRepOwner.hxx>
+#include <TColStd_ListOfInteger.hxx>
+#include <TColStd_ListIteratorOfListOfInteger.hxx>
 #include <TColStd_MapOfTransient.hxx>
 #include <TColStd_MapIteratorOfMapOfTransient.hxx>
 #include <Prs3d_Presentation.hxx>
@@ -915,28 +917,78 @@ void AIS_LocalContext::ClearSelected (const Standard_Boolean updateviewer)
 }
 
 //==================================================
-// Function: ClearSelected
+// Function: ClearOutdatedSelection
 // Purpose :
 //==================================================
-void AIS_LocalContext::ClearSelected (const Handle(AIS_InteractiveObject)& theIO,
-                                      const Standard_Boolean toUpdateViewer)
+void AIS_LocalContext::ClearOutdatedSelection (const Handle(AIS_InteractiveObject)& theIO,
+                                               const Standard_Boolean toClearDeactivated)
 {
+  // 1. Collect selectable entities
+  SelectMgr_IndexedMapOfOwner aValidOwners;
+
+  const TColStd_ListOfInteger& aModes = SelectionModes (theIO);
+
+  TColStd_ListIteratorOfListOfInteger aModeIter (aModes);
+  for (; aModeIter.More(); aModeIter.Next())
+  {
+    int aMode = aModeIter.Value();
+    if (!theIO->HasSelection(aMode))
+    {
+      continue;
+    }
+
+    if (toClearDeactivated && !mySM->IsActivated (theIO, myMainVS, aMode))
+    {
+      continue;
+    }
+
+    Handle(SelectMgr_Selection) aSelection = theIO->Selection(aMode);
+    for (aSelection->Init(); aSelection->More(); aSelection->Next())
+    {
+      Handle(SelectBasics_SensitiveEntity) anEntity = aSelection->Sensitive();
+      if (anEntity.IsNull())
+      {
+        continue;
+      }
+
+      Handle(SelectMgr_EntityOwner) anOwner =
+        Handle(SelectMgr_EntityOwner)::DownCast (anEntity->OwnerId());
+
+      if (anOwner.IsNull())
+      {
+        continue;
+      }
+
+      aValidOwners.Add(anOwner);
+    }
+  }
+
+  // 2. Refresh context's detection and selection and keep only active owners
   // Keep last detected object for lastindex initialization.
   Handle(SelectMgr_EntityOwner) aLastPicked = myMainVS->OnePicked();
 
-  // Remove the interactive object from detected sequence
-  for (Standard_Integer anIdx = 1; anIdx <= myAISDetectedSeq.Length(); ++anIdx)
+  // Remove entity owners from detected sequences
+  for (Standard_Integer anIdx = 1; anIdx <= myDetectedSeq.Length(); ++anIdx)
   {
-    Handle(AIS_InteractiveObject) aDetectedIO = myAISDetectedSeq.Value (anIdx);
-    if (!aDetectedIO.IsNull() && aDetectedIO == theIO)
+    Handle(SelectMgr_EntityOwner) anOwner = myMainVS->Picked (myDetectedSeq (anIdx));
+    if (anOwner.IsNull() || anOwner->Selectable() != theIO || aValidOwners.Contains (anOwner))
     {
-      myAISDetectedSeq.Remove (anIdx--);
+      continue;
+    }
+
+    myDetectedSeq.Remove (anIdx--);
+
+    if (anIdx < myCurDetected)
+    {
+      myCurDetected--;
     }
   }
+  myCurDetected = Max (myCurDetected, 1);
 
-  Standard_Integer aHilightMode = theIO->HasHilightMode() ? theIO->HilightMode() : 0;
+  Standard_Boolean isAISRemainsDetected = Standard_False;
 
-  // Remove entity owners from AIS_Selection
+  // 3. Remove entity owners from AIS_Selection
+  const Handle(V3d_Viewer)& aViewer = myCTX->CurrentViewer();
   Handle(AIS_Selection) aSelection = AIS_Selection::Selection (mySelName.ToCString());
   AIS_NListTransient::Iterator anIter (aSelection->Objects());
   AIS_NListTransient aRemoveEntites;
@@ -948,22 +1000,27 @@ void AIS_LocalContext::ClearSelected (const Handle(AIS_InteractiveObject)& theIO
       continue;
     }
 
-    aRemoveEntites.Append (anOwner);
+    if (aValidOwners.Contains (anOwner))
+    {
+      isAISRemainsDetected = Standard_True;
+    }
 
-    if (IsSelected (anOwner))
+    aRemoveEntites.Append (anOwner);
+    anOwner->SetSelected (Standard_False);
+    for (aViewer->InitActiveViews(); aViewer->MoreActiveViews(); aViewer->NextActiveViews())
     {
-      anOwner->Unhilight (myMainPM, aHilightMode);
+      Unhilight (anOwner, aViewer->ActiveView());
     }
   }
+
   AIS_NListTransient::Iterator anIterRemove (aRemoveEntites);
   for (; anIterRemove.More(); anIterRemove.Next())
   {
     aSelection->Select (anIterRemove.Value());
   }
 
-  // Remove entity owners from myMapOfOwner
+  // 4. Remove entity owners from myMapOfOwner
   SelectMgr_IndexedMapOfOwner anOwnersToKeep;
-  const Handle(V3d_Viewer)& aViewer = myCTX->CurrentViewer();
   for (Standard_Integer anIdx = 1; anIdx <= myMapOfOwner.Extent(); anIdx++)
   {
     Handle(SelectMgr_EntityOwner) anOwner = myMapOfOwner (anIdx);
@@ -972,7 +1029,7 @@ void AIS_LocalContext::ClearSelected (const Handle(AIS_InteractiveObject)& theIO
       continue;
     }
 
-    if (anOwner->Selectable() != theIO)
+    if (anOwner->Selectable() != theIO || aValidOwners.Contains (anOwner))
     {
       anOwnersToKeep.Add (anOwner);
     }
@@ -988,9 +1045,25 @@ void AIS_LocalContext::ClearSelected (const Handle(AIS_InteractiveObject)& theIO
   myMapOfOwner.Assign (anOwnersToKeep);
   mylastindex = myMapOfOwner.FindIndex (aLastPicked);
 
-  if (toUpdateViewer)
+  if (!isAISRemainsDetected)
   {
-    aViewer->Update();
+    // Remove the interactive object from detected sequences
+    for (Standard_Integer anIdx = 1; anIdx <= myAISDetectedSeq.Length(); ++anIdx)
+    {
+      Handle(AIS_InteractiveObject) aDetectedIO = myAISDetectedSeq.Value (anIdx);
+      if (aDetectedIO.IsNull() || aDetectedIO != theIO)
+      {
+        continue;
+      }
+
+      myAISDetectedSeq.Remove (anIdx--);
+
+      if (anIdx < myAISCurDetected)
+      {
+        myAISCurDetected--;
+      }
+    }
+    myAISCurDetected = Max (myAISCurDetected, 1);
   }
 }
 
@@ -1361,7 +1434,7 @@ Standard_Integer AIS_LocalContext::HilightNextDetected (const Handle(V3d_View)&
   {
     myCurDetected = 1;
   }
-  Handle(SelectMgr_EntityOwner) anOwner = myMainVS->Picked (myCurDetected);
+  Handle(SelectMgr_EntityOwner) anOwner = myMainVS->Picked (myDetectedSeq (myCurDetected));
   if (anOwner.IsNull())
   {
     return 0;
@@ -1386,7 +1459,7 @@ Standard_Integer AIS_LocalContext::HilightPreviousDetected (const Handle(V3d_Vie
   {
     myCurDetected = 1;
   }
-  Handle(SelectMgr_EntityOwner) anOwner = myMainVS->Picked (myCurDetected);
+  Handle(SelectMgr_EntityOwner) anOwner = myMainVS->Picked (myDetectedSeq (myCurDetected));
   if (anOwner.IsNull())
   {
     return 0;
diff --git a/tests/bugs/vis/bug24965 b/tests/bugs/vis/bug24965
new file mode 100644 (file)
index 0000000..fad47ab
--- /dev/null
@@ -0,0 +1,62 @@
+puts "============"
+puts "OCC24966"
+puts "============"
+puts ""
+####################################################################################
+# Problem in local selection mode with selected objects staying in the viewer
+# Outdated entity owners remain selected after recompute of presentation in
+# local context.
+# The following cases are tested:
+# o Recompute should not clear per-object selection (neutral selection context).
+# o Recompute should clear per-owner selection (local selection context).
+####################################################################################
+
+set check_recomputed_x 227
+set check_recomputed_y 269
+set check_untouched_x 239
+set check_untouched_y 309
+
+vinit View1
+vpoint p1 100 100 0
+vpoint p2 150 150 0
+vpoint p3 100 150 0
+vplane pln1 p1 p2 p3
+veraseall
+vdisplay pln1 p1 p2 p3
+vselect 0 0 2500 2500
+vchangeplane pln1 x=100 y=100 z=200 dx=0.707 dy=0.707 dz=0.707
+vfit
+
+checkcolor $check_recomputed_x $check_recomputed_y 0.8 0.8 0.8
+if { $stat != 1 } {
+   puts "Error : Neutral selection of updated object is erased."
+}
+
+checkcolor $check_untouched_x $check_untouched_y 0.8 0.8 0.8
+if { $stat != 1 } {
+   puts "Error : Neutral selection of unmodified object is erased."
+}
+
+vinit View2
+vpoint p4 100 100 0
+vpoint p5 150 150 0
+vpoint p6 100 150 0
+vplane pln2 p4 p5 p6
+veraseall
+vdisplay -local pln2 p4 p5 p6 
+vselect 0 0 2500 2500
+vchangeplane pln2 x=100 y=100 z=200 dx=0.707 dy=0.707 dz=0.707
+vfit
+
+checkcolor $check_recomputed_x $check_recomputed_y 0 1 0
+if { $stat != 1 } {
+   puts "Error : Local (renewed) selection of updated object is not updated."
+}
+
+checkcolor $check_untouched_x $check_untouched_y 0.8 0.8 0.8
+if { $stat != 1 } {
+   puts "Error : Local selection of unmodified object is erased."
+}
+
+vdump ${imagedir}/${casename}_View1.png
+vdump ${imagedir}/${casename}_View2.png