X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FXGUI%2FXGUI_Displayer.cpp;h=cb2503f0486e7522f106b6eab129bbf0db0a0004;hb=9129370ff85bfb4c0c37d9f32f9d107041ec2fe8;hp=68e8b68bdf16e7720c362e0da0c88edb7d904462;hpb=ae10303116314dd4ae5b01246229f7eb5e3b2cdc;p=modules%2Fshaper.git diff --git a/src/XGUI/XGUI_Displayer.cpp b/src/XGUI/XGUI_Displayer.cpp index 68e8b68bd..cb2503f04 100644 --- a/src/XGUI/XGUI_Displayer.cpp +++ b/src/XGUI/XGUI_Displayer.cpp @@ -1,19 +1,32 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + // File: XGUI_Displayer.cpp // Created: 20 Apr 2014 // Author: Natalia ERMOLAEVA #include "XGUI_Displayer.h" -#include "XGUI_Viewer.h" #include "XGUI_Workshop.h" #include "XGUI_ViewerProxy.h" +#include "XGUI_SelectionMgr.h" +#include "XGUI_Selection.h" +#include "XGUI_CustomPrs.h" + +#include #include #include #include #include +#include +#include + +#include +#include +#include #include #include +#include #include #include @@ -21,14 +34,69 @@ #include #include #include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include #include const int MOUSE_SENSITIVITY_IN_PIXEL = 10; ///< defines the local context mouse selection sensitivity +//#define DEBUG_ACTIVATE_OBJECTS +//#define DEBUG_DEACTIVATE +//#define DEBUG_ACTIVATE_AIS +//#define DEBUG_DEACTIVATE_AIS + +//#define DEBUG_DISPLAY +//#define DEBUG_FEATURE_REDISPLAY +//#define DEBUG_SELECTION_FILTERS + +//#define DEBUG_COMPOSILID_DISPLAY +// Workaround for bug #25637 +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(", ")) +{ + QStringList anInfo; + QIntList::const_iterator anIt = theValues.begin(), aLast = theValues.end(); + for (; anIt != aLast; anIt++) { + anInfo.append(QString::number(*anIt)); + } + return anInfo.join(theSeparator); +} + XGUI_Displayer::XGUI_Displayer(XGUI_Workshop* theWorkshop) + : myWorkshop(theWorkshop) { - myWorkshop = theWorkshop; + enableUpdateViewer(true); + myCustomPrs = std::shared_ptr(new XGUI_CustomPrs()); } XGUI_Displayer::~XGUI_Displayer() @@ -37,38 +105,89 @@ XGUI_Displayer::~XGUI_Displayer() bool XGUI_Displayer::isVisible(ObjectPtr theObject) const { - return myResult2AISObjectMap.find(theObject) != myResult2AISObjectMap.end(); + return myResult2AISObjectMap.contains(theObject); } -void XGUI_Displayer::display(ObjectPtr theObject, bool isUpdateViewer) +void XGUI_Displayer::display(ObjectPtr theObject, bool theUpdateViewer) { if (isVisible(theObject)) { - redisplay(theObject, isUpdateViewer); +#ifdef DEBUG_COMPOSILID_DISPLAY + ResultCompSolidPtr aCompsolidResult = std::dynamic_pointer_cast(theObject); + if (aCompsolidResult.get()) { + for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) { + ResultPtr aSubResult = aCompsolidResult->subResult(i); + if (aSubResult.get()) + redisplay(aSubResult, false); + } + if (theUpdateViewer) + updateViewer(); + } + else +#endif + redisplay(theObject, theUpdateViewer); } else { - boost::shared_ptr anAIS; + AISObjectPtr anAIS; - GeomPresentablePtr aPrs = boost::dynamic_pointer_cast(theObject); + GeomPresentablePtr aPrs = std::dynamic_pointer_cast(theObject); bool isShading = false; - if (aPrs) { - anAIS = aPrs->getAISObject(boost::shared_ptr()); + if (aPrs.get() != NULL) { + anAIS = aPrs->getAISObject(anAIS); } else { - ResultPtr aResult = boost::dynamic_pointer_cast(theObject); - if (aResult) { - boost::shared_ptr aShapePtr = ModelAPI_Tools::shape(aResult); - if (aShapePtr) { - anAIS = boost::shared_ptr(new GeomAPI_AISObject()); - anAIS->createShape(aShapePtr); + ResultPtr aResult = std::dynamic_pointer_cast(theObject); + if (aResult.get() != NULL) { +#ifdef DEBUG_COMPOSILID_DISPLAY + ResultCompSolidPtr aCompsolidResult = std::dynamic_pointer_cast(theObject); + if (aCompsolidResult.get()) { + for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) { + ResultPtr aSubResult = aCompsolidResult->subResult(i); + if (aSubResult.get()) + display(aSubResult, false); + } + if (theUpdateViewer) + updateViewer(); + } + else { +#endif + 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))); + //anAIS->createShape(aShapePtr); isShading = true; } +#ifdef DEBUG_COMPOSILID_DISPLAY + } // close else +#endif } } if (anAIS) - display(theObject, anAIS, isShading, isUpdateViewer); + display(theObject, anAIS, isShading, theUpdateViewer); } } -void XGUI_Displayer::display(ObjectPtr theObject, boost::shared_ptr theAIS, - bool isShading, bool isUpdateViewer) +bool canBeShaded(Handle(AIS_InteractiveObject) theAIS) +{ + Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(theAIS); + if (!aShapePrs.IsNull()) { + TopoDS_Shape aShape = aShapePrs->Shape(); + if (aShape.IsNull()) + return false; + TopAbs_ShapeEnum aType = aShape.ShapeType(); + if ((aType == TopAbs_VERTEX) || (aType == TopAbs_EDGE) || (aType == TopAbs_WIRE)) + 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 false; +} + +void XGUI_Displayer::display(ObjectPtr theObject, AISObjectPtr theAIS, + bool isShading, bool theUpdateViewer) { Handle(AIS_InteractiveContext) aContext = AISContext(); if (aContext.IsNull()) @@ -76,13 +195,24 @@ void XGUI_Displayer::display(ObjectPtr theObject, boost::shared_ptrimpl(); if (!anAISIO.IsNull()) { - myResult2AISObjectMap[theObject] = theAIS; - aContext->Display(anAISIO, false); - aContext->SetDisplayMode(anAISIO, isShading? Shading : Wireframe, isUpdateViewer); - } + appendResultObject(theObject, theAIS); + + bool isCustomized = customizeObject(theObject); + + int aDispMode = isShading? Shading : Wireframe; + if (isShading) + anAISIO->Attributes()->SetFaceBoundaryDraw( Standard_True ); + anAISIO->SetDisplayMode(aDispMode); + aContext->Display(anAISIO, aDispMode, 0, false, true, AIS_DS_Displayed); + + emit objectDisplayed(theObject, theAIS); + activate(anAISIO, myActiveSelectionModes, theUpdateViewer); + } + if (theUpdateViewer) + updateViewer(); } -void XGUI_Displayer::erase(ObjectPtr theObject, const bool isUpdateViewer) +void XGUI_Displayer::erase(ObjectPtr theObject, const bool theUpdateViewer) { if (!isVisible(theObject)) return; @@ -90,348 +220,528 @@ void XGUI_Displayer::erase(ObjectPtr theObject, const bool isUpdateViewer) Handle(AIS_InteractiveContext) aContext = AISContext(); if (aContext.IsNull()) return; - boost::shared_ptr anObject = myResult2AISObjectMap[theObject]; + AISObjectPtr anObject = myResult2AISObjectMap[theObject]; if (anObject) { Handle(AIS_InteractiveObject) anAIS = anObject->impl(); if (!anAIS.IsNull()) { - aContext->Remove(anAIS, isUpdateViewer); + emit beforeObjectErase(theObject, anObject); + aContext->Remove(anAIS, theUpdateViewer); } } - myResult2AISObjectMap.erase(theObject); + myResult2AISObjectMap.remove(theObject); + +#ifdef DEBUG_DISPLAY + std::ostringstream aPtrStr; + aPtrStr << theObject.get(); + qDebug(QString("erase object: %1").arg(aPtrStr.str().c_str()).toStdString().c_str()); + qDebug(getResult2AISObjectMapInfo().c_str()); +#endif } -void XGUI_Displayer::redisplay(ObjectPtr theObject, bool isUpdateViewer) +void XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer) { if (!isVisible(theObject)) return; - Handle(AIS_InteractiveObject) aAISIO; - boost::shared_ptr aAISObj = getAISObject(theObject); - GeomPresentablePtr aPrs = boost::dynamic_pointer_cast(theObject); + AISObjectPtr aAISObj = getAISObject(theObject); + Handle(AIS_InteractiveObject) aAISIO = aAISObj->impl(); + + GeomPresentablePtr aPrs = std::dynamic_pointer_cast(theObject); if (aPrs) { - boost::shared_ptr aAIS_Obj = aPrs->getAISObject(aAISObj); - if (aAISObj && !aAIS_Obj) { - erase(theObject, isUpdateViewer); + AISObjectPtr aAIS_Obj = aPrs->getAISObject(aAISObj); + if (!aAIS_Obj) { + erase(theObject, theUpdateViewer); return; } - aAISIO = aAIS_Obj->impl(); - } else { - ResultPtr aResult = boost::dynamic_pointer_cast(theObject); - if (aResult) { - boost::shared_ptr aShapePtr = ModelAPI_Tools::shape(aResult); - if (aShapePtr) { - Handle(AIS_Shape) aAISShape = Handle(AIS_Shape)::DownCast( - aAISObj->impl()); - if (!aAISShape.IsNull()) { - aAISShape->Set(aShapePtr->impl()); - aAISIO = aAISShape; - } - } + if (aAIS_Obj != aAISObj) { + appendResultObject(theObject, aAIS_Obj); } + aAISIO = aAIS_Obj->impl(); } + if (!aAISIO.IsNull()) { Handle(AIS_InteractiveContext) aContext = AISContext(); if (aContext.IsNull()) return; - aContext->Redisplay(aAISIO, isUpdateViewer); - //if (aContext->HasOpenedContext()) { - // aContext->Load(aAISIO, -1, true/*allow decomposition*/); - //} - } -} - -void XGUI_Displayer::activateInLocalContext(ObjectPtr theResult, const std::list& theModes, - const bool isUpdateViewer) -{ - Handle(AIS_InteractiveContext) aContext = AISContext(); - if (aContext.IsNull()) - return; - // Open local context if there is no one - if (!aContext->HasOpenedContext()) { - aContext->ClearCurrents(false); - //aContext->OpenLocalContext(false/*use displayed objects*/, true/*allow shape decomposition*/); - aContext->OpenLocalContext(); - aContext->NotUseDisplayedObjects(); - } - // display or redisplay presentation - Handle(AIS_InteractiveObject) anAIS; - if (isVisible(theResult)) { - boost::shared_ptr anObj = myResult2AISObjectMap[theResult]; - if (anObj) - anAIS = anObj->impl(); - } - - // Activate selection of objects from prs - if (!anAIS.IsNull()) { - aContext->ClearSelected(false); // ToCheck - //aContext->upClearSelected(false); // ToCheck - aContext->Load(anAIS, -1, true/*allow decomposition*/); - aContext->Deactivate(anAIS); - - std::list::const_iterator anIt = theModes.begin(), aLast = theModes.end(); - for (; anIt != aLast; anIt++) { - aContext->Activate(anAIS, (*anIt)); + // 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 + // in the browser is lost + + // this check is not necessary anymore because the selection store/restore is realized + // before and after the values modification. + // Moreother, this check avoids customize and redisplay presentation if the presentable + // parameter is changed. + bool isEqualShapes = false; + ResultPtr aResult = std::dynamic_pointer_cast(theObject); + if (aResult.get() != NULL) { + Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(aAISIO); + if (!aShapePrs.IsNull()) { + std::shared_ptr aShapePtr = ModelAPI_Tools::shape(aResult); + if (aShapePtr.get()) { + const TopoDS_Shape& aOldShape = aShapePrs->Shape(); + if (!aOldShape.IsNull()) + isEqualShapes = aOldShape.IsEqual(aShapePtr->impl()); + } + } + } + // Customization of presentation + 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()); + #endif + if (!isEqualShapes || isCustomized) { + aContext->Redisplay(aAISIO, false); + #ifdef DEBUG_FEATURE_REDISPLAY + qDebug(" Redisplay happens"); + #endif + if (theUpdateViewer) + updateViewer(); } } - - if (isUpdateViewer) - updateViewer(); } -void XGUI_Displayer::deactivate(ObjectPtr theObject) +void XGUI_Displayer::deactivate(ObjectPtr theObject, const bool theUpdateViewer) { +#ifdef DEBUG_DEACTIVATE + QString anInfoStr = ModuleBase_Tools::objectInfo(theObject); + qDebug(QString("deactivate: myActiveSelectionModes[%1]: %2, objects = "). + arg(myActiveSelectionModes.size()).arg(qIntListInfo(myActiveSelectionModes)). + arg(anInfoStr). + toStdString().c_str()); +#endif if (isVisible(theObject)) { Handle(AIS_InteractiveContext) aContext = AISContext(); if (aContext.IsNull()) return; - boost::shared_ptr anObj = myResult2AISObjectMap[theObject]; + AISObjectPtr anObj = myResult2AISObjectMap[theObject]; Handle(AIS_InteractiveObject) anAIS = anObj->impl(); - aContext->Deactivate(anAIS); + + deactivateAIS(anAIS); + // the selection from the previous activation modes should be cleared manually (#26172) + aContext->LocalContext()->ClearOutdatedSelection(anAIS, true); + if (theUpdateViewer) + updateViewer(); } } -void XGUI_Displayer::activate(ObjectPtr theObject) +void XGUI_Displayer::getModesOfActivation(ObjectPtr theObject, QIntList& theModes) { - if (isVisible(theObject)) { - Handle(AIS_InteractiveContext) aContext = AISContext(); - if (aContext.IsNull()) - return; + if (!isVisible(theObject)) + return; - boost::shared_ptr anObj = myResult2AISObjectMap[theObject]; - Handle(AIS_InteractiveObject) anAIS = anObj->impl(); - aContext->Activate(anAIS); + Handle(AIS_InteractiveContext) aContext = AISContext(); + if (aContext.IsNull()) + return; + + AISObjectPtr aAISObj = getAISObject(theObject); + + if (aAISObj.get() != NULL) { + Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl(); + TColStd_ListOfInteger aTColModes; + aContext->ActivatedModes(anAISIO, aTColModes); + TColStd_ListIteratorOfListOfInteger itr( aTColModes ); + for (; itr.More(); itr.Next() ) { + theModes.append(itr.Value()); + } } } -void XGUI_Displayer::stopSelection(const QList& theResults, const bool isStop, - const bool isUpdateViewer) +void XGUI_Displayer::activateObjects(const QIntList& theModes, const QObjectPtrList& theObjList, + const bool theUpdateViewer) { + // Convert shape types to selection types + QIntList aModes; + foreach(int aType, theModes) { + if (aType > TopAbs_SHAPE) + aModes.append(aType); + else + aModes.append(AIS_Shape::SelectionMode((TopAbs_ShapeEnum)aType)); + } + +#ifdef DEBUG_ACTIVATE_OBJECTS + QStringList anInfo; + QObjectPtrList::const_iterator anIt = theObjList.begin(), aLast = theObjList.end(); + for (; anIt != aLast; ++anIt) { + anInfo.append(ModuleBase_Tools::objectInfo((*anIt))); + } + 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)). + arg(anInfoStr). + toStdString().c_str()); +#endif + // In order to avoid doblications of selection modes + QIntList aNewModes; + foreach (int aMode, aModes) { + if (!aNewModes.contains(aMode)) + aNewModes.append(aMode); + } + myActiveSelectionModes = aNewModes; Handle(AIS_InteractiveContext) aContext = AISContext(); if (aContext.IsNull()) return; + // Open local context if there is no one + if (!aContext->HasOpenedContext()) + return; - Handle(AIS_Shape) anAIS; - QList::const_iterator anIt = theResults.begin(), aLast = theResults.end(); - ObjectPtr aFeature; - for (; anIt != aLast; anIt++) { - aFeature = *anIt; - if (isVisible(aFeature)) - anAIS = Handle(AIS_Shape)::DownCast( - myResult2AISObjectMap[aFeature]->impl()); - if (anAIS.IsNull()) - continue; - - if (isStop) { - QColor aColor(Qt::white); - anAIS->SetColor( - Quantity_Color(aColor.red() / 255., aColor.green() / 255., aColor.blue() / 255., - Quantity_TOC_RGB)); - anAIS->Redisplay(); - } else { - QColor aColor(Qt::red); - anAIS->SetColor( - Quantity_Color(aColor.red() / 255., aColor.green() / 255., aColor.blue() / 255., - Quantity_TOC_RGB)); - anAIS->Redisplay(); + //aContext->UseDisplayedObjects(); + //myUseExternalObjects = true; + + Handle(AIS_InteractiveObject) anAISIO; + AIS_ListOfInteractive aPrsList; + if (theObjList.isEmpty()) + return; + else { + foreach(ObjectPtr aObj, theObjList) { + if (myResult2AISObjectMap.contains(aObj)) + aPrsList.Append(myResult2AISObjectMap[aObj]->impl()); } } - if (isUpdateViewer) + + AIS_ListIteratorOfListOfInteractive aLIt(aPrsList); + for(aLIt.Initialize(aPrsList); aLIt.More(); aLIt.Next()){ + anAISIO = aLIt.Value(); + activate(anAISIO, myActiveSelectionModes, false); + } + if (theUpdateViewer) updateViewer(); } -void XGUI_Displayer::setSelected(const QList& theResults, const bool isUpdateViewer) +bool XGUI_Displayer::isActive(ObjectPtr theObject) const { Handle(AIS_InteractiveContext) aContext = AISContext(); - // we need to unhighligth objects manually in the current local context - // in couple with the selection clear (TODO) - Handle(AIS_LocalContext) aLocalContext = aContext->LocalContext(); - if (!aLocalContext.IsNull()) - aLocalContext->UnhilightLastDetected(myWorkshop->viewer()->activeView()); - - aContext->ClearSelected(); - foreach(ObjectPtr aResult, theResults) - { - if (myResult2AISObjectMap.find(aResult) == myResult2AISObjectMap.end()) - continue; - - boost::shared_ptr anObj = myResult2AISObjectMap[aResult]; - if (anObj) { - Handle(AIS_InteractiveObject) anAIS = anObj->impl(); - if (!anAIS.IsNull()) - aContext->AddOrRemoveSelected(anAIS, false); + if (aContext.IsNull()) + return false; + if (!isVisible(theObject)) + return false; + + AISObjectPtr anObj = myResult2AISObjectMap[theObject]; + Handle(AIS_InteractiveObject) anAIS = anObj->impl(); + + TColStd_ListOfInteger aModes; + aContext->ActivatedModes(anAIS, aModes); + return aModes.Extent() > 0; +} +void XGUI_Displayer::setSelected(const QList& theValues, bool theUpdateViewer) +{ + Handle(AIS_InteractiveContext) aContext = AISContext(); + if (aContext.IsNull()) + return; + if (aContext->HasOpenedContext()) { + aContext->UnhilightSelected(); + aContext->ClearSelected(); + 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(); + aContext->ClearCurrents(); + foreach (ModuleBase_ViewerPrs aPrs, theValues) { + 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 (isUpdateViewer) + if (theUpdateViewer) updateViewer(); } -void XGUI_Displayer::eraseAll(const bool isUpdateViewer) +void XGUI_Displayer::clearSelected() { - Handle(AIS_InteractiveContext) ic = AISContext(); - if (ic.IsNull()) - return; + Handle(AIS_InteractiveContext) aContext = AISContext(); + if (aContext) { + aContext->UnhilightCurrents(false); + aContext->ClearSelected(); + } +} - ResultToAISMap::iterator aIt; - for (aIt = myResult2AISObjectMap.begin(); aIt != myResult2AISObjectMap.end(); aIt++) { - // erase an object - boost::shared_ptr aAISObj = (*aIt).second; - Handle(AIS_InteractiveObject) anIO = aAISObj->impl(); - if (!anIO.IsNull()) - ic->Remove(anIO, false); - } - myResult2AISObjectMap.clear(); - if (isUpdateViewer) - updateViewer(); - } - -void XGUI_Displayer::eraseDeletedResults(const bool isUpdateViewer) +void XGUI_Displayer::eraseAll(const bool theUpdateViewer) { Handle(AIS_InteractiveContext) aContext = AISContext(); - if (aContext.IsNull()) - return; - - ResultToAISMap::const_iterator aFIt = myResult2AISObjectMap.begin(), aFLast = - myResult2AISObjectMap.end(); - std::list aRemoved; - for (; aFIt != aFLast; aFIt++) { - ObjectPtr aFeature = (*aFIt).first; - if (!aFeature || !aFeature->data() || !aFeature->data()->isValid()) { - boost::shared_ptr anObj = (*aFIt).second; - if (!anObj) - continue; - Handle(AIS_InteractiveObject) anAIS = anObj->impl(); - if (!anAIS.IsNull()) { - aContext->Remove(anAIS, false); - aRemoved.push_back(aFeature); + if (!aContext.IsNull()) { + foreach (ObjectPtr aObj, myResult2AISObjectMap.keys()) { + AISObjectPtr aAISObj = myResult2AISObjectMap[aObj]; + // erase an object + Handle(AIS_InteractiveObject) anIO = aAISObj->impl(); + if (!anIO.IsNull()) { + emit beforeObjectErase(aObj, aAISObj); + aContext->Remove(anIO, false); } } + if (theUpdateViewer) + updateViewer(); } - std::list::const_iterator anIt = aRemoved.begin(), aLast = aRemoved.end(); - for (; anIt != aLast; anIt++) { - myResult2AISObjectMap.erase(myResult2AISObjectMap.find(*anIt)); - } + myResult2AISObjectMap.clear(); +#ifdef DEBUG_DISPLAY + qDebug("eraseAll"); + qDebug(getResult2AISObjectMapInfo().c_str()); +#endif +} - if (isUpdateViewer) - updateViewer(); +void XGUI_Displayer::deactivateTrihedron() const +{ + Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext(); + + AIS_ListOfInteractive aList; + aContext->DisplayedObjects(aList, true); + AIS_ListIteratorOfListOfInteractive aIt; + for (aIt.Initialize(aList); aIt.More(); aIt.Next()) { + Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast(aIt.Value()); + if (!aTrihedron.IsNull()) { + aContext->Deactivate(aTrihedron); + } + } } void XGUI_Displayer::openLocalContext() { - Handle(AIS_InteractiveContext) aContext = AISContext(); + Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext(); if (aContext.IsNull()) return; // Open local context if there is no one if (!aContext->HasOpenedContext()) { - aContext->ClearCurrents(false); - //aContext->OpenLocalContext(false/*use displayed objects*/, true/*allow shape decomposition*/); + // Preserve selected objects + //AIS_ListOfInteractive aAisList; + //for (aContext->InitCurrent(); aContext->MoreCurrent(); aContext->NextCurrent()) + // aAisList.Append(aContext->Current()); + + // get the filters from the global context and append them to the local context + // a list of filters in the global context is not cleared and should be cleared here + SelectMgr_ListOfFilter aFilters; + aFilters.Assign(aContext->Filters()); + // it is important to remove the filters in the global context, because there is a code + // in the closeLocalContex, which restore the global context filters + aContext->RemoveFilters(); + + //aContext->ClearCurrents(); aContext->OpenLocalContext(); - aContext->NotUseDisplayedObjects(); + deactivateTrihedron(); + //aContext->NotUseDisplayedObjects(); + + //myUseExternalObjects = false; + + SelectMgr_ListIteratorOfListOfFilter aIt(aFilters); + for (;aIt.More(); aIt.Next()) { + aContext->AddFilter(aIt.Value()); + } + // Restore selection + //AIS_ListIteratorOfListOfInteractive aIt2(aAisList); + //for(; aIt2.More(); aIt2.Next()) { + // aContext->SetSelected(aIt2.Value(), false); + //} } } -void XGUI_Displayer::closeLocalContexts(const bool isUpdateViewer) +void XGUI_Displayer::closeLocalContexts(const bool theUpdateViewer) { - AISContext()->ClearSelected(false); - closeAllContexts(true); + Handle(AIS_InteractiveContext) aContext = AISContext(); + if ( (!aContext.IsNull()) && (aContext->HasOpenedContext()) ) { + // Preserve selected objects + //AIS_ListOfInteractive aAisList; + //for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected()) + // aAisList.Append(aContext->SelectedInteractive()); + + // get the filters from the local context and append them to the global context + // a list of filters in the local context is cleared + SelectMgr_ListOfFilter aFilters; + aFilters.Assign(aContext->Filters()); + + //aContext->ClearSelected(); + aContext->CloseAllContexts(false); + + // Redisplay all object if they were displayed in localContext + Handle(AIS_InteractiveObject) aAISIO; + foreach (AISObjectPtr aAIS, myResult2AISObjectMap) { + aAISIO = aAIS->impl(); + if (aContext->DisplayStatus(aAISIO) != AIS_DS_Displayed) { + 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); + for (;aIt.More(); aIt.Next()) { + Handle(SelectMgr_Filter) aFilter = aIt.Value(); + aContext->AddFilter(aFilter); + } + + if (theUpdateViewer) + updateViewer(); + //myUseExternalObjects = false; + + // Restore selection + //AIS_ListIteratorOfListOfInteractive aIt2(aAisList); + //for(; aIt2.More(); aIt2.Next()) { + // if (aContext->IsDisplayed(aIt2.Value())) + // aContext->SetCurrentObject(aIt2.Value(), false); + //} + } } -boost::shared_ptr XGUI_Displayer::getAISObject(ObjectPtr theObject) const +AISObjectPtr XGUI_Displayer::getAISObject(ObjectPtr theObject) const { - boost::shared_ptr anIO; - if (myResult2AISObjectMap.find(theObject) != myResult2AISObjectMap.end()) - anIO = (myResult2AISObjectMap.find(theObject))->second; + AISObjectPtr anIO; + if (myResult2AISObjectMap.contains(theObject)) + anIO = myResult2AISObjectMap[theObject]; return anIO; } -ObjectPtr XGUI_Displayer::getObject(Handle(AIS_InteractiveObject) theIO) const +ObjectPtr XGUI_Displayer::getObject(const AISObjectPtr& theIO) const { - ObjectPtr aFeature; - ResultToAISMap::const_iterator aFIt = myResult2AISObjectMap.begin(), aFLast = - myResult2AISObjectMap.end(); - for (; aFIt != aFLast && !aFeature; aFIt++) { - boost::shared_ptr anObj = (*aFIt).second; - if (!anObj) - continue; - Handle(AIS_InteractiveObject) anAIS = anObj->impl(); - if (anAIS != theIO) - continue; - aFeature = (*aFIt).first; + Handle(AIS_InteractiveObject) aRefAIS = theIO->impl(); + return getObject(aRefAIS); +} + +ObjectPtr XGUI_Displayer::getObject(const Handle(AIS_InteractiveObject)& theIO) const +{ + ObjectPtr anObject; + foreach (ObjectPtr anObj, myResult2AISObjectMap.keys()) { + AISObjectPtr aAIS = myResult2AISObjectMap[anObj]; + Handle(AIS_InteractiveObject) anAIS = aAIS->impl(); + if (anAIS == theIO) + anObject = anObj; + if (anObject.get()) + break; } - return aFeature; + if (!anObject.get()) { + std::shared_ptr anAISObj = AISObjectPtr(new GeomAPI_AISObject()); + if (!theIO.IsNull()) { + anAISObj->setImpl(new Handle(AIS_InteractiveObject)(theIO)); + } + anObject = myWorkshop->module()->findPresentedObject(anAISObj); + } + return anObject; } -void XGUI_Displayer::closeAllContexts(const bool isUpdateViewer) +bool XGUI_Displayer::enableUpdateViewer(const bool isEnabled) { - Handle(AIS_InteractiveContext) ic = AISContext(); - if (!ic.IsNull()) { - ic->CloseAllContexts(false); - if (isUpdateViewer) - updateViewer(); + bool aWasEnabled = myEnableUpdateViewer; + + myEnableUpdateViewer = isEnabled; + + return aWasEnabled; +} + +void XGUI_Displayer::updateViewer() const +{ + Handle(AIS_InteractiveContext) aContext = AISContext(); + if (!aContext.IsNull() && myEnableUpdateViewer) { + myWorkshop->viewer()->Zfitall(); + aContext->UpdateCurrentViewer(); } } -void XGUI_Displayer::updateViewer() +void XGUI_Displayer::activateAIS(const Handle(AIS_InteractiveObject)& theIO, + const int theMode, const bool theUpdateViewer) const { - Handle(AIS_InteractiveContext) ic = AISContext(); - if (!ic.IsNull()) - ic->UpdateCurrentViewer(); + Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext(); + aContext->Activate(theIO, theMode, theUpdateViewer); + +#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()); +#endif } -Handle(AIS_InteractiveContext) XGUI_Displayer::AISContext() const +void XGUI_Displayer::deactivateAIS(const Handle(AIS_InteractiveObject)& theIO, const int theMode) const { - return myWorkshop->viewer()->AISContext(); + Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext(); + if (theMode == -1) + aContext->Deactivate(theIO); + else + aContext->Deactivate(theIO, theMode); + +#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()); +#endif } -void XGUI_Displayer::display(boost::shared_ptr theAIS, bool isUpdate) +Handle(AIS_InteractiveContext) XGUI_Displayer::AISContext() const { - Handle(AIS_InteractiveContext) aContext = AISContext(); - Handle(AIS_InteractiveObject) anAISIO = theAIS->impl(); - if (!anAISIO.IsNull()) - aContext->Display(anAISIO, isUpdate); + Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext(); + if ((!aContext.IsNull()) && (!aContext->HasOpenedContext())) { + aContext->OpenLocalContext(); + deactivateTrihedron(); + aContext->DefaultDrawer()->VIsoAspect()->SetNumber(0); + aContext->DefaultDrawer()->UIsoAspect()->SetNumber(0); + } + return aContext; } -void XGUI_Displayer::erase(boost::shared_ptr theAIS, const bool isUpdate) +Handle(SelectMgr_AndFilter) XGUI_Displayer::GetFilter() { Handle(AIS_InteractiveContext) aContext = AISContext(); - Handle(AIS_InteractiveObject) anAISIO = theAIS->impl(); - if (!anAISIO.IsNull()) { - aContext->Remove(anAISIO, isUpdate); + if (myAndFilter.IsNull() && !aContext.IsNull()) { + myAndFilter = new SelectMgr_AndFilter(); + aContext->AddFilter(myAndFilter); } + return myAndFilter; } -void XGUI_Displayer::activateObjectsOutOfContext(const std::list& theModes, - Handle(SelectMgr_Filter) theFilter) +void XGUI_Displayer::displayAIS(AISObjectPtr theAIS, bool theUpdateViewer) { Handle(AIS_InteractiveContext) aContext = AISContext(); - // Open local context if there is no one - if (!aContext->HasOpenedContext()) + if (aContext.IsNull()) return; - - aContext->UseDisplayedObjects(); - std::list::const_iterator anIt = theModes.begin(), aLast = theModes.end(); - for (; anIt != aLast; anIt++) { - aContext->ActivateStandardMode((TopAbs_ShapeEnum)(*anIt)); + Handle(AIS_InteractiveObject) anAISIO = theAIS->impl(); + if (!anAISIO.IsNull()) { + aContext->Display(anAISIO, theUpdateViewer); + if (aContext->HasOpenedContext()) { + if (myActiveSelectionModes.size() == 0) + activateAIS(anAISIO, 0, theUpdateViewer); + else { + foreach(int aMode, myActiveSelectionModes) { + activateAIS(anAISIO, aMode, theUpdateViewer); + } + } + } } - - if (!theFilter.IsNull()) - aContext->AddFilter(theFilter); } - -void XGUI_Displayer::deactivateObjectsOutOfContext() +void XGUI_Displayer::eraseAIS(AISObjectPtr theAIS, const bool theUpdateViewer) { Handle(AIS_InteractiveContext) aContext = AISContext(); - // Open local context if there is no one - if (!aContext->HasOpenedContext()) + if (aContext.IsNull()) return; - - aContext->RemoveFilters(); - aContext->NotUseDisplayedObjects(); + Handle(AIS_InteractiveObject) anAISIO = theAIS->impl(); + if (!anAISIO.IsNull()) { + aContext->Remove(anAISIO, theUpdateViewer); + } } -void XGUI_Displayer::setDisplayMode(ObjectPtr theObject, DisplayMode theMode, bool toUpdate) +void XGUI_Displayer::setDisplayMode(ObjectPtr theObject, DisplayMode theMode, bool theUpdateViewer) { if (theMode == NoMode) return; @@ -440,22 +750,24 @@ void XGUI_Displayer::setDisplayMode(ObjectPtr theObject, DisplayMode theMode, bo if (aContext.IsNull()) return; - boost::shared_ptr aAISObj = getAISObject(theObject); + AISObjectPtr aAISObj = getAISObject(theObject); if (!aAISObj) return; Handle(AIS_InteractiveObject) aAISIO = aAISObj->impl(); - aContext->SetDisplayMode(aAISIO, theMode, toUpdate); + aContext->SetDisplayMode(aAISIO, theMode, false); + // Redisplay in order to update new mode because it could be not computed before + if (theUpdateViewer) + updateViewer(); } - XGUI_Displayer::DisplayMode XGUI_Displayer::displayMode(ObjectPtr theObject) const { Handle(AIS_InteractiveContext) aContext = AISContext(); if (aContext.IsNull()) return NoMode; - boost::shared_ptr aAISObj = getAISObject(theObject); + AISObjectPtr aAISObj = getAISObject(theObject); if (!aAISObj) return NoMode; @@ -463,3 +775,220 @@ XGUI_Displayer::DisplayMode XGUI_Displayer::displayMode(ObjectPtr theObject) con return (XGUI_Displayer::DisplayMode) aAISIO->DisplayMode(); } +void XGUI_Displayer::addSelectionFilter(const Handle(SelectMgr_Filter)& theFilter) +{ + Handle(AIS_InteractiveContext) aContext = AISContext(); + if (aContext.IsNull() || hasSelectionFilter(theFilter)) + return; + + Handle(SelectMgr_CompositionFilter) aCompFilter = GetFilter(); + aCompFilter->Add(theFilter); +#ifdef DEBUG_SELECTION_FILTERS + int aCount = GetFilter()->StoredFilters().Extent(); + qDebug(QString("addSelectionFilter: filters.count() = %1").arg(aCount).toStdString().c_str()); +#endif +} + +void XGUI_Displayer::removeSelectionFilter(const Handle(SelectMgr_Filter)& theFilter) +{ + Handle(AIS_InteractiveContext) aContext = AISContext(); + if (aContext.IsNull()) + return; + Handle(SelectMgr_AndFilter) aCompositeFilter = GetFilter(); + if (aCompositeFilter->IsIn(theFilter)) + aCompositeFilter->Remove(theFilter); +#ifdef DEBUG_SELECTION_FILTERS + int aCount = GetFilter()->StoredFilters().Extent(); + qDebug(QString("removeSelectionFilter: filters.count() = %1").arg(aCount).toStdString().c_str()); +#endif +} + +bool XGUI_Displayer::hasSelectionFilter(const Handle(SelectMgr_Filter)& theFilter) +{ + bool aFilterFound = false; + + Handle(AIS_InteractiveContext) aContext = AISContext(); + if (aContext.IsNull()) + return aFilterFound; + const SelectMgr_ListOfFilter& aFilters = aContext->Filters(); + SelectMgr_ListIteratorOfListOfFilter aIt(aFilters); + for (; aIt.More() && !aFilterFound; aIt.Next()) { + if (theFilter.Access() == aIt.Value().Access()) + aFilterFound = true; + } + Handle(SelectMgr_CompositionFilter) aCompFilter = GetFilter(); + const SelectMgr_ListOfFilter& aStoredFilters = aCompFilter->StoredFilters(); + for (aIt.Initialize(aStoredFilters); aIt.More() && !aFilterFound; aIt.Next()) { + if (theFilter.Access() == aIt.Value().Access()) + aFilterFound = true; + } + return aFilterFound; +} + +void XGUI_Displayer::removeFilters() +{ + Handle(AIS_InteractiveContext) aContext = AISContext(); + if (aContext.IsNull()) + return; + GetFilter()->Clear(); +} + +void XGUI_Displayer::showOnly(const QObjectPtrList& theList) +{ + QObjectPtrList aDispList = myResult2AISObjectMap.keys(); + foreach(ObjectPtr aObj, aDispList) { + if (!theList.contains(aObj)) + erase(aObj, false); + } + foreach(ObjectPtr aObj, theList) { + if (!isVisible(aObj)) + display(aObj, false); + } + updateViewer(); +} + +bool XGUI_Displayer::canBeShaded(ObjectPtr theObject) const +{ + if (!isVisible(theObject)) + return false; + + AISObjectPtr aAISObj = getAISObject(theObject); + if (aAISObj.get() == NULL) + return false; + + Handle(AIS_InteractiveObject) anAIS = aAISObj->impl(); + return ::canBeShaded(anAIS); +} + +void XGUI_Displayer::activate(const Handle(AIS_InteractiveObject)& theIO, + const QIntList& theModes, + const bool theUpdateViewer) const +{ + Handle(AIS_InteractiveContext) aContext = AISContext(); + if (aContext.IsNull() || theIO.IsNull()) + return; + + // 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 + // is modified in OCC(version: 6.8.0) and the selection of the object later is lost. + // By this reason, the number of the IO deactivate is decreased and the object is deactivated + // only if there is a difference in the current modes and the parameters modes. + // 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. + TColStd_ListOfInteger aTColModes; + aContext->ActivatedModes(theIO, aTColModes); + TColStd_ListIteratorOfListOfInteger itr( aTColModes ); + QIntList aModesActivatedForIO; + bool isDeactivated = false; + for (; itr.More(); itr.Next() ) { + Standard_Integer aMode = itr.Value(); + if (!theModes.contains(aMode)) { + deactivateAIS(theIO, aMode); + isDeactivated = true; + } + else { + aModesActivatedForIO.append(aMode); + } + } + if (isDeactivated) { + // the selection from the previous activation modes should be cleared manually (#26172) + aContext->LocalContext()->ClearOutdatedSelection(theIO, true); + if (theUpdateViewer) + updateViewer(); + } + + // loading the interactive object allowing the decomposition + if (aTColModes.IsEmpty()) { + aContext->Load(theIO, -1, true); + } + + // trihedron AIS check should be after the AIS loading. + // If it is not loaded, it is steel selectable in the viewer. + Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast(theIO); + if (aTrihedron.IsNull()) { + //aContext->Load(anAISIO, -1, true); + // In order to clear active modes list + if (theModes.size() == 0) { + //aContext->Load(anAISIO, 0, true); + activateAIS(theIO, 0, theUpdateViewer); + } else { + foreach(int aMode, theModes) { + //aContext->Load(anAISIO, aMode, true); + if (!aModesActivatedForIO.contains(aMode)) { + activateAIS(theIO, aMode, theUpdateViewer); + } + } + } + } +} + +bool XGUI_Displayer::customizeObject(ObjectPtr theObject) +{ + AISObjectPtr anAISObj = getAISObject(theObject); + // correct the result's color it it has the attribute + ResultPtr aResult = std::dynamic_pointer_cast(theObject); + + // Customization of presentation + GeomCustomPrsPtr aCustomPrs; + FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); + if (aFeature.get() != NULL) { + GeomCustomPrsPtr aCustPrs = std::dynamic_pointer_cast(aFeature); + if (aCustPrs.get() != NULL) + aCustomPrs = aCustPrs; + } + if (aCustomPrs.get() == NULL) { + GeomPresentablePtr aPrs = std::dynamic_pointer_cast(theObject); + // we ignore presentable not customized objects + if (aPrs.get() == NULL) + aCustomPrs = myCustomPrs; + } + bool isCustomized = aCustomPrs.get() && + aCustomPrs->customisePresentation(aResult, anAISObj, myCustomPrs); + myWorkshop->module()->customizeObject(theObject); + return isCustomized; +} + + +QColor XGUI_Displayer::setObjectColor(ObjectPtr theObject, const QColor& theColor, bool theUpdateViewer) +{ + if (!isVisible(theObject)) + return Qt::black; + + AISObjectPtr anAISObj = getAISObject(theObject); + int aR, aG, aB; + anAISObj->getColor(aR, aG, aB); + anAISObj->setColor(theColor.red(), theColor.green(), theColor.blue()); + if (theUpdateViewer) + updateViewer(); + return QColor(aR, aG, aB); +} + +void XGUI_Displayer::appendResultObject(ObjectPtr theObject, AISObjectPtr theAIS) +{ + myResult2AISObjectMap[theObject] = theAIS; + +#ifdef DEBUG_DISPLAY + std::ostringstream aPtrStr; + aPtrStr << theObject.get(); + qDebug(QString("display object: %1").arg(aPtrStr.str().c_str()).toStdString().c_str()); + qDebug(getResult2AISObjectMapInfo().c_str()); +#endif +} + +std::string XGUI_Displayer::getResult2AISObjectMapInfo() const +{ + QStringList aContent; + foreach (ObjectPtr aObj, myResult2AISObjectMap.keys()) { + AISObjectPtr aAISObj = myResult2AISObjectMap[aObj]; + std::ostringstream aPtrStr; + 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").arg(myResult2AISObjectMap.size()). + arg(aContent.join("\n")).toStdString().c_str(); +}