X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FXGUI%2FXGUI_Displayer.cpp;h=eb2b6bbc7dd0c82ed90391fe41cce9ffff6d72da;hb=440f972571097934b69e41ed3f264e2cd355051e;hp=3899d5e37fdffb31f1939b95d75823f0e043d6a6;hpb=ee3f547de2d32b374e38cb29887a2fe10923439f;p=modules%2Fshaper.git diff --git a/src/XGUI/XGUI_Displayer.cpp b/src/XGUI/XGUI_Displayer.cpp index 3899d5e37..eb2b6bbc7 100644 --- a/src/XGUI/XGUI_Displayer.cpp +++ b/src/XGUI/XGUI_Displayer.cpp @@ -1,8 +1,22 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> - -// File: XGUI_Displayer.cpp -// Created: 20 Apr 2014 -// Author: Natalia ERMOLAEVA +// Copyright (C) 2014-2017 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or +// email : webmaster.salome@opencascade.com +// #include "XGUI_Displayer.h" #include "XGUI_Workshop.h" @@ -25,22 +39,28 @@ #include #include #include +#include +#include #include #include #include +#include + #include -#include #include #include #include #include #include #include +#ifdef BEFORE_TRIHEDRON_PATCH #include #include #include +#endif +#include #include #include #include @@ -53,12 +73,17 @@ #include #include +#ifdef TINSPECTOR +#include +#endif + #include #include #include -const int MOUSE_SENSITIVITY_IN_PIXEL = 10; ///< defines the local context mouse selection sensitivity +/// defines the local context mouse selection sensitivity +const int MOUSE_SENSITIVITY_IN_PIXEL = 10; //#define DEBUG_ACTIVATE_OBJECTS //#define DEBUG_DEACTIVATE @@ -70,26 +95,15 @@ const int MOUSE_SENSITIVITY_IN_PIXEL = 10; ///< defines the local context mouse //#define DEBUG_SELECTION_FILTERS //#define DEBUG_COMPOSILID_DISPLAY -// Workaround for bug #25637 + +//#define DEBUG_OCCT_SHAPE_SELECTION + +#define CLEAR_OUTDATED_SELECTION_BEFORE_REDISPLAY + void displayedObjects(const Handle(AIS_InteractiveContext)& theAIS, AIS_ListOfInteractive& theList) { // Get from null point theAIS->DisplayedObjects(theList, true); - if (theAIS->HasOpenedContext()) { - // get from local context - const Handle(AIS_LocalContext)& aLC = theAIS->LocalContext(); - TColStd_MapOfTransient aMap; - int NbDisp = aLC->DisplayedObjects(aMap); - TColStd_MapIteratorOfMapOfTransient aIt(aMap); - - Handle(AIS_InteractiveObject) curIO; - Handle(Standard_Transient) Tr; - for(; aIt.More(); aIt.Next()){ - Tr = aIt.Key(); - curIO = *((Handle(AIS_InteractiveObject)*) &Tr); - theList.Append(curIO); - } - } } QString qIntListInfo(const QIntList& theValues, const QString& theSeparator = QString(", ")) @@ -102,11 +116,32 @@ QString qIntListInfo(const QIntList& theValues, const QString& theSeparator = QS return anInfo.join(theSeparator); } +void deselectPresentation(const Handle(AIS_InteractiveObject) theObject, + const Handle(AIS_InteractiveContext)& theContext) +{ + NCollection_List aResultOwners; + + for (theContext->InitSelected(); theContext->MoreSelected(); theContext->NextSelected()) { + Handle(SelectMgr_EntityOwner) anOwner = theContext->SelectedOwner(); + if (anOwner.IsNull()) // TODO: check why it is possible + continue; + if (anOwner->Selectable() == theObject && anOwner->IsSelected()) + aResultOwners.Append(anOwner); + } + NCollection_List::Iterator anOwnersIt (aResultOwners); + Handle(SelectMgr_EntityOwner) anOwner; + for (; anOwnersIt.More(); anOwnersIt.Next()) { + anOwner = Handle(SelectMgr_EntityOwner)::DownCast(anOwnersIt.Value()); + if (!anOwner.IsNull()) + theContext->AddOrRemoveSelected(anOwner, false); + } +} + XGUI_Displayer::XGUI_Displayer(XGUI_Workshop* theWorkshop) - : myWorkshop(theWorkshop), myEnableUpdateViewer(true), myNeedUpdate(false), - myIsTrihedronActive(false) + : myWorkshop(theWorkshop), myNeedUpdate(false), + myIsTrihedronActive(true), myViewerBlockedRecursiveCount(0), + myIsFirstAISContextUse(true) { - enableUpdateViewer(true); myCustomPrs = std::shared_ptr(new XGUI_CustomPrs(theWorkshop)); } @@ -124,7 +159,8 @@ bool XGUI_Displayer::display(ObjectPtr theObject, bool theUpdateViewer) bool aDisplayed = false; if (isVisible(theObject)) { #ifdef DEBUG_COMPOSILID_DISPLAY - ResultCompSolidPtr aCompsolidResult = std::dynamic_pointer_cast(theObject); + ResultCompSolidPtr aCompsolidResult = + std::dynamic_pointer_cast(theObject); if (aCompsolidResult.get()) { for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) { ResultPtr aSubResult = aCompsolidResult->subResult(i); @@ -143,11 +179,24 @@ bool XGUI_Displayer::display(ObjectPtr theObject, bool theUpdateViewer) bool isShading = false; if (aPrs.get() != NULL) { anAIS = aPrs->getAISObject(anAIS); + if (anAIS.get()) { + // correct deviation coefficient for + /*Handle(AIS_InteractiveObject) anAISPrs = anAIS->impl(); + if (!anAISPrs.IsNull()) { + Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(anAISPrs); + if (!aShapePrs.IsNull()) { + TopoDS_Shape aShape = aShapePrs->Shape(); + if (!aShape.IsNull()) + //ModuleBase_Tools::setDefaultDeviationCoefficient(aShape, anAISPrs->Attributes()); + } + }*/ + } } else { ResultPtr aResult = std::dynamic_pointer_cast(theObject); if (aResult.get() != NULL) { #ifdef DEBUG_COMPOSILID_DISPLAY - ResultCompSolidPtr aCompsolidResult = std::dynamic_pointer_cast(theObject); + ResultCompSolidPtr aCompsolidResult = + std::dynamic_pointer_cast(theObject); if (aCompsolidResult.get()) { for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) { ResultPtr aSubResult = aCompsolidResult->subResult(i); @@ -162,7 +211,16 @@ bool XGUI_Displayer::display(ObjectPtr theObject, bool theUpdateViewer) std::shared_ptr aShapePtr = ModelAPI_Tools::shape(aResult); if (aShapePtr.get() != NULL) { anAIS = AISObjectPtr(new GeomAPI_AISObject()); - anAIS->setImpl(new Handle(AIS_InteractiveObject)(new ModuleBase_ResultPrs(aResult))); + Handle(AIS_InteractiveObject) anAISPrs = + myWorkshop->module()->createPresentation(aResult); + if (anAISPrs.IsNull()) + anAISPrs = new ModuleBase_ResultPrs(aResult); + else { + Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(anAISPrs); + if (!aShapePrs.IsNull()) + ModuleBase_Tools::setPointBallHighlighting((AIS_Shape*) aShapePrs.get()); + } + anAIS->setImpl(new Handle(AIS_InteractiveObject)(anAISPrs)); //anAIS->createShape(aShapePtr); isShading = true; } @@ -177,7 +235,7 @@ bool XGUI_Displayer::display(ObjectPtr theObject, bool theUpdateViewer) return aDisplayed; } -bool canBeShaded(Handle(AIS_InteractiveObject) theAIS) +bool canBeShaded(Handle(AIS_InteractiveObject) theAIS, ModuleBase_IModule* theModule) { Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(theAIS); if (!aShapePrs.IsNull()) { @@ -189,16 +247,13 @@ bool canBeShaded(Handle(AIS_InteractiveObject) theAIS) return false; else { // Check that the presentation is not a sketch - Handle(ModuleBase_ResultPrs) aPrs = Handle(ModuleBase_ResultPrs)::DownCast(theAIS); - if (!aPrs.IsNull()) - return !aPrs->isSketchMode(); - return true; + return theModule->canBeShaded(theAIS); } } return false; } -bool XGUI_Displayer::display(ObjectPtr theObject, AISObjectPtr theAIS, +bool XGUI_Displayer::display(ObjectPtr theObject, AISObjectPtr theAIS, bool isShading, bool theUpdateViewer) { bool aDisplayed = false; @@ -217,21 +272,15 @@ bool XGUI_Displayer::display(ObjectPtr theObject, AISObjectPtr theAIS, if (isShading) anAISIO->Attributes()->SetFaceBoundaryDraw( Standard_True ); anAISIO->SetDisplayMode(aDispMode); - aContext->Display(anAISIO, aDispMode, 0, false, true, AIS_DS_Displayed); + aContext->Display(anAISIO, aDispMode, 0, false, true, AIS_DS_Displayed); + #ifdef TINSPECTOR + if (getCallBack()) getCallBack()->Display(anAISIO); + #endif aDisplayed = true; emit objectDisplayed(theObject, theAIS); activate(anAISIO, myActiveSelectionModes, theUpdateViewer); - // the fix from VPA for more suitable selection of sketcher lines - if(anAISIO->Width() > 1) { - for(int aModeIdx = 0; aModeIdx < myActiveSelectionModes.length(); ++aModeIdx) { - int aMode = myActiveSelectionModes.value(aModeIdx); - double aPrecision = (aMode == getSelectionMode(TopAbs_VERTEX))? 20 : - (anAISIO->Width() + 2); - aContext->SetSelectionSensitivity(anAISIO, aMode, aPrecision); - } - } - } + } if (theUpdateViewer) updateViewer(); @@ -253,7 +302,10 @@ bool XGUI_Displayer::erase(ObjectPtr theObject, const bool theUpdateViewer) Handle(AIS_InteractiveObject) anAIS = anObject->impl(); if (!anAIS.IsNull()) { emit beforeObjectErase(theObject, anObject); - aContext->Remove(anAIS, theUpdateViewer); + aContext->Remove(anAIS, false/*update viewer*/); + #ifdef TINSPECTOR + if (getCallBack()) getCallBack()->Remove(anAIS); + #endif aErased = true; } } @@ -265,6 +317,10 @@ bool XGUI_Displayer::erase(ObjectPtr theObject, const bool theUpdateViewer) qDebug(QString("erase object: %1").arg(aPtrStr.str().c_str()).toStdString().c_str()); qDebug(getResult2AISObjectMapInfo().c_str()); #endif + + if (theUpdateViewer) + updateViewer(); + return aErased; } @@ -293,7 +349,7 @@ bool XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer) Handle(AIS_InteractiveContext) aContext = AISContext(); if (!aContext.IsNull() && !aAISIO.IsNull()) { // Check that the visualized shape is the same and the redisplay is not necessary - // Redisplay of AIS object leads to this object selection compute and the selection + // Redisplay of AIS object leads to this object selection compute and the selection // in the browser is lost // this check is not necessary anymore because the selection store/restore is realized // before and after the values modification. @@ -316,10 +372,27 @@ bool XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer) bool isCustomized = customizeObject(theObject); #ifdef DEBUG_FEATURE_REDISPLAY qDebug(QString("Redisplay: %1, isEqualShapes=%2, isCustomized=%3"). - arg(!isEqualShapes || isCustomized).arg(isEqualShapes).arg(isCustomized).toStdString().c_str()); + arg(!isEqualShapes || isCustomized).arg(isEqualShapes) + .arg(isCustomized).toStdString().c_str()); #endif if (!isEqualShapes || isCustomized) { + /// if shapes are equal and presentation are customized, selection should be restored + bool aNeedToRestoreSelection = isEqualShapes && isCustomized; + if (aNeedToRestoreSelection) + myWorkshop->module()->storeSelection(); + +#ifdef CLEAR_OUTDATED_SELECTION_BEFORE_REDISPLAY + deselectPresentation(aAISIO, aContext); +#endif aContext->Redisplay(aAISIO, false); + + #ifdef TINSPECTOR + if (getCallBack()) getCallBack()->Redisplay(aAISIO); + #endif + + if (aNeedToRestoreSelection) + myWorkshop->module()->restoreSelection(); + aRedisplayed = true; #ifdef DEBUG_FEATURE_REDISPLAY qDebug(" Redisplay happens"); @@ -360,7 +433,9 @@ void XGUI_Displayer::deactivate(ObjectPtr theObject, const bool theUpdateViewer) deactivateAIS(anAIS); // the selection from the previous activation modes should be cleared manually (#26172) - aContext->LocalContext()->ClearOutdatedSelection(anAIS, true); +#ifndef CLEAR_OUTDATED_SELECTION_BEFORE_REDISPLAY + deselectPresentation(anAIS, aContext); +#endif if (theUpdateViewer) updateViewer(); } @@ -403,10 +478,81 @@ void XGUI_Displayer::getModesOfActivation(ObjectPtr theObject, QIntList& theMode int XGUI_Displayer::getSelectionMode(int theShapeType) { - return (theShapeType >= TopAbs_SHAPE)? theShapeType : - AIS_Shape::SelectionMode((TopAbs_ShapeEnum)theShapeType); + return (theShapeType > TopAbs_SHAPE) ? theShapeType : + AIS_Shape::SelectionMode((TopAbs_ShapeEnum)theShapeType); } +bool XGUI_Displayer::isVisible(XGUI_Displayer* theDisplayer, const ObjectPtr& theObject) +{ + bool aVisible = false; + GeomPresentablePtr aPrs = std::dynamic_pointer_cast(theObject); + ResultPtr aResult = std::dynamic_pointer_cast(theObject); + if (aPrs.get() || aResult.get()) { + aVisible = theDisplayer->isVisible(theObject); + // compsolid is not visualized in the viewer, + // but should have presentation when all sub solids are + // visible. It is useful for highlight presentation where compsolid shape is selectable + if (!aVisible && aResult.get() && aResult->groupName() == ModelAPI_ResultCompSolid::group()) { + ResultCompSolidPtr aCompsolidResult = + std::dynamic_pointer_cast(aResult); + if (aCompsolidResult.get() != NULL) { // change colors for all sub-solids + bool anAllSubsVisible = aCompsolidResult->numberOfSubs() > 0; + for(int i = 0; i < aCompsolidResult->numberOfSubs() && anAllSubsVisible; i++) { + anAllSubsVisible = theDisplayer->isVisible(aCompsolidResult->subResult(i)); + } + aVisible = anAllSubsVisible; + } + } + } + // it is possible that feature is presentable and has results, so we should check visibility + // of results if presentation is not shown (e.g. Sketch Circle/Arc features) + if (!aVisible) { + // check if all results of the feature are visible + FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); + std::list aResults; + ModelAPI_Tools::allResults(aFeature, aResults); + std::list::const_iterator aIt; + aVisible = !aResults.empty(); + for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { + aVisible = aVisible && theDisplayer->isVisible(*aIt); + } + } + return aVisible; +} + +#ifdef DEBUG_ACTIVATE_OBJECTS +QString getModeInfo(const int theMode) +{ + QString anInfo = "Undefined"; + switch(theMode) { + case 0: anInfo = "SHAPE(0)"; break; + case 1: anInfo = "VERTEX(1)"; break; + case 2: anInfo = "EDGE(2)"; break; + case 3: anInfo = "WIRE(3)"; break; + case 4: anInfo = "FACE(4)"; break; + case 5: anInfo = "SHELL(5)"; break; + case 6: anInfo = "SOLID(6)"; break; + case 7: anInfo = "COMPSOLID(7)"; break; + case 8: anInfo = "COMPOUND(8)"; break; + case 100: anInfo = "Sel_Mode_First(100)"; break; //SketcherPrs_Tools + case 101: anInfo = "Sel_Constraint(101)"; break; + case 102: anInfo = "Sel_Dimension_All(102)"; break; + case 103: anInfo = "Sel_Dimension_Line(103)"; break; + case 104: anInfo = "Sel_Dimension_Text(104)"; break; + default: break; + } + return anInfo; +} + +QString getModesInfo(const QIntList& theModes) +{ + QStringList aModesInfo; + for (int i = 0, aSize = theModes.size(); i < aSize; i++) + aModesInfo.append(getModeInfo(theModes[i])); + return QString("[%1] = %2").arg(aModesInfo.size()).arg(aModesInfo.join(", ")); +} +#endif + void XGUI_Displayer::activateObjects(const QIntList& theModes, const QObjectPtrList& theObjList, const bool theUpdateViewer) { @@ -424,9 +570,10 @@ void XGUI_Displayer::activateObjects(const QIntList& theModes, const QObjectPtrL } QString anInfoStr = anInfo.join(", "); - qDebug(QString("activateObjects: aModes[%1] = %2, myActiveSelectionModes[%3] = %4, objects = %5"). - arg(aModes.size()).arg(qIntListInfo(aModes)). - arg(myActiveSelectionModes.size()).arg(qIntListInfo(myActiveSelectionModes)). + qDebug(QString("activateObjects: new modes%1, active modes%2, objects[%3] = %4"). + arg(getModesInfo(aModes)). + arg(getModesInfo(myActiveSelectionModes)). + arg(theObjList.size()). arg(anInfoStr). toStdString().c_str()); #endif @@ -439,7 +586,7 @@ void XGUI_Displayer::activateObjects(const QIntList& theModes, const QObjectPtrL myActiveSelectionModes = aNewModes; Handle(AIS_InteractiveContext) aContext = AISContext(); // Open local context if there is no one - if (aContext.IsNull() || !aContext->HasOpenedContext()) + if (aContext.IsNull()) return; //aContext->UseDisplayedObjects(); @@ -473,13 +620,6 @@ void XGUI_Displayer::activateObjects(const QIntList& theModes, const QObjectPtrL if (activate(anAISIO, myActiveSelectionModes, false)) isActivationChanged = true; } - if (!aTrihedron.IsNull()) { - foreach(int aMode, myActiveSelectionModes) - aContext->SetSelectionSensitivity(aTrihedron, aMode, 20); - } - // VSV It seems that there is no necessity to update viewer on activation - //if (theUpdateViewer && isActivationChanged) - // updateViewer(); } bool XGUI_Displayer::isActive(ObjectPtr theObject) const @@ -487,67 +627,91 @@ bool XGUI_Displayer::isActive(ObjectPtr theObject) const Handle(AIS_InteractiveContext) aContext = AISContext(); if (aContext.IsNull() || !isVisible(theObject)) return false; - + AISObjectPtr anObj = myResult2AISObjectMap[theObject]; Handle(AIS_InteractiveObject) anAIS = anObj->impl(); TColStd_ListOfInteger aModes; aContext->ActivatedModes(anAIS, aModes); + #ifdef TINSPECTOR + if (getCallBack()) getCallBack()->ActivatedModes(anAIS, aModes); + #endif + return aModes.Extent() > 0; } -void XGUI_Displayer::setSelected(const QList& theValues, bool theUpdateViewer) + + +void XGUI_Displayer::setSelected(const QList& theValues, + bool theUpdateViewer) { Handle(AIS_InteractiveContext) aContext = AISContext(); if (aContext.IsNull()) return; - if (aContext->HasOpenedContext()) { - aContext->UnhilightSelected(false); - aContext->ClearSelected(false); - foreach (ModuleBase_ViewerPrs aPrs, theValues) { - const TopoDS_Shape& aShape = aPrs.shape(); - if (!aShape.IsNull()) { - aContext->AddOrRemoveSelected(aShape, false); - } else { - ObjectPtr anObject = aPrs.object(); - ResultPtr aResult = std::dynamic_pointer_cast(anObject); - if (aResult.get() && isVisible(aResult)) { - AISObjectPtr anObj = myResult2AISObjectMap[aResult]; - Handle(AIS_InteractiveObject) anAIS = anObj->impl(); - if (!anAIS.IsNull()) { - // The methods are replaced in order to provide multi-selection, e.g. restore selection - // by activating multi selector widget. It also gives an advantage that the multi - // selection in OB gives multi-selection in the viewer - //aContext->SetSelected(anAIS, false); - // The selection in the context was cleared, so the method sets the objects are selected - aContext->AddOrRemoveSelected(anAIS, false); - } - } - } - } - } else { - aContext->UnhilightCurrents(false); - aContext->ClearCurrents(false); - foreach (ModuleBase_ViewerPrs aPrs, theValues) { - ObjectPtr anObject = aPrs.object(); + aContext->UnhilightSelected(false); + aContext->ClearSelected(false); + #ifdef TINSPECTOR + if (getCallBack()) getCallBack()->ClearSelected(); + #endif + NCollection_DataMap> + aShapesToBeSelected; + + foreach (ModuleBase_ViewerPrsPtr aPrs, theValues) { + const GeomShapePtr& aGeomShape = aPrs->shape(); + if (aGeomShape.get() && !aGeomShape->isNull()) { + const TopoDS_Shape& aShape = aGeomShape->impl(); +#ifdef DEBUG_OCCT_SHAPE_SELECTION + // problem 1: performance + // problem 2: IO is not specified, so the first found owner is selected, as a result + // it might belong to another result + aContext->AddOrRemoveSelected(aShape, false); + #ifdef TINSPECTOR + if (getCallBack()) getCallBack()->AddOrRemoveSelected(aShape); + #endif +#else + NCollection_Map aPresentations; + if (aShapesToBeSelected.IsBound(aShape)) + aPresentations = aShapesToBeSelected.Find(aShape); + ObjectPtr anObject = aPrs->object(); + getPresentations(anObject, aPresentations); + + aShapesToBeSelected.Bind(aShape, aPresentations); +#endif + } else { + ObjectPtr anObject = aPrs->object(); ResultPtr aResult = std::dynamic_pointer_cast(anObject); if (aResult.get() && isVisible(aResult)) { AISObjectPtr anObj = myResult2AISObjectMap[aResult]; Handle(AIS_InteractiveObject) anAIS = anObj->impl(); - if (!anAIS.IsNull()) - aContext->SetCurrentObject(anAIS, false); + if (!anAIS.IsNull()) { + // The methods are replaced in order to provide multi-selection, e.g. restore selection + // by activating multi selector widget. It also gives an advantage that the multi + // selection in OB gives multi-selection in the viewer + //aContext->SetSelected(anAIS, false); + // The selection in the context was cleared, so the method sets the objects are selected + aContext->AddOrRemoveSelected(anAIS, false); + #ifdef TINSPECTOR + if (getCallBack()) getCallBack()->AddOrRemoveSelected(anAIS); + #endif + } } } } + if (!aShapesToBeSelected.IsEmpty()) + XGUI_Displayer::AddOrRemoveSelectedShapes(aContext, aShapesToBeSelected); + if (theUpdateViewer) updateViewer(); } -void XGUI_Displayer::clearSelected() +void XGUI_Displayer::clearSelected(const bool theUpdateViewer) { Handle(AIS_InteractiveContext) aContext = AISContext(); if (!aContext.IsNull()) { - aContext->UnhilightCurrents(false); - aContext->ClearSelected(); + aContext->UnhilightSelected(false);//UnhilightCurrents(false); + aContext->ClearSelected(theUpdateViewer); + #ifdef TINSPECTOR + if (getCallBack()) getCallBack()->ClearSelected(); + #endif } } @@ -562,7 +726,10 @@ bool XGUI_Displayer::eraseAll(const bool theUpdateViewer) Handle(AIS_InteractiveObject) anIO = aAISObj->impl(); if (!anIO.IsNull()) { emit beforeObjectErase(aObj, aAISObj); - aContext->Remove(anIO, false); + aContext->Remove(anIO, false/*update viewer*/); + #ifdef TINSPECTOR + if (getCallBack()) getCallBack()->Remove(anIO); + #endif aErased = true; } } @@ -578,15 +745,17 @@ bool XGUI_Displayer::eraseAll(const bool theUpdateViewer) } void deactivateObject(Handle(AIS_InteractiveContext) theContext, - Handle(AIS_InteractiveObject) theObject, - const bool theClear = true) + Handle(AIS_InteractiveObject) theObject +#ifdef TINSPECTOR + , Handle(VInspectorAPI_CallBack) theCallBack +#endif + ) { if (!theObject.IsNull()) { theContext->Deactivate(theObject); - //if (theClear) { - //theObject->ClearSelected(); - // theContext->LocalContext()->ClearOutdatedSelection(theObject, true); - //} + #ifdef TINSPECTOR + if (theCallBack) theCallBack->Deactivate(theObject); + #endif } } @@ -596,20 +765,51 @@ void XGUI_Displayer::deactivateTrihedron(const bool theUpdateViewer) const Handle(AIS_InteractiveContext) aContext = AISContext(); if (!aTrihedron.IsNull() && aContext->IsDisplayed(aTrihedron)) { Handle(AIS_Trihedron) aTrie = Handle(AIS_Trihedron)::DownCast(aTrihedron); - deactivateObject(aContext, aTrie); + deactivateObject(aContext, aTrie + #ifdef TINSPECTOR + , getCallBack() + #endif + ); /// #1136 hidden axis are selected in sketch - /// workaround for Cascade: there is a crash in AIS_LocalContext::ClearOutdatedSelection - /// for Position AIS object in SelectionModes. - deactivateObject(aContext, aTrie->XAxis()); - deactivateObject(aContext, aTrie->YAxis()); - deactivateObject(aContext, aTrie->Axis()); - deactivateObject(aContext, aTrie->Position()); - - deactivateObject(aContext, aTrie->XYPlane()); - deactivateObject(aContext, aTrie->XZPlane()); - deactivateObject(aContext, aTrie->YZPlane()); +#ifdef BEFORE_TRIHEDRON_PATCH + deactivateObject(aContext, aTrie->XAxis() + #ifdef TINSPECTOR + , getCallBack() + #endif + ); + deactivateObject(aContext, aTrie->YAxis() + #ifdef TINSPECTOR + , getCallBack() + #endif + ); + deactivateObject(aContext, aTrie->Axis() + #ifdef TINSPECTOR + , getCallBack() + #endif + ); + deactivateObject(aContext, aTrie->Position() + #ifdef TINSPECTOR + , getCallBack() + #endif + ); + deactivateObject(aContext, aTrie->XYPlane() + #ifdef TINSPECTOR + , getCallBack() + #endif + ); + deactivateObject(aContext, aTrie->XZPlane() + #ifdef TINSPECTOR + , getCallBack() + #endif + ); + deactivateObject(aContext, aTrie->YZPlane() + #ifdef TINSPECTOR + , getCallBack() + #endif + ); +#endif if (theUpdateViewer) updateViewer(); } @@ -620,7 +820,7 @@ Handle(AIS_InteractiveObject) XGUI_Displayer::getTrihedron() const return myWorkshop->viewer()->trihedron(); } -void XGUI_Displayer::openLocalContext() +/*void XGUI_Displayer::openLocalContext() { Handle(AIS_InteractiveContext) aContext = AISContext(); // Open local context if there is no one @@ -655,9 +855,9 @@ void XGUI_Displayer::openLocalContext() // aContext->SetSelected(aIt2.Value(), false); //} } -} +}*/ -void XGUI_Displayer::closeLocalContexts(const bool theUpdateViewer) +/*void XGUI_Displayer::closeLocalContexts(const bool theUpdateViewer) { Handle(AIS_InteractiveContext) aContext = AISContext(); if (!aContext.IsNull() && aContext->HasOpenedContext()) { @@ -685,7 +885,7 @@ void XGUI_Displayer::closeLocalContexts(const bool theUpdateViewer) aContext->Display(aAISIO, false); aContext->SetDisplayMode(aAISIO, Shading, false); } - }*/ + }*+/ // Append the filters from the local selection in the global selection context SelectMgr_ListIteratorOfListOfFilter aIt(aFilters); @@ -705,7 +905,7 @@ void XGUI_Displayer::closeLocalContexts(const bool theUpdateViewer) // aContext->SetCurrentObject(aIt2.Value(), false); //} } -} +}*/ AISObjectPtr XGUI_Displayer::getAISObject(ObjectPtr theObject) const { @@ -744,21 +944,29 @@ ObjectPtr XGUI_Displayer::getObject(const Handle(AIS_InteractiveObject)& theIO) bool XGUI_Displayer::enableUpdateViewer(const bool isEnabled) { - bool aWasEnabled = myEnableUpdateViewer; + bool aWasEnabled = isUpdateEnabled(); + if (isEnabled) + myViewerBlockedRecursiveCount--; + else + myViewerBlockedRecursiveCount++; - myEnableUpdateViewer = isEnabled; - if (myNeedUpdate && myEnableUpdateViewer) { + if (myNeedUpdate && isUpdateEnabled()) { updateViewer(); myNeedUpdate = false; } return aWasEnabled; } +bool XGUI_Displayer::isUpdateEnabled() const +{ + return myViewerBlockedRecursiveCount == 0; +} + void XGUI_Displayer::updateViewer() const { Handle(AIS_InteractiveContext) aContext = AISContext(); - if (!aContext.IsNull() && myEnableUpdateViewer) { - myWorkshop->viewer()->Zfitall(); + if (!aContext.IsNull() && isUpdateEnabled()) { + //myWorkshop->viewer()->Zfitall(); aContext->UpdateCurrentViewer(); } else { myNeedUpdate = true; @@ -769,30 +977,70 @@ void XGUI_Displayer::activateAIS(const Handle(AIS_InteractiveObject)& theIO, const int theMode, const bool theUpdateViewer) const { Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext(); + if (!theIO.IsNull() && theIO == getTrihedron()) { + if (theMode != AIS_Shape::SelectionType(TopAbs_EDGE) && + theMode != AIS_Shape::SelectionType(TopAbs_VERTEX)) + return; + } if (!aContext.IsNull()) { - aContext->Activate(theIO, theMode, theUpdateViewer); + if (myWorkshop->module()) { + int aMode = (theMode > 8)? theMode : AIS_Shape::SelectionType(theMode); + aContext->Activate(theIO, theMode, false); + } else + aContext->Activate(theIO, theMode, false); + #ifdef TINSPECTOR + if (getCallBack()) getCallBack()->Activate(theIO, theMode); + #endif + + // the fix from VPA for more suitable selection of sketcher lines + if (theIO->Width() > 1) { + double aPrecision = theIO->Width() + 2; + if (theMode == getSelectionMode(TopAbs_VERTEX)) + aPrecision = ModuleBase_Preferences::resourceMgr()->doubleValue("Viewer", + "point-selection-sensitivity", + 12); + else if ((theMode == getSelectionMode(TopAbs_EDGE)) || + (theMode == getSelectionMode(TopAbs_WIRE))) + aPrecision = theIO->Width() + + ModuleBase_Preferences::resourceMgr()->doubleValue("Viewer", + "edge-selection-sensitivity", 2); + aContext->SetSelectionSensitivity(theIO, theMode, aPrecision); + } #ifdef DEBUG_ACTIVATE_AIS ObjectPtr anObject = getObject(theIO); anInfo.append(ModuleBase_Tools::objectInfo((*anIt))); - qDebug(QString("activateAIS: theMode = %1, object = %2").arg(theMode).arg(anInfo).toStdString().c_str()); + qDebug(QString("activateAIS: theMode = %1, object = %2").arg(theMode) + .arg(anInfo).toStdString().c_str()); #endif + if (theUpdateViewer) + updateViewer(); } } -void XGUI_Displayer::deactivateAIS(const Handle(AIS_InteractiveObject)& theIO, const int theMode) const +void XGUI_Displayer::deactivateAIS(const Handle(AIS_InteractiveObject)& theIO, + const int theMode) const { Handle(AIS_InteractiveContext) aContext = AISContext(); if (!aContext.IsNull()) { - if (theMode == -1) + if (theMode == -1) { aContext->Deactivate(theIO); - else + #ifdef TINSPECTOR + if (getCallBack()) getCallBack()->Deactivate(theIO); + #endif + } + else { aContext->Deactivate(theIO, theMode); + #ifdef TINSPECTOR + if (getCallBack()) getCallBack()->Deactivate(theIO, theMode); + #endif + } #ifdef DEBUG_DEACTIVATE_AIS ObjectPtr anObject = getObject(theIO); anInfo.append(ModuleBase_Tools::objectInfo((*anIt))); - qDebug(QString("deactivateAIS: theMode = %1, object = %2").arg(theMode).arg(anInfo).toStdString().c_str()); + qDebug(QString("deactivateAIS: theMode = %1, object = %2").arg(theMode) + .arg(anInfo).toStdString().c_str()); #endif } } @@ -800,8 +1048,10 @@ void XGUI_Displayer::deactivateAIS(const Handle(AIS_InteractiveObject)& theIO, c Handle(AIS_InteractiveContext) XGUI_Displayer::AISContext() const { Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext(); - if (!aContext.IsNull() && !aContext->HasOpenedContext()) { - aContext->OpenLocalContext(); + if (!aContext.IsNull() && myIsFirstAISContextUse/*&& !aContext->HasOpenedContext()*/) { + XGUI_Displayer* aDisplayer = (XGUI_Displayer*)this; + aDisplayer->myIsFirstAISContextUse = false; + //aContext->OpenLocalContext(); if (!isTrihedronActive()) deactivateTrihedron(true); aContext->DefaultDrawer()->VIsoAspect()->SetNumber(0); @@ -821,27 +1071,36 @@ Handle(SelectMgr_AndFilter) XGUI_Displayer::GetFilter() } bool XGUI_Displayer::displayAIS(AISObjectPtr theAIS, const bool toActivateInSelectionModes, - bool theUpdateViewer) + const Standard_Integer theDisplayMode, bool theUpdateViewer) { bool aDisplayed = false; Handle(AIS_InteractiveContext) aContext = AISContext(); Handle(AIS_InteractiveObject) anAISIO = theAIS->impl(); if (!aContext.IsNull() && !anAISIO.IsNull()) { - aContext->Display(anAISIO, 0/*wireframe*/, 0, theUpdateViewer, true, AIS_DS_Displayed); + aContext->Display(anAISIO, theDisplayMode, 0, false/*update viewer*/, true, AIS_DS_Displayed); + #ifdef TINSPECTOR + if (getCallBack()) getCallBack()->Display(anAISIO); + #endif aDisplayed = true; aContext->Deactivate(anAISIO); + #ifdef TINSPECTOR + if (getCallBack()) getCallBack()->Deactivate(anAISIO); + #endif aContext->Load(anAISIO); + #ifdef TINSPECTOR + if (getCallBack()) getCallBack()->Load(anAISIO); + #endif if (toActivateInSelectionModes) { - if (aContext->HasOpenedContext()) { - if (myActiveSelectionModes.size() == 0) - activateAIS(anAISIO, 0, theUpdateViewer); - else { - foreach(int aMode, myActiveSelectionModes) { - activateAIS(anAISIO, aMode, theUpdateViewer); - } + if (myActiveSelectionModes.size() == 0) + activateAIS(anAISIO, 0, theUpdateViewer); + else { + foreach(int aMode, myActiveSelectionModes) { + activateAIS(anAISIO, aMode, theUpdateViewer); } } } + if (theUpdateViewer) + updateViewer(); } return aDisplayed; } @@ -853,7 +1112,10 @@ bool XGUI_Displayer::eraseAIS(AISObjectPtr theAIS, const bool theUpdateViewer) if (!aContext.IsNull()) { Handle(AIS_InteractiveObject) anAISIO = theAIS->impl(); if (!anAISIO.IsNull() && aContext->IsDisplayed(anAISIO)) { - aContext->Remove(anAISIO, theUpdateViewer); + aContext->Remove(anAISIO, false/*update viewer*/); + #ifdef TINSPECTOR + if (getCallBack()) getCallBack()->Remove(anAISIO); + #endif aErased = true; } } @@ -943,7 +1205,8 @@ void XGUI_Displayer::removeSelectionFilter(const Handle(SelectMgr_Filter)& theFi aCompositeFilter->Remove(theFilter); #ifdef DEBUG_SELECTION_FILTERS int aCount = aCompositeFilter->StoredFilters().Extent(); - qDebug(QString("removeSelectionFilter: filters.count() = %1").arg(aCount).toStdString().c_str()); + qDebug(QString("removeSelectionFilter: filters.count() = %1") + .arg(aCount).toStdString().c_str()); #endif } } @@ -958,14 +1221,14 @@ bool XGUI_Displayer::hasSelectionFilter(const Handle(SelectMgr_Filter)& theFilte const SelectMgr_ListOfFilter& aFilters = aContext->Filters(); SelectMgr_ListIteratorOfListOfFilter aIt(aFilters); for (; aIt.More() && !aFilterFound; aIt.Next()) { - if (theFilter.Access() == aIt.Value().Access()) + if (theFilter.get() == aIt.Value().get()) aFilterFound = true; } Handle(SelectMgr_CompositionFilter) aCompositeFilter = GetFilter(); if (!aCompositeFilter.IsNull()) { const SelectMgr_ListOfFilter& aStoredFilters = aCompositeFilter->StoredFilters(); for (aIt.Initialize(aStoredFilters); aIt.More() && !aFilterFound; aIt.Next()) { - if (theFilter.Access() == aIt.Value().Access()) + if (theFilter.get() == aIt.Value().get()) aFilterFound = true; } } @@ -998,7 +1261,7 @@ void XGUI_Displayer::showOnly(const QObjectPtrList& theList) } bool XGUI_Displayer::canBeShaded(ObjectPtr theObject) const -{ +{ if (!isVisible(theObject)) return false; @@ -1007,7 +1270,7 @@ bool XGUI_Displayer::canBeShaded(ObjectPtr theObject) const return false; Handle(AIS_InteractiveObject) anAIS = aAISObj->impl(); - return ::canBeShaded(anAIS); + return ::canBeShaded(anAIS, myWorkshop->module()); } bool XGUI_Displayer::activate(const Handle(AIS_InteractiveObject)& theIO, @@ -1017,7 +1280,7 @@ bool XGUI_Displayer::activate(const Handle(AIS_InteractiveObject)& theIO, Handle(AIS_InteractiveContext) aContext = AISContext(); if (aContext.IsNull() || theIO.IsNull()) return false; - + bool isActivationChanged = false; // deactivate object in all modes, which are not in the list of activation // It seems that after the IO deactivation the selected state of the IO's owners @@ -1027,14 +1290,21 @@ bool XGUI_Displayer::activate(const Handle(AIS_InteractiveObject)& theIO, // If the selection problem happens again, it is possible to write a test scenario and create // a bug. The bug steps are the following: // Create two IO, activate them in 5 modes, select the first IO, deactivate 3 modes for both, - // with clicked SHIFT select the second object. The result is the selection of the first IO is lost. + // with clicked SHIFT select the second object. + // The result is the selection of the first IO is lost. TColStd_ListOfInteger aTColModes; aContext->ActivatedModes(theIO, aTColModes); + #ifdef TINSPECTOR + if (getCallBack()) getCallBack()->ActivatedModes(theIO, aTColModes); + #endif TColStd_ListIteratorOfListOfInteger itr( aTColModes ); QIntList aModesActivatedForIO; bool isDeactivated = false; + bool aHasValidMode = false; for (; itr.More(); itr.Next() ) { Standard_Integer aMode = itr.Value(); + aHasValidMode = aHasValidMode || aMode != -1; + int aShapeMode = (aMode > 8)? aMode : AIS_Shape::SelectionType(aMode); if (!theModes.contains(aMode)) { deactivateAIS(theIO, aMode); isDeactivated = true; @@ -1045,8 +1315,13 @@ bool XGUI_Displayer::activate(const Handle(AIS_InteractiveObject)& theIO, } if (isDeactivated) { // the selection from the previous activation modes should be cleared manually (#26172) - theIO->ClearSelected(); - aContext->LocalContext()->ClearOutdatedSelection(theIO, true); + //theIO->ClearSelected(); + //#ifdef TINSPECTOR + //if (getCallBack()) getCallBack()->ClearSelected(theIO); + //#endif +#ifndef CLEAR_OUTDATED_SELECTION_BEFORE_REDISPLAY + deselectPresentation(theIO, aContext); +#endif // For performance issues //if (theUpdateViewer) // updateViewer(); @@ -1054,8 +1329,19 @@ bool XGUI_Displayer::activate(const Handle(AIS_InteractiveObject)& theIO, } // loading the interactive object allowing the decomposition - if (aTColModes.IsEmpty()) { + if (aTColModes.IsEmpty() || !aHasValidMode) { aContext->Load(theIO, -1, true); + Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast(theIO); + if (!aTrihedron.IsNull()) { + // Workaround for Trihedron. It should be loaded using the next Load method to + // add this object to myGlobal map of selection manager + // it is important to activate trihedron in two selection modes: edges and vertices + aContext->SelectionManager()->Load(theIO); + } + + #ifdef TINSPECTOR + if (getCallBack()) getCallBack()->Load(theIO); + #endif } // trihedron AIS check should be after the AIS loading. @@ -1101,11 +1387,15 @@ bool XGUI_Displayer::customizeObject(ObjectPtr theObject) } bool isCustomized = aCustomPrs.get() && aCustomPrs->customisePresentation(aResult, anAISObj, myCustomPrs); + isCustomized = myWorkshop->module()->afterCustomisePresentation(aResult, anAISObj, myCustomPrs) + || isCustomized; return isCustomized; } -QColor XGUI_Displayer::setObjectColor(ObjectPtr theObject, const QColor& theColor, bool theUpdateViewer) +QColor XGUI_Displayer::setObjectColor(ObjectPtr theObject, + const QColor& theColor, + bool theUpdateViewer) { if (!isVisible(theObject)) return Qt::black; @@ -1131,6 +1421,7 @@ void XGUI_Displayer::appendResultObject(ObjectPtr theObject, AISObjectPtr theAIS #endif } +#ifdef _DEBUG std::string XGUI_Displayer::getResult2AISObjectMapInfo() const { QStringList aContent; @@ -1140,16 +1431,61 @@ std::string XGUI_Displayer::getResult2AISObjectMapInfo() const aPtrStr << "aObj = " << aObj.get() << ":"; aPtrStr << "anAIS = " << aAISObj.get() << ":"; aPtrStr << "[" << ModuleBase_Tools::objectInfo(aObj).toStdString().c_str() << "]"; - + aContent.append(aPtrStr.str().c_str()); } return QString("myResult2AISObjectMap: size = %1\n%2\n").arg(myResult2AISObjectMap.size()). arg(aContent.join("\n")).toStdString().c_str(); } +#endif + +void XGUI_Displayer::getPresentations(const ObjectPtr& theObject, + NCollection_Map& thePresentations) +{ + ResultPtr aResult = std::dynamic_pointer_cast(theObject); + if (aResult.get()) { + AISObjectPtr aAISObj = getAISObject(aResult); + if (aAISObj.get() == NULL) { + // if result is a result of a composite feature, it is visualized by visualization of + // composite children, so we should get one of this presentations + ResultCompSolidPtr aCompSolid = std::dynamic_pointer_cast(aResult); + if (aCompSolid.get() && aCompSolid->numberOfSubs() > 0) { + aAISObj = getAISObject(aCompSolid->subResult(0)); + } + } + if (aAISObj.get() != NULL) { + Handle(AIS_InteractiveObject) anAIS = aAISObj->impl(); + if (!anAIS.IsNull() && !thePresentations.Contains(anAIS)) + thePresentations.Add(anAIS); + } + } + else { + FeaturePtr aFeature = std::dynamic_pointer_cast(theObject); + // find presentation of the feature + AISObjectPtr aAISObj = getAISObject(aFeature); + if (aAISObj.get() != NULL) { + Handle(AIS_InteractiveObject) anAIS = aAISObj->impl(); + if (!anAIS.IsNull() && !thePresentations.Contains(anAIS)) + thePresentations.Add(anAIS); + } + // find presentations of the feature results + std::list aResults; + ModelAPI_Tools::allResults(aFeature, aResults); + std::list::const_iterator anIt = aResults.begin(), aLast = aResults.end(); + for (; anIt != aLast; ++anIt) { + AISObjectPtr aAISObj = getAISObject(*anIt); + if (aAISObj.get() != NULL) { + Handle(AIS_InteractiveObject) anAIS = aAISObj->impl(); + if (!anAIS.IsNull() && !thePresentations.Contains(anAIS)) + thePresentations.Add(anAIS); + } + } + } +} -void XGUI_Displayer::activateTrihedron(bool theIsActive) -{ - myIsTrihedronActive = theIsActive; +void XGUI_Displayer::activateTrihedron(bool theIsActive) +{ + myIsTrihedronActive = theIsActive; if (!myIsTrihedronActive) { deactivateTrihedron(true); } @@ -1171,6 +1507,9 @@ void XGUI_Displayer::displayTrihedron(bool theToDisplay) const Standard_True /* update viewer*/, Standard_False /* allow decomposition */, AIS_DS_Displayed /* xdisplay status */); + #ifdef TINSPECTOR + if (getCallBack()) getCallBack()->Display(aTrihedron); + #endif if (!isTrihedronActive()) deactivateTrihedron(false); @@ -1178,11 +1517,96 @@ void XGUI_Displayer::displayTrihedron(bool theToDisplay) const activate(aTrihedron, myActiveSelectionModes, false); } else { deactivateTrihedron(false); - //aContext->LocalContext()->ClearOutdatedSelection(aTrihedron, true); - // the selection from the previous activation modes should be cleared manually (#26172) - aContext->Erase(aTrihedron); + aContext->Erase(aTrihedron, Standard_True); + #ifdef TINSPECTOR + if (getCallBack()) getCallBack()->Remove(aTrihedron); + #endif } updateViewer(); } + +QIntList XGUI_Displayer::activeSelectionModes() const +{ + QIntList aModes; + foreach (int aMode, myActiveSelectionModes) { + // aMode < 9 is a Shape Enum values + aModes << ((aMode < 9)? AIS_Shape::SelectionType(aMode) : aMode); + } + return aModes; +} + +void XGUI_Displayer::AddOrRemoveSelectedShapes(Handle(AIS_InteractiveContext) theContext, + const NCollection_DataMap>& theShapesToBeSelected) +{ + NCollection_Map aCompsolidPresentations; + NCollection_Map aSelectedPresentations; + + NCollection_List anActiveOwners; + theContext->MainSelector()->ActiveOwners(anActiveOwners); + NCollection_List::Iterator anOwnersIt (anActiveOwners); + Handle(SelectMgr_EntityOwner) anOwner; + + /// It is very important to check that the owner is processed only once and has a map of + /// processed owners because SetSelected works as a switch. + /// If count of calls setSelectec is even, the object stays in the previous state + /// (selected, deselected) + /// OCCT: to write about the problem that active owners method returns one owner several times + QList aSelectedIds; // Remember of selected address in order to avoid duplicates + for (; anOwnersIt.More(); anOwnersIt.Next()) { + anOwner = Handle(SelectMgr_EntityOwner)::DownCast (anOwnersIt.Value()); + if (aSelectedIds.contains((long)anOwner.get())) + continue; + aSelectedIds.append((long)anOwner.get()); + + Handle(StdSelect_BRepOwner) BROwnr = Handle(StdSelect_BRepOwner)::DownCast(anOwner); + if (!BROwnr.IsNull() && BROwnr->HasShape()) { + const TopoDS_Shape& aShape = BROwnr->Shape(); + if (aShape.IsNull()) + continue; + + Handle(ModuleBase_BRepOwner) aCustomOwner = Handle(ModuleBase_BRepOwner)::DownCast(anOwner); + + NCollection_DataMap > + ::Iterator aShapeIt(theShapesToBeSelected); + for (; aShapeIt.More(); aShapeIt.Next()) { + const TopoDS_Shape& aParameterShape = aShapeIt.Key(); + // isSame should be used here as it does not check orientation of shapes + // despite on isEqual of shapes or IsBound for shape in QMap. Orientation is + // different for Edges shapes in model shape and owner even if this is the same shape + if (aParameterShape.IsSame(aShape)) { + Handle(AIS_InteractiveObject) anOwnerPresentation = + Handle(AIS_InteractiveObject)::DownCast(anOwner->Selectable()); + NCollection_Map aPresentations = + theShapesToBeSelected.Find(aParameterShape); + if (aPresentations.Contains(anOwnerPresentation)) { + theContext->AddOrRemoveSelected(anOwner, Standard_False); + anOwner->SetSelected (Standard_True); + // collect selected presentations to do not select them if compsolid is selected + if (!aSelectedPresentations.Contains(anOwnerPresentation)) + aSelectedPresentations.Add(anOwnerPresentation); + } + } + else if (!aCustomOwner.IsNull()) { // CompSolid processing #2219 + // shape of owner is compound, but shape to be selected is compsolid, so + // we need to compare shape to AIS presentation of owner(rule of the owner creation) + Handle(AIS_Shape) anOwnerPresentation = + Handle(AIS_Shape)::DownCast(anOwner->Selectable()); + const TopoDS_Shape& aPresentationShape = anOwnerPresentation->Shape(); + if (aParameterShape.IsSame(anOwnerPresentation->Shape()) && + !aCompsolidPresentations.Contains(anOwnerPresentation)) + aCompsolidPresentations.Add(anOwnerPresentation); + } + } + } + } + // select CompSolid presentations if their owners was not selected yet + NCollection_Map::Iterator anIt (aCompsolidPresentations); + for (; anIt.More(); anIt.Next()) { + if (aSelectedPresentations.Contains(anIt.Value())) + continue; + theContext->AddOrRemoveSelected(anIt.Value(), Standard_False); + } +}