From f7a533506e3db4dd75f61459c6898863ff9e8ac0 Mon Sep 17 00:00:00 2001 From: nds Date: Thu, 23 May 2019 19:58:59 +0300 Subject: [PATCH] 0030737: Visualization - implementing new selection schemes in context --- src/AIS/AIS_InteractiveContext.cxx | 6 ++ src/AIS/AIS_InteractiveContext.hxx | 11 +++ src/AIS/AIS_InteractiveContext_1.cxx | 112 +++++++++++++++++---------- src/AIS/AIS_Selection.cxx | 70 +++++++++++++++++ src/AIS/AIS_Selection.hxx | 24 ++++++ src/AIS/AIS_SelectionScheme.hxx | 31 ++++++++ src/AIS/AIS_SelectionType.hxx | 31 ++++++++ src/AIS/FILES | 2 + 8 files changed, 244 insertions(+), 43 deletions(-) create mode 100644 src/AIS/AIS_SelectionScheme.hxx create mode 100644 src/AIS/AIS_SelectionType.hxx diff --git a/src/AIS/AIS_InteractiveContext.cxx b/src/AIS/AIS_InteractiveContext.cxx index 5c8aa1368c..7daeb7a38b 100644 --- a/src/AIS/AIS_InteractiveContext.cxx +++ b/src/AIS/AIS_InteractiveContext.cxx @@ -163,6 +163,12 @@ myIsAutoActivateSelMode(Standard_True) aStyle->SetMethod(Aspect_TOHM_COLOR); aStyle->SetColor (Quantity_NOC_GRAY40); } + SetSelectionScheme (AIS_SelectionType_Select, AIS_SelectionScheme_ClearAndAdd); + SetSelectionScheme (AIS_SelectionType_SelectInRect, AIS_SelectionScheme_ClearAndAdd); + SetSelectionScheme (AIS_SelectionType_SelectInPoly, AIS_SelectionScheme_ClearAndAdd); + SetSelectionScheme (AIS_SelectionType_ShiftSelect, AIS_SelectionScheme_Switch); + SetSelectionScheme (AIS_SelectionType_ShiftSelectInRect, AIS_SelectionScheme_Switch); + SetSelectionScheme (AIS_SelectionType_ShiftSelectInPoly, AIS_SelectionScheme_Switch); InitAttributes(); } diff --git a/src/AIS/AIS_InteractiveContext.hxx b/src/AIS/AIS_InteractiveContext.hxx index 779af679bc..868a47b7e1 100644 --- a/src/AIS/AIS_InteractiveContext.hxx +++ b/src/AIS/AIS_InteractiveContext.hxx @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include #include @@ -443,6 +445,14 @@ public: //! @name Selection management return AddSelect (theObject->GlobalSelOwner()); } + //! Returns selection scheme used in Select + AIS_SelectionScheme SelectionScheme (const AIS_SelectionType theType) const + { return mySelectionSchemes.Find (theType); } + + //! Returns selection scheme used in Select + void SetSelectionScheme (const AIS_SelectionType theType, const AIS_SelectionScheme theScheme) + { mySelectionSchemes.Bind (theType, theScheme); } + //! Selects everything found in the bounding rectangle defined by the pixel minima and maxima, XPMin, YPMin, XPMax, and YPMax in the view. //! The objects detected are passed to the main viewer, which is then updated. Standard_EXPORT AIS_StatusOfPick Select (const Standard_Integer theXPMin, @@ -1361,6 +1371,7 @@ protected: //! @name internal fields Standard_Boolean myAutoHilight; Standard_Boolean myIsAutoActivateSelMode; + NCollection_DataMap mySelectionSchemes; }; DEFINE_STANDARD_HANDLE(AIS_InteractiveContext, Standard_Transient) diff --git a/src/AIS/AIS_InteractiveContext_1.cxx b/src/AIS/AIS_InteractiveContext_1.cxx index 15b388d436..8ad48b24eb 100644 --- a/src/AIS/AIS_InteractiveContext_1.cxx +++ b/src/AIS/AIS_InteractiveContext_1.cxx @@ -454,18 +454,22 @@ AIS_StatusOfPick AIS_InteractiveContext::Select (const Standard_Integer theXPMi // all objects detected by the selector are taken, previous current objects are emptied, // new objects are put... - ClearSelected (Standard_False); + if (myAutoHilight) + { + clearDynamicHighlight(); + UnhilightSelected (Standard_False); + } myWasLastMain = Standard_True; + myMainSel->Pick (theXPMin, theYPMin, theXPMax, theYPMax, theView); + + AIS_NListOfEntityOwner aPickedOwners; for (Standard_Integer aPickIter = 1; aPickIter <= myMainSel->NbPicked(); ++aPickIter) { - const Handle(SelectMgr_EntityOwner)& aCurOwner = myMainSel->Picked (aPickIter); - if (aCurOwner.IsNull() || !aCurOwner->HasSelectable() || !myFilters->IsOk (aCurOwner)) - continue; - - mySelection->Select (aCurOwner); + aPickedOwners.Append (myMainSel->Picked (aPickIter)); aCurOwner->SetSelected (Standard_True); } + mySelection->SelectOwners (aPickedOwners, SelectionScheme (AIS_SelectionType_SelectInRect), myFilters); if (myAutoHilight) { @@ -495,18 +499,22 @@ AIS_StatusOfPick AIS_InteractiveContext::Select (const TColgp_Array1OfPnt2d& the // all objects detected by the selector are taken, previous current objects are emptied, // new objects are put... - ClearSelected (Standard_False); + if (myAutoHilight) + { + clearDynamicHighlight(); + UnhilightSelected (Standard_False); + } + myWasLastMain = Standard_True; myMainSel->Pick (thePolyline, theView); + + AIS_NListOfEntityOwner aPickedOwners; for (Standard_Integer aPickIter = 1; aPickIter <= myMainSel->NbPicked(); ++aPickIter) { - const Handle(SelectMgr_EntityOwner) anOwner = myMainSel->Picked (aPickIter); - if (anOwner.IsNull() || !anOwner->HasSelectable() || !myFilters->IsOk (anOwner)) - continue; - - mySelection->Select (anOwner); + aPickedOwners.Append (myMainSel->Picked (aPickIter)); anOwner->SetSelected (Standard_True); } + mySelection->SelectOwners (aPickedOwners, SelectionScheme (AIS_SelectionType_SelectInPoly), myFilters); if (myAutoHilight) { @@ -527,26 +535,34 @@ AIS_StatusOfPick AIS_InteractiveContext::Select (const TColgp_Array1OfPnt2d& the //======================================================================= AIS_StatusOfPick AIS_InteractiveContext::Select (const Standard_Boolean toUpdateViewer) { - if (myWasLastMain && !myLastinMain.IsNull()) + // special case: single selection of detected owner - is it necessary ? + /*if (myWasLastMain && !myLastinMain.IsNull() && !myAutoHilight && + (myLastinMain->IsSelected() + && !myLastinMain->IsForcedHilight() + && NbSelected() <= 1)) { - if (myAutoHilight) - { - clearDynamicHighlight(); - } - if (!myLastinMain->IsSelected() - || myLastinMain->IsForcedHilight() - || NbSelected() > 1) - { - SetSelected (myLastinMain, Standard_False); - if(toUpdateViewer) - { - UpdateCurrentViewer(); - } - } + mySelection->selectOwner(myLastinMain, aPrevSelected, SelectionScheme (AIS_SelectionType_Select)); + return getStatusOfPick (NbSelected()); + }*/ + + if (myAutoHilight) + { + clearDynamicHighlight(); + UnhilightSelected (Standard_False); } - else + + AIS_NListOfEntityOwner aPickedOwners; + aPickedOwners.Append (myLastinMain); + mySelection->SelectOwners (aPickedOwners, SelectionScheme (AIS_SelectionType_Select), myFilters); + + if (myAutoHilight) { - ClearSelected (toUpdateViewer); + HilightSelected (toUpdateViewer); + } + + if(toUpdateViewer) + { + UpdateCurrentViewer(); } Standard_Integer aSelNum = NbSelected(); @@ -562,15 +578,25 @@ AIS_StatusOfPick AIS_InteractiveContext::Select (const Standard_Boolean toUpdate //======================================================================= AIS_StatusOfPick AIS_InteractiveContext::ShiftSelect (const Standard_Boolean toUpdateViewer) { + AIS_NListOfEntityOwner aPrevSelected = mySelection->Objects(); if (myAutoHilight) { clearDynamicHighlight(); + UnhilightSelected (Standard_False); } - if (myWasLastMain && !myLastinMain.IsNull()) + + AIS_NListOfEntityOwner aPickedOwners; + aPickedOwners.Append (myLastinMain); + mySelection->SelectOwners (aPickedOwners, SelectionScheme (AIS_SelectionType_ShiftSelect), myFilters); + + if (myAutoHilight) { - AddOrRemoveSelected (myLastinMain, toUpdateViewer); + HilightSelected (toUpdateViewer); } + if (toUpdateViewer) + UpdateCurrentViewer(); + Standard_Integer aSelNum = NbSelected(); return (aSelNum == 0) ? AIS_SOP_NothingSelected @@ -594,21 +620,21 @@ AIS_StatusOfPick AIS_InteractiveContext::ShiftSelect (const Standard_Integer the throw Standard_ProgramError ("AIS_InteractiveContext::ShiftSelect() - invalid argument"); } + AIS_NListOfEntityOwner aPrevSelected = mySelection->Objects(); if (myAutoHilight) { + clearDynamicHighlight(); UnhilightSelected (Standard_False); } myWasLastMain = Standard_True; myMainSel->Pick (theXPMin, theYPMin, theXPMax, theYPMax, theView); + + AIS_NListOfEntityOwner aPickedOwners; for (Standard_Integer aPickIter = 1; aPickIter <= myMainSel->NbPicked(); ++aPickIter) { - const Handle(SelectMgr_EntityOwner) anOwner = myMainSel->Picked (aPickIter); - if (anOwner.IsNull() || !anOwner->HasSelectable() || !myFilters->IsOk (anOwner)) - continue; - - AIS_SelectStatus aSelStatus = mySelection->Select (anOwner); - anOwner->SetSelected (aSelStatus == AIS_SS_Added); + aPickedOwners.Append (myMainSel->Picked (aPickIter)); } + mySelection->SelectOwners (aPickedOwners, SelectionScheme (AIS_SelectionType_ShiftSelectInRect), myFilters); if (myAutoHilight) { @@ -636,21 +662,21 @@ AIS_StatusOfPick AIS_InteractiveContext::ShiftSelect (const TColgp_Array1OfPnt2d throw Standard_ProgramError ("AIS_InteractiveContext::ShiftSelect() - invalid argument"); } + AIS_NListOfEntityOwner aPrevSelected = mySelection->Objects(); if (myAutoHilight) { + clearDynamicHighlight(); UnhilightSelected (Standard_False); } myWasLastMain = Standard_True; myMainSel->Pick (thePolyline, theView); + + AIS_NListOfEntityOwner aPickedOwners; for (Standard_Integer aPickIter = 1; aPickIter <= myMainSel->NbPicked(); ++aPickIter) { - const Handle(SelectMgr_EntityOwner) anOwner = myMainSel->Picked (aPickIter); - if (anOwner.IsNull() || !anOwner->HasSelectable() || !myFilters->IsOk (anOwner)) - continue; - - AIS_SelectStatus aSelStatus = mySelection->Select (anOwner); - anOwner->SetSelected (aSelStatus == AIS_SS_Added); + aPickedOwners.Append (myMainSel->Picked (aPickIter)); } + mySelection->SelectOwners (aPickedOwners, SelectionScheme (AIS_SelectionType_ShiftSelectInPoly), myFilters); if (myAutoHilight) { diff --git a/src/AIS/AIS_Selection.cxx b/src/AIS/AIS_Selection.cxx index 1af6833a9a..2a8e86e1ac 100644 --- a/src/AIS/AIS_Selection.cxx +++ b/src/AIS/AIS_Selection.cxx @@ -15,6 +15,8 @@ #include #include +#include +#include IMPLEMENT_STANDARD_RTTIEXT(AIS_Selection, Standard_Transient) @@ -122,3 +124,71 @@ AIS_SelectStatus AIS_Selection::AddSelect (const Handle(SelectMgr_EntityOwner)& myResultMap.Bind (theObject, aListIter); return AIS_SS_Added; } + +//======================================================================= +//function : SelectOwners +//purpose : +//======================================================================= +void AIS_Selection::SelectOwners (const AIS_NListOfEntityOwner& thePickedOwners, + const int theSelScheme, + const Handle(SelectMgr_Filter)& theFilter) +{ + int aSelScheme = theSelScheme; + AIS_NListOfEntityOwner aPrevSelected = Objects(); + if (theSelScheme & AIS_SelectionScheme_Clear) + { + Clear(); + + if (theSelScheme & AIS_SelectionScheme_Switch && + theSelScheme & AIS_SelectionScheme_PickedIfEmpty && + thePickedOwners.Size() < aPrevSelected.Size()) + { + // check if all picked objects are in previous selected list, if so, all objects will be deselected, + // but in mode AIS_SelectionScheme_PickedIfEmpty new picked objects should be selected, here, after Clear, Add + Standard_Boolean anOtherFound = Standard_False; + for (AIS_NListOfEntityOwner::Iterator aSelIter (thePickedOwners); aSelIter.More(); aSelIter.Next()) + { + anOtherFound = !aPrevSelected.Contains (aSelIter.Value()); + if (anOtherFound) + break; + } + if (!anOtherFound) + aSelScheme = AIS_SelectionScheme_Add; + } + } + + for (AIS_NListOfEntityOwner::Iterator aSelIter (thePickedOwners); aSelIter.More(); aSelIter.Next()) + { + selectOwner(aSelIter.Value(), aPrevSelected, aSelScheme, theFilter); + } +} + +//======================================================================= +//function : selectOwner +//purpose : +//======================================================================= +AIS_SelectStatus AIS_Selection::selectOwner (const Handle(SelectMgr_EntityOwner)& theOwner, + const AIS_NListOfEntityOwner& thePreviousSelected, + const int theSelScheme, + const Handle(SelectMgr_Filter)& theFilter) +{ + if (theOwner.IsNull() || !theOwner->HasSelectable() || !theFilter->IsOk (theOwner)) + return AIS_SS_NotDone; + + if (theSelScheme & AIS_SelectionScheme_Add) + { + return AddSelect (theOwner); + } + else if (theSelScheme & AIS_SelectionScheme_Switch) + { + if (thePreviousSelected.Contains (theOwner)) // was selected, should not be now + { + if (theOwner->IsSelected()) + return Select (theOwner); // deselect + } + else + return AddSelect (theOwner); // was not selected, should be now + } + + return AIS_SS_NotDone; +} diff --git a/src/AIS/AIS_Selection.hxx b/src/AIS/AIS_Selection.hxx index 8e7cf50e91..dc56d6dad6 100644 --- a/src/AIS/AIS_Selection.hxx +++ b/src/AIS/AIS_Selection.hxx @@ -22,6 +22,8 @@ #include #include +class SelectMgr_Filter; + //! Class holding the list of selected owners. class AIS_Selection : public Standard_Transient { @@ -75,6 +77,28 @@ public: //! Return selected object at iterator position. const Handle(SelectMgr_EntityOwner)& Value() const { return myIterator.Value(); } + //! Select or deselect owners depending on the selection scheme + //! \param theOwners elements to change selection state + //! \param theSelScheme selection scheme, defines how owner is selected + //! \param theFilter context filter to skip not acceptable owners + //! \return result of selection + Standard_EXPORT virtual void SelectOwners (const AIS_NListOfEntityOwner& thePickedOwners, + const int theSelScheme, + const Handle(SelectMgr_Filter)& theFilter); + +protected: + //! Select or deselect owner depending on the selection scheme + //! \param theOwner element to change selection state + //! \param thePreviousSelected previous selected objects + //! \param theSelScheme selection scheme, defines how owner is selected + //! \param theFilter context filter to skip not acceptable owners + //! \return result of selection + Standard_EXPORT virtual AIS_SelectStatus selectOwner (const Handle(SelectMgr_EntityOwner)& theOwner, + const AIS_NListOfEntityOwner& thePreviousSelected, + const int theSelScheme, + const Handle(SelectMgr_Filter)& theFilter); + + private: AIS_NListOfEntityOwner myresult; diff --git a/src/AIS/AIS_SelectionScheme.hxx b/src/AIS/AIS_SelectionScheme.hxx new file mode 100644 index 0000000000..d34c3f40c3 --- /dev/null +++ b/src/AIS/AIS_SelectionScheme.hxx @@ -0,0 +1,31 @@ +// Copyright (c) 2019 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_SelectionScheme_HeaderFile +#define _AIS_SelectionScheme_HeaderFile + + +//! Sets selection schemes for interactive contexts. +//! It is possible to use combination of schemes. +enum AIS_SelectionScheme +{ + AIS_SelectionScheme_Clear = 0x0001, // clears current selection + AIS_SelectionScheme_Add = 0x0002, // add detected object to current selection + AIS_SelectionScheme_Switch = 0x0004, // switch selection state in values selected/deselected + AIS_SelectionScheme_PickedIfEmpty = 0x0008, // if after switch, result selection is empty, select picked objects + AIS_SelectionScheme_ClearAndSwitch = AIS_SelectionScheme_Clear | AIS_SelectionScheme_Switch, + AIS_SelectionScheme_ClearAndAdd = AIS_SelectionScheme_Clear | AIS_SelectionScheme_Add +}; + +#endif // _AIS_SelectionScheme_HeaderFile diff --git a/src/AIS/AIS_SelectionType.hxx b/src/AIS/AIS_SelectionType.hxx new file mode 100644 index 0000000000..22c11aa386 --- /dev/null +++ b/src/AIS/AIS_SelectionType.hxx @@ -0,0 +1,31 @@ +// Copyright (c) 2019 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_SelectionType_HeaderFile +#define _AIS_SelectionType_HeaderFile + + +//! Sets selection schemes for interactive contexts. +//! It is possible to use combination of schemes. +enum AIS_SelectionType +{ + AIS_SelectionType_Select, + AIS_SelectionType_SelectInRect, + AIS_SelectionType_SelectInPoly, + AIS_SelectionType_ShiftSelect, + AIS_SelectionType_ShiftSelectInRect, + AIS_SelectionType_ShiftSelectInPoly +}; + +#endif // _AIS_SelectionType_HeaderFile diff --git a/src/AIS/FILES b/src/AIS/FILES index c7d6cca95f..40ae9d0018 100644 --- a/src/AIS/FILES +++ b/src/AIS/FILES @@ -138,6 +138,8 @@ AIS_Selection.cxx AIS_Selection.hxx AIS_SelectStatus.hxx AIS_SelectionModesConcurrency.hxx +AIS_SelectionScheme.hxx +AIS_SelectionType.hxx AIS_SequenceOfDimension.hxx AIS_SequenceOfInteractive.hxx AIS_Shape.cxx -- 2.39.5