From 8873182f935a9f77cdb25a770d4c8780b7669773 Mon Sep 17 00:00:00 2001 From: nds Date: Tue, 8 Sep 2015 08:40:58 +0300 Subject: [PATCH] Operation Prs is corrected: 1. to be not visualized if the module can not display the feature of the presentation[e.g. sketch sub-entity creation, when the mouse is not over viewer]; 2. Call redisplay of the presentation by the REDISPLAY/CREATE message, instead of doing that by the UPDATE message. Correction in selection processing, cased by #26658. Scenario: Create two lines in the sketch, start Distance constraint, Click in the common point of lines three times[without moving], the result is that both distance attributes are filled with the same value. However there is a filter that prohibits this. --- src/ModuleBase/ModuleBase_WidgetSelector.cpp | 6 +- src/PartSet/PartSet_OperationPrs.cpp | 6 ++ src/XGUI/XGUI_Displayer.cpp | 64 +++++++++++------ src/XGUI/XGUI_Displayer.h | 75 ++++++++------------ src/XGUI/XGUI_WorkshopListener.cpp | 47 ++++++++---- src/XGUI/XGUI_WorkshopListener.h | 4 ++ 6 files changed, 120 insertions(+), 82 deletions(-) diff --git a/src/ModuleBase/ModuleBase_WidgetSelector.cpp b/src/ModuleBase/ModuleBase_WidgetSelector.cpp index 96cabdd00..268a2515f 100755 --- a/src/ModuleBase/ModuleBase_WidgetSelector.cpp +++ b/src/ModuleBase/ModuleBase_WidgetSelector.cpp @@ -45,7 +45,11 @@ void ModuleBase_WidgetSelector::onSelectionChanged() QList aSelected = getFilteredSelected(); - bool isDone = setSelection(aSelected, false); + bool isDone = setSelection(aSelected, true/*false*/); + // "false" flag should be used here, it connects to the #26658 OCC bug, when the user click in + // the same place repeatedly without mouse moved. In the case validation by filters is not + // perfromed, so an invalid object is selected. E.g. distance constraint, selection of a point. + // the 3rd click in the same point allow using this point. emit valuesChanged(); // the updateObject method should be called to flush the updated sigal. The workshop listens it, // calls validators for the feature and, as a result, updates the Apply button state. diff --git a/src/PartSet/PartSet_OperationPrs.cpp b/src/PartSet/PartSet_OperationPrs.cpp index 64e785960..66e146f96 100755 --- a/src/PartSet/PartSet_OperationPrs.cpp +++ b/src/PartSet/PartSet_OperationPrs.cpp @@ -12,6 +12,7 @@ #include "XGUI_Displayer.h" #include "ModuleBase_Tools.h" +#include "ModuleBase_IModule.h" #include #include @@ -78,6 +79,11 @@ void PartSet_OperationPrs::Compute(const Handle(PrsMgr_PresentationManager3d)& t const Handle(Prs3d_Presentation)& thePresentation, const Standard_Integer theMode) { + // when the feature can not be visualized in the module, the operation preview should not + // be visualized also + if (!myWorkshop->module()->canDisplayObject(myFeature)) + return; + Quantity_Color aColor(1., 1., 0., Quantity_TOC_RGB); // yellow SetColor(aColor); diff --git a/src/XGUI/XGUI_Displayer.cpp b/src/XGUI/XGUI_Displayer.cpp index 887e70468..3ee0ccdaa 100644 --- a/src/XGUI/XGUI_Displayer.cpp +++ b/src/XGUI/XGUI_Displayer.cpp @@ -111,8 +111,9 @@ bool XGUI_Displayer::isVisible(ObjectPtr theObject) const return myResult2AISObjectMap.contains(theObject); } -void XGUI_Displayer::display(ObjectPtr theObject, bool theUpdateViewer) +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); @@ -127,10 +128,9 @@ void XGUI_Displayer::display(ObjectPtr theObject, bool theUpdateViewer) } else #endif - redisplay(theObject, theUpdateViewer); + aDisplayed = redisplay(theObject, theUpdateViewer); } else { AISObjectPtr anAIS; - GeomPresentablePtr aPrs = std::dynamic_pointer_cast(theObject); bool isShading = false; if (aPrs.get() != NULL) { @@ -164,8 +164,9 @@ void XGUI_Displayer::display(ObjectPtr theObject, bool theUpdateViewer) } } if (anAIS) - display(theObject, anAIS, isShading, theUpdateViewer); + aDisplayed = display(theObject, anAIS, isShading, theUpdateViewer); } + return aDisplayed; } bool canBeShaded(Handle(AIS_InteractiveObject) theAIS) @@ -189,12 +190,14 @@ bool canBeShaded(Handle(AIS_InteractiveObject) theAIS) return false; } -void XGUI_Displayer::display(ObjectPtr theObject, AISObjectPtr theAIS, +bool XGUI_Displayer::display(ObjectPtr theObject, AISObjectPtr theAIS, bool isShading, bool theUpdateViewer) { + bool aDisplayed = false; + Handle(AIS_InteractiveContext) aContext = AISContext(); if (aContext.IsNull()) - return; + return aDisplayed; Handle(AIS_InteractiveObject) anAISIO = theAIS->impl(); if (!anAISIO.IsNull()) { @@ -207,6 +210,7 @@ void XGUI_Displayer::display(ObjectPtr theObject, AISObjectPtr theAIS, anAISIO->Attributes()->SetFaceBoundaryDraw( Standard_True ); anAISIO->SetDisplayMode(aDispMode); aContext->Display(anAISIO, aDispMode, 0, false, true, AIS_DS_Displayed); + aDisplayed = true; emit objectDisplayed(theObject, theAIS); activate(anAISIO, myActiveSelectionModes, theUpdateViewer); @@ -220,22 +224,26 @@ void XGUI_Displayer::display(ObjectPtr theObject, AISObjectPtr theAIS, } if (theUpdateViewer) updateViewer(); + + return aDisplayed; } -void XGUI_Displayer::erase(ObjectPtr theObject, const bool theUpdateViewer) +bool XGUI_Displayer::erase(ObjectPtr theObject, const bool theUpdateViewer) { + bool aErased = false; if (!isVisible(theObject)) - return; + return aErased; Handle(AIS_InteractiveContext) aContext = AISContext(); if (aContext.IsNull()) - return; + return aErased; AISObjectPtr anObject = myResult2AISObjectMap[theObject]; if (anObject) { Handle(AIS_InteractiveObject) anAIS = anObject->impl(); if (!anAIS.IsNull()) { emit beforeObjectErase(theObject, anObject); aContext->Remove(anAIS, theUpdateViewer); + aErased = true; } } myResult2AISObjectMap.remove(theObject); @@ -246,12 +254,14 @@ void 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 + return aErased; } -void XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer) +bool XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer) { + bool aRedisplayed = false; if (!isVisible(theObject)) - return; + return aRedisplayed; AISObjectPtr aAISObj = getAISObject(theObject); Handle(AIS_InteractiveObject) aAISIO = aAISObj->impl(); @@ -260,8 +270,8 @@ void XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer) if (aPrs) { AISObjectPtr aAIS_Obj = aPrs->getAISObject(aAISObj); if (!aAIS_Obj) { - erase(theObject, theUpdateViewer); - return; + aRedisplayed = erase(theObject, theUpdateViewer); + return aRedisplayed; } if (aAIS_Obj != aAISObj) { appendResultObject(theObject, aAIS_Obj); @@ -269,14 +279,11 @@ void XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer) aAISIO = aAIS_Obj->impl(); } - if (!aAISIO.IsNull()) { - Handle(AIS_InteractiveContext) aContext = AISContext(); - if (aContext.IsNull()) - return; + Handle(AIS_InteractiveContext) aContext = AISContext(); + if (!aAISIO.IsNull() && !aContext.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 // 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 @@ -302,6 +309,7 @@ void XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer) #endif if (!isEqualShapes || isCustomized) { aContext->Redisplay(aAISIO, false); + aRedisplayed = true; #ifdef DEBUG_FEATURE_REDISPLAY qDebug(" Redisplay happens"); #endif @@ -309,6 +317,7 @@ void XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer) updateViewer(); } } + return aRedisplayed; } void XGUI_Displayer::redisplayObjects() @@ -516,8 +525,9 @@ void XGUI_Displayer::clearSelected() } } -void XGUI_Displayer::eraseAll(const bool theUpdateViewer) +bool XGUI_Displayer::eraseAll(const bool theUpdateViewer) { + bool aErased = false; Handle(AIS_InteractiveContext) aContext = AISContext(); if (!aContext.IsNull()) { foreach (ObjectPtr aObj, myResult2AISObjectMap.keys()) { @@ -527,6 +537,7 @@ void XGUI_Displayer::eraseAll(const bool theUpdateViewer) if (!anIO.IsNull()) { emit beforeObjectErase(aObj, aAISObj); aContext->Remove(anIO, false); + aErased = true; } } if (theUpdateViewer) @@ -537,6 +548,7 @@ void XGUI_Displayer::eraseAll(const bool theUpdateViewer) qDebug("eraseAll"); qDebug(getResult2AISObjectMapInfo().c_str()); #endif + return aErased; } void XGUI_Displayer::deactivateTrihedron() const @@ -746,15 +758,17 @@ Handle(SelectMgr_AndFilter) XGUI_Displayer::GetFilter() return myAndFilter; } -void XGUI_Displayer::displayAIS(AISObjectPtr theAIS, const bool toActivateInSelectionModes, +bool XGUI_Displayer::displayAIS(AISObjectPtr theAIS, const bool toActivateInSelectionModes, bool theUpdateViewer) { + bool aDisplayed = false; Handle(AIS_InteractiveContext) aContext = AISContext(); if (aContext.IsNull()) - return; + return aDisplayed; Handle(AIS_InteractiveObject) anAISIO = theAIS->impl(); if (!anAISIO.IsNull()) { aContext->Display(anAISIO, 0/*wireframe*/, 0, theUpdateViewer, true, AIS_DS_Displayed); + aDisplayed = true; aContext->Deactivate(anAISIO); aContext->Load(anAISIO); if (toActivateInSelectionModes) { @@ -769,17 +783,21 @@ void XGUI_Displayer::displayAIS(AISObjectPtr theAIS, const bool toActivateInSele } } } + return aDisplayed; } -void XGUI_Displayer::eraseAIS(AISObjectPtr theAIS, const bool theUpdateViewer) +bool XGUI_Displayer::eraseAIS(AISObjectPtr theAIS, const bool theUpdateViewer) { + bool aErased = false; Handle(AIS_InteractiveContext) aContext = AISContext(); if (aContext.IsNull()) - return; + return aErased; Handle(AIS_InteractiveObject) anAISIO = theAIS->impl(); if (!anAISIO.IsNull() && aContext->IsDisplayed(anAISIO)) { aContext->Remove(anAISIO, theUpdateViewer); + aErased = true; } + return aErased; } diff --git a/src/XGUI/XGUI_Displayer.h b/src/XGUI/XGUI_Displayer.h index dfaffc9bb..9e853afb0 100644 --- a/src/XGUI/XGUI_Displayer.h +++ b/src/XGUI/XGUI_Displayer.h @@ -64,8 +64,8 @@ class XGUI_EXPORT XGUI_Displayer: public QObject /// Display the feature. Obtain the visualized object from the feature. /// \param theObject an object to display /// \param theUpdateViewer the parameter whether the viewer should be update immediatelly - /// Returns true if the Feature succesfully displayed - void display(ObjectPtr theObject, bool theUpdateViewer = true); + /// \return true if the object visibility state is changed + bool display(ObjectPtr theObject, bool theUpdateViewer = true); /// Display the given AIS object. This object is not added to the displayer internal map of objects /// So, it can not be obtained from displayer. This is just a wrap method of OCC display in order @@ -74,46 +74,45 @@ class XGUI_EXPORT XGUI_Displayer: public QObject /// \param toActivateInSelectionModes boolean value whether the presentation should be /// activated in the current selection modes /// \param theUpdateViewer the parameter whether the viewer should be update immediatelly - void displayAIS(AISObjectPtr theAIS, const bool toActivateInSelectionModes, + /// \return true if the object visibility state is changed + bool displayAIS(AISObjectPtr theAIS, const bool toActivateInSelectionModes, bool theUpdateViewer = true); - /** Redisplay the shape if it was displayed - * \param theObject an object instance - * \param theUpdateViewer the parameter whether the viewer should be update immediatelly - */ - void redisplay(ObjectPtr theObject, bool theUpdateViewer = true); + /// Redisplay the shape if it was displayed + /// \param theObject an object instance + /// \param theUpdateViewer the parameter whether the viewer should be update immediatelly + /// \return true if the object visibility state is changed + bool redisplay(ObjectPtr theObject, bool theUpdateViewer = true); - /** - * Sends and flushes a signal to redisplay all visualized objects. - */ + /// Sends and flushes a signal to redisplay all visualized objects. void redisplayObjects(); - /** - * Add presentations to current selection. It unhighlight and deselect the current selection. - * The shape and result components are processed in the values. If the presentation shape is not - * empty, select it, otherwise select the result. - * \param theValues a list of presentation to be selected - * \param theUpdateViewer the parameter whether the viewer should be update immediatelly - */ + /// Add presentations to current selection. It unhighlight and deselect the current selection. + /// The shape and result components are processed in the values. If the presentation shape is not + /// empty, select it, otherwise select the result. + /// \param theValues a list of presentation to be selected + /// \param theUpdateViewer the parameter whether the viewer should be update immediatelly void setSelected(const QList& theValues, bool theUpdateViewer = true); - /// Unselect all objects void clearSelected(); /// Erase the feature and a shape. /// \param theObject an object instance /// \param theUpdateViewer the parameter whether the viewer should be update immediatelly - void erase(ObjectPtr theObject, const bool theUpdateViewer = true); + /// \return true if the object visibility state is changed + bool erase(ObjectPtr theObject, const bool theUpdateViewer = true); /// Erase the given AIS object displayed by corresponded display method /// \param theAIS instance of AIS object /// \param theUpdateViewer the parameter whether the viewer should be update immediatelly - void eraseAIS(AISObjectPtr theAIS, const bool theUpdateViewer = true); + /// \return true if the object visibility state is changed + bool eraseAIS(AISObjectPtr theAIS, const bool theUpdateViewer = true); /// Erase all presentations /// \param theUpdateViewer the parameter whether the viewer should be update immediatelly - void eraseAll(const bool theUpdateViewer = true); + /// \return true if the object visibility state is changed + bool eraseAll(const bool theUpdateViewer = true); /// Deactivates selection of sub-shapes /// \param theUpdateViewer the parameter whether the viewer should be update immediatelly @@ -137,11 +136,9 @@ class XGUI_EXPORT XGUI_Displayer: public QObject /// Remove all selection filters void removeFilters(); - /** - * Sets a flag to the displayer whether the internal viewer can be updated by - * the updateViewer method call. If it is not enabled, this method do nothing - * \param isEnabled a boolean value - */ + /// Sets a flag to the displayer whether the internal viewer can be updated by + /// the updateViewer method call. If it is not enabled, this method do nothing + /// \param isEnabled a boolean value bool enableUpdateViewer(const bool isEnabled); /// Updates the viewer @@ -177,20 +174,11 @@ class XGUI_EXPORT XGUI_Displayer: public QObject void deactivateObjects(const QObjectPtrList& theObjList, const bool theUpdateViewer = true); - /// Activates the given object (it can be selected) - /// \param theObject object to activate - /// \param theModes - modes on which it has to be activated (can be empty) - //void activate(ObjectPtr theObject, const QIntList& theModes); - /// Returns the modes of activation /// \param theObject the feature or NULL if it not visualized /// \param theModes - modes on which it is activated (can be empty) void getModesOfActivation(ObjectPtr theObject, QIntList& theModes); - /// Activates the given object with default modes - /// \param theObject object to activate - //void activate(ObjectPtr theObject); - /// Returns true if the given object can be selected /// \param theObject object to check bool isActive(ObjectPtr theObject) const; @@ -257,8 +245,8 @@ signals: /// \param theAIS AIS presentation /// \param isShading flag to show in shading mode /// \param theUpdateViewer the parameter whether the viewer should be update immediatelly - /// \return true if the object is succesfully displayed - void display(ObjectPtr theObject, AISObjectPtr theAIS, bool isShading, + /// \return true if the object visibility state is changed + bool display(ObjectPtr theObject, AISObjectPtr theAIS, bool isShading, bool theUpdateViewer = true); private: @@ -278,12 +266,11 @@ private: /// Opens local context. Does nothing if it is already opened. void openLocalContext(); - /** Update the object presentable properties such as color, lines width and other - * If the object is result with the color attribute value set, it is used, - * otherwise the customize is applyed to the object's feature if it is a custom prs - * \param theObject an object instance - * \return the true state if there is changes and the presentation is customized - */ + /// Update the object presentable properties such as color, lines width and other + /// If the object is result with the color attribute value set, it is used, + /// otherwise the customize is applyed to the object's feature if it is a custom prs + /// \param theObject an object instance + /// \return the true state if there is changes and the presentation is customized bool customizeObject(ObjectPtr theObject); /// Append the objects in the internal map. Checks whether the map already contains the object diff --git a/src/XGUI/XGUI_WorkshopListener.cpp b/src/XGUI/XGUI_WorkshopListener.cpp index 6a30664d4..6e4879d57 100755 --- a/src/XGUI/XGUI_WorkshopListener.cpp +++ b/src/XGUI/XGUI_WorkshopListener.cpp @@ -216,7 +216,6 @@ void XGUI_WorkshopListener::onFeatureUpdatedMsg( QString anInfoStr = anInfo.join(";\t"); qDebug(QString("onFeatureUpdatedMsg: %1, %2").arg(aObjects.size()).arg(anInfoStr).toStdString().c_str()); #endif - bool isModified = false; std::set aFeatures = theMsg->objects(); XGUI_OperationMgr* anOperationMgr = workshop()->operationMgr(); if (anOperationMgr->hasOperation()) { @@ -232,15 +231,12 @@ void XGUI_WorkshopListener::onFeatureUpdatedMsg( break; } } - isModified = myWorkshop->module()->customizeObject(aCurrentFeature, false); } } anOperationMgr->onValidateOperation(); //if (myObjectBrowser) // myObjectBrowser->processEvent(theMsg); - if (isModified) - workshop()->displayer()->updateViewer(); } //****************************************************** @@ -260,6 +256,7 @@ void XGUI_WorkshopListener::onFeatureRedisplayMsg(const std::shared_ptrdisplayer(); + bool aRedisplayed = false; for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) { ObjectPtr aObj = (*aIt); @@ -282,7 +279,7 @@ void XGUI_WorkshopListener::onFeatureRedisplayMsg(const std::shared_ptrerase(aObj, false); + aRedisplayed = aDisplayer->erase(aObj, false) || aRedisplayed; #ifdef DEBUG_FEATURE_REDISPLAY // Redisplay the visible object or the object of the current operation bool isVisibleObject = aDisplayer->isVisible(aObj); @@ -311,21 +308,24 @@ void XGUI_WorkshopListener::onFeatureRedisplayMsg(const std::shared_ptr(aObj))) { - aDisplayer->erase(aObj, false); + aRedisplayed = aDisplayer->erase(aObj, false) || aRedisplayed; } else { - aDisplayer->redisplay(aObj, false); + aRedisplayed = aDisplayer->redisplay(aObj, false) || aRedisplayed; // Deactivate object of current operation from selection aWorkshop->deactivateActiveObject(aObj, false); } } else { // display object if the current operation has it if (displayObject(aObj)) { + aRedisplayed = true; // Deactivate object of current operation from selection aWorkshop->deactivateActiveObject(aObj, false); } } } } + aRedisplayed = customizeCurrentObject() | aRedisplayed; + if (aRedisplayed) aDisplayer->updateViewer(); } //****************************************************** @@ -343,7 +343,7 @@ void XGUI_WorkshopListener::onFeatureCreatedMsg(const std::shared_ptrmodule()->canDisplayObject(anObject)) { anObject->setDisplayed(true); - isDisplayed = displayObject(*aIt); + aDisplayed = displayObject(*aIt); } else anObject->setDisplayed(false); } } + aDisplayed = customizeCurrentObject() || aDisplayed; + //if (myObjectBrowser) // myObjectBrowser->processEvent(theMsg); - if (isDisplayed) + if (aDisplayed) workshop()->displayer()->updateViewer(); //if (aHasPart) { // TODO: Avoid activate last part on loading of document // activateLastPart(); @@ -511,23 +513,40 @@ bool XGUI_WorkshopListener::displayObject(ObjectPtr theObj) } #endif + bool aDisplayed = false; XGUI_Workshop* aWorkshop = workshop(); // do not display the object if it has sub objects. They should be displayed separately. if (!aWorkshop->module()->canDisplayObject(theObj) || ModelAPI_Tools::hasSubResults(std::dynamic_pointer_cast(theObj))) - return false; + return aDisplayed; XGUI_Displayer* aDisplayer = aWorkshop->displayer(); ResultBodyPtr aBody = std::dynamic_pointer_cast(theObj); if (aBody.get() != NULL) { int aNb = aDisplayer->objectsCount(); - aDisplayer->display(theObj, false); + aDisplayed = aDisplayer->display(theObj, false); if (aNb == 0) myWorkshop->viewer()->fitAll(); } else - aDisplayer->display(theObj, false); + aDisplayed = aDisplayer->display(theObj, false); + + return aDisplayed; +} - return true; +bool XGUI_WorkshopListener::customizeCurrentObject() +{ + bool aCustomized = false; + XGUI_OperationMgr* anOperationMgr = workshop()->operationMgr(); + if (anOperationMgr->hasOperation()) { + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (anOperationMgr->currentOperation()); + if (aFOperation) { + FeaturePtr aCurrentFeature = aFOperation->feature(); + if (aCurrentFeature.get()) + aCustomized = myWorkshop->module()->customizeObject(aCurrentFeature, false); + } + } + return aCustomized; } XGUI_Workshop* XGUI_WorkshopListener::workshop() const diff --git a/src/XGUI/XGUI_WorkshopListener.h b/src/XGUI/XGUI_WorkshopListener.h index 912fb85df..fa41577cc 100755 --- a/src/XGUI/XGUI_WorkshopListener.h +++ b/src/XGUI/XGUI_WorkshopListener.h @@ -72,6 +72,10 @@ protected: /// \return true if the object is displayed bool displayObject(ObjectPtr theObj); + /// Calls the module method of cusomize object for the feature of the current operation + /// \return true if the object is modified + bool customizeCurrentObject(); + /// Returns the workshop XGUI_Workshop* workshop() const; -- 2.39.2