0028416: Visualization - SelectMgr_SelectionManager::Activate() should not implicitly...
authorkgv <kgv@opencascade.com>
Tue, 31 Jan 2017 08:26:48 +0000 (11:26 +0300)
committerkgv <kgv@opencascade.com>
Thu, 30 Nov 2017 20:08:56 +0000 (23:08 +0300)
Implicit deactivation of global selection mode has been removed from SelectMgr_SelectionManager::Activate().

Added new method AIS_InteractiveContext::SetSelectionModeActive() as replacement
of AIS_InteractiveContext::Activate() / ::Deactivate().
New method takes an argument AIS_SelectionModesConcurrency which defines
what to do with already activated selection modes in 3 ways:
- AIS_SelectionModesConcurrency_Single, only one selection mode can be activated at
  the same moment - previously activated should be deactivated
- AIS_SelectionModesConcurrency_GlobalOrLocal, either Global (AIS_InteractiveObject::GlobalSelectionMode()
  or Local (multiple) selection modes can be active at the same moment
- AIS_SelectionModesConcurrency_Multiple, any combination of selection modes can be activated.

src/AIS/AIS_InteractiveContext.hxx
src/AIS/AIS_InteractiveContext_2.cxx
src/AIS/AIS_LocalContext.cxx
src/AIS/AIS_LocalContext.hxx
src/AIS/AIS_SelectionModesConcurrency.hxx [new file with mode: 0644]
src/AIS/FILES
src/SelectMgr/SelectMgr_SelectionManager.cxx
src/SelectMgr/SelectMgr_ToleranceMap.cxx
src/ViewerTest/ViewerTest_ObjectCommands.cxx

index c954768..f235aed 100644 (file)
@@ -25,6 +25,7 @@
 #include <AIS_KindOfInteractive.hxx>
 #include <AIS_ListOfInteractive.hxx>
 #include <AIS_Selection.hxx>
+#include <AIS_SelectionModesConcurrency.hxx>
 #include <AIS_StatusOfDetection.hxx>
 #include <AIS_StatusOfPick.hxx>
 #include <AIS_TypeOfIso.hxx>
@@ -596,18 +597,48 @@ public: //! @name immediate mode rendering
 
 public: //! @name management of active Selection Modes
 
+  //! Activates or deactivates the selection mode for specified object.
+  //! Has no effect if selection mode was already active/deactivated.
+  //! @param theObj         object to activate/deactivate selection mode
+  //! @param theMode        selection mode to activate/deactivate;
+  //!                       deactivation of -1 selection mode will effectively deactivate all selection modes;
+  //!                       activation of -1 selection mode with AIS_SelectionModesConcurrency_Single
+  //!                       will deactivate all selection modes, and will has no effect otherwise
+  //! @param theToActivate  activation/deactivation flag
+  //! @param theConcurrency specifies how to handle already activated selection modes;
+  //!                       default value (AIS_SelectionModesConcurrency_Multiple) means active selection modes should be left as is,
+  //!                       AIS_SelectionModesConcurrency_Single can be used if only one selection mode is expected to be active
+  //!                       and AIS_SelectionModesConcurrency_GlobalOrLocal can be used if either AIS_InteractiveObject::GlobalSelectionMode()
+  //!                       or any combination of Local selection modes is acceptable;
+  //!                       this value is considered only if theToActivate set to TRUE
+  //! @param theIsForce     when set to TRUE, the display status will be ignored while activating selection mode
+  Standard_EXPORT void SetSelectionModeActive (const Handle(AIS_InteractiveObject)& theObj,
+                                               const Standard_Integer theMode,
+                                               const Standard_Boolean theToActivate,
+                                               const AIS_SelectionModesConcurrency theConcurrency = AIS_SelectionModesConcurrency_Multiple,
+                                               const Standard_Boolean theIsForce = Standard_False);
+
   //! Activates the selection mode aMode whose index is given, for the given interactive entity anIobj.
-  Standard_EXPORT void Activate (const Handle(AIS_InteractiveObject)& anIobj, const Standard_Integer aMode = 0, const Standard_Boolean theIsForce = Standard_False);
+  void Activate (const Handle(AIS_InteractiveObject)& theObj, const Standard_Integer theMode = 0, const Standard_Boolean theIsForce = Standard_False)
+  {
+    SetSelectionModeActive (theObj, theMode, Standard_True, AIS_SelectionModesConcurrency_GlobalOrLocal, theIsForce);
+  }
 
   //! Activates the given selection mode for the all displayed objects.
   Standard_EXPORT void Activate (const Standard_Integer theMode,
                                  const Standard_Boolean theIsForce = Standard_False);
   
   //! Deactivates all the activated selection modes of an object.
-  Standard_EXPORT void Deactivate (const Handle(AIS_InteractiveObject)& anIObj);
+  void Deactivate (const Handle(AIS_InteractiveObject)& theObj)
+  {
+    SetSelectionModeActive (theObj, -1, Standard_False, AIS_SelectionModesConcurrency_Single);
+  }
 
   //! Deactivates all the activated selection modes of the interactive object anIobj with a given selection mode aMode.
-  Standard_EXPORT void Deactivate (const Handle(AIS_InteractiveObject)& anIobj, const Standard_Integer aMode);
+  void Deactivate (const Handle(AIS_InteractiveObject)& theObj, const Standard_Integer theMode)
+  {
+    SetSelectionModeActive (theObj, theMode, Standard_False);
+  }
 
   //! Deactivates the given selection mode for all displayed objects.
   Standard_EXPORT void Deactivate (const Standard_Integer theMode);
index b62d0a5..1a0c69a 100644 (file)
@@ -216,27 +216,121 @@ Standard_Integer AIS_InteractiveContext::HighestIndex() const
 
 }
 
-
 //=======================================================================
-//function : Activate
-//purpose  : 
+//function : SetSelectionModeActive
+//purpose  :
 //=======================================================================
-
-void AIS_InteractiveContext::
-Activate(const Handle(AIS_InteractiveObject)& anIObj, 
-         const Standard_Integer aMode,
-         const Standard_Boolean theIsForce)
+void AIS_InteractiveContext::SetSelectionModeActive (const Handle(AIS_InteractiveObject)& theObj,
+                                                     const Standard_Integer theMode,
+                                                     const Standard_Boolean theIsActive,
+                                                     const AIS_SelectionModesConcurrency theActiveFilter,
+                                                     const Standard_Boolean theIsForce)
 {
-  if(!HasOpenedContext()){
-    if(!myObjects.IsBound(anIObj)) return;
-    const Handle(AIS_GlobalStatus)& STAT = myObjects(anIObj);
-    if(STAT->GraphicStatus()==AIS_DS_Displayed || theIsForce)
-      mgrSelector->Activate(anIObj,aMode,myMainSel);
-    STAT ->AddSelectionMode(aMode);
+  if (theObj.IsNull())
+  {
+    return;
   }
-  else{
-   myLocalContexts(myCurLocalIndex)->ActivateMode(anIObj,aMode);
+  else if (HasOpenedContext())
+  {
+    myLocalContexts (myCurLocalIndex)->SetSelectionModeActive (theObj, theMode, theIsActive, theActiveFilter);
+    return;
+  }
+
+  const Handle(AIS_GlobalStatus)* aStat = myObjects.Seek (theObj);
+  if (aStat == NULL)
+  {
+    return;
+  }
+
+  if (!theIsActive
+   || (theMode == -1
+    && theActiveFilter == AIS_SelectionModesConcurrency_Single))
+  {
+    if ((*aStat)->GraphicStatus() == AIS_DS_Displayed
+     || theIsForce)
+    {
+      if (theMode == -1)
+      {
+        for (TColStd_ListIteratorOfListOfInteger aModeIter ((*aStat)->SelectionModes()); aModeIter.More(); aModeIter.Next())
+        {
+          mgrSelector->Deactivate (theObj, aModeIter.Value(), myMainSel);
+        }
+      }
+      else
+      {
+        mgrSelector->Deactivate (theObj, theMode, myMainSel);
+      }
+    }
+
+    if (theMode == -1)
+    {
+      (*aStat)->ClearSelectionModes();
+    }
+    else
+    {
+      (*aStat)->RemoveSelectionMode (theMode);
+    }
+    return;
+  }
+  else if (theMode == -1)
+  {
+    return;
+  }
+
+  if ((*aStat)->SelectionModes().Size() == 1
+   && (*aStat)->SelectionModes().First() == theMode)
+  {
+    return;
   }
+
+  if ((*aStat)->GraphicStatus() == AIS_DS_Displayed
+    || theIsForce)
+  {
+    switch (theActiveFilter)
+    {
+      case AIS_SelectionModesConcurrency_Single:
+      {
+        for (TColStd_ListIteratorOfListOfInteger aModeIter ((*aStat)->SelectionModes()); aModeIter.More(); aModeIter.Next())
+        {
+          mgrSelector->Deactivate (theObj, aModeIter.Value(), myMainSel);
+        }
+        (*aStat)->ClearSelectionModes();
+        break;
+      }
+      case AIS_SelectionModesConcurrency_GlobalOrLocal:
+      {
+        const Standard_Integer aGlobSelMode = theObj->GlobalSelectionMode();
+        TColStd_ListOfInteger aRemovedModes;
+        for (TColStd_ListIteratorOfListOfInteger aModeIter ((*aStat)->SelectionModes()); aModeIter.More(); aModeIter.Next())
+        {
+          if ((theMode == aGlobSelMode && aModeIter.Value() != aGlobSelMode)
+           || (theMode != aGlobSelMode && aModeIter.Value() == aGlobSelMode))
+          {
+            mgrSelector->Deactivate (theObj, aModeIter.Value(), myMainSel);
+            aRemovedModes.Append (aModeIter.Value());
+          }
+        }
+        if (aRemovedModes.Size() == (*aStat)->SelectionModes().Size())
+        {
+          (*aStat)->ClearSelectionModes();
+        }
+        else
+        {
+          for (TColStd_ListIteratorOfListOfInteger aModeIter (aRemovedModes); aModeIter.More(); aModeIter.Next())
+          {
+            (*aStat)->RemoveSelectionMode (aModeIter.Value());
+          }
+        }
+        break;
+      }
+      case AIS_SelectionModesConcurrency_Multiple:
+      {
+        break;
+      }
+    }
+    mgrSelector->Activate (theObj, theMode, myMainSel);
+  }
+  (*aStat)->AddSelectionMode (theMode);
 }
 
 // ============================================================================
@@ -269,52 +363,6 @@ Handle( StdSelect_ViewerSelector3d ) AIS_InteractiveContext::LocalSelector() con
       return myLocalContexts( myCurLocalIndex )->MainSelector();
 }
 
-
-//=======================================================================
-//function : DeActivate
-//purpose  : 
-//=======================================================================
-void AIS_InteractiveContext::
-Deactivate(const Handle(AIS_InteractiveObject)& anIObj)
-{
-  if(!HasOpenedContext()){
-    if(!myObjects.IsBound(anIObj)) return;
-    TColStd_ListIteratorOfListOfInteger ItL;
-    for(ItL.Initialize(myObjects(anIObj)->SelectionModes());
-        ItL.More();
-        ItL.Next()){
-      if(myObjects(anIObj)->GraphicStatus() == AIS_DS_Displayed)
-        mgrSelector->Deactivate(anIObj,ItL.Value(),myMainSel);
-    }
-    myObjects(anIObj)->ClearSelectionModes();
-  }
-  else{
-    const Handle(AIS_LocalContext)& LC = myLocalContexts(myCurLocalIndex);
-    LC->Deactivate(anIObj);
-  }
-}
-
-//=======================================================================
-//function : Deactivate
-//purpose  : 
-//=======================================================================
-
-void AIS_InteractiveContext::Deactivate(const Handle(AIS_InteractiveObject)& anIObj, 
-           const Standard_Integer aMode)
-{
-  if(!HasOpenedContext()){
-    if(!myObjects.IsBound(anIObj)) return;
-    const Handle(AIS_GlobalStatus)& STAT = myObjects(anIObj);
-
-    if(STAT->GraphicStatus() == AIS_DS_Displayed)
-      mgrSelector->Deactivate(anIObj,aMode,myMainSel);
-    STAT->RemoveSelectionMode(aMode);
-  }
-  else{
-   myLocalContexts(myCurLocalIndex)->DeactivateMode(anIObj,aMode);
-  }
-}
-
 // ============================================================================
 // function : Deactivate
 // purpose  :
index cbe5936..2545a59 100644 (file)
@@ -376,48 +376,95 @@ void AIS_LocalContext::Clear(const AIS_ClearMode aType)
     ClearDetected();
   }
 }
+
 //=======================================================================
-//function : ActivateMode
-//purpose  : 
+//function : SetSelectionModeActive
+//purpose  :
 //=======================================================================
-
-void AIS_LocalContext::ActivateMode(const Handle(AIS_InteractiveObject)& aSelectable,
-                                      const Standard_Integer aMode)
+void AIS_LocalContext::SetSelectionModeActive (const Handle(AIS_InteractiveObject)& theObj,
+                                               const Standard_Integer theMode,
+                                               const Standard_Boolean theIsActive,
+                                               const AIS_SelectionModesConcurrency theActiveFilter)
 {
-  if(!myActiveObjects.IsBound(aSelectable)) return;
-//  if(myActiveObjects(aSelectable)->SelectionMode()!=aMode)
-//    mySM->Deactivate(aSelectable,aMode,myMainVS);
-  if(aMode != -1){
-    myActiveObjects(aSelectable)->AddSelectionMode(aMode);
-    mySM->Activate(aSelectable,aMode,myMainVS);
+  const Handle(AIS_LocalStatus)* aStat = myActiveObjects.Seek (theObj);
+  if (aStat == NULL)
+  {
+    return;
   }
-}
-//=======================================================================
-//function : ActivateMode
-//purpose  : 
-//=======================================================================
 
-void AIS_LocalContext::DeactivateMode(const Handle(AIS_InteractiveObject)& aSelectable,
-                                        const Standard_Integer aMode)
-{
-  if(!myActiveObjects.IsBound(aSelectable)) return;
-  
-  if(aMode==-1) return;
-  
-  myActiveObjects(aSelectable)->RemoveSelectionMode(aMode);
-  mySM->Deactivate(aSelectable,aMode,myMainVS);
-}
-//=======================================================================
-//function : ActivateMode
-//purpose  : 
-//=======================================================================
+  if (!theIsActive
+   || (theMode == -1
+    && theActiveFilter == AIS_SelectionModesConcurrency_Single))
+  {
+    if (theMode == -1)
+    {
+      for (TColStd_ListIteratorOfListOfInteger aModeIter ((*aStat)->SelectionModes()); aModeIter.More(); aModeIter.Next())
+      {
+        mySM->Deactivate (theObj, aModeIter.Value(), myMainVS);
+      }
+      (*aStat)->ClearSelectionModes();
+    }
+    else
+    {
+      mySM->Deactivate (theObj, theMode, myMainVS);
+      (*aStat)->RemoveSelectionMode (theMode);
+    }
+    return;
+  }
+  else if (theMode == -1)
+  {
+    return;
+  }
+  else if ((*aStat)->SelectionModes().Size() == 1
+        && (*aStat)->SelectionModes().First() == theMode)
+  {
+    return;
+  }
 
-void AIS_LocalContext::Deactivate(const Handle(AIS_InteractiveObject)& aSelectable)
-{
-  if(!myActiveObjects.IsBound(aSelectable)) return;
-  
-  mySM->Deactivate(aSelectable, -1, myMainVS);
-  myActiveObjects(aSelectable)->ClearSelectionModes();
+  switch (theActiveFilter)
+  {
+    case AIS_SelectionModesConcurrency_Single:
+    {
+      for (TColStd_ListIteratorOfListOfInteger aModeIter ((*aStat)->SelectionModes()); aModeIter.More(); aModeIter.Next())
+      {
+        mySM->Deactivate (theObj, aModeIter.Value(), myMainVS);
+      }
+      (*aStat)->ClearSelectionModes();
+      break;
+    }
+    case AIS_SelectionModesConcurrency_GlobalOrLocal:
+    {
+      const Standard_Integer aGlobSelMode = theObj->GlobalSelectionMode();
+      TColStd_ListOfInteger aRemovedModes;
+      for (TColStd_ListIteratorOfListOfInteger aModeIter ((*aStat)->SelectionModes()); aModeIter.More(); aModeIter.Next())
+      {
+        if ((theMode == aGlobSelMode && aModeIter.Value() != aGlobSelMode)
+          || (theMode != aGlobSelMode && aModeIter.Value() == aGlobSelMode))
+        {
+          mySM->Deactivate (theObj, aModeIter.Value(), myMainVS);
+          aRemovedModes.Append (aModeIter.Value());
+        }
+      }
+      if (aRemovedModes.Size() == (*aStat)->SelectionModes().Size())
+      {
+        (*aStat)->ClearSelectionModes();
+      }
+      else
+      {
+        for (TColStd_ListIteratorOfListOfInteger aModeIter (aRemovedModes); aModeIter.More(); aModeIter.Next())
+        {
+          (*aStat)->RemoveSelectionMode (aModeIter.Value());
+        }
+      }
+      break;
+    }
+    case AIS_SelectionModesConcurrency_Multiple:
+    {
+      break;
+    }
+  }
+  mySM->Activate (theObj, theMode, myMainVS);
+  (*aStat)->AddSelectionMode (theMode);
 }
 
 //=======================================================================
index 0a9af0b..60ec5ba 100644 (file)
@@ -30,6 +30,7 @@
 #include <Standard_Integer.hxx>
 #include <TColStd_SequenceOfInteger.hxx>
 #include <AIS_SequenceOfInteractive.hxx>
+#include <AIS_SelectionModesConcurrency.hxx>
 #include <Standard_Transient.hxx>
 #include <AIS_ClearMode.hxx>
 #include <TopAbs_ShapeEnum.hxx>
@@ -120,12 +121,26 @@ public:
   //! the selector (filters, modeof activation, objects...)
   Standard_EXPORT void Clear (const AIS_ClearMode atype = AIS_CM_All);
   
+  Standard_EXPORT void SetSelectionModeActive (const Handle(AIS_InteractiveObject)& theObj,
+                                               const Standard_Integer theMode,
+                                               const Standard_Boolean theIsActive,
+                                               const AIS_SelectionModesConcurrency theActiveFilter);
+
   //! optional : activation of a mode which is not 0 for a selectable...
-  Standard_EXPORT void ActivateMode (const Handle(AIS_InteractiveObject)& aSelectable, const Standard_Integer aMode);
-  
-  Standard_EXPORT void DeactivateMode (const Handle(AIS_InteractiveObject)& aSelectable, const Standard_Integer aMode);
-  
-  Standard_EXPORT void Deactivate (const Handle(AIS_InteractiveObject)& aSelectable);
+  void ActivateMode (const Handle(AIS_InteractiveObject)& theObj, const Standard_Integer theMode)
+  {
+    SetSelectionModeActive (theObj, theMode, Standard_True, AIS_SelectionModesConcurrency_GlobalOrLocal);
+  }
+
+  void DeactivateMode (const Handle(AIS_InteractiveObject)& theObj, const Standard_Integer theMode)
+  {
+    SetSelectionModeActive (theObj, theMode, Standard_False, AIS_SelectionModesConcurrency_GlobalOrLocal);
+  }
+
+  void Deactivate (const Handle(AIS_InteractiveObject)& theObj)
+  {
+    SetSelectionModeActive (theObj, -1, Standard_False, AIS_SelectionModesConcurrency_Single);
+  }
   
   //! decomposition of shapes into <aType>
   Standard_EXPORT void ActivateStandardMode (const TopAbs_ShapeEnum aType);
diff --git a/src/AIS/AIS_SelectionModesConcurrency.hxx b/src/AIS/AIS_SelectionModesConcurrency.hxx
new file mode 100644 (file)
index 0000000..aa1d9dc
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright (c) 2017 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _AIS_SelectionModesConcurrency_HeaderFile
+#define _AIS_SelectionModesConcurrency_HeaderFile
+
+//! The mode specifying how multiple active Selection Modes should be treated during activation of new one.
+enum AIS_SelectionModesConcurrency
+{
+  AIS_SelectionModesConcurrency_Single,        //!< only one selection mode can be activated at the same moment - previously activated should be deactivated
+  AIS_SelectionModesConcurrency_GlobalOrLocal, //!< either Global (AIS_InteractiveObject::GlobalSelectionMode() or Local (multiple) selection modes can be active at the same moment
+  AIS_SelectionModesConcurrency_Multiple,      //!< any combination of selection modes can be activated
+};
+
+#endif // _AIS_SelectionModesConcurrency_HeaderFile
index e424026..e9d3257 100644 (file)
@@ -146,6 +146,7 @@ AIS_RubberBand.cxx
 AIS_Selection.cxx
 AIS_Selection.hxx
 AIS_SelectStatus.hxx
+AIS_SelectionModesConcurrency.hxx
 AIS_SequenceOfDimension.hxx
 AIS_SequenceOfInteractive.hxx
 AIS_Shape.cxx
index 8ce14f4..a730aa4 100644 (file)
@@ -380,12 +380,6 @@ void SelectMgr_SelectionManager::Activate (const Handle(SelectMgr_SelectableObje
 
   if (myGlobal.Contains (theObject))
   {
-    const Standard_Integer aGlobalSelMode = theObject->GlobalSelectionMode();
-    if (theMode != aGlobalSelMode
-     && theSelector->IsActive (theObject, aGlobalSelMode))
-    {
-      theSelector->Deactivate (theObject->Selection (aGlobalSelMode));
-    }
     theSelector->Activate (theObject->Selection (theMode));
   }
   else
index 5e102fa..bdea8cc 100644 (file)
@@ -72,7 +72,9 @@ void SelectMgr_ToleranceMap::Decrement (const Standard_Integer& theTolerance)
     return;
   }
 
+  Standard_ProgramError_Raise_if (*aFreq == 0, "SelectMgr_ToleranceMap::Decrement() - internal error");
   --(*aFreq);
+
   if (theTolerance == myLargestKey
   && *aFreq == 0)
   {
index c7a2d65..db7fe99 100644 (file)
@@ -4324,82 +4324,70 @@ static Standard_Integer VListConnected (Draw_Interpretor& /*di*/,
   return 0;
 }
 
-namespace
-{
-  //! Checks if theMode is already turned on for theObj.
-  static Standard_Boolean InList (const Handle(AIS_InteractiveContext)& theAISContext,
-                                  const Handle(AIS_InteractiveObject)&  theObj,
-                                  const Standard_Integer                theMode)
-  {
-    TColStd_ListOfInteger anActiveModes;
-    theAISContext->ActivatedModes (theObj, anActiveModes);
-    for (TColStd_ListIteratorOfListOfInteger aModeIt (anActiveModes); aModeIt.More(); aModeIt.Next())
-    {
-      if (aModeIt.Value() == theMode)
-      {
-        return Standard_True;
-      }
-    }
-    return Standard_False;
-  }
-}
-
 //===============================================================================================
 //function : VSetSelectionMode
-//purpose  : Sets input selection mode for input object or for all displayed objects 
-//Draw arg : vselmode [object] mode On/Off (1/0)
+//purpose  : vselmode
 //===============================================================================================
 static Standard_Integer VSetSelectionMode (Draw_Interpretor& /*di*/,
-                                           Standard_Integer  theArgc,
+                                           Standard_Integer  theNbArgs,
                                            const char**      theArgv)
 {
   // Check errors
   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
   if (anAISContext.IsNull())
   {
-    std::cerr << "Call vinit before!" << std::endl;
-    return 1;
-  }
-
-  // Check the arguments
-  if (theArgc < 3 && theArgc > 5)
-  {
-    std::cerr << "vselmode error : expects at least 2 arguments.\n"
-              << "Type help "<< theArgv[0] <<" for more information." << std::endl;
+    std::cout << "Error: no active Viewer\n";
     return 1;
   }
 
-  TCollection_AsciiString aLastArg (theArgv[theArgc - 1]);
-  aLastArg.LowerCase();
-  Standard_Boolean isToOpenLocalCtx = aLastArg == "-local";
-
-  // get objects to change selection mode
-  AIS_ListOfInteractive aTargetIOs;
-  Standard_Integer anArgNb = isToOpenLocalCtx ? theArgc - 1 : theArgc;
-  if (anArgNb == 3)
-  {
-    anAISContext->DisplayedObjects (aTargetIOs);
-  }
-  else
+  NCollection_Sequence<TCollection_AsciiString> anObjNames;
+  Standard_Integer toOpenLocalCtx = -1;
+  Standard_Integer aSelectionMode = -1;
+  Standard_Boolean toTurnOn = Standard_True;
+  AIS_SelectionModesConcurrency aSelModeConcurrency = AIS_SelectionModesConcurrency_GlobalOrLocal;
+  for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
   {
-    // Check if there is an object with given name in context
-    const TCollection_AsciiString aNameIO (theArgv[1]);
-    if (GetMapOfAIS().IsBound2 (aNameIO))
+    TCollection_AsciiString anArgCase (theArgv[anArgIter]);
+    anArgCase.LowerCase();
+    if (toOpenLocalCtx == -1
+     && anArgCase == "-local")
     {
-      Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (aNameIO));
-      if (anIO.IsNull())
-      {
-        std::cerr << "vselmode error : object name is used for non AIS viewer" << std::endl;
-        return 1;
-      }
-      aTargetIOs.Append (anIO);
+      toOpenLocalCtx = 1;
+    }
+    else if (anArgCase == "-set"
+          || anArgCase == "-replace"
+          || anArgCase == "-single"
+          || anArgCase == "-exclusive")
+    {
+      aSelModeConcurrency = AIS_SelectionModesConcurrency_Single;
+    }
+    else if (anArgCase == "-add"
+          || anArgCase == "-combine"
+          || anArgCase == "-combination"
+          || anArgCase == "-multiple")
+    {
+      aSelModeConcurrency = AIS_SelectionModesConcurrency_Multiple;
+    }
+    else if (anArgCase == "-globalorlocal"
+          || anArgCase == "-localorglobal")
+    {
+      aSelModeConcurrency = AIS_SelectionModesConcurrency_GlobalOrLocal;
+    }
+    else
+    {
+      anObjNames.Append (theArgv[anArgIter]);
     }
   }
-
-  Standard_Integer aSelectionMode = -1;
-  Standard_Boolean toTurnOn = Standard_True;
+  if (anObjNames.Size() < 2
+  || !ViewerTest::ParseOnOff (anObjNames.Last().ToCString(), toTurnOn))
+  {
+    std::cout << "Syntax error: wrong number of arguments\n";
+    return 1;
+  }
+  anObjNames.Remove (anObjNames.Upper());
   {
-    const TCollection_AsciiString aSelModeString (theArgv[anArgNb == 3 ? 1 : 2]);
+    const TCollection_AsciiString aSelModeString = anObjNames.Last();
+    anObjNames.Remove (anObjNames.Upper());
     TopAbs_ShapeEnum aShapeType = TopAbs_SHAPE;
     if (aSelModeString.IsIntegerValue())
     {
@@ -4415,77 +4403,52 @@ static Standard_Integer VSetSelectionMode (Draw_Interpretor& /*di*/,
       return 1;
     }
   }
-  if (!ViewerTest::ParseOnOff (theArgv[anArgNb == 3 ? 2 : 3], toTurnOn))
-  {
-    std::cout << "Syntax error: on/off is expected by found '" << theArgv[anArgNb == 3 ? 2 : 3] << "'\n";
-    return 1;
-  }
 
-  Standard_DISABLE_DEPRECATION_WARNINGS
-  if (aSelectionMode == 0 && anAISContext->HasOpenedContext())
-  {
-    anAISContext->CloseLocalContext();
-  }
-  Standard_ENABLE_DEPRECATION_WARNINGS
-
-  if (aSelectionMode == 0)
+  AIS_ListOfInteractive aTargetIOs;
+  for (NCollection_Sequence<TCollection_AsciiString>::Iterator anObjIter (anObjNames); anObjIter.More(); anObjIter.Next())
   {
-    if (toTurnOn)
+    const TCollection_AsciiString& aNameIO = anObjIter.Value();
+    Handle(AIS_InteractiveObject) anIO;
+    if (GetMapOfAIS().IsBound2 (aNameIO))
     {
-      for (AIS_ListIteratorOfListOfInteractive aTargetIt (aTargetIOs); aTargetIt.More(); aTargetIt.Next())
-      {
-        const Handle(AIS_InteractiveObject)& anIO = aTargetIt.Value();
-        TColStd_ListOfInteger anActiveModes;
-        anAISContext->ActivatedModes (anIO, anActiveModes);
-        if (!anActiveModes.IsEmpty())
-        {
-          anAISContext->Deactivate (anIO);
-        }
-        if (!InList (anAISContext, anIO, aSelectionMode))
-        {
-          anAISContext->Activate (anIO);
-        }
-      }
+      anIO = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (aNameIO));
     }
-    else
+
+    if (anIO.IsNull())
     {
-      for (AIS_ListIteratorOfListOfInteractive aTargetIt (aTargetIOs); aTargetIt.More(); aTargetIt.Next())
-      {
-        const Handle(AIS_InteractiveObject)& anIO = aTargetIt.Value();
-        if (InList (anAISContext, anIO, aSelectionMode))
-        {
-          anAISContext->Deactivate (anIO);
-        }
-      }
+      std::cout << "Syntax error: undefined presentable object " << aNameIO << "\n";
+      return 1;
     }
+    aTargetIOs.Append (anIO);
+  }
+  if (aTargetIOs.IsEmpty())
+  {
+    anAISContext->DisplayedObjects (aTargetIOs);
   }
 
-  if (aSelectionMode != 0 && toTurnOn) // Turn on specified mode
+  Standard_DISABLE_DEPRECATION_WARNINGS
+  if (aSelectionMode == 0 && anAISContext->HasOpenedContext())
   {
-    Standard_DISABLE_DEPRECATION_WARNINGS
-    if (!anAISContext->HasOpenedContext() && isToOpenLocalCtx)
+    anAISContext->CloseLocalContext();
+  }
+  else if (aSelectionMode != 0 && toTurnOn)
+  {
+    if (!anAISContext->HasOpenedContext() && toOpenLocalCtx == 1)
     {
       anAISContext->OpenLocalContext (Standard_False);
     }
-    Standard_ENABLE_DEPRECATION_WARNINGS
-
-    for (AIS_ListIteratorOfListOfInteractive aTargetIt (aTargetIOs); aTargetIt.More(); aTargetIt.Next())
-    {
-      const Handle(AIS_InteractiveObject)& anIO = aTargetIt.Value();
-      anAISContext->Deactivate (anIO, 0);
-      anAISContext->Load (anIO, -1, Standard_True);
-      anAISContext->Activate (anIO, aSelectionMode);
-    }
   }
+  Standard_ENABLE_DEPRECATION_WARNINGS
 
-  if (aSelectionMode != 0 && !toTurnOn) // Turn off specified mode
+  for (AIS_ListIteratorOfListOfInteractive aTargetIt (aTargetIOs); aTargetIt.More(); aTargetIt.Next())
   {
-    for (AIS_ListIteratorOfListOfInteractive aTargetIt (aTargetIOs); aTargetIt.More(); aTargetIt.Next())
+    const Handle(AIS_InteractiveObject)& anIO = aTargetIt.Value();
+    if (toOpenLocalCtx == 1 && toTurnOn && aSelectionMode != 0)
     {
-      anAISContext->Deactivate (aSelectionMode);
+      anAISContext->Load (anIO, -1, Standard_True);
     }
+    anAISContext->SetSelectionModeActive (anIO, aSelectionMode, toTurnOn, aSelModeConcurrency);
   }
-
   return 0;
 }
 
@@ -6695,24 +6658,19 @@ void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands)
 
 
   theCommands.Add("vselmode", 
-    "vselmode : [object] mode_number is_turned_on=(1|0)\n"
-    "  switches selection mode for the determined object or\n"
-    "  for all objects in context.\n"
-    "  mode_number is non-negative integer that has different\n"
-    "    meaning for different interactive object classes.\n"
-    "    For shapes the following mode_number values are allowed:\n"
-    "      0 - shape\n"
-    "      1 - vertex\n"
-    "      2 - edge\n"
-    "      3 - wire\n"
-    "      4 - face\n"
-    "      5 - shell\n"
-    "      6 - solid\n"
-    "      7 - compsolid\n"
-    "      8 - compound\n"
-    "  is_turned_on is:\n"
-    "    1 if mode is to be switched on\n"
-    "    0 if mode is to be switched off\n", 
+                "vselmode [object] selectionMode {on|off}"
+      "\n\t\t:            [{-add|-set|-globalOrLocal}=-globalOrLocal]"
+      "\n\t\t: Switches selection mode for the specified object or for all objects in context."
+      "\n\t\t: Selection mode is either an integer number specific to Interactive Object,"
+      "\n\t\t: or sub-shape type in case of AIS_Shape:"
+      "\n\t\t:   Shape, Vertex, Edge, Wire, Face, Shell, Solid, CompSolid, Compound"
+      "\n\t\t: The integer mode 0 (Shape in case of AIS_Shape) is reserved for selecting object as whole."
+      "\n\t\t: Additional options:"
+      "\n\t\t:  -add           already activated selection modes will be left activated"
+      "\n\t\t:  -set           already activated selection modes will be deactivated"
+      "\n\t\t:  -globalOrLocal (default) if new mode is Global selection mode,"
+      "\n\t\t:                 then active local selection modes will be deactivated"
+      "\n\t\t:                 and the samthen active local selection modes will be deactivated",
     __FILE__, VSetSelectionMode, group);
 
   theCommands.Add("vselnext",