From: nds Date: Tue, 21 Jun 2016 13:32:01 +0000 (+0300) Subject: Selection priority in Sketch, clear selection when sketch goes from entity to neutral... X-Git-Tag: V_2.4.0~80 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=5b4e69308550c299e14f336d489dc0aefbc5d6f4;p=modules%2Fshaper.git Selection priority in Sketch, clear selection when sketch goes from entity to neutral point, #1349 selection with SHIFT correction, selection synchronization correction for no select in neutral point. --- diff --git a/src/ModuleBase/CMakeLists.txt b/src/ModuleBase/CMakeLists.txt index c4fc1a276..c4fe31943 100644 --- a/src/ModuleBase/CMakeLists.txt +++ b/src/ModuleBase/CMakeLists.txt @@ -8,6 +8,7 @@ SET(PROJECT_HEADERS ModuleBase_ActionInfo.h ModuleBase_Definitions.h ModuleBase_DoubleSpinBox.h + ModuleBase_Events.h ModuleBase_Filter.h ModuleBase_FilterFactory.h ModuleBase_FilterValidated.h diff --git a/src/ModuleBase/ModuleBase_Events.h b/src/ModuleBase/ModuleBase_Events.h new file mode 100755 index 000000000..f6f4c7ee6 --- /dev/null +++ b/src/ModuleBase/ModuleBase_Events.h @@ -0,0 +1,14 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: ModuleBase_Events.h +// Created: 21 June 2016 +// Author: Natalia Ermolaeva + +#ifndef ModuleBase_Events_H +#define ModuleBase_Events_H + +#include "ModuleBase.h" + +static const char * EVENT_UPDATE_BY_WIDGET_SELECTION = "SelectionUpdatedByWidget"; + +#endif diff --git a/src/ModuleBase/ModuleBase_OperationFeature.cpp b/src/ModuleBase/ModuleBase_OperationFeature.cpp index ea72d2307..6066fa00a 100755 --- a/src/ModuleBase/ModuleBase_OperationFeature.cpp +++ b/src/ModuleBase/ModuleBase_OperationFeature.cpp @@ -117,7 +117,8 @@ void ModuleBase_OperationFeature::startOperation() myVisualizedObjects.clear(); // store hidden result features - std::list aResults = aFeature->results(); + std::list aResults; + ModelAPI_Tools::allResults(aFeature, aResults); std::list::const_iterator aIt; for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { ObjectPtr anObject = *aIt; @@ -140,7 +141,8 @@ void ModuleBase_OperationFeature::stopOperation() return; // store hidden result features - std::list aResults = aFeature->results(); + std::list aResults; + ModelAPI_Tools::allResults(aFeature, aResults); std::list::const_iterator aIt; for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { ObjectPtr anObject = *aIt; @@ -194,11 +196,13 @@ bool ModuleBase_OperationFeature::hasObject(ObjectPtr theObj) const if (aFeature) { if (aFeature == theObj) return true; - std::list aResults = aFeature->results(); + std::list aResults; + ModelAPI_Tools::allResults(aFeature, aResults); std::list::const_iterator aIt; for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) { - if (theObj == (*aIt)) - return true; + ResultPtr aResult = *aIt; + if (theObj == aResult) + return true; } #ifdef DEBUG_DO_NOT_ACTIVATE_SUB_FEATURE if (aFeature->isMacro()) { @@ -453,7 +457,8 @@ void ModuleBase_OperationFeature::initSelection(ModuleBase_ISelection* theSelect if (aFeature) { QList aSelected = theSelection->getSelected(ModuleBase_ISelection::AllControls); - std::list aResults = aFeature->results(); + std::list aResults; + ModelAPI_Tools::allResults(aFeature, aResults); QObjectPtrList aResList; std::list::const_iterator aIt; for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) diff --git a/src/ModuleBase/ModuleBase_ResultPrs.cpp b/src/ModuleBase/ModuleBase_ResultPrs.cpp index 128770c2f..d9460ce72 100755 --- a/src/ModuleBase/ModuleBase_ResultPrs.cpp +++ b/src/ModuleBase/ModuleBase_ResultPrs.cpp @@ -31,6 +31,7 @@ #include #include #include +#include IMPLEMENT_STANDARD_HANDLE(ModuleBase_BRepOwner, StdSelect_BRepOwner); IMPLEMENT_STANDARD_RTTIEXT(ModuleBase_BRepOwner, StdSelect_BRepOwner); @@ -45,7 +46,7 @@ IMPLEMENT_STANDARD_RTTIEXT(ModuleBase_ResultPrs, ViewerData_AISShape); ModuleBase_ResultPrs::ModuleBase_ResultPrs(ResultPtr theResult) - : ViewerData_AISShape(TopoDS_Shape()), myResult(theResult) + : ViewerData_AISShape(TopoDS_Shape()), myResult(theResult), myAdditionalSelectionPriority(0) { std::shared_ptr aShapePtr = ModelAPI_Tools::shape(theResult); TopoDS_Shape aShape = aShapePtr->impl(); @@ -63,6 +64,11 @@ ModuleBase_ResultPrs::ModuleBase_ResultPrs(ResultPtr theResult) ModuleBase_Tools::setPointBallHighlighting(this); } +void ModuleBase_ResultPrs::setAdditionalSelectionPriority(const int thePriority) +{ + myAdditionalSelectionPriority = thePriority; +} + void ModuleBase_ResultPrs::Compute(const Handle(PrsMgr_PresentationManager3d)& thePresentationManager, const Handle(Prs3d_Presentation)& thePresentation, const Standard_Integer theMode) @@ -92,6 +98,16 @@ void ModuleBase_ResultPrs::ComputeSelection(const Handle(SelectMgr_Selection)& a // In order to avoid using custom selection modes return; + // TODO: OCCT issue should be created for the COMPOUND processing + // before it is fixed, the next workaround in necessary + if (aMode == AIS_Shape::SelectionMode(TopAbs_COMPOUND)) { + const TopoDS_Shape& aShape = Shape(); + TopExp_Explorer aCompExp(aShape, TopAbs_COMPOUND); + // do not activate in compound mode shapes which do not contain compounds + if (!aCompExp.More()) + return; + } + if (aMode == AIS_Shape::SelectionMode(TopAbs_COMPSOLID)) { // Limit selection area only by actual object (Shape) ResultCompSolidPtr aCompSolid = ModelAPI_Tools::compSolidOwner(myResult); @@ -117,6 +133,14 @@ void ModuleBase_ResultPrs::ComputeSelection(const Handle(SelectMgr_Selection)& a //AIS_Shape::ComputeSelection(aSelection, 0); } AIS_Shape::ComputeSelection(aSelection, aMode); + + if (myAdditionalSelectionPriority > 0) { + for (aSelection->Init(); aSelection->More(); aSelection->Next()) { + Handle(SelectBasics_EntityOwner) aBasicsOwner = aSelection->Sensitive()->BaseSensitive()->OwnerId(); + if (!aBasicsOwner.IsNull()) + aBasicsOwner->Set(aBasicsOwner->Priority() + myAdditionalSelectionPriority); + } + } } void ModuleBase_ResultPrs::appendWiresSelection(const Handle(SelectMgr_Selection)& theSelection, diff --git a/src/ModuleBase/ModuleBase_ResultPrs.h b/src/ModuleBase/ModuleBase_ResultPrs.h index 240d64eaf..e1143734c 100644 --- a/src/ModuleBase/ModuleBase_ResultPrs.h +++ b/src/ModuleBase/ModuleBase_ResultPrs.h @@ -15,6 +15,8 @@ #include #include +#include + DEFINE_STANDARD_HANDLE(ModuleBase_BRepOwner, StdSelect_BRepOwner) /** @@ -73,6 +75,15 @@ public: /// Returns result object Standard_EXPORT ResultPtr getResult() const { return myResult; } + /// Returns selection priorities that will be added to created selection owner + /// \return integer value + Standard_EXPORT int getAdditionalSelectionPriority() const { return myAdditionalSelectionPriority; } + + /// Appends a special priority for the mode of selection + /// \param theSelectionMode a mode of selection, used in ComputeSelection + /// \param thePriority a new priority value + Standard_EXPORT void setAdditionalSelectionPriority(const int thePriority); + DEFINE_STANDARD_RTTI(ModuleBase_ResultPrs) protected: /// Redefinition of virtual function @@ -95,6 +106,8 @@ private: /// Original shape of the result object TopoDS_Shape myOriginalShape; + /// selection priority that will be added to the standard selection priority of the selection entity + int myAdditionalSelectionPriority; }; diff --git a/src/ModuleBase/ModuleBase_Tools.cpp b/src/ModuleBase/ModuleBase_Tools.cpp index 986d22d18..9e77f0650 100755 --- a/src/ModuleBase/ModuleBase_Tools.cpp +++ b/src/ModuleBase/ModuleBase_Tools.cpp @@ -390,8 +390,9 @@ QString displayedInteractiveObjects(Handle(AIS_InteractiveContext)& theContext, if (!aShapePrs.IsNull()) { const TopoDS_Shape& aShape = aShapePrs->Shape(); - if (aShape.IsNull()) - Events_Error::throwException("An empty AIS presentation"); + if (aShape.IsNull()) { + //Events_Error::throwException("An empty AIS presentation"); + } else anInfo += QString(", shape type: %1").arg(getShapeTypeInfo(aShape.ShapeType())); } @@ -451,8 +452,9 @@ QString activeOwners(Handle(AIS_InteractiveContext)& theContext, const bool theS if (!BROwnr.IsNull() && BROwnr->HasShape()) { const TopoDS_Shape& aShape = BROwnr->Shape(); - if (aShape.IsNull()) - Events_Error::throwException("An empty AIS presentation"); + if (aShape.IsNull()) { + //Events_Error::throwException("An empty AIS presentation"); + } else anInfo += QString(", shape type: %1").arg(getShapeTypeInfo(aShape.ShapeType())); } @@ -851,6 +853,8 @@ GeomShapePtr getShape(const AttributePtr& theAttribute, ModuleBase_IWorkshop* th (theAttribute); aShape = aSelectAttr->value(); } + else // Geom2D point processing + aShape = theWorkshop->module()->findShape(theAttribute); return aShape; } @@ -934,7 +938,7 @@ void refsToFeatureInFeatureDocument(const ObjectPtr& theObject, std::set aRefFeatures; @@ -945,10 +949,10 @@ bool isSubOfComposite(const ObjectPtr& theObject) isSub = isSubOfComposite(theObject, *anIt); } return isSub; -} +}*/ //************************************************************** -bool isSubOfComposite(const ObjectPtr& theObject, const FeaturePtr& theFeature) +/*bool isSubOfComposite(const ObjectPtr& theObject, const FeaturePtr& theFeature) { bool isSub = false; CompositeFeaturePtr aComposite = std::dynamic_pointer_cast(theFeature); @@ -964,7 +968,7 @@ bool isSubOfComposite(const ObjectPtr& theObject, const FeaturePtr& theFeature) } } return isSub; -} +}*/ //************************************************************** ResultPtr firstResult(const ObjectPtr& theObject) diff --git a/src/ModuleBase/ModuleBase_Tools.h b/src/ModuleBase/ModuleBase_Tools.h index 376337dc4..4fb4146b0 100755 --- a/src/ModuleBase/ModuleBase_Tools.h +++ b/src/ModuleBase/ModuleBase_Tools.h @@ -264,13 +264,13 @@ void MODULEBASE_EXPORT refsToFeatureInFeatureDocument(const ObjectPtr& theObject /// \param theObject a candidate to be a sub object /// \param theFeature a candidate to be a composite feature /// \return a boolean value -bool MODULEBASE_EXPORT isSubOfComposite(const ObjectPtr& theObject, const FeaturePtr& theFeature); +//bool MODULEBASE_EXPORT isSubOfComposite(const ObjectPtr& theObject, const FeaturePtr& theFeature); /// Returns true if the result is a sub object of some composite object /// \param theObject a result object /// \returns boolean value -bool MODULEBASE_EXPORT isSubOfComposite(const ObjectPtr& theObject); +//bool MODULEBASE_EXPORT isSubOfComposite(const ObjectPtr& theObject); /// Returns first result of the feature: the object itself if it is a result of diff --git a/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp b/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp index 932b3d5af..378aa4a62 100755 --- a/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp +++ b/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include #include @@ -302,10 +304,11 @@ bool ModuleBase_WidgetMultiSelector::isValidSelectionCustom(const ModuleBase_Vie if (aValid) { if (myFeature) { // We can not select a result of our feature - const std::list& aResList = myFeature->results(); + std::list aResults; + ModelAPI_Tools::allResults(myFeature, aResults); std::list::const_iterator aIt; bool isSkipSelf = false; - for (aIt = aResList.cbegin(); aIt != aResList.cend(); ++aIt) { + for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) { if ((*aIt) == aResult) { isSkipSelf = true; break; @@ -402,8 +405,15 @@ void ModuleBase_WidgetMultiSelector::onSelectionChanged() { if (!myIsNeutralPointClear) { QList aSelected = getFilteredSelected(); - if (aSelected.size() == 0) - return; + // do not clear selected object + if (aSelected.size() == 0) { + if (!getAttributeSelection().empty()) { + // Restore selection in the viewer by the attribute selection list + // it should be postponed to exit from the selectionChanged processing + static Events_ID anEvent = Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION); + ModelAPI_EventCreator::get()->sendUpdated(myFeature, anEvent); + } + } } ModuleBase_WidgetSelector::onSelectionChanged(); } diff --git a/src/ModuleBase/ModuleBase_WidgetSelector.cpp b/src/ModuleBase/ModuleBase_WidgetSelector.cpp index ce06eb4a6..caa9c798b 100755 --- a/src/ModuleBase/ModuleBase_WidgetSelector.cpp +++ b/src/ModuleBase/ModuleBase_WidgetSelector.cpp @@ -15,8 +15,10 @@ #include #include #include +#include #include +#include #include @@ -163,7 +165,9 @@ void ModuleBase_WidgetSelector::activateCustom() activateSelectionAndFilters(true); // Restore selection in the viewer by the attribute selection list - myWorkshop->setSelected(getAttributeSelection()); + // it should be postponed to have current widget as active to validate restored selection + static Events_ID anEvent = Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION); + ModelAPI_EventCreator::get()->sendUpdated(myFeature, anEvent); } //******************************************************************** diff --git a/src/ModuleBase/ModuleBase_WidgetSelector.h b/src/ModuleBase/ModuleBase_WidgetSelector.h index 9db264010..3a309beb0 100755 --- a/src/ModuleBase/ModuleBase_WidgetSelector.h +++ b/src/ModuleBase/ModuleBase_WidgetSelector.h @@ -59,6 +59,11 @@ Q_OBJECT /// The methiod called when widget is deactivated virtual void deactivate(); + /// Return the attribute values wrapped in a list of viewer presentations + /// \return a list of viewer presentations, which contains an attribute result and + /// a shape. If the attribute do not uses the shape, it is empty + virtual QList> getAttributeSelection() const; + protected slots: /// Slot which is called on selection event virtual void onSelectionChanged(); @@ -72,12 +77,6 @@ protected: // NDS: has body is temporary virtual void updateFocus() {}; - /// Return the attribute values wrapped in a list of viewer presentations - /// \return a list of viewer presentations, which contains an attribute result and - /// a shape. If the attribute do not uses the shape, it is empty - // NDS: has body is temporary - virtual QList> getAttributeSelection() const; - /// Retunrs a list of possible shape types /// \return a list of shapes QIntList getShapeTypes() const; diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index 37754a8b1..d3eb60aa1 100755 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -332,7 +333,8 @@ void PartSet_Module::operationStarted(ModuleBase_Operation* theOperation) // the objects of the current operation should be deactivated QObjectPtrList anObjects; anObjects.append(aFeature); - std::list aResults = aFeature->results(); + std::list aResults; + ModelAPI_Tools::allResults(aFeature, aResults); std::list::const_iterator aIt; for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { anObjects.append(*aIt); @@ -949,13 +951,13 @@ bool PartSet_Module::customisePresentation(ResultPtr theResult, AISObjectPtr the { bool aCustomized = false; - if (theResult.get()) - return aCustomized; - XGUI_Workshop* aWorkshop = getWorkshop(); XGUI_Displayer* aDisplayer = aWorkshop->displayer(); ObjectPtr anObject = aDisplayer->getObject(thePrs); - if (anObject.get()) { + if (!anObject) + return aCustomized; + + if (!theResult.get()) { bool isConflicting = myOverconstraintListener->isConflictingObject(anObject); // customize sketch symbol presentation if (thePrs.get()) { @@ -992,10 +994,9 @@ bool PartSet_Module::customisePresentation(ResultPtr theResult, AISObjectPtr the aCustomized = thePrs->setColor(aColor[0], aColor[1], aColor[2]); } } - - // customize dimentional constrains - sketchMgr()->customizePresentation(anObject); } + // customize dimentional constrains + sketchMgr()->customizePresentation(anObject); return aCustomized; } diff --git a/src/PartSet/PartSet_OperationPrs.cpp b/src/PartSet/PartSet_OperationPrs.cpp index 1f8d0c560..d5e812723 100755 --- a/src/PartSet/PartSet_OperationPrs.cpp +++ b/src/PartSet/PartSet_OperationPrs.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -331,9 +332,10 @@ void PartSet_OperationPrs::getResultShapes(const FeaturePtr& theFeature, XGUI_Displayer* aDisplayer = XGUI_Tools::workshop(theWorkshop)->displayer(); - std::list aFeatureResults = theFeature->results(); - std::list::const_iterator aRIt = aFeatureResults.begin(), - aRLast = aFeatureResults.end(); + std::list aResults; + ModelAPI_Tools::allResults(theFeature, aResults); + std::list::const_iterator aRIt = aResults.begin(), + aRLast = aResults.end(); for (; aRIt != aRLast; aRIt++) { ResultPtr aResult = *aRIt; GeomShapePtr aGeomShape = aResult->shape(); diff --git a/src/PartSet/PartSet_SketcherMgr.cpp b/src/PartSet/PartSet_SketcherMgr.cpp index beb3206c7..b95786c36 100755 --- a/src/PartSet/PartSet_SketcherMgr.cpp +++ b/src/PartSet/PartSet_SketcherMgr.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include @@ -384,11 +385,6 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE return; Handle(AIS_InteractiveContext) aContext = aViewer->AISContext(); - if (!aContext.IsNull()) { - // MoveTo in order to highlight current object - aContext->MoveTo(theEvent->x(), theEvent->y(), theWnd->v3dView()); - ModuleBase_Tools::selectionInfo(aContext, "PartSet_SketcherMgr::onMousePressed -- MoveTo"); - } // Remember highlighted objects for editing ModuleBase_ISelection* aSelect = aWorkshop->selection(); @@ -433,13 +429,8 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE myPreviousDrawModeEnabled = aViewer->enableDrawMode(false); - // this is temporary commented in order to avoid the following wrong case: - // Distance constraint is under edition, double click on the digit -> nothing happens - // because QApplication::processEvents() calls onMouseDoubleClick, which try to show editor - // but as the prev edit is commited an new one is not started, editor is not shown. - // This is necessary in order to finalize previous operation - //QApplication::processEvents(); launchEditing(); + restoreSelection(); } } } @@ -1003,6 +994,9 @@ void PartSet_SketcherMgr::stopNestedSketch(ModuleBase_Operation* theOperation) qDebug("stopNestedSketch() : None"); #endif } + /// improvement to deselect automatically all eventual selected objects, when + // returning to the neutral point of the Sketcher + workshop()->selector()->clearSelection(); } void PartSet_SketcherMgr::commitNestedSketch(ModuleBase_Operation* theOperation) @@ -1576,6 +1570,18 @@ void PartSet_SketcherMgr::customizePresentation(const ObjectPtr& theObject) if (aFOperation && (PartSet_SketcherMgr::isSketchOperation(aFOperation) || PartSet_SketcherMgr::isNestedSketchOperation(aFOperation))) SketcherPrs_Tools::sendExpressionShownEvent(myIsConstraintsShown[PartSet_Tools::Expressions]); + + // update entities selection priorities + FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); + if (aFeature.get() && PartSet_SketcherMgr::isEntity(aFeature->getKind())) { + // update priority for feature + updateSelectionPriority(aFeature, aFeature); + // update priority for results of the feature + std::list aResults = aFeature->results(); + std::list::const_iterator anIt = aResults.begin(), aLastIt = aResults.end(); + for (; anIt != aLastIt; anIt++) + updateSelectionPriority(*anIt, aFeature); + } } ModuleBase_Operation* PartSet_SketcherMgr::getCurrentOperation() const @@ -1728,6 +1734,53 @@ void PartSet_SketcherMgr::updateBySketchParameters( } } +void PartSet_SketcherMgr::updateSelectionPriority(ObjectPtr theObject, + FeaturePtr theFeature) +{ + if (!theObject.get() || !theFeature.get()) + return; + + AISObjectPtr anAIS = workshop()->displayer()->getAISObject(theObject); + Handle(AIS_InteractiveObject) anAISIO; + if (anAIS.get() != NULL) { + anAISIO = anAIS->impl(); + } + + if (!anAISIO.IsNull()) { // the presentation for the object is visualized + int anAdditionalPriority = 0; + // current feature + std::shared_ptr aSPFeature = + std::dynamic_pointer_cast(theFeature); + if (aSPFeature.get() != NULL) { + // 1. Vertices + // 2. Simple segments + // 3. External objects (violet color) + // 4. Auxiliary segments (dotted) + // StdSelect_BRepSelectionTool::Load uses priority calculating: + // Standard_Integer aPriority = (thePriority == -1) ? GetStandardPriority (theShape, theType) : thePriority; + // Priority of Vertex is 8, edge(segment) is 7. + // It might be not corrected as provides the condition above. + bool isExternal = aSPFeature->isExternal(); + bool isAuxiliary = PartSet_Tools::isAuxiliarySketchEntity(aSPFeature); + // current feature + if (!isExternal && !isAuxiliary) + anAdditionalPriority = 30; + // external feature + if (isExternal) + anAdditionalPriority = 20; + // auxiliary feature + if (isAuxiliary) { + anAdditionalPriority = 10; /// auxiliary objects should have less priority that + // edges/vertices of local selection on not-sketch objects + } + Handle(ModuleBase_ResultPrs) aResult = Handle(ModuleBase_ResultPrs)::DownCast(anAISIO); + if (!aResult.IsNull()) { + aResult->setAdditionalSelectionPriority(anAdditionalPriority); + } + } + } +} + XGUI_Workshop* PartSet_SketcherMgr::workshop() const { ModuleBase_IWorkshop* anIWorkshop = myModule->workshop(); diff --git a/src/PartSet/PartSet_SketcherMgr.h b/src/PartSet/PartSet_SketcherMgr.h index ec9ea8f82..f8e85809b 100644 --- a/src/PartSet/PartSet_SketcherMgr.h +++ b/src/PartSet/PartSet_SketcherMgr.h @@ -366,6 +366,10 @@ private: const bool isToDisplay, const bool isFlushRedisplay = true); private: + /// Updates selection priority of the presentation + /// \param theObject object to find a presentation which will be corrected + /// \param theFeature a feature of the presentation + void updateSelectionPriority(ObjectPtr theObject, FeaturePtr theFeature); /// Returns current workshop XGUI_Workshop* workshop() const; /// Returns operation manager diff --git a/src/PartSet/PartSet_WidgetSketchCreator.h b/src/PartSet/PartSet_WidgetSketchCreator.h index 5290cef0a..60a3cf30e 100644 --- a/src/PartSet/PartSet_WidgetSketchCreator.h +++ b/src/PartSet/PartSet_WidgetSketchCreator.h @@ -13,7 +13,6 @@ class QLabel; class PartSet_Module; -class ModelAPI_Tools; class ModuleBase_Operation; class ModuleBase_IWorkshop; class PartSet_PreviewPlanes; diff --git a/src/SketchPlugin/SketchPlugin_SketchEntity.h b/src/SketchPlugin/SketchPlugin_SketchEntity.h index f0fb44020..3174d09ea 100644 --- a/src/SketchPlugin/SketchPlugin_SketchEntity.h +++ b/src/SketchPlugin/SketchPlugin_SketchEntity.h @@ -104,7 +104,9 @@ class SketchPlugin_SketchEntity : public SketchPlugin_Feature, public GeomAPI_IC virtual bool customisePresentation(ResultPtr theResult, AISObjectPtr thePrs, std::shared_ptr theDefaultPrs) { - bool isCustomized = false; + //bool isCustomized = false; + bool isCustomized = theDefaultPrs.get() != NULL && + theDefaultPrs->customisePresentation(theResult, thePrs, theDefaultPrs); int aShapeType = thePrs->getShapeType(); // a compound is processed like the edge because the arc feature uses the compound for presentable AIS if (aShapeType != 6/*an edge*/ && aShapeType != 7/*a vertex*/ && aShapeType != 0/*compound*/) diff --git a/src/SketcherPrs/SketcherPrs_Tools.h b/src/SketcherPrs/SketcherPrs_Tools.h index cfc15dbfc..04db3704c 100644 --- a/src/SketcherPrs/SketcherPrs_Tools.h +++ b/src/SketcherPrs/SketcherPrs_Tools.h @@ -25,7 +25,7 @@ class Handle_Prs3d_DimensionAspect; //#define MyTextHeight 20 -/// Message that document (Part, PartSet) was created +/// Message that style of visualization of parameter is changed. It will be shown as expression or value class SketcherPrs_ParameterStyleMessage : public Events_Message { public: diff --git a/src/XGUI/XGUI_CustomPrs.cpp b/src/XGUI/XGUI_CustomPrs.cpp index f07582125..5878f4635 100644 --- a/src/XGUI/XGUI_CustomPrs.cpp +++ b/src/XGUI/XGUI_CustomPrs.cpp @@ -85,11 +85,7 @@ bool XGUI_CustomPrs::customisePresentation(ResultPtr theResult, AISObjectPtr the } aCustomized = !aColor.empty() && thePrs->setColor(aColor[0], aColor[1], aColor[2]); } - else { - if (!aCustomized) { - ModuleBase_IModule* aModule = myWorkshop->module(); - aCustomized = aModule->customisePresentation(theResult, thePrs, theCustomPrs); - } - } + ModuleBase_IModule* aModule = myWorkshop->module(); + aCustomized = aModule->customisePresentation(theResult, thePrs, theCustomPrs) || aCustomized; return aCustomized; } diff --git a/src/XGUI/XGUI_Displayer.cpp b/src/XGUI/XGUI_Displayer.cpp index 83e738a05..b35bd80c8 100644 --- a/src/XGUI/XGUI_Displayer.cpp +++ b/src/XGUI/XGUI_Displayer.cpp @@ -79,7 +79,7 @@ const int MOUSE_SENSITIVITY_IN_PIXEL = 10; ///< defines the local context mouse //#define DEBUG_OCCT_SHAPE_SELECTION -#define WORKAROUND_UNTIL_27523_IS_FIXED +//#define WORKAROUND_UNTIL_27523_IS_FIXED void displayedObjects(const Handle(AIS_InteractiveContext)& theAIS, AIS_ListOfInteractive& theList) { @@ -476,7 +476,8 @@ bool XGUI_Displayer::isVisible(XGUI_Displayer* theDisplayer, const ObjectPtr& th if (!aVisible) { // check if all results of the feature are visible FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); - std::list aResults = aFeature->results(); + std::list aResults; + ModelAPI_Tools::allResults(aFeature, aResults); std::list::const_iterator aIt; aVisible = !aResults.empty(); for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { @@ -601,6 +602,8 @@ bool XGUI_Displayer::isActive(ObjectPtr theObject) const aContext->ActivatedModes(anAIS, aModes); return aModes.Extent() > 0; } + + void XGUI_Displayer::setSelected(const QList& theValues, bool theUpdateViewer) { Handle(AIS_InteractiveContext) aContext = AISContext(); @@ -609,16 +612,25 @@ void XGUI_Displayer::setSelected(const QList& theValue if (aContext->HasOpenedContext()) { aContext->UnhilightSelected(false); aContext->ClearSelected(false); - NCollection_Map aShapesToBeSelected; + 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); #else - aShapesToBeSelected.Add(aShape); + 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(); @@ -1297,6 +1309,42 @@ std::string XGUI_Displayer::getResult2AISObjectMapInfo() const arg(aContent.join("\n")).toStdString().c_str(); } +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) { + 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; @@ -1348,14 +1396,13 @@ QIntList XGUI_Displayer::activeSelectionModes() const } void XGUI_Displayer::AddOrRemoveSelectedShapes(Handle(AIS_InteractiveContext) theContext, - const NCollection_Map& theShapesToBeSelected) + const NCollection_DataMap>& theShapesToBeSelected) { Handle(AIS_LocalContext) aLContext = theContext->LocalContext(); TCollection_AsciiString aSelectionName = aLContext->SelectionName(); aLContext->UnhilightPicked(Standard_False); - NCollection_Map aShapesSelected; - NCollection_List anActiveOwners; aLContext->MainSelector()->ActiveOwners(anActiveOwners); NCollection_List::Iterator anOwnersIt (anActiveOwners); @@ -1363,12 +1410,18 @@ void XGUI_Displayer::AddOrRemoveSelectedShapes(Handle(AIS_InteractiveContext) th for (; anOwnersIt.More(); anOwnersIt.Next()) { anOwner = Handle(SelectMgr_EntityOwner)::DownCast (anOwnersIt.Value()); Handle(StdSelect_BRepOwner) BROwnr = Handle(StdSelect_BRepOwner)::DownCast(anOwner); - if (!BROwnr.IsNull() && BROwnr->HasShape() && theShapesToBeSelected.Contains(BROwnr->Shape())) { - if (aShapesSelected.Contains(BROwnr->Shape())) - continue; - AIS_Selection::Selection(aSelectionName.ToCString())->Select(anOwner); - anOwner->SetSelected (Standard_True); - aShapesSelected.Add(BROwnr->Shape()); + if (!BROwnr.IsNull() && BROwnr->HasShape()) { + const TopoDS_Shape& aShape = BROwnr->Shape(); + if (!aShape.IsNull() && theShapesToBeSelected.IsBound(aShape)) { + Handle(AIS_InteractiveObject) anOwnerPresentation = + Handle(AIS_InteractiveObject)::DownCast(anOwner->Selectable()); + NCollection_Map aPresentations = + theShapesToBeSelected.Find(aShape); + if (aPresentations.Contains(anOwnerPresentation)) { + AIS_Selection::Selection(aSelectionName.ToCString())->Select(anOwner); + anOwner->SetSelected (Standard_True); + } + } } } aLContext->HilightPicked(Standard_False); diff --git a/src/XGUI/XGUI_Displayer.h b/src/XGUI/XGUI_Displayer.h index b80165b69..529aab5ef 100644 --- a/src/XGUI/XGUI_Displayer.h +++ b/src/XGUI/XGUI_Displayer.h @@ -13,7 +13,8 @@ #include #include #include -#include +#include +#include #include @@ -322,6 +323,13 @@ private: /// \return a string representation std::string getResult2AISObjectMapInfo() const; + /// Returns container of visible presentations for the object. For a feature object, + /// the feature results are processed also. The presentations map is not cleared inside. + /// \param theObject a feature or result + /// \param thePresentations result map of presentations + void getPresentations(const ObjectPtr& theObject, + NCollection_Map& thePresentations); + /// Sets the shapes selected in the context. It contains logic of the similar method /// in OCCT but improved for performance. The modification is to iterates by a list /// of owners in the context only once. @@ -329,7 +337,10 @@ private: /// \param theShapesToBeSelected a map of shapes. Owner's shape is searched in the map and the owner /// is selected if it is found there. Only first owner is processed(according to OCCT logic) static void AddOrRemoveSelectedShapes(Handle(AIS_InteractiveContext) theContext, - const NCollection_Map& theShapesToBeSelected); + const NCollection_DataMap>& theShapesToBeSelected); + + //const NCollection_Map& theShapesToBeSelected); protected: /// Reference to workshop diff --git a/src/XGUI/XGUI_PropertyPanel.cpp b/src/XGUI/XGUI_PropertyPanel.cpp index 10d39b798..e37d69f91 100755 --- a/src/XGUI/XGUI_PropertyPanel.cpp +++ b/src/XGUI/XGUI_PropertyPanel.cpp @@ -17,6 +17,9 @@ #include #include #include +#include + +#include #include #include @@ -436,6 +439,9 @@ bool XGUI_PropertyPanel::setActiveWidget(ModuleBase_ModelWidget* theWidget) theWidget->activate(); } myActiveWidget = theWidget; + static Events_ID anEvent = Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION); + Events_Loop::loop()->flush(anEvent); + return true; } diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index f36f9353e..cffb0d4b0 100755 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -627,7 +627,8 @@ void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation) if (aFeature.get()) { // feature may be not created (plugin load fail) if (myDisplayer->isVisible(aFeature) && !myDisplayer->isActive(aFeature)) anObjects.append(aFeature); - std::list aResults = aFeature->results(); + std::list aResults; + ModelAPI_Tools::allResults(aFeature, aResults); std::list::const_iterator aIt; for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { ResultPtr anObject = *aIt; @@ -1552,7 +1553,9 @@ std::list allFeatures(const DocumentPtr& theDocument) // The order of appending features of the part and the part itself is important // Append features from a part feature - foreach (const ResultPtr& aResult, aFeature->results()) { + std::list aResults; + ModelAPI_Tools::allResults(aFeature, aResults); + foreach (const ResultPtr& aResult, aResults) { ResultPartPtr aResultPart = std::dynamic_pointer_cast(aResult); if (aResultPart.get() && aResultPart->partDoc().get()) { @@ -1957,7 +1960,8 @@ void XGUI_Workshop::highlightResults(const QObjectPtrList& theObjects) foreach(ObjectPtr aObj, theObjects) { aFeature = std::dynamic_pointer_cast(aObj); if (aFeature.get()) { - aResList = aFeature->results(); + std::list aResults; + ModelAPI_Tools::allResults(aFeature, aResults); std::list >::const_iterator aIt; for(aIt = aResList.cbegin(); aIt != aResList.cend(); aIt++) { aHasHidden |= (*aIt)->isConcealed(); diff --git a/src/XGUI/XGUI_WorkshopListener.cpp b/src/XGUI/XGUI_WorkshopListener.cpp index 366336a1f..984388b5c 100755 --- a/src/XGUI/XGUI_WorkshopListener.cpp +++ b/src/XGUI/XGUI_WorkshopListener.cpp @@ -16,6 +16,7 @@ #endif #include +#include #include #include @@ -39,6 +40,7 @@ #include #include #include +#include #include #include @@ -94,6 +96,7 @@ void XGUI_WorkshopListener::initializeEventListening() aLoop->registerListener(this, Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED)); aLoop->registerListener(this, Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED)); aLoop->registerListener(this, Events_Loop::eventByName(EVENT_EMPTY_AIS_PRESENTATION)); + aLoop->registerListener(this, Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION)); } //****************************************************** @@ -133,7 +136,15 @@ void XGUI_WorkshopListener::processEvent(const std::shared_ptr& std::shared_ptr aUpdMsg = std::dynamic_pointer_cast(theMessage); onFeatureEmptyPresentationMsg(aUpdMsg); + } else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION)) { + ModuleBase_ModelWidget* aWidget = workshop()->propertyPanel()->activeWidget(); + if (aWidget) { + ModuleBase_WidgetSelector* aWidgetSelector = dynamic_cast(aWidget); + if (aWidgetSelector) + myWorkshop->setSelected(aWidgetSelector->getAttributeSelection()); + } } + //Update property panel on corresponding message. If there is no current operation (no //property panel), or received message has different feature to the current - do nothing. else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) {