X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2FPartSet%2FPartSet_SketcherMgr.cpp;h=a46d07f9d7413038f82e3b2086aca17e33aaa3e0;hb=023c72db1a0c06efe73559cc2ff37c841842823a;hp=a90f4a0f8aca8d201aae48aefc8ded020b247d63;hpb=868158fe6d39b25e60ac528295b1c908821e4af5;p=modules%2Fshaper.git diff --git a/src/PartSet/PartSet_SketcherMgr.cpp b/src/PartSet/PartSet_SketcherMgr.cpp index a90f4a0f8..a46d07f9d 100755 --- a/src/PartSet/PartSet_SketcherMgr.cpp +++ b/src/PartSet/PartSet_SketcherMgr.cpp @@ -7,11 +7,11 @@ #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" +#include "PartSet_ResultSketchPrs.h" #include #include @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include @@ -34,6 +36,9 @@ #include #include #include +#include +#include +#include #include @@ -58,8 +63,11 @@ #include #include #include +#include +#include #include #include +#include #include @@ -68,57 +76,26 @@ //#include #include +#include #include #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. @@ -158,7 +135,7 @@ PartSet_SketcherMgr::PartSet_SketcherMgr(PartSet_Module* theModule) : QObject(theModule), myModule(theModule), myIsDragging(false), myDragDone(false), myIsMouseOverWindow(false), myIsMouseOverViewProcessed(true), myPreviousUpdateViewerEnabled(true), - myIsPopupMenuActive(false), myIsConstraintsShown(true) + myIsPopupMenuActive(false) { ModuleBase_IWorkshop* anIWorkshop = myModule->workshop(); ModuleBase_IViewer* aViewer = anIWorkshop->viewer(); @@ -180,6 +157,10 @@ PartSet_SketcherMgr::PartSet_SketcherMgr(PartSet_Module* theModule) XGUI_ModuleConnector* aConnector = dynamic_cast(anIWorkshop); XGUI_Workshop* aWorkshop = aConnector->workshop(); connect(aWorkshop, SIGNAL(applicationStarted()), this, SLOT(onApplicationStarted())); + + myIsConstraintsShown[PartSet_Tools::Geometrical] = true; + myIsConstraintsShown[PartSet_Tools::Dimensional] = true; + myIsConstraintsShown[PartSet_Tools::Expressions] = false; } PartSet_SketcherMgr::~PartSet_SketcherMgr() @@ -210,7 +191,7 @@ void PartSet_SketcherMgr::onEnterViewPort() } } - if (!isNestedCreateOperation(getCurrentOperation())) + if (!isNestedCreateOperation(getCurrentOperation(), activeSketch())) return; operationMgr()->onValidateOperation(); @@ -235,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; @@ -250,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, @@ -258,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 @@ -287,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 @@ -301,9 +281,11 @@ void PartSet_SketcherMgr::onBeforeValuesChangedInPropertyPanel() void PartSet_SketcherMgr::onAfterValuesChangedInPropertyPanel() { - if (!isNestedEditOperation(getCurrentOperation()) || - myModule->sketchReentranceMgr()->isInternalEditActive()) + if (!isNestedEditOperation(getCurrentOperation(), myModule->sketchMgr()->activeSketch()) || + myModule->sketchReentranceMgr()->isInternalEditActive()) { + myModule->sketchReentranceMgr()->updateInternalEditActiveState(); return; + } // it is necessary to restore current selection in order to restore it after the values are modified restoreSelection(); myCurrentSelection.clear(); @@ -316,6 +298,8 @@ void PartSet_SketcherMgr::onAfterValuesChangedInPropertyPanel() XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); aDisplayer->enableUpdateViewer(myPreviousUpdateViewerEnabled); aDisplayer->updateViewer(); + + } void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) @@ -355,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)) @@ -368,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(); @@ -392,8 +372,11 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE myIsDragging = true; get2dPoint(theWnd, theEvent, myCurrentPoint); myDragDone = false; - // TODO: Has to be uncommented when SALOME patch on draw mode become avialable + 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 = @@ -413,12 +396,13 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE myIsDragging = true; get2dPoint(theWnd, theEvent, myCurrentPoint); myDragDone = false; - // TODO: Has to be uncommented when SALOME patch on draw mode become avialable - myPreviousDrawModeEnabled = aViewer->enableDrawMode(false); - // This is necessary in order to finalize previous operation - QApplication::processEvents(); + 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(); + restoreSelection(); } } } @@ -434,31 +418,23 @@ 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(); - */ } } } } - // TODO: Has to be uncommented when SALOME patch on draw mode become avialable + aWorkshop->viewer()->enableDrawMode(myPreviousDrawModeEnabled); - //aWorkshop->viewer()->enableSelection(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) @@ -466,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) { @@ -499,10 +471,6 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve // mouse press signal in the viewer(it call Select for AIS context and the dragged objects are // deselected). This flag should be restored in the slot, processed the mouse release signal. - // TODO: Has to be commented out when SALOME patch on draw mode become avialable - //ModuleBase_IViewer* aViewer = myModule->workshop()->viewer(); - //aViewer->enableSelection(false); - ModuleBase_Operation* aCurrentOperation = getCurrentOperation(); if (!aCurrentOperation) return; @@ -599,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(); @@ -681,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); } } @@ -700,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() @@ -718,41 +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.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(); + 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) @@ -766,29 +732,54 @@ void PartSet_SketcherMgr::sketchSelectionModes(QIntList& theModes) theModes.append(TopAbs_EDGE); } +Handle(AIS_InteractiveObject) PartSet_SketcherMgr::createPresentation(const ResultPtr& theResult) +{ + Handle(AIS_InteractiveObject) aPrs; + + FeaturePtr aFeature = ModelAPI_Feature::feature(theResult); + if (aFeature.get() && aFeature->getKind() == SketchPlugin_Sketch::ID()) { + aPrs = new PartSet_ResultSketchPrs(theResult); + } + return aPrs; +} + 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) @@ -801,12 +792,17 @@ bool PartSet_SketcherMgr::isEntity(const std::string& theId) bool PartSet_SketcherMgr::isDistanceOperation(ModuleBase_Operation* theOperation) { - std::string aId = theOperation ? theOperation->id().toStdString() : ""; + std::string anId = theOperation ? theOperation->id().toStdString() : ""; - return (aId == SketchPlugin_ConstraintLength::ID()) || - (aId == SketchPlugin_ConstraintDistance::ID()) || - (aId == SketchPlugin_ConstraintRadius::ID()) || - (aId == SketchPlugin_ConstraintAngle::ID()); + return isDistanceKind(anId); +} + +bool PartSet_SketcherMgr::isDistanceKind(std::string& theKind) +{ + return (theKind == SketchPlugin_ConstraintLength::ID()) || + (theKind == SketchPlugin_ConstraintDistance::ID()) || + (theKind == SketchPlugin_ConstraintRadius::ID()) || + (theKind == SketchPlugin_ConstraintAngle::ID()); } void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation) @@ -821,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(); @@ -831,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) { @@ -841,33 +877,39 @@ 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()); + } + + myModule->workshop()->viewer()->addSelectionFilter(myCirclePointFilter); if (myPlaneFilter.IsNull()) myPlaneFilter = new ModuleBase_ShapeInPlaneFilter(); 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(); } void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation) { myIsMouseOverWindow = false; - myIsConstraintsShown = true; + myIsConstraintsShown[PartSet_Tools::Geometrical] = true; + myIsConstraintsShown[PartSet_Tools::Dimensional] = true; + myIsConstraintsShown[PartSet_Tools::Expressions] = false; XGUI_ModuleConnector* aConnector = dynamic_cast(myModule->workshop()); @@ -876,10 +918,11 @@ void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation) XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); // The sketch was aborted myCurrentSketch = CompositeFeaturePtr(); + // TODO: move this outside of if-else + myModule->workshop()->viewer()->removeSelectionFilter(myCirclePointFilter); myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter); // Erase all sketcher objects - QStringList aSketchIds = sketchOperationIdList(); QObjectPtrList aObjects = aDisplayer->displayedObjects(); foreach (ObjectPtr aObj, aObjects) { DataPtr aObjData = aObj->data(); @@ -918,13 +961,14 @@ void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation) myCurrentSketch->setDisplayed(true); myCurrentSketch = CompositeFeaturePtr(); + + myModule->workshop()->viewer()->removeSelectionFilter(myCirclePointFilter); myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter); Events_Loop::loop()->flush(aDispEvent); } // restore the module selection modes, which were changed on startSketch aConnector->activateModuleSelectionModes(); - aConnector->workshop()->displayer()->activateTrihedron(false); } void PartSet_SketcherMgr::startNestedSketch(ModuleBase_Operation* theOperation) @@ -950,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) { @@ -968,14 +1017,52 @@ void PartSet_SketcherMgr::commitNestedSketch(ModuleBase_Operation* theOperation) } } +void PartSet_SketcherMgr::activatePlaneFilter(const bool& toActivate) +{ + if (toActivate) + myModule->workshop()->viewer()->addSelectionFilter(myPlaneFilter); + else + myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter); +} + +bool PartSet_SketcherMgr::operationActivatedByPreselection() +{ + bool isOperationStopped = false; + ModuleBase_Operation* anOperation = getCurrentOperation(); + if(anOperation && PartSet_SketcherMgr::isNestedSketchOperation(anOperation, activeSketch())) { + // Set final definitions if they are necessary + //propertyPanelDefined(aOperation); + /// Commit sketcher operations automatically + /// distance operation are able to show popup editor to modify the distance value + /// after entering the value, the operation should be committed/aborted(by Esc key) + bool aCanCommitOperation = true; + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (anOperation); + if (aFOperation && PartSet_SketcherMgr::isDistanceOperation(aFOperation)) { + bool aValueAccepted = setDistanceValueByPreselection(anOperation, myModule->workshop(), + aCanCommitOperation); + if (!aValueAccepted) + return isOperationStopped; + } + + if (aCanCommitOperation) + isOperationStopped = anOperation->commit(); + else { + anOperation->abort(); + isOperationStopped = true; + } + } + return isOperationStopped; +} + 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 @@ -1013,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 @@ -1028,48 +1120,184 @@ 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 (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 } } - if (!isObjectFound) - return aCanDisplay; - - // 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(); + + // checks the sketcher constraints visibility according to active sketch check box states + if (aCanDisplay) { + bool aProcessed = false; + FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); + if (aFeature.get()) { + bool aConstraintDisplayed = canDisplayConstraint(aFeature, PartSet_Tools::Any, aProcessed); + if (aProcessed) + aCanDisplay = aConstraintDisplayed; } } - #endif + return aCanDisplay; } +bool PartSet_SketcherMgr::canDisplayConstraint(const FeaturePtr& theFeature, + const PartSet_Tools::ConstraintVisibleState& theState, + bool& isProcessed) const +{ + bool aSwitchedOn = true; + + const QStringList& aConstrIds = constraintsIdList(); + + std::string aKind = theFeature->getKind(); + if (aConstrIds.contains(QString(aKind.c_str()))) { + bool isTypedConstraint = false; + + switch (theState) { + case PartSet_Tools::Dimensional: { + bool isDistance = isDistanceKind(aKind); + if (isDistance) { + isProcessed = true; + aSwitchedOn = myIsConstraintsShown[theState]; + } + } + break; + case PartSet_Tools::Geometrical: { + bool isGeometrical = !isDistanceKind(aKind); + if (isGeometrical) { + isProcessed = true; + aSwitchedOn = myIsConstraintsShown[theState]; + } + } + break; + case PartSet_Tools::Any: { + isProcessed = true; + bool isDistance = isDistanceKind(aKind); + if (isDistance) + aSwitchedOn = myIsConstraintsShown[PartSet_Tools::Dimensional]; + else + aSwitchedOn = myIsConstraintsShown[PartSet_Tools::Geometrical]; + } + break; + default: + break; + } + } + return aSwitchedOn; +} + +/*void PartSet_SketcherMgr::processHiddenObject(const std::list& theObjects) +{ + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getCurrentOperation()); + if (aFOperation && myCurrentSketch.get()) { + // find results of the current operation + // these results should not be proposed to be deleted + FeaturePtr anOperationFeature = aFOperation->feature(); + std::list anOperationResultList = anOperationFeature->results(); + std::set anOperationResults; + std::list::const_iterator aRIt = anOperationResultList.begin(), + aRLast = anOperationResultList.end(); + for (; aRIt != aRLast; aRIt++) + anOperationResults.insert(*aRIt); + + std::set anObjectsToBeDeleted; + QStringList anObjectsToBeDeletedNames; + std::list::const_iterator anIt = theObjects.begin(), aLast = theObjects.end(); + for (; anIt != aLast; anIt++) { + ObjectPtr anObject = *anIt; + bool aCanErase = true; + // when the sketch operation is active, results of sketch sub-feature can not be hidden + ResultPtr aResult = std::dynamic_pointer_cast(anObject); + // the result is found between current feature results + if (anOperationResults.find(aResult) != anOperationResults.end()) + continue; + + if (aResult.get()) { + // Display sketcher objects + for (int i = 0; i < myCurrentSketch->numberOfSubs() && aCanErase; i++) { + FeaturePtr aFeature = myCurrentSketch->subFeature(i); + std::list aResults = aFeature->results(); + std::list::const_iterator anIt; + for (anIt = aResults.begin(); anIt != aResults.end() && aCanErase; ++anIt) { + aCanErase = *anIt != aResult; + } + } + } + if (!aCanErase) { + FeaturePtr aFeature = ModelAPI_Feature::feature(anObject); + if (aFeature.get() && anObjectsToBeDeleted.find(aFeature) == anObjectsToBeDeleted.end()) { + anObjectsToBeDeleted.insert(aFeature); + anObjectsToBeDeletedNames.append(aFeature->name().c_str()); + } + } + } + if (!anObjectsToBeDeleted.empty()) { + QString aFeatureNames = anObjectsToBeDeletedNames.join(", "); + QString aMessage = tr("The following features have incorrect presentation and \ +will be hidden: %1. Would you like to delete them?") + .arg(aFeatureNames); + int anAnswer = QMessageBox::question(qApp->activeWindow(), tr("Features hide"), + aMessage, QMessageBox::Ok | QMessageBox::Cancel, + QMessageBox::Cancel); + if (anAnswer == QMessageBox::Ok) { + QObjectPtrList anObjects; + std::set::const_iterator anIt = anObjectsToBeDeleted.begin(), + aLast = anObjectsToBeDeleted.end(); + for (; anIt != aLast; anIt++) + anObjects.append(*anIt); + SessionPtr aMgr = ModelAPI_Session::get(); + DocumentPtr aDoc = aMgr->activeDocument(); + bool aIsOp = aMgr->isOperation(); + if (!aIsOp) + aMgr->startOperation(); + workshop()->deleteFeatures(anObjects); + //static Events_ID aDeletedEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED); + //static Events_ID aRedispEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY); + //Events_Loop::loop()->flush(aDeletedEvent); + //Events_Loop::loop()->flush(aRedispEvent); + + if (!aIsOp) + aMgr->finishOperation(); + } + } + } +}*/ + bool PartSet_SketcherMgr::canDisplayCurrentCreatedFeature() const { bool aCanDisplay = myIsMouseOverWindow; @@ -1083,10 +1311,15 @@ bool PartSet_SketcherMgr::canDisplayCurrentCreatedFeature() const bool PartSet_SketcherMgr::canChangeCursor(ModuleBase_Operation* theOperation) const { - return isNestedCreateOperation(theOperation) || + return isNestedCreateOperation(theOperation, activeSketch()) || myModule->sketchReentranceMgr()->isInternalEditActive(); } +const QMap& PartSet_SketcherMgr::showConstraintStates() +{ + return myIsConstraintsShown; +} + bool PartSet_SketcherMgr::isObjectOfSketch(const ObjectPtr& theObject) const { bool isFoundObject = false; @@ -1110,52 +1343,80 @@ void PartSet_SketcherMgr::onPlaneSelected(const std::shared_ptr& th myPlaneFilter->setPlane(thePln); } -void PartSet_SketcherMgr::getCurrentSelection(const FeaturePtr& theFeature, - const FeaturePtr& theSketch, - ModuleBase_IWorkshop* theWorkshop, - FeatureToSelectionMap& theSelection) +bool PartSet_SketcherMgr::setDistanceValueByPreselection(ModuleBase_Operation* theOperation, + ModuleBase_IWorkshop* theWorkshop, + bool& theCanCommitOperation) { - if (theFeature.get() == NULL) - return; + bool isValueAccepted = false; + theCanCommitOperation = false; - 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); + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (theOperation); + FeaturePtr aFeature = aFOperation->feature(); + // editor is shown only if all attribute references are filled by preseletion + bool anAllRefAttrInitialized = true; + + std::list aRefAttrs = aFeature->data()->attributes( + ModelAPI_AttributeRefAttr::typeId()); + std::list::const_iterator anIt = aRefAttrs.begin(), aLast = aRefAttrs.end(); + for (; anIt != aLast && anAllRefAttrInitialized; anIt++) { + anAllRefAttrInitialized = (*anIt)->isInitialized(); + } + if (anAllRefAttrInitialized) { + // Activate dimension value editing on double click + ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel(); + QList aWidgets = aPanel->modelWidgets(); + // Find corresponded widget to activate value editing + foreach (ModuleBase_ModelWidget* aWgt, aWidgets) { + if (aWgt->attributeID() == "ConstraintValue") { + // the featue should be displayed in order to find the AIS text position, + // the place where the editor will be shown + aFeature->setDisplayed(true); + /// the execute is necessary to perform in the feature compute for flyout position + aFeature->execute(); + + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED)); + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); + + PartSet_WidgetEditor* anEditor = dynamic_cast(aWgt); + if (anEditor) { + int aX = 0, anY = 0; + + XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(theWorkshop); + XGUI_Displayer* aDisplayer = aWorkshop->displayer(); + AISObjectPtr anAIS = aDisplayer->getAISObject(aFeature); + Handle(AIS_InteractiveObject) anAISIO; + if (anAIS.get() != NULL) { + anAISIO = anAIS->impl(); + } + if (anAIS.get() != NULL) { + Handle(AIS_InteractiveObject) anAISIO = anAIS->impl(); + + if (!anAISIO.IsNull()) { + Handle(AIS_Dimension) aDim = Handle(AIS_Dimension)::DownCast(anAISIO); + if (!aDim.IsNull()) { + gp_Pnt aPosition = aDim->GetTextPosition(); + + ModuleBase_IViewer* aViewer = aWorkshop->viewer(); + Handle(V3d_View) aView = aViewer->activeView(); + int aCX, aCY; + aView->Convert(aPosition.X(), aPosition.Y(), aPosition.Z(), aCX, aCY); + + QWidget* aViewPort = aViewer->activeViewPort(); + QPoint aGlPoint = aViewPort->mapToGlobal(QPoint(aCX, aCY)); + aX = aGlPoint.x(); + anY = aGlPoint.y(); + } + } + anEditor->setCursorPosition(aX, anY); + isValueAccepted = anEditor->showPopupEditor(false); + theCanCommitOperation = true; + } + } } } } - theSelection[theFeature] = std::make_pair(aSelectedAttributes, aSelectedResults); + return isValueAccepted; } void PartSet_SketcherMgr::getSelectionOwners(const FeaturePtr& theFeature, @@ -1248,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)); @@ -1256,6 +1517,27 @@ void PartSet_SketcherMgr::widgetStateChanged(int thePreviousState) } } +void PartSet_SketcherMgr::customizePresentation(const ObjectPtr& theObject) +{ + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getCurrentOperation()); + if (aFOperation && (PartSet_SketcherMgr::isSketchOperation(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 { return myModule->workshop()->currentOperation(); @@ -1314,32 +1596,72 @@ void PartSet_SketcherMgr::visualizeFeature(const FeaturePtr& theFeature, void PartSet_SketcherMgr::storeSelection(const bool theHighlightedOnly) { + if (!myCurrentSketch.get()) + return; + 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()); } void PartSet_SketcherMgr::restoreSelection() { + if (!myCurrentSketch.get()) + return; + //qDebug(QString("restoreSelection: %1").arg(myCurrentSelection.size()).toStdString().c_str()); ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); @@ -1354,37 +1676,108 @@ void PartSet_SketcherMgr::restoreSelection() } } -void PartSet_SketcherMgr::onShowConstraintsToggle(bool theOn) +void PartSet_SketcherMgr::onShowConstraintsToggle(int theType, bool theState) +{ + PartSet_Tools::ConstraintVisibleState aType = (PartSet_Tools::ConstraintVisibleState)theType; + + updateBySketchParameters(aType, theState); +} + +void PartSet_SketcherMgr::updateBySketchParameters( + const PartSet_Tools::ConstraintVisibleState& theType, + bool theState) { - if (myIsConstraintsShown == theOn) - return; if (myCurrentSketch.get() == NULL) return; - myIsConstraintsShown = theOn; + bool aPrevState = myIsConstraintsShown[theType]; + myIsConstraintsShown[theType] = theState; + + switch (theType) { + case PartSet_Tools::Geometrical: + case PartSet_Tools::Dimensional: { + if (aPrevState != theState) { + ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); + XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); + for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) { + FeaturePtr aSubFeature = myCurrentSketch->subFeature(i); + bool aProcessed = false; + bool aConstraintDisplayed = canDisplayConstraint(aSubFeature, theType, aProcessed); + if (aProcessed) + aSubFeature->setDisplayed(aConstraintDisplayed); + } + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); + } + } + break; + case PartSet_Tools::Expressions: { + 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; + } +} - ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); - XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); +void PartSet_SketcherMgr::updateSelectionPriority(ObjectPtr theObject, + FeaturePtr theFeature) +{ + if (!theObject.get() || !theFeature.get()) + return; - const QStringList& aConstrIds = constraintsIdList(); - for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) { - FeaturePtr aSubFeature = myCurrentSketch->subFeature(i); - if (aConstrIds.contains(QString(aSubFeature->getKind().c_str()))) { - if (myIsConstraintsShown) - aSubFeature->setDisplayed(true); - else - aSubFeature->setDisplayed(false); + 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); + } } } - Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); } -XGUI_OperationMgr* PartSet_SketcherMgr::operationMgr() const +XGUI_Workshop* PartSet_SketcherMgr::workshop() const { ModuleBase_IWorkshop* anIWorkshop = myModule->workshop(); XGUI_ModuleConnector* aConnector = dynamic_cast(anIWorkshop); - XGUI_Workshop* aWorkshop = aConnector->workshop(); + return aConnector->workshop(); +} - return aWorkshop->operationMgr(); +XGUI_OperationMgr* PartSet_SketcherMgr::operationMgr() const +{ + return workshop()->operationMgr(); }