X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FPartSet%2FPartSet_SketcherMgr.cpp;h=a46d07f9d7413038f82e3b2086aca17e33aaa3e0;hb=023c72db1a0c06efe73559cc2ff37c841842823a;hp=06fbec26cddd5bf4e0e5f2647c27293ae1e39cf2;hpb=28bbf47d23aa7fc8217e1cbf9ab089acef27cec3;p=modules%2Fshaper.git diff --git a/src/PartSet/PartSet_SketcherMgr.cpp b/src/PartSet/PartSet_SketcherMgr.cpp index 06fbec26c..a46d07f9d 100755 --- a/src/PartSet/PartSet_SketcherMgr.cpp +++ b/src/PartSet/PartSet_SketcherMgr.cpp @@ -7,8 +7,7 @@ #include "PartSet_SketcherMgr.h" #include "PartSet_SketcherReetntrantMgr.h" #include "PartSet_Module.h" -#include "PartSet_WidgetPoint2d.h" -#include "PartSet_WidgetPoint2dDistance.h" +#include "PartSet_MouseProcessor.h" #include "PartSet_Tools.h" #include "PartSet_WidgetSketchLabel.h" #include "PartSet_WidgetEditor.h" @@ -24,6 +23,7 @@ #include #include #include +#include #include #include @@ -36,6 +36,9 @@ #include #include #include +#include +#include +#include #include @@ -79,53 +82,20 @@ #include #include +#include +#include + #include #include #include #include +#include //#define DEBUG_DO_NOT_BY_ENTER +//#define DEBUG_SKETCHER_ENTITIES //#define DEBUG_CURSOR -/// Returns list of unique objects by sum of objects from List1 and List2 -/*QList getSumList(const QList& theList1, - const QList& theList2) -{ - QList aRes; - foreach (ModuleBase_ViewerPrs aPrs, theList1) { - if (!aRes.contains(aPrs)) - aRes.append(aPrs); - } - foreach (ModuleBase_ViewerPrs aPrs, theList2) { - if (!aRes.contains(aPrs)) - aRes.append(aPrs); - } - return aRes; -}*/ - -// Fills the list of features the list of selected presentations. -// \param theList a list of selected presentations -// \param theSketch a sketch to project a vertex shape of a presentation to the plane -// and find the corresponded attribute -// \param theFeatureList an output list of features -void fillFeatureList(const QList& theList, - const FeaturePtr theSketch, - QList& theFeatureList) -{ - QList aRes; - - QList::const_iterator anIt = theList.begin(), - aLast = theList.end(); - for (; anIt != aLast; anIt++) - { - ModuleBase_ViewerPrs aPrs = *anIt; - FeaturePtr aFeature = ModelAPI_Feature::feature(aPrs.object()); - if (aFeature.get() && !theFeatureList.contains(aFeature)) - theFeatureList.append(aFeature); - } -} - /// Fills attribute and result lists by the selected owner. In case if the attribute is found, /// by the owner shape, it is put to the list. Otherwise if type of owner shape is edge, put the function /// result as is to the list of results. @@ -221,7 +191,7 @@ void PartSet_SketcherMgr::onEnterViewPort() } } - if (!isNestedCreateOperation(getCurrentOperation())) + if (!isNestedCreateOperation(getCurrentOperation(), activeSketch())) return; operationMgr()->onValidateOperation(); @@ -246,9 +216,6 @@ void PartSet_SketcherMgr::onLeaveViewPort() { myIsMouseOverViewProcessed = false; myIsMouseOverWindow = false; - // it is important to validate operation here only if sketch entity create operation is active - // because at this operation we reacts to the mouse leave/enter view port - //operationMgr()->onValidateOperation(); #ifdef DEBUG_DO_NOT_BY_ENTER return; @@ -261,7 +228,7 @@ void PartSet_SketcherMgr::onLeaveViewPort() #endif } - if (!isNestedCreateOperation(getCurrentOperation())) + if (!isNestedCreateOperation(getCurrentOperation(), activeSketch())) return; // the method should be performed if the popup menu is called, @@ -269,6 +236,8 @@ void PartSet_SketcherMgr::onLeaveViewPort() if (myIsPopupMenuActive) return; + // it is important to validate operation here only if sketch entity create operation is active + // because at this operation we reacts to the mouse leave/enter view port operationMgr()->onValidateOperation(); // 2. if the mouse IS NOT over window, reset the active widget value and hide the presentation @@ -298,7 +267,7 @@ void PartSet_SketcherMgr::onLeaveViewPort() void PartSet_SketcherMgr::onBeforeValuesChangedInPropertyPanel() { - if (!isNestedEditOperation(getCurrentOperation()) || + if (!isNestedEditOperation(getCurrentOperation(), myModule->sketchMgr()->activeSketch()) || myModule->sketchReentranceMgr()->isInternalEditActive()) return; // it is necessary to save current selection in order to restore it after the values are modifed @@ -312,7 +281,7 @@ void PartSet_SketcherMgr::onBeforeValuesChangedInPropertyPanel() void PartSet_SketcherMgr::onAfterValuesChangedInPropertyPanel() { - if (!isNestedEditOperation(getCurrentOperation()) || + if (!isNestedEditOperation(getCurrentOperation(), myModule->sketchMgr()->activeSketch()) || myModule->sketchReentranceMgr()->isInternalEditActive()) { myModule->sketchReentranceMgr()->updateInternalEditActiveState(); return; @@ -370,7 +339,7 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE return; bool isSketcher = isSketchOperation(aFOperation); - bool isSketchOpe = isNestedSketchOperation(aFOperation); + bool isSketchOpe = isNestedSketchOperation(aFOperation, activeSketch()); // Avoid non-sketch operations if ((!isSketchOpe) && (!isSketcher)) @@ -383,10 +352,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()); - } // Remember highlighted objects for editing ModuleBase_ISelection* aSelect = aWorkshop->selection(); @@ -409,6 +374,9 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE myDragDone = false; myPreviousDrawModeEnabled = aViewer->enableDrawMode(false); + // selection should be restored before edit operation start to process the + // selected entities, e.g. selection of point(attribute on a line) should edit the point + restoreSelection(); launchEditing(); if (aFeature.get() != NULL) { std::shared_ptr aSPFeature = @@ -430,14 +398,11 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE myDragDone = false; 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(); + // selection should be restored before edit operation start to process the + // selected entities, e.g. selection of point(attribute on a line) should edit the point + restoreSelection(); launchEditing(); + restoreSelection(); } } } @@ -453,23 +418,11 @@ void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouse return; ModuleBase_Operation* aOp = getCurrentOperation(); if (aOp) { - if (isNestedSketchOperation(aOp)) { - //get2dPoint(theWnd, theEvent, myClickedPoint); - + if (isNestedSketchOperation(aOp, activeSketch())) { // Only for sketcher operations if (myIsDragging) { if (myDragDone) { - //aOp->commit(); myCurrentSelection.clear(); - /*Handle(AIS_InteractiveContext) aContext = aViewer->AISContext(); - if (!aContext.IsNull()) { - // Reselect edited object - aContext->MoveTo(theEvent->x(), theEvent->y(), theWnd->v3dView()); - if (theEvent->modifiers() & Qt::ShiftModifier) - aContext->ShiftSelect(); - else - aContext->Select(); - */ } } } @@ -477,6 +430,11 @@ void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouse aWorkshop->viewer()->enableDrawMode(myPreviousDrawModeEnabled); myIsDragging = false; + + ModuleBase_ModelWidget* anActiveWidget = getActiveWidget(); + PartSet_MouseProcessor* aProcessor = dynamic_cast(anActiveWidget); + if (aProcessor) + aProcessor->mouseReleased(theWnd, theEvent); } void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) @@ -484,31 +442,27 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve if (myModule->sketchReentranceMgr()->processMouseMoved(theWnd, theEvent)) return; - if (isNestedCreateOperation(getCurrentOperation()) && !myIsMouseOverViewProcessed) { - myIsMouseOverViewProcessed = true; + if (isNestedCreateOperation(getCurrentOperation(), activeSketch())) { // 1. perform the widget mouse move functionality and display the presentation // the mouse move should be processed in the widget, if it can in order to visualize correct // presentation. These widgets correct the feature attribute according to the mouse position - ModuleBase_ModelWidget* anActiveWidget = getActiveWidget(); - PartSet_WidgetPoint2D* aPoint2DWdg = dynamic_cast(anActiveWidget); - if (aPoint2DWdg) { - aPoint2DWdg->onMouseMove(theWnd, theEvent); - } - PartSet_WidgetPoint2dDistance* aDistanceWdg = dynamic_cast - (anActiveWidget); - if (aDistanceWdg) { - aDistanceWdg->onMouseMove(theWnd, theEvent); - } - // the feature is to be erased here, but it is correct to call canDisplayObject because - // there can be additional check (e.g. editor widget in distance constraint) - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (getCurrentOperation()); - if (aFOperation) { - FeaturePtr aFeature = aFOperation->feature(); - visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature)); + ModuleBase_ModelWidget* anActiveWidget = myModule->activeWidget(); + PartSet_MouseProcessor* aProcessor = dynamic_cast(anActiveWidget); + if (aProcessor) + aProcessor->mouseMoved(theWnd, theEvent); + if (!myIsMouseOverViewProcessed) { + myIsMouseOverViewProcessed = true; + + // the feature is to be erased here, but it is correct to call canDisplayObject because + // there can be additional check (e.g. editor widget in distance constraint) + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getCurrentOperation()); + if (aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); + visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature)); + } } } - //myClickedPoint.clear(); if (myIsDragging) { @@ -613,7 +567,8 @@ void PartSet_SketcherMgr::onMouseDoubleClick(ModuleBase_IViewWindow* theWnd, QMo QList aWidgets = aPanel->modelWidgets(); // Find corresponded widget to activate value editing foreach (ModuleBase_ModelWidget* aWgt, aWidgets) { - if (aWgt->attributeID() == "ConstraintValue") { + if (aWgt->attributeID() == SketchPlugin_Constraint::VALUE() || + aWgt->attributeID() == SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()) { PartSet_WidgetEditor* anEditor = dynamic_cast(aWgt); if (anEditor) anEditor->showPopupEditor(); @@ -695,7 +650,7 @@ void PartSet_SketcherMgr::launchEditing() FeaturePtr aFeature = myCurrentSelection.begin().key(); std::shared_ptr aSPFeature = std::dynamic_pointer_cast(aFeature); - if (aSPFeature) { + if (aSPFeature && (!aSPFeature->isExternal())) { myModule->editFeature(aSPFeature); } } @@ -714,16 +669,17 @@ bool PartSet_SketcherMgr::sketchSolverError() QString PartSet_SketcherMgr::getFeatureError(const FeaturePtr& theFeature) { - QString anError = ""; + std::string anError = ""; if (!theFeature.get() || !theFeature->data()->isValid()) - return anError; + return anError.c_str(); CompositeFeaturePtr aSketch = activeSketch(); if (aSketch.get() && aSketch == theFeature) { AttributeStringPtr aAttributeString = aSketch->string(SketchPlugin_Sketch::SOLVER_ERROR()); - anError = aAttributeString->value().c_str(); + anError = aAttributeString->value(); + ModuleBase_Tools::translate(aSketch->getKind(), anError); } - return anError; + return anError.c_str(); } void PartSet_SketcherMgr::clearClickedFlags() @@ -732,47 +688,37 @@ void PartSet_SketcherMgr::clearClickedFlags() myCurrentPoint.clear(); } -const QStringList& PartSet_SketcherMgr::sketchOperationIdList() +const QStringList& PartSet_SketcherMgr::replicationsIdList() { - static QStringList aIds; - if (aIds.size() == 0) { - aIds << SketchPlugin_Line::ID().c_str(); - aIds << SketchPlugin_Point::ID().c_str(); - aIds << SketchPlugin_Arc::ID().c_str(); - aIds << SketchPlugin_Circle::ID().c_str(); - aIds << SketchPlugin_ConstraintFillet::ID().c_str(); - aIds << SketchPlugin_IntersectionPoint::ID().c_str(); - // TODO - // SketchRectangle is a python feature, so its ID is passed just as a string - aIds << "SketchRectangle"; - aIds.append(constraintsIdList()); + static QStringList aReplicationIds; + if (aReplicationIds.size() == 0) { + aReplicationIds << SketchPlugin_ConstraintMirror::ID().c_str(); + aReplicationIds << SketchPlugin_MultiRotation::ID().c_str(); + aReplicationIds << SketchPlugin_MultiTranslation::ID().c_str(); } - return aIds; + return aReplicationIds; } const QStringList& PartSet_SketcherMgr::constraintsIdList() { - static QStringList aIds; - if (aIds.size() == 0) { - aIds << SketchPlugin_ConstraintLength::ID().c_str(); - aIds << SketchPlugin_ConstraintDistance::ID().c_str(); - aIds << SketchPlugin_ConstraintRigid::ID().c_str(); - aIds << SketchPlugin_ConstraintRadius::ID().c_str(); - aIds << SketchPlugin_ConstraintPerpendicular::ID().c_str(); - aIds << SketchPlugin_ConstraintParallel::ID().c_str(); - aIds << SketchPlugin_ConstraintHorizontal::ID().c_str(); - aIds << SketchPlugin_ConstraintVertical::ID().c_str(); - aIds << SketchPlugin_ConstraintEqual::ID().c_str(); - aIds << SketchPlugin_ConstraintTangent::ID().c_str(); - aIds << SketchPlugin_ConstraintCoincidence::ID().c_str(); - aIds << SketchPlugin_ConstraintMirror::ID().c_str(); - aIds << SketchPlugin_ConstraintAngle::ID().c_str(); - aIds << SketchPlugin_MultiRotation::ID().c_str(); - aIds << SketchPlugin_MultiTranslation::ID().c_str(); - aIds << SketchPlugin_ConstraintCollinear::ID().c_str(); - aIds << SketchPlugin_ConstraintMiddle::ID().c_str(); + static QStringList aConstraintIds; + if (aConstraintIds.size() == 0) { + aConstraintIds << SketchPlugin_ConstraintLength::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintDistance::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintRigid::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintRadius::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintPerpendicular::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintParallel::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintHorizontal::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintVertical::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintEqual::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintTangent::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintCoincidence::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintAngle::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintCollinear::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintMiddle::ID().c_str(); } - return aIds; + return aConstraintIds; } void PartSet_SketcherMgr::sketchSelectionModes(QIntList& theModes) @@ -802,24 +748,38 @@ bool PartSet_SketcherMgr::isSketchOperation(ModuleBase_Operation* theOperation) return theOperation && theOperation->id().toStdString() == SketchPlugin_Sketch::ID(); } -bool PartSet_SketcherMgr::isNestedSketchOperation(ModuleBase_Operation* theOperation) +bool PartSet_SketcherMgr::isNestedSketchOperation(ModuleBase_Operation* theOperation, + const CompositeFeaturePtr& theSketch) { - return theOperation && - PartSet_SketcherMgr::sketchOperationIdList().contains(theOperation->id()); + bool aNestedSketch = false; + + if (theOperation && theSketch.get()) { + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (theOperation); + if (aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); + aNestedSketch = theSketch->isSub(aFeature); + } + } + return aNestedSketch; } -bool PartSet_SketcherMgr::isNestedCreateOperation(ModuleBase_Operation* theOperation) +bool PartSet_SketcherMgr::isNestedCreateOperation(ModuleBase_Operation* theOperation, + const CompositeFeaturePtr& theSketch) { ModuleBase_OperationFeature* aFOperation = dynamic_cast (theOperation); - return aFOperation && !aFOperation->isEditOperation() && isNestedSketchOperation(aFOperation); + return aFOperation && !aFOperation->isEditOperation() && + isNestedSketchOperation(aFOperation, theSketch); } -bool PartSet_SketcherMgr::isNestedEditOperation(ModuleBase_Operation* theOperation) +bool PartSet_SketcherMgr::isNestedEditOperation(ModuleBase_Operation* theOperation, + const CompositeFeaturePtr& theSketch) { ModuleBase_OperationFeature* aFOperation = dynamic_cast (theOperation); - return aFOperation && aFOperation->isEditOperation() && isNestedSketchOperation(aFOperation); + return aFOperation && aFOperation->isEditOperation() && + isNestedSketchOperation(aFOperation, theSketch); } bool PartSet_SketcherMgr::isEntity(const std::string& theId) @@ -857,7 +817,6 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation) // Display all sketcher sub-Objects myCurrentSketch = std::dynamic_pointer_cast(aFOperation->feature()); XGUI_ModuleConnector* aConnector = dynamic_cast(myModule->workshop()); - aConnector->workshop()->displayer()->activateTrihedron(true); // Hide sketcher result std::list aResults = myCurrentSketch->results(); @@ -867,9 +826,50 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation) } myCurrentSketch->setDisplayed(false); + // Remove invalid sketch entities + std::set anInvalidFeatures; + ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators(); + for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) { + FeaturePtr aFeature = myCurrentSketch->subFeature(i); + if (aFeature.get()) { + if (!aFactory->validate(aFeature)) + anInvalidFeatures.insert(aFeature); + } + } + if (!anInvalidFeatures.empty()) { + std::map > aReferences; + ModelAPI_Tools::findAllReferences(anInvalidFeatures, aReferences, false); + + std::set::const_iterator anIt = anInvalidFeatures.begin(), + aLast = anInvalidFeatures.end(); + // separate features to references to parameter features and references to others + QStringList anInvalidFeatureNames; + for (; anIt != aLast; anIt++) { + FeaturePtr aFeature = *anIt; + if (aFeature.get()) + anInvalidFeatureNames.append(aFeature->name().c_str()); + } + std::string aPrefixInfo = QString("Invalid features of the sketch will be deleted: %1.\n\n"). + arg(anInvalidFeatureNames.join(", ")).toStdString().c_str(); + std::set aFeatureRefsToDelete; + if (ModuleBase_Tools::askToDelete(anInvalidFeatures, aReferences, aConnector->desktop(), + aFeatureRefsToDelete, aPrefixInfo)) { + if (!aFeatureRefsToDelete.empty()) + anInvalidFeatures.insert(aFeatureRefsToDelete.begin(), aFeatureRefsToDelete.end()); + ModelAPI_Tools::removeFeatures(anInvalidFeatures, true); + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); + // TODO: call the next method in the XGUI_OperationMgr::onOperationStarted(). + workshop()->errorMgr()->updateAcceptAllAction(myCurrentSketch); + } + } + // Display sketcher objects + QStringList anInfo; for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) { FeaturePtr aFeature = myCurrentSketch->subFeature(i); +#ifdef DEBUG_SKETCHER_ENTITIES + anInfo.append(ModuleBase_Tools::objectInfo(aFeature)); +#endif std::list aResults = aFeature->results(); std::list::const_iterator aIt; for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { @@ -877,6 +877,10 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation) } aFeature->setDisplayed(true); } +#ifdef DEBUG_SKETCHER_ENTITIES + QString anInfoStr = anInfo.join(";\t"); + qDebug(QString("startSketch: %1, %2").arg(anInfo.size()).arg(anInfoStr).toStdString().c_str()); +#endif if(myCirclePointFilter.IsNull()) { myCirclePointFilter = new PartSet_CirclePointFilter(myModule->workshop()); @@ -890,18 +894,13 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation) myModule->workshop()->viewer()->addSelectionFilter(myPlaneFilter); bool aHasPlane = false; std::shared_ptr aPln; - if (aFOperation->isEditOperation()) { - // If it is editing of sketch then it means that plane is already defined - aPln = PartSet_Tools::sketchPlane(myCurrentSketch); - if (aPln.get()) - aHasPlane = true; - } + aPln = PartSet_Tools::sketchPlane(myCurrentSketch); myPlaneFilter->setPlane(aPln); Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); - // all sketch objects should be activated in the sketch selection modes by edit operation start - // in case of creation operation, there is an active widget, which activates own selection mode - if (aFOperation->isEditOperation() && aHasPlane) + // all displayed objects should be activated in current selection modes according to switched + // plane filter + if (aPln.get()) aConnector->activateModuleSelectionModes(); } @@ -924,7 +923,6 @@ void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation) myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter); // Erase all sketcher objects - QStringList aSketchIds = sketchOperationIdList(); QObjectPtrList aObjects = aDisplayer->displayedObjects(); foreach (ObjectPtr aObj, aObjects) { DataPtr aObjData = aObj->data(); @@ -971,7 +969,6 @@ void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation) } // restore the module selection modes, which were changed on startSketch aConnector->activateModuleSelectionModes(); - aConnector->workshop()->displayer()->activateTrihedron(false); } void PartSet_SketcherMgr::startNestedSketch(ModuleBase_Operation* theOperation) @@ -997,11 +994,16 @@ 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 + // if the operation is restarted, the previous selection is used to initialize started operation + if (!myModule->sketchReentranceMgr()->isInternalEditStarted()) + workshop()->selector()->clearSelection(); } void PartSet_SketcherMgr::commitNestedSketch(ModuleBase_Operation* theOperation) { - if (isNestedCreateOperation(theOperation)) { + if (isNestedCreateOperation(theOperation, activeSketch())) { ModuleBase_OperationFeature* aFOperation = dynamic_cast (theOperation); if (aFOperation) { @@ -1027,7 +1029,7 @@ bool PartSet_SketcherMgr::operationActivatedByPreselection() { bool isOperationStopped = false; ModuleBase_Operation* anOperation = getCurrentOperation(); - if(anOperation && PartSet_SketcherMgr::isNestedSketchOperation(anOperation)) { + if(anOperation && PartSet_SketcherMgr::isNestedSketchOperation(anOperation, activeSketch())) { // Set final definitions if they are necessary //propertyPanelDefined(aOperation); /// Commit sketcher operations automatically @@ -1036,8 +1038,12 @@ bool PartSet_SketcherMgr::operationActivatedByPreselection() bool aCanCommitOperation = true; ModuleBase_OperationFeature* aFOperation = dynamic_cast (anOperation); - if (aFOperation && PartSet_SketcherMgr::isDistanceOperation(aFOperation)) - aCanCommitOperation = setDistanceValueByPreselection(anOperation, myModule->workshop()); + if (aFOperation && PartSet_SketcherMgr::isDistanceOperation(aFOperation)) { + bool aValueAccepted = setDistanceValueByPreselection(anOperation, myModule->workshop(), + aCanCommitOperation); + if (!aValueAccepted) + return isOperationStopped; + } if (aCanCommitOperation) isOperationStopped = anOperation->commit(); @@ -1051,12 +1057,12 @@ bool PartSet_SketcherMgr::operationActivatedByPreselection() bool PartSet_SketcherMgr::canUndo() const { - return isNestedCreateOperation(getCurrentOperation()); + return isNestedCreateOperation(getCurrentOperation(), activeSketch()); } bool PartSet_SketcherMgr::canRedo() const { - return isNestedCreateOperation(getCurrentOperation()); + return isNestedCreateOperation(getCurrentOperation(), activeSketch()); } bool PartSet_SketcherMgr::canEraseObject(const ObjectPtr& theObject) const @@ -1094,6 +1100,11 @@ bool PartSet_SketcherMgr::canDisplayObject(const ObjectPtr& theObject) const if (aFeature.get() != NULL && aFeature == activeSketch()) { aCanDisplay = false; } + std::shared_ptr aSketchFeature = + std::dynamic_pointer_cast(aFeature); + /// some sketch entities should be never shown, e.g. projection feature + if (aSketchFeature.get()) + aCanDisplay = aSketchFeature->canBeDisplayed(); } else { // there are no an active sketch // 2. sketch sub-features should not be visualized if the sketch operation is not active @@ -1109,43 +1120,45 @@ bool PartSet_SketcherMgr::canDisplayObject(const ObjectPtr& theObject) const // 3. the method should not filter the objects, which are not related to the current operation. // The object is filtered just if it is a current operation feature or this feature result - bool isObjectFound = false; - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (getCurrentOperation()); - if (aFOperation) { - FeaturePtr aFeature = aFOperation->feature(); - if (aFeature.get()) { - std::list aResults = aFeature->results(); - if (theObject == aFeature) - isObjectFound = true; - else { - std::list::const_iterator anIt = aResults.begin(), aLast = aResults.end(); - for (; anIt != aLast && !isObjectFound; anIt++) { - isObjectFound = *anIt == theObject; + if (aCanDisplay) { + bool isObjectFound = false; + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getCurrentOperation()); + if (aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); + if (aFeature.get()) { + std::list aResults = aFeature->results(); + if (theObject == aFeature) + isObjectFound = true; + else { + std::list::const_iterator anIt = aResults.begin(), aLast = aResults.end(); + for (; anIt != aLast && !isObjectFound; anIt++) { + isObjectFound = *anIt == theObject; + } } } } - } - if (isObjectFound) { - // 4. For created nested feature operation do not display the created feature if - // the mouse curstor leaves the OCC window. - // The correction cases, which ignores this condition: - // a. the property panel values modification - // b. the popup menu activated - // c. widget editor control - #ifndef DEBUG_DO_NOT_BY_ENTER - if (aCanDisplay && isNestedCreateOperation(getCurrentOperation())) { - ModuleBase_ModelWidget* anActiveWidget = getActiveWidget(); - ModuleBase_WidgetEditor* anEditorWdg = anActiveWidget ? dynamic_cast(anActiveWidget) : 0; - // the active widget editor should not influence here. The presentation should be visible always - // when this widget is active. - if (!anEditorWdg && !myIsPopupMenuActive) { - // during a nested create operation, the feature is redisplayed only if the mouse over view - // of there was a value modified in the property panel after the mouse left the view - aCanDisplay = canDisplayCurrentCreatedFeature(); + if (isObjectFound) { + // 4. For created nested feature operation do not display the created feature if + // the mouse curstor leaves the OCC window. + // The correction cases, which ignores this condition: + // a. the property panel values modification + // b. the popup menu activated + // c. widget editor control + #ifndef DEBUG_DO_NOT_BY_ENTER + if (isNestedCreateOperation(getCurrentOperation(), activeSketch())) { + ModuleBase_ModelWidget* anActiveWidget = getActiveWidget(); + ModuleBase_WidgetEditor* anEditorWdg = anActiveWidget ? dynamic_cast(anActiveWidget) : 0; + // the active widget editor should not influence here. The presentation should be visible always + // when this widget is active. + if (!anEditorWdg && !myIsPopupMenuActive) { + // during a nested create operation, the feature is redisplayed only if the mouse over view + // of there was a value modified in the property panel after the mouse left the view + aCanDisplay = canDisplayCurrentCreatedFeature(); + } } + #endif } - #endif } // checks the sketcher constraints visibility according to active sketch check box states @@ -1207,7 +1220,7 @@ bool PartSet_SketcherMgr::canDisplayConstraint(const FeaturePtr& theFeature, return aSwitchedOn; } -void PartSet_SketcherMgr::processHiddenObject(const std::list& theObjects) +/*void PartSet_SketcherMgr::processHiddenObject(const std::list& theObjects) { ModuleBase_OperationFeature* aFOperation = dynamic_cast (getCurrentOperation()); @@ -1283,7 +1296,7 @@ will be hidden: %1. Would you like to delete them?") } } } -} +}*/ bool PartSet_SketcherMgr::canDisplayCurrentCreatedFeature() const { @@ -1298,7 +1311,7 @@ bool PartSet_SketcherMgr::canDisplayCurrentCreatedFeature() const bool PartSet_SketcherMgr::canChangeCursor(ModuleBase_Operation* theOperation) const { - return isNestedCreateOperation(theOperation) || + return isNestedCreateOperation(theOperation, activeSketch()) || myModule->sketchReentranceMgr()->isInternalEditActive(); } @@ -1331,9 +1344,11 @@ void PartSet_SketcherMgr::onPlaneSelected(const std::shared_ptr& th } bool PartSet_SketcherMgr::setDistanceValueByPreselection(ModuleBase_Operation* theOperation, - ModuleBase_IWorkshop* theWorkshop) + ModuleBase_IWorkshop* theWorkshop, + bool& theCanCommitOperation) { bool isValueAccepted = false; + theCanCommitOperation = false; ModuleBase_OperationFeature* aFOperation = dynamic_cast (theOperation); @@ -1395,6 +1410,7 @@ bool PartSet_SketcherMgr::setDistanceValueByPreselection(ModuleBase_Operation* t } anEditor->setCursorPosition(aX, anY); isValueAccepted = anEditor->showPopupEditor(false); + theCanCommitOperation = true; } } } @@ -1403,54 +1419,6 @@ bool PartSet_SketcherMgr::setDistanceValueByPreselection(ModuleBase_Operation* t return isValueAccepted; } -void PartSet_SketcherMgr::getCurrentSelection(const FeaturePtr& theFeature, - const FeaturePtr& theSketch, - ModuleBase_IWorkshop* theWorkshop, - FeatureToSelectionMap& theSelection) -{ - if (theFeature.get() == NULL) - return; - - std::set aSelectedAttributes; - std::set aSelectedResults; - - ModuleBase_IViewer* aViewer = theWorkshop->viewer(); - Handle(AIS_InteractiveContext) aContext = aViewer->AISContext(); - if (!aContext.IsNull()) { - XGUI_ModuleConnector* aConnector = dynamic_cast(theWorkshop); - XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); - - std::list aResults = theFeature->results(); - std::list::const_iterator aIt; - for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) - { - ResultPtr aResult = *aIt; - AISObjectPtr aAISObj = aDisplayer->getAISObject(aResult); - if (aAISObj.get() == NULL) - continue; - Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl(); - for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected()) - { - Handle(SelectMgr_EntityOwner) anOwner = aContext->SelectedOwner(); - if (anOwner->Selectable() != anAISIO) - continue; - getAttributesOrResults(anOwner, theFeature, theSketch, aResult, - aSelectedAttributes, aSelectedResults); - } - for (aContext->InitDetected(); aContext->MoreDetected(); aContext->NextDetected()) { - Handle(SelectMgr_EntityOwner) anOwner = aContext->DetectedOwner(); - if (anOwner.IsNull()) - continue; - if (anOwner->Selectable() != anAISIO) - continue; - getAttributesOrResults(anOwner, theFeature, theSketch, aResult, - aSelectedAttributes, aSelectedResults); - } - } - } - theSelection[theFeature] = std::make_pair(aSelectedAttributes, aSelectedResults); -} - void PartSet_SketcherMgr::getSelectionOwners(const FeaturePtr& theFeature, const FeaturePtr& theSketch, ModuleBase_IWorkshop* theWorkshop, @@ -1541,7 +1509,7 @@ void PartSet_SketcherMgr::widgetStateChanged(int thePreviousState) (getCurrentOperation()); if (aFOperation) { if (PartSet_SketcherMgr::isSketchOperation(aFOperation) || - PartSet_SketcherMgr::isNestedSketchOperation(aFOperation) && + PartSet_SketcherMgr::isNestedSketchOperation(aFOperation, activeSketch()) && thePreviousState == ModuleBase_ModelWidget::ModifiedInPP) { FeaturePtr aFeature = aFOperation->feature(); visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature)); @@ -1554,8 +1522,20 @@ void PartSet_SketcherMgr::customizePresentation(const ObjectPtr& theObject) ModuleBase_OperationFeature* aFOperation = dynamic_cast (getCurrentOperation()); if (aFOperation && (PartSet_SketcherMgr::isSketchOperation(aFOperation) || - PartSet_SketcherMgr::isNestedSketchOperation(aFOperation))) + PartSet_SketcherMgr::isNestedSketchOperation(aFOperation, activeSketch()))) 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 @@ -1621,24 +1601,58 @@ void PartSet_SketcherMgr::storeSelection(const bool theHighlightedOnly) ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); ModuleBase_ISelection* aSelect = aWorkshop->selection(); - QList aHighlighted = aSelect->getHighlighted(); + QList aStoredPrs = aSelect->getHighlighted(); QList aFeatureList; - if (theHighlightedOnly) { - fillFeatureList(aHighlighted, myCurrentSketch, aFeatureList); - } - else { - fillFeatureList(aHighlighted, myCurrentSketch, aFeatureList); - - QList aSelected = aSelect->getSelected(ModuleBase_ISelection::AllControls); - fillFeatureList(aSelected, myCurrentSketch, aFeatureList); + if (!theHighlightedOnly) { + QList aSelected = aSelect->getSelected( + ModuleBase_ISelection::AllControls); + aStoredPrs.append(aSelected); } // 1. it is necessary to save current selection in order to restore it after the features moving myCurrentSelection.clear(); - QList::const_iterator anIt = aFeatureList.begin(), aLast = aFeatureList.end(); + + QList::const_iterator anIt = aStoredPrs.begin(), aLast = aStoredPrs.end(); + + CompositeFeaturePtr aSketch = activeSketch(); for (; anIt != aLast; anIt++) { - getCurrentSelection(*anIt, myCurrentSketch, aWorkshop, myCurrentSelection); + ModuleBase_ViewerPrsPtr aPrs = *anIt; + ObjectPtr anObject = aPrs->object(); + if (!anObject.get()) + continue; + + ResultPtr aResult = std::dynamic_pointer_cast(anObject); + FeaturePtr aFeature; + if (aResult.get()) + aFeature = ModelAPI_Feature::feature(aResult); + else + aFeature = std::dynamic_pointer_cast(anObject); + + + std::set aSelectedAttributes; + std::set aSelectedResults; + if (myCurrentSelection.find(aFeature) != myCurrentSelection.end()) { + std::pair, std::set > aPair = myCurrentSelection.find(aFeature).value(); + aSelectedAttributes = aPair.first; + aSelectedResults = aPair.second; + } + + Handle(SelectMgr_EntityOwner) anOwner = aPrs->owner(); + if (aResult.get()) { + getAttributesOrResults(anOwner, aFeature, aSketch, aResult, + aSelectedAttributes, aSelectedResults); + } + else { + std::list aResults = aFeature->results(); + std::list::const_iterator aIt; + for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { + ResultPtr aResult = *aIt; + getAttributesOrResults(anOwner, aFeature, aSketch, aResult, + aSelectedAttributes, aSelectedResults); + } + } + myCurrentSelection[aFeature] = std::make_pair(aSelectedAttributes, aSelectedResults); } //qDebug(QString(" storeSelection: %1").arg(myCurrentSelection.size()).toStdString().c_str()); } @@ -1697,15 +1711,64 @@ void PartSet_SketcherMgr::updateBySketchParameters( } break; case PartSet_Tools::Expressions: { - /// call all sketch features redisplay, the expression state will be corrected in customize - /// of distance presentation - Events_ID anEventId = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); - PartSet_Tools::sendSubFeaturesEvent(myCurrentSketch, anEventId); + if (aPrevState != theState) { + /// call all sketch features redisplay, the expression state will be corrected in customize + /// of distance presentation + Events_ID anEventId = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); + PartSet_Tools::sendSubFeaturesEvent(myCurrentSketch, anEventId); + } } break; } } +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();