X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FPartSet%2FPartSet_SketcherMgr.cpp;h=6e5a2d3850ca4651198483d0729182a70ee02be3;hb=b3f7b461d00b6ddf3736c8284498a9f33428577c;hp=22c4b653a1c586ccf11b1a317a6da2db49a12372;hpb=58cd2cdf0944265453f410cc533fb389793a3a4a;p=modules%2Fshaper.git diff --git a/src/PartSet/PartSet_SketcherMgr.cpp b/src/PartSet/PartSet_SketcherMgr.cpp old mode 100755 new mode 100644 index 22c4b653a..6e5a2d385 --- a/src/PartSet/PartSet_SketcherMgr.cpp +++ b/src/PartSet/PartSet_SketcherMgr.cpp @@ -1,29 +1,47 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: PartSet_SketcherMgr.cpp -// Created: 19 Dec 2014 -// Author: Vitaly SMETANNIKOV +// Copyright (C) 2014-2022 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// #include "PartSet_SketcherMgr.h" -#include "PartSet_SketcherReetntrantMgr.h" + +#include "PartSet_Filters.h" +#include "PartSet_SketcherReentrantMgr.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 "PartSet_ExternalPointsMgr.h" +#include "PartSet_PreviewSketchPlane.h" #include #include #include #include #include +#include #include #include #include #include #include +#include #include #include @@ -37,8 +55,14 @@ #include #include #include +#include +#include +#include #include +#include + +#include #include @@ -47,6 +71,8 @@ #include #include #include +#include +#include #include #include #include @@ -58,7 +84,7 @@ #include #include #include -#include +#include #include #include #include @@ -66,70 +92,48 @@ #include #include #include +#include +#include +#include +#include #include #include #include -//#include #include -#include +#include #include #include #include +#include +#include + #include #include #include #include +#include -//#define DEBUG_DO_NOT_BY_ENTER +#include +//#define DEBUG_DO_NOT_BY_ENTER +//#define DEBUG_SKETCHER_ENTITIES +//#define DEBUG_SKETCH_ENTITIES_ON_MOVE +//#define DRAGGING_DEBUG //#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_ViewerPrsPtr aPrs, theList1) { - if (!aRes.contains(aPrs)) - aRes.append(aPrs); - } - foreach (ModuleBase_ViewerPrsPtr 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_ViewerPrsPtr aPrs = *anIt; - FeaturePtr aFeature = ModelAPI_Feature::feature(aPrs->object()); - if (aFeature.get() && !theFeatureList.contains(aFeature)) - theFeatureList.append(aFeature); - } -} +#ifdef DRAGGING_DEBUG +#include +#endif /// 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. +/// 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. /// \param theOwner a viewer selected owner /// \param theFeature a feature, where the attribute is searched /// \param theSketch a current sketch @@ -138,8 +142,9 @@ void fillFeatureList(const QList& theList, void getAttributesOrResults(const Handle(SelectMgr_EntityOwner)& theOwner, const FeaturePtr& theFeature, const FeaturePtr& theSketch, const ResultPtr& theResult, - std::set& aSelectedAttributes, - std::set& aSelectedResults) + std::map& theSelectedAttributes, + std::set& theSelectedResults, + TopTools_MapOfShape& theShapes) { Handle(StdSelect_BRepOwner) aBRepOwner = Handle(StdSelect_BRepOwner)::DownCast(theOwner); if (aBRepOwner.IsNull()) @@ -148,25 +153,33 @@ void getAttributesOrResults(const Handle(SelectMgr_EntityOwner)& theOwner, aBRepOwner->Selectable()); if (aBRepOwner->HasShape()) { const TopoDS_Shape& aShape = aBRepOwner->Shape(); + theShapes.Add(aShape); TopAbs_ShapeEnum aShapeType = aShape.ShapeType(); if (aShapeType == TopAbs_VERTEX) { - AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(theFeature, - aShape, theSketch); - if (aPntAttr.get() != NULL) - aSelectedAttributes.insert(aPntAttr); + std::pair aPntAttrIndex = + PartSet_Tools::findAttributeBy2dPoint(theFeature, aShape, theSketch); + if (aPntAttrIndex.first.get() != NULL) + theSelectedAttributes[aPntAttrIndex.first] = aPntAttrIndex.second; } else if (aShapeType == TopAbs_EDGE && - aSelectedResults.find(theResult) == aSelectedResults.end()) { - aSelectedResults.insert(theResult); + theSelectedResults.find(theResult) == theSelectedResults.end()) { + theSelectedResults.insert(theResult); } } } PartSet_SketcherMgr::PartSet_SketcherMgr(PartSet_Module* theModule) - : QObject(theModule), myModule(theModule), myIsDragging(false), myDragDone(false), + : QObject(theModule), + myModule(theModule), + myIsEditLaunching(false), + myIsDragging(false), + myDragDone(false), myIsMouseOverWindow(false), - myIsMouseOverViewProcessed(true), myPreviousUpdateViewerEnabled(true), - myIsPopupMenuActive(false) + myIsMouseOverViewProcessed(true), + myIsPopupMenuActive(false), + myPreviousUpdateViewerEnabled(true), + myExternalPointsMgr(0), + myNoDragMoving(false) { ModuleBase_IWorkshop* anIWorkshop = myModule->workshop(); ModuleBase_IViewer* aViewer = anIWorkshop->viewer(); @@ -192,12 +205,18 @@ PartSet_SketcherMgr::PartSet_SketcherMgr(PartSet_Module* theModule) myIsConstraintsShown[PartSet_Tools::Geometrical] = true; myIsConstraintsShown[PartSet_Tools::Dimensional] = true; myIsConstraintsShown[PartSet_Tools::Expressions] = false; + + mySketchPlane = new PartSet_PreviewSketchPlane(); + + registerSelectionFilter(SF_SketchCirclePointFilter, new PartSet_CirclePointFilter(anIWorkshop)); + registerSelectionFilter(SF_SketchPlaneFilter, new ModuleBase_ShapeInPlaneFilter()); + + Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_DOF_OBJECTS)); } PartSet_SketcherMgr::~PartSet_SketcherMgr() { - if (!myPlaneFilter.IsNull()) - myPlaneFilter.Nullify(); + delete mySketchPlane; } void PartSet_SketcherMgr::onEnterViewPort() @@ -212,17 +231,19 @@ void PartSet_SketcherMgr::onEnterViewPort() return; #endif - if (canChangeCursor(getCurrentOperation())) { - QCursor* aCurrentCursor = QApplication::overrideCursor(); - if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) { - QApplication::setOverrideCursor(QCursor(Qt::CrossCursor)); -#ifdef DEBUG_CURSOR - qDebug("onEnterViewPort() : Qt::CrossCursor"); -#endif + // It is switched off because of + // Task #3067: 5.2.2 Drawing in the sketcher: change the mouse cursor arrow + if (canChangeCursor(getCurrentOperation())) { + QCursor* aCurrentCursor = QApplication::overrideCursor(); + if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) { + QApplication::setOverrideCursor(PartSet_Tools::getOperationCursor()); + //#ifdef DEBUG_CURSOR + // qDebug("onEnterViewPort() : Qt::CrossCursor"); + //#endif + } } - } - if (!isNestedCreateOperation(getCurrentOperation())) + if (!isNestedCreateOperation(getCurrentOperation(), activeSketch())) return; operationMgr()->onValidateOperation(); @@ -247,9 +268,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; @@ -257,12 +275,12 @@ void PartSet_SketcherMgr::onLeaveViewPort() if (canChangeCursor(getCurrentOperation())) { QApplication::restoreOverrideCursor(); -#ifdef DEBUG_CURSOR - qDebug("onLeaveViewPort() : None"); -#endif +//#ifdef DEBUG_CURSOR +// qDebug("onLeaveViewPort() : None"); +//#endif } - if (!isNestedCreateOperation(getCurrentOperation())) + if (!isNestedCreateOperation(getCurrentOperation(), activeSketch())) return; // the method should be performed if the popup menu is called, @@ -270,6 +288,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 @@ -297,13 +317,15 @@ void PartSet_SketcherMgr::onLeaveViewPort() aDisplayer->enableUpdateViewer(isEnableUpdateViewer); } +/* +//Temporary commented as we do not modify values in property panel 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 - storeSelection(); + storeSelection(ST_SelectAndHighlightType); ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); @@ -313,16 +335,16 @@ void PartSet_SketcherMgr::onBeforeValuesChangedInPropertyPanel() void PartSet_SketcherMgr::onAfterValuesChangedInPropertyPanel() { - if (!isNestedEditOperation(getCurrentOperation()) || + 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 + // it is necessary to restore current selection in order to restore it after values are modified restoreSelection(); myCurrentSelection.clear(); - // 3. the flag to disable the update viewer should be set in order to avoid blinking in the + // 3. the flag to disable the update viewer should be set in order to avoid blinking in the // viewer happens by deselect/select the modified objects. The flag should be restored after // the selection processing. The update viewer should be also called. ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); @@ -330,34 +352,63 @@ void PartSet_SketcherMgr::onAfterValuesChangedInPropertyPanel() XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); aDisplayer->enableUpdateViewer(myPreviousUpdateViewerEnabled); aDisplayer->updateViewer(); - - } +*/ + +bool PartSet_SketcherMgr::isDragModeCreation() const +{ + ModuleBase_Operation* aOp = getCurrentOperation(); + if (!aOp) + return false; + bool aUserPref = Config_PropManager::boolean(SKETCH_TAB_NAME, "create_by_dragging"); + if (!aUserPref) + return false; + QString aId = aOp->id(); + // Acceptable features; + QStringList aList; + aList << "SketchLine" << "SketchMacroCircle" << "SketchMacroArc" << + "SketchMacroEllipse" << "SketchMacroEllipticArc" << "SketchMacroRectangle"; + return aList.contains(aId); +} + +static bool MyModeByDrag = false; +static bool MyMultiselectionState = true; void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) { + MyModeByDrag = isDragModeCreation(); + + // Clear dragging mode + myIsDragging = false; + + myMousePoint.setX(theEvent->x()); + myMousePoint.setY(theEvent->y()); + if (myModule->sketchReentranceMgr()->processMousePressed(theWnd, theEvent)) return; - //get2dPoint(theWnd, theEvent, myClickedPoint); - if (!(theEvent->buttons() & Qt::LeftButton)) return; - // Clear dragging mode - myIsDragging = false; - ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); ModuleBase_IViewer* aViewer = aWorkshop->viewer(); - if (!aViewer->canDragByMouse()) - return; + //if (!aViewer->canDragByMouse()) + // return; ModuleBase_OperationFeature* aFOperation = dynamic_cast (getCurrentOperation()); if (!aFOperation) return; - if (aFOperation->isEditOperation()) { + bool isEditing = aFOperation->isEditOperation(); + bool aCanDrag = aViewer->canDragByMouse(); + + //if (!aViewer->canDragByMouse() && isEditing) { + // // Do not edit by dragging + // return; + //} + + if (isEditing) { // If the current widget is a selector, do nothing, it processes the mouse press ModuleBase_ModelWidget* anActiveWidget = getActiveWidget(); if(anActiveWidget && anActiveWidget->isViewerSelector()) { @@ -377,22 +428,27 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE if ((!isSketchOpe) && (!isSketcher)) return; - bool isEditing = aFOperation->isEditOperation(); - // Ignore creation sketch operation - if ((!isSketcher) && (!isEditing)) + if ((!isSketcher) && (!isEditing)) { + if (MyModeByDrag) { + ModuleBase_ModelWidget* anActiveWidget = getActiveWidget(); + PartSet_MouseProcessor* aProcessor = dynamic_cast(anActiveWidget); + if (aProcessor) { + MyMultiselectionState = aViewer->isMultiSelectionEnabled(); + aViewer->enableMultiselection(false); + myIsDragging = true; + ModuleBase_ISelection* aSelection = aWorkshop->selection(); + QList aPreSelected = aSelection->getHighlighted(); + if (!aPreSelected.empty()) + aProcessor->setPreSelection(aPreSelected.first(), theWnd, theEvent); + else + aProcessor->mouseReleased(theWnd, theEvent); + } + } 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(); - bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier); - storeSelection(!aHasShift); + storeSelection(aHasShift ? ST_SelectAndHighlightType : ST_HighlightType, myCurrentSelection); if (myCurrentSelection.empty()) { if (isSketchOpe && (!isSketcher)) @@ -403,138 +459,234 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE } // Init flyout point for radius rotation FeaturePtr aFeature = myCurrentSelection.begin().key(); - + get2dPoint(theWnd, theEvent, myCurrentPoint); if (isSketcher) { - myIsDragging = true; - get2dPoint(theWnd, theEvent, myCurrentPoint); - myDragDone = false; - + if (aCanDrag) { + myIsDragging = true; + myDragDone = false; + } myPreviousDrawModeEnabled = aViewer->enableDrawMode(false); launchEditing(); + } else if (isSketchOpe && isEditing) { + // If selected another object commit current result + bool aPrevLaunchingState = myIsEditLaunching; + /// store editing state for Edit operation in order to do not clear highlight by restart + /// of edit operation. + /// Internal edit should not be stored as editing operation as the result will be a + /// creation operation, where previous selection should not be used(and will be cleared) + myIsEditLaunching = !myModule->sketchReentranceMgr()->isInternalEditActive(); + + std::shared_ptr aSPFeature = + std::dynamic_pointer_cast(aFOperation->feature()); + bool isRelaunchEditing = true; + if (aSPFeature->isExternal()) { + foreach(FeaturePtr aF, myCurrentSelection.keys()) { + FeaturePtr aProducerFeature = PartSet_Tools::findRefsToMeFeature(aF, + aSPFeature->getKind()); + if (aProducerFeature == aSPFeature) { + isRelaunchEditing = false; + break; + } + } + } + else { + if (myCurrentSelection.size() > 1) + isRelaunchEditing = !myCurrentSelection.contains(aSPFeature); + } + if (isRelaunchEditing) + aFOperation->commit(); + + if (aCanDrag) { + myIsDragging = true; + myDragDone = false; + } + myPreviousDrawModeEnabled = aViewer->enableDrawMode(false); + if (isRelaunchEditing) + launchEditing(); + else { + if (myCurrentSelection.size() > 1) + aFOperation->propertyPanel()->cleanContent(); + } + myIsEditLaunching = aPrevLaunchingState; if (aFeature.get() != NULL) { - std::shared_ptr aSPFeature = + std::shared_ptr aSketchFeature = std::dynamic_pointer_cast(aFeature); - if (aSPFeature.get() && aSPFeature->getKind() == SketchPlugin_ConstraintRadius::ID()) { - DataPtr aData = aSPFeature->data(); + if (aSketchFeature.get() && + (aSketchFeature->getKind() == SketchPlugin_ConstraintRadius::ID() || + aSketchFeature->getKind() == SketchPlugin_ConstraintAngle::ID())) { + DataPtr aData = aSketchFeature->data(); AttributePtr aAttr = aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()); - std::shared_ptr aFPAttr = + std::shared_ptr aFPAttr = std::dynamic_pointer_cast(aAttr); aFPAttr->setValue(myCurrentPoint.myCurX, myCurrentPoint.myCurY); } } - } else if (isSketchOpe && isEditing) { - // If selected another object commit current result - aFOperation->commit(); - - myIsDragging = true; - get2dPoint(theWnd, theEvent, myCurrentPoint); - 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(); - launchEditing(); } } } void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) { - if (myModule->sketchReentranceMgr()->processMouseReleased(theWnd, theEvent)) - return; - ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); ModuleBase_IViewer* aViewer = aWorkshop->viewer(); - if (!aViewer->canDragByMouse()) + if (myIsDragging) + aViewer->enableDrawMode(myPreviousDrawModeEnabled); + + bool aWasDragging = myIsDragging; + myIsDragging = false; + + if (myModule->sketchReentranceMgr()->processMouseReleased(theWnd, theEvent)) { return; - ModuleBase_Operation* aOp = getCurrentOperation(); + } + // if mouse is pressed when it was over view and at release the mouse is out of view, do nothing + if (!myIsMouseOverViewProcessed) { + return; + } + + ModuleBase_OperationFeature* aOp = + dynamic_cast(getCurrentOperation()); + bool isEditing = false; if (aOp) { - if (isNestedSketchOperation(aOp)) { - //get2dPoint(theWnd, theEvent, myClickedPoint); - - // 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(); - */ + isEditing = aOp->isEditOperation(); + bool aStartNoDragOperation = !aViewer->canDragByMouse() && isEditing; + if (aStartNoDragOperation || myNoDragMoving) { + // Process edit operation without dragging + if (myCurrentSelection.size() > 0) + myNoDragMoving = !myNoDragMoving; + else + myNoDragMoving = false; + if (myNoDragMoving) + return; + else { + restoreSelection(myCurrentSelection); + myCurrentSelection.clear(); + } + } + else { + if (isNestedSketchOperation(aOp)) { + // Only for sketcher operations + if (aWasDragging) { + if (myDragDone) { + /// the previous selection is lost by mouse release in the viewer(Select method), but + /// it is still stored in myCurrentSelection. So, it is possible to restore selection + /// It is important for drag(edit with mouse) of sketch entities. + restoreSelection(myCurrentSelection); + myCurrentSelection.clear(); + } } } } } - aWorkshop->viewer()->enableDrawMode(myPreviousDrawModeEnabled); - myIsDragging = false; + ModuleBase_ModelWidget* anActiveWidget = getActiveWidget(); + PartSet_MouseProcessor* aProcessor = dynamic_cast(anActiveWidget); + if (aProcessor) { + ModuleBase_ISelection* aSelection = aWorkshop->selection(); + QList aPreSelected = aSelection->getHighlighted(); + if (MyModeByDrag && !aPreSelected.empty() && !isEditing) + aProcessor->setPreSelection(aPreSelected.first(), theWnd, theEvent); + else + aProcessor->mouseReleased(theWnd, theEvent); + } + if (MyModeByDrag && aOp) { + aViewer->enableMultiselection(true); + QString aOpId = aOp->id(); + if (aOpId == "Sketch") + return; + QPoint aPnt(theEvent->x(), theEvent->y()); + anActiveWidget = getActiveWidget(); + if ((aPnt == myMousePoint) && anActiveWidget) { + aOp->abort(); + return; + } + bool aCanRestart = !anActiveWidget && !isEditing; + if (aCanRestart) { + module()->launchOperation(aOpId, true); + } + } } void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) { +#ifdef DEBUG_SKETCH_ENTITIES_ON_MOVE + CompositeFeaturePtr aSketch = activeSketch(); + if (aSketch.get()) { + std::cout << "mouse move SKETCH FEATURES [" << aSketch->numberOfSubs() << "]:" << std::endl; + QStringList anInfo; + for (int i = 0, aNbSubs = aSketch->numberOfSubs(); i < aNbSubs; i++) { + //std::cout << getFeatureInfo(aSketch->subFeature(i), false) << std::endl; + anInfo.append(ModuleBase_Tools::objectInfo(aSketch->subFeature(i))); + } + QString anInfoStr = anInfo.join("\n"); + qDebug(QString("%1").arg(anInfo.size()).arg(anInfoStr).toStdString().c_str()); + } +#endif + if (myModule->sketchReentranceMgr()->processMouseMoved(theWnd, theEvent)) return; - if (isNestedCreateOperation(getCurrentOperation()) && !myIsMouseOverViewProcessed) { - myIsMouseOverViewProcessed = true; + ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); + XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); + XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); + + if (isNestedCreateOperation(getCurrentOperation(), activeSketch())) { +#ifdef DRAGGING_DEBUG + QTime t; + t.start(); +#endif // 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)); + } } + aDisplayer->updateViewer(); +#ifdef DRAGGING_DEBUG + cout << "Mouse move processing " << t.elapsed() << endl; +#endif } - //myClickedPoint.clear(); - if (myIsDragging) { - // 1. the current selection is saved in the mouse press method in order to restore it after moving + if (myIsDragging || myNoDragMoving) { + // 1. the current selection is saved in the mouse press method in order to restore it after + // moving // 2. the enable selection in the viewer should be temporary switched off in order to ignore // 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. - ModuleBase_Operation* aCurrentOperation = getCurrentOperation(); if (!aCurrentOperation) return; if (isSketchOperation(aCurrentOperation)) return; // No edit operation activated +#ifdef DRAGGING_DEBUG + QTime t; + t.start(); +#endif + Handle(V3d_View) aView = theWnd->v3dView(); - gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView); - double aX, aY; - PartSet_Tools::convertTo2D(aPoint, myCurrentSketch, aView, aX, aY); - double dX = aX - myCurrentPoint.myCurX; - double dY = aY - myCurrentPoint.myCurY; - - ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); - XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); - XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); - // 3. the flag to disable the update viewer should be set in order to avoid blinking in the + Point aMousePnt; + get2dPoint(theWnd, theEvent, aMousePnt); + + std::shared_ptr anOriginalPosition = std::shared_ptr( + new GeomAPI_Pnt2d(myCurrentPoint.myCurX, myCurrentPoint.myCurY)); + std::shared_ptr aCurrentPosition = std::shared_ptr( + new GeomAPI_Pnt2d(aMousePnt.myCurX, aMousePnt.myCurY)); + + // 3. the flag to disable the update viewer should be set in order to avoid blinking in the // viewer happens by deselect/select the modified objects. The flag should be restored after // the selection processing. The update viewer should be also called. bool isEnableUpdateViewer = aDisplayer->enableUpdateViewer(false); @@ -542,43 +694,54 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve static Events_ID aMoveEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED); //static Events_ID aUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); FeatureToSelectionMap::const_iterator anIt = myCurrentSelection.begin(), - aLast = myCurrentSelection.end(); + aLast = myCurrentSelection.end(); // 4. the features and attributes modification(move) bool isModified = false; for (; anIt != aLast; anIt++) { FeaturePtr aFeature = anIt.key(); - std::set anAttributes = anIt.value().first; + std::map anAttributes = anIt.value().myAttributes; // Process selection by attribute: the priority to the attribute if (!anAttributes.empty()) { - std::set::const_iterator anAttIt = anAttributes.begin(), - anAttLast = anAttributes.end(); + std::map::const_iterator anAttIt = anAttributes.begin(), + anAttLast = anAttributes.end(); for (; anAttIt != anAttLast; anAttIt++) { - AttributePtr anAttr = *anAttIt; + AttributePtr anAttr = anAttIt->first; if (anAttr.get() == NULL) continue; std::string aAttrId = anAttr->id(); DataPtr aData = aFeature->data(); if (aData->isValid()) { - std::shared_ptr aPoint = - std::dynamic_pointer_cast(aData->attribute(aAttrId)); - if (aPoint.get() != NULL) { + AttributePtr aPoint = aData->attribute(aAttrId); + if (aPoint->attributeType() == GeomDataAPI_Point2D::typeId() || + aPoint->attributeType() == GeomDataAPI_Point2DArray::typeId()) { bool isImmutable = aPoint->setImmutable(true); - aPoint->move(dX, dY); + + std::shared_ptr aMessage = std::shared_ptr + (new ModelAPI_ObjectMovedMessage(this)); + aMessage->setMovedAttribute(aPoint, anAttIt->second); + aMessage->setOriginalPosition(anOriginalPosition); + aMessage->setCurrentPosition(aCurrentPosition); + Events_Loop::loop()->send(aMessage); + isModified = true; - ModelAPI_EventCreator::get()->sendUpdated(aFeature, aMoveEvent); aPoint->setImmutable(isImmutable); } } } - } else { + } + else { // Process selection by feature std::shared_ptr aSketchFeature = std::dynamic_pointer_cast(aFeature); if (aSketchFeature) { - aSketchFeature->move(dX, dY); + std::shared_ptr aMessage = std::shared_ptr + (new ModelAPI_ObjectMovedMessage(this)); + aMessage->setMovedObject(aFeature); + aMessage->setOriginalPosition(anOriginalPosition); + aMessage->setCurrentPosition(aCurrentPosition); + Events_Loop::loop()->send(aMessage); isModified = true; - ModelAPI_EventCreator::get()->sendUpdated(aSketchFeature, aMoveEvent); } } } @@ -586,18 +749,22 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve // were changed here if (isModified) { aCurrentOperation->onValuesChanged(); + Events_Loop::loop()->flush(aMoveEvent); // up all move events - to be processed in the solver } - Events_Loop::loop()->flush(aMoveEvent); // up all move events - to be processed in the solver //Events_Loop::loop()->flush(aUpdateEvent); // up update events - to redisplay presentations // 5. it is necessary to save current selection in order to restore it after the features moving - restoreSelection(); + restoreSelection(myCurrentSelection); // 6. restore the update viewer flag and call this update aDisplayer->enableUpdateViewer(isEnableUpdateViewer); aDisplayer->updateViewer(); +#ifdef DRAGGING_DEBUG + cout << "Mouse move processing " << t.elapsed() << endl; +#endif + myDragDone = true; - myCurrentPoint.setValue(aX, aY); + myCurrentPoint = aMousePnt; } } @@ -614,7 +781,10 @@ 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") { + std::string anId = aWgt->attributeID(); + if (anId == SketchPlugin_Constraint::VALUE() || + anId == SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID() || + anId == SketchPlugin_ConstraintDistanceAlongDir::DISTANCE_VALUE_ID()) { PartSet_WidgetEditor* anEditor = dynamic_cast(aWgt); if (anEditor) anEditor->showPopupEditor(); @@ -630,7 +800,7 @@ void PartSet_SketcherMgr::onApplicationStarted() ModuleBase_IWorkshop* anIWorkshop = myModule->workshop(); XGUI_ModuleConnector* aConnector = dynamic_cast(anIWorkshop); XGUI_Workshop* aWorkshop = aConnector->workshop(); - PartSet_SketcherReetntrantMgr* aReentranceMgr = myModule->sketchReentranceMgr(); + PartSet_SketcherReentrantMgr* aReentranceMgr = myModule->sketchReentranceMgr(); XGUI_PropertyPanel* aPropertyPanel = aWorkshop->propertyPanel(); if (aPropertyPanel) { @@ -639,8 +809,8 @@ void PartSet_SketcherMgr::onApplicationStarted() connect(aPropertyPanel, SIGNAL(noMoreWidgets(const std::string&)), aReentranceMgr, SLOT(onNoMoreWidgets(const std::string&))); - connect(aPropertyPanel, SIGNAL(widgetActivated(ModuleBase_ModelWidget*)), - aReentranceMgr, SLOT(onWidgetActivated())); + //connect(aPropertyPanel, SIGNAL(widgetActivated(ModuleBase_ModelWidget*)), + // aReentranceMgr, SLOT(onWidgetActivated())); } XGUI_ViewerProxy* aViewerProxy = aWorkshop->viewer(); @@ -680,7 +850,7 @@ void PartSet_SketcherMgr::onAfterContextMenu() myIsPopupMenuActive = false; } -void PartSet_SketcherMgr::get2dPoint(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent, +void PartSet_SketcherMgr::get2dPoint(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent, Point& thePoint) { Handle(V3d_View) aView = theWnd->v3dView(); @@ -694,10 +864,22 @@ void PartSet_SketcherMgr::launchEditing() { if (!myCurrentSelection.empty()) { FeaturePtr aFeature = myCurrentSelection.begin().key(); - std::shared_ptr aSPFeature = + std::shared_ptr aSPFeature = std::dynamic_pointer_cast(aFeature); if (aSPFeature) { - myModule->editFeature(aSPFeature); + if (!aSPFeature->isExternal()) + myModule->editFeature(aSPFeature); + else { + // need to edit a feature (Projection/IntersectionPoint), + // which produces current External feature + FeaturePtr aProducerFeature = PartSet_Tools::findRefsToMeFeature(aFeature, + SketchPlugin_Projection::ID()); + if (!aProducerFeature.get()) + aProducerFeature = PartSet_Tools::findRefsToMeFeature(aFeature, + SketchPlugin_IntersectionPoint::ID()); + if (aProducerFeature.get()) + myModule->editFeature(aProducerFeature); + } } } } @@ -715,14 +897,14 @@ bool PartSet_SketcherMgr::sketchSolverError() QString PartSet_SketcherMgr::getFeatureError(const FeaturePtr& theFeature) { - QString anError = ""; + QString anError; if (!theFeature.get() || !theFeature->data()->isValid()) return anError; CompositeFeaturePtr aSketch = activeSketch(); if (aSketch.get() && aSketch == theFeature) { - AttributeStringPtr aAttributeString = aSketch->string(SketchPlugin_Sketch::SOLVER_ERROR()); - anError = aAttributeString->value().c_str(); + std::string aSolverError = aSketch->string(SketchPlugin_Sketch::SOLVER_ERROR())->value(); + anError = ModuleBase_Tools::translate(aSketch->getKind(), aSolverError); } return anError; } @@ -733,52 +915,50 @@ 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(); - } - return aIds; -} - -void PartSet_SketcherMgr::sketchSelectionModes(QIntList& theModes) -{ - theModes.clear(); + 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(); + aConstraintIds << SketchPlugin_ConstraintMirror::ID().c_str(); + aConstraintIds << SketchPlugin_MultiTranslation::ID().c_str(); + aConstraintIds << SketchPlugin_MultiRotation::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintDistanceAlongDir::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintDistanceHorizontal::ID().c_str(); + aConstraintIds << SketchPlugin_ConstraintDistanceVertical::ID().c_str(); + } + return aConstraintIds; +} + +void PartSet_SketcherMgr::sketchSelectionModes(const CompositeFeaturePtr& theSketch, + QIntList& theModes) +{ + if (!theSketch.get() || !PartSet_Tools::sketchPlane(theSketch).get()) + return; theModes.append(SketcherPrs_Tools::Sel_Dimension_Text); theModes.append(SketcherPrs_Tools::Sel_Dimension_Line); @@ -787,13 +967,15 @@ void PartSet_SketcherMgr::sketchSelectionModes(QIntList& theModes) theModes.append(TopAbs_EDGE); } -Handle(AIS_InteractiveObject) PartSet_SketcherMgr::createPresentation(const ResultPtr& theResult) +Handle(AIS_InteractiveObject) PartSet_SketcherMgr::createPresentation(const ObjectPtr& theObj) { Handle(AIS_InteractiveObject) aPrs; - FeaturePtr aFeature = ModelAPI_Feature::feature(theResult); + FeaturePtr aFeature = ModelAPI_Feature::feature(theObj); if (aFeature.get() && aFeature->getKind() == SketchPlugin_Sketch::ID()) { - aPrs = new PartSet_ResultSketchPrs(theResult); + ResultPtr aResult = std::dynamic_pointer_cast(theObj); + if (aResult.get()) + aPrs = new PartSet_ResultSketchPrs(aResult); } return aPrs; } @@ -803,24 +985,59 @@ 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 { - return theOperation && - PartSet_SketcherMgr::sketchOperationIdList().contains(theOperation->id()); + bool aNestedSketch = false; + + FeaturePtr anActiveSketch = activeSketch(); + if (anActiveSketch.get() && theOperation) { + ModuleBase_Operation* aSketchOperation = operationMgr()->findOperation( + anActiveSketch->getKind().c_str()); + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (theOperation); + if (aSketchOperation && aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); + if (aFeature.get()) { + QStringList aGrantedOpIds = aSketchOperation->grantedOperationIds(); + aNestedSketch = aGrantedOpIds.contains(aFeature->getKind().c_str()); + } + } + } + return aNestedSketch; } -bool PartSet_SketcherMgr::isNestedCreateOperation(ModuleBase_Operation* theOperation) +bool PartSet_SketcherMgr::isNestedSketchFeature(const QString& theFeatureKind) const +{ + bool aNestedSketch = false; + + FeaturePtr anActiveSketch = activeSketch(); + if (anActiveSketch.get()) { + ModuleBase_Operation* aSketchOperation = operationMgr()->findOperation( + anActiveSketch->getKind().c_str()); + if (aSketchOperation) { + QStringList aGrantedOpIds = aSketchOperation->grantedOperationIds(); + aNestedSketch = aGrantedOpIds.contains(theFeatureKind); + } + } + return aNestedSketch; +} + +bool PartSet_SketcherMgr::isNestedCreateOperation(ModuleBase_Operation* theOperation, + const CompositeFeaturePtr& theSketch) const { ModuleBase_OperationFeature* aFOperation = dynamic_cast (theOperation); - return aFOperation && !aFOperation->isEditOperation() && isNestedSketchOperation(aFOperation); + return aFOperation && !aFOperation->isEditOperation() && + isNestedSketchOperation(aFOperation); } -bool PartSet_SketcherMgr::isNestedEditOperation(ModuleBase_Operation* theOperation) +bool PartSet_SketcherMgr::isNestedEditOperation(ModuleBase_Operation* theOperation, + const CompositeFeaturePtr& theSketch) const { ModuleBase_OperationFeature* aFOperation = dynamic_cast (theOperation); - return aFOperation && aFOperation->isEditOperation() && isNestedSketchOperation(aFOperation); + return aFOperation && aFOperation->isEditOperation() && + isNestedSketchOperation(aFOperation); } bool PartSet_SketcherMgr::isEntity(const std::string& theId) @@ -828,7 +1045,18 @@ bool PartSet_SketcherMgr::isEntity(const std::string& theId) return (theId == SketchPlugin_Line::ID()) || (theId == SketchPlugin_Point::ID()) || (theId == SketchPlugin_Arc::ID()) || - (theId == SketchPlugin_Circle::ID()); + (theId == SketchPlugin_Circle::ID()) || + (theId == SketchPlugin_Ellipse::ID()) || + (theId == SketchPlugin_Projection::ID()) || + (theId == SketchPlugin_IntersectionPoint::ID()) || + (theId == SketchPlugin_EllipticArc::ID()); +} + +bool PartSet_SketcherMgr::isExternalFeature(const FeaturePtr& theFeature) +{ + std::shared_ptr aSPFeature = + std::dynamic_pointer_cast(theFeature); + return aSPFeature.get() && aSPFeature->isExternal(); } bool PartSet_SketcherMgr::isDistanceOperation(ModuleBase_Operation* theOperation) @@ -843,22 +1071,39 @@ bool PartSet_SketcherMgr::isDistanceKind(std::string& theKind) return (theKind == SketchPlugin_ConstraintLength::ID()) || (theKind == SketchPlugin_ConstraintDistance::ID()) || (theKind == SketchPlugin_ConstraintRadius::ID()) || - (theKind == SketchPlugin_ConstraintAngle::ID()); + (theKind == SketchPlugin_ConstraintAngle::ID()) || + (theKind == SketchPlugin_ConstraintDistanceHorizontal::ID()) || + (theKind == SketchPlugin_ConstraintDistanceVertical::ID()) || + (theKind == SketchPlugin_ConstraintDistanceAlongDir::ID()); } void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation) { + static Events_ID EVENT_ATTR = Events_Loop::loop()->eventByName(EVENT_VISUAL_ATTRIBUTES); + static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); + ModuleBase_OperationFeature* aFOperation = dynamic_cast (getCurrentOperation()); if (!aFOperation) return; + SketcherPrs_Tools::setPixelRatio(ModuleBase_Tools::currentPixelRatio()); + myModule->onViewTransformed(); // Display all sketcher sub-Objects myCurrentSketch = std::dynamic_pointer_cast(aFOperation->feature()); + double aSizeOfView = 0; + std::shared_ptr aCentralPoint; + // Reset size of view from previous launches + mySketchPlane->setSizeOfView(aSizeOfView, false, aCentralPoint); + if (aFOperation->isEditOperation() && + mySketchPlane->getDefaultSizeOfView(myCurrentSketch, aSizeOfView, aCentralPoint)) { + mySketchPlane->setSizeOfView(aSizeOfView, true, aCentralPoint); + } + + mySketchPlane->createSketchPlane(myCurrentSketch, myModule->workshop()); XGUI_ModuleConnector* aConnector = dynamic_cast(myModule->workshop()); - aConnector->workshop()->displayer()->activateTrihedron(true); // Hide sketcher result std::list aResults = myCurrentSketch->results(); @@ -868,59 +1113,121 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation) } myCurrentSketch->setDisplayed(false); - // Display sketcher objects - for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) { + // Remove invalid sketch entities + std::set anInvalidFeatures; + ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators(); + int aNumberOfSubs = myCurrentSketch->numberOfSubs(); + for (int i = 0; i < aNumberOfSubs; i++) { FeaturePtr aFeature = myCurrentSketch->subFeature(i); - std::list aResults = aFeature->results(); - std::list::const_iterator aIt; - for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { - (*aIt)->setDisplayed(true); + if (aFeature.get()) { + if (!aFactory->validate(aFeature)) + anInvalidFeatures.insert(aFeature); } - aFeature->setDisplayed(true); } - - if(myCirclePointFilter.IsNull()) { - myCirclePointFilter = new PartSet_CirclePointFilter(myModule->workshop()); + 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(QString::fromStdWString(aFeature->name())); + } + 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); + } } - myModule->workshop()->viewer()->addSelectionFilter(myCirclePointFilter); - - if (myPlaneFilter.IsNull()) - myPlaneFilter = new ModuleBase_ShapeInPlaneFilter(); + // update state of overconstraint listener should be done before sketch features/results + // display (as the display will ask custom color from the listener) + myModule->overconstraintListener()->setActive(true); + // Display sketcher objects + QStringList anInfo; + const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get(); + aNumberOfSubs = myCurrentSketch->numberOfSubs(); + for (int i = 0; i < aNumberOfSubs; i++) { + FeaturePtr aFeature = myCurrentSketch->subFeature(i); +#ifdef DEBUG_SKETCHER_ENTITIES + anInfo.append(ModuleBase_Tools::objectInfo(aFeature)); +#endif + std::list aFeatResults = aFeature->results(); + for (aIt = aFeatResults.begin(); aIt != aFeatResults.end(); ++aIt) { + if ((*aIt)->isDisplayed()) + // Display object if it was created outside of GUI + aECreator->sendUpdated((*aIt), EVENT_DISP); + else + (*aIt)->setDisplayed(true); + } + if (aFeature->isDisplayed()) + aECreator->sendUpdated(aFeature, EVENT_DISP); + else + aFeature->setDisplayed(true); + aECreator->sendUpdated(aFeature, EVENT_ATTR); + } +#ifdef DEBUG_SKETCHER_ENTITIES + QString anInfoStr = anInfo.join(";\t"); + qDebug(QString("startSketch: %1, %2").arg(anInfo.size()).arg(anInfoStr).toStdString().c_str()); +#endif - myModule->workshop()->viewer()->addSelectionFilter(myPlaneFilter); - bool aHasPlane = false; std::shared_ptr aPln; aPln = PartSet_Tools::sketchPlane(myCurrentSketch); - myPlaneFilter->setPlane(aPln); + Handle(SelectMgr_Filter) aFilter = myModule->selectionFilter(SF_SketchPlaneFilter); + if (!aFilter.IsNull()) + Handle(ModuleBase_ShapeInPlaneFilter)::DownCast(aFilter)->setPlane(aPln); + + workshop()->selectionActivate()->updateSelectionFilters(); + workshop()->selectionActivate()->updateSelectionModes(); + + Events_Loop::loop()->flush(EVENT_ATTR); + Events_Loop::loop()->flush(EVENT_DISP); + + myExternalPointsMgr = new PartSet_ExternalPointsMgr(myModule->workshop(), myCurrentSketch); + + workshop()->viewer()->set2dMode(true); - Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); - // all displayed objects should be activated in current selection modes according to switched - // plane filter - if (aPln.get()) - aConnector->activateModuleSelectionModes(); + PartSet_Fitter* aFitter = new PartSet_Fitter(this); + myModule->workshop()->viewer()->setFitter(aFitter); } void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation) { + XGUI_ModuleConnector* aConnector = dynamic_cast(myModule->workshop()); + PartSet_Fitter* aFitter = (PartSet_Fitter*)myModule->workshop()->viewer()->fitter(); + myModule->workshop()->viewer()->setFitter(0); + delete aFitter; + myIsMouseOverWindow = false; myIsConstraintsShown[PartSet_Tools::Geometrical] = true; myIsConstraintsShown[PartSet_Tools::Dimensional] = true; myIsConstraintsShown[PartSet_Tools::Expressions] = false; - XGUI_ModuleConnector* aConnector = dynamic_cast(myModule->workshop()); + if (myExternalPointsMgr) { + delete myExternalPointsMgr; + myExternalPointsMgr = 0; + } + onShowPoints(false); DataPtr aData = myCurrentSketch->data(); if (!aData->isValid()) { 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); + mySketchPlane->eraseSketchPlane(myModule->workshop()); // Erase all sketcher objects - QStringList aSketchIds = sketchOperationIdList(); QObjectPtrList aObjects = aDisplayer->displayedObjects(); foreach (ObjectPtr aObj, aObjects) { DataPtr aObjData = aObj->data(); @@ -930,7 +1237,8 @@ void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation) } else { // Hide all sketcher sub-Objects - for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) { + int aNumberOfSubs = myCurrentSketch->numberOfSubs(); + for (int i = 0; i < aNumberOfSubs; i++) { FeaturePtr aFeature = myCurrentSketch->subFeature(i); std::list aResults = aFeature->results(); std::list::const_iterator aIt; @@ -957,17 +1265,15 @@ void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation) } if (!aFOperation->isDisplayedOnStart(myCurrentSketch)) myCurrentSketch->setDisplayed(true); - - myCurrentSketch = CompositeFeaturePtr(); - myModule->workshop()->viewer()->removeSelectionFilter(myCirclePointFilter); - myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter); + myCurrentSketch = CompositeFeaturePtr(); + mySketchPlane->eraseSketchPlane(myModule->workshop()); Events_Loop::loop()->flush(aDispEvent); } - // restore the module selection modes, which were changed on startSketch - aConnector->activateModuleSelectionModes(); - aConnector->workshop()->displayer()->activateTrihedron(false); + workshop()->selectionActivate()->updateSelectionFilters(); + workshop()->selectionActivate()->updateSelectionModes(); + workshop()->viewer()->set2dMode(false); } void PartSet_SketcherMgr::startNestedSketch(ModuleBase_Operation* theOperation) @@ -975,10 +1281,10 @@ void PartSet_SketcherMgr::startNestedSketch(ModuleBase_Operation* theOperation) if (canChangeCursor(theOperation) && myIsMouseOverWindow) { QCursor* aCurrentCursor = QApplication::overrideCursor(); if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) { - QApplication::setOverrideCursor(QCursor(Qt::CrossCursor)); -#ifdef DEBUG_CURSOR - qDebug("startNestedSketch() : Qt::CrossCursor"); -#endif + QApplication::setOverrideCursor(PartSet_Tools::getOperationCursor()); +//#ifdef DEBUG_CURSOR +// qDebug("startNestedSketch() : Qt::CrossCursor"); +//#endif } } } @@ -987,17 +1293,35 @@ void PartSet_SketcherMgr::stopNestedSketch(ModuleBase_Operation* theOperation) { myIsMouseOverViewProcessed = true; operationMgr()->onValidateOperation(); + // when sketch nested operation is stopped the cursor should be restored unconditionally if (canChangeCursor(theOperation)) { QApplication::restoreOverrideCursor(); #ifdef DEBUG_CURSOR qDebug("stopNestedSketch() : None"); #endif } + /// improvement to deselect automatically all eventual selected objects, when + // returning to the neutral point of the Sketcher + bool isClearSelectionPossible = true; + if (myIsEditLaunching) { + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (theOperation); + if (aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); + if (aFeature.get() && PartSet_SketcherMgr::isEntity(aFeature->getKind())) { + isClearSelectionPossible = false; + } + } + } + if (isClearSelectionPossible) + workshop()->selector()->clearSelection(); + if (myPointsHighlight.size()) + onShowPoints(true); } void PartSet_SketcherMgr::commitNestedSketch(ModuleBase_Operation* theOperation) { - if (isNestedCreateOperation(theOperation)) { + if (isNestedCreateOperation(theOperation, activeSketch())) { ModuleBase_OperationFeature* aFOperation = dynamic_cast (theOperation); if (aFOperation) { @@ -1011,19 +1335,23 @@ void PartSet_SketcherMgr::commitNestedSketch(ModuleBase_Operation* theOperation) } } -void PartSet_SketcherMgr::activatePlaneFilter(const bool& toActivate) +bool PartSet_SketcherMgr::sketchSelectionFilter(const ModuleBase_SelectionFilterType theFilterType) { - if (toActivate) - myModule->workshop()->viewer()->addSelectionFilter(myPlaneFilter); - else - myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter); + return mySelectionFilterTypes.find(theFilterType) != mySelectionFilterTypes.end(); +} + +void PartSet_SketcherMgr::registerSelectionFilter( + const ModuleBase_SelectionFilterType theFilterType, const Handle(SelectMgr_Filter)& theFilter) +{ + mySelectionFilterTypes.insert(theFilterType); + myModule->registerSelectionFilter(theFilterType, theFilter); } bool PartSet_SketcherMgr::operationActivatedByPreselection() { bool isOperationStopped = false; ModuleBase_Operation* anOperation = getCurrentOperation(); - if(anOperation && PartSet_SketcherMgr::isNestedSketchOperation(anOperation)) { + if(anOperation && isNestedSketchOperation(anOperation)) { // Set final definitions if they are necessary //propertyPanelDefined(aOperation); /// Commit sketcher operations automatically @@ -1032,8 +1360,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(); @@ -1047,12 +1379,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 @@ -1060,19 +1392,7 @@ bool PartSet_SketcherMgr::canEraseObject(const ObjectPtr& theObject) const bool aCanErase = true; // when the sketch operation is active, results of sketch sub-feature can not be hidden if (myCurrentSketch.get()) { - ResultPtr aResult = std::dynamic_pointer_cast(theObject); - 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; - } - } - } + return !isObjectOfSketch(theObject); } return aCanErase; } @@ -1084,12 +1404,17 @@ bool PartSet_SketcherMgr::canDisplayObject(const ObjectPtr& theObject) const bool aHasActiveSketch = activeSketch().get() != NULL; if (aHasActiveSketch) { // 1. the sketch feature should not be displayed during the sketch active operation - // it is hidden by a sketch operation start and shown by a sketch stop, just the sketch + // it is hidden by a sketch operation start and shown by a sketch stop, just the sketch // nested features can be visualized FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); 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 @@ -1105,43 +1430,47 @@ 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 @@ -1168,8 +1497,6 @@ bool PartSet_SketcherMgr::canDisplayConstraint(const FeaturePtr& theFeature, 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); @@ -1203,7 +1530,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()); @@ -1279,7 +1606,7 @@ will be hidden: %1. Would you like to delete them?") } } } -} +}*/ bool PartSet_SketcherMgr::canDisplayCurrentCreatedFeature() const { @@ -1294,7 +1621,7 @@ bool PartSet_SketcherMgr::canDisplayCurrentCreatedFeature() const bool PartSet_SketcherMgr::canChangeCursor(ModuleBase_Operation* theOperation) const { - return isNestedCreateOperation(theOperation) || + return isNestedCreateOperation(theOperation, activeSketch()) || myModule->sketchReentranceMgr()->isInternalEditActive(); } @@ -1305,31 +1632,36 @@ const QMap& PartSet_SketcherMgr::sh bool PartSet_SketcherMgr::isObjectOfSketch(const ObjectPtr& theObject) const { - bool isFoundObject = false; - + if (!myCurrentSketch.get()) + return false; FeaturePtr anObjectFeature = ModelAPI_Feature::feature(theObject); if (anObjectFeature.get()) { int aSize = myCurrentSketch->numberOfSubs(); - for (int i = 0; i < myCurrentSketch->numberOfSubs() && !isFoundObject; i++) { - FeaturePtr aCurrentFeature = myCurrentSketch->subFeature(i); - isFoundObject = myCurrentSketch->subFeature(i) == anObjectFeature; + FeaturePtr aCurrentFeature; + for (int i = 0; i < aSize; i++) { + aCurrentFeature = myCurrentSketch->subFeature(i); + if (myCurrentSketch->subFeature(i) == anObjectFeature) + return true; } } - return isFoundObject; + return false; } -void PartSet_SketcherMgr::onPlaneSelected(const std::shared_ptr& thePln) +void PartSet_SketcherMgr::onPlaneSelected(const std::shared_ptr& thePlane) { - if (myPlaneFilter.IsNull()) - myPlaneFilter = new ModuleBase_ShapeInPlaneFilter(); + Handle(SelectMgr_Filter) aFilter = myModule->selectionFilter(SF_SketchPlaneFilter); + if (!aFilter.IsNull()) + Handle(ModuleBase_ShapeInPlaneFilter)::DownCast(aFilter)->setPlane(thePlane); - myPlaneFilter->setPlane(thePln); + workshop()->selectionActivate()->updateSelectionModes(); } 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); @@ -1371,10 +1703,10 @@ bool PartSet_SketcherMgr::setDistanceValueByPreselection(ModuleBase_Operation* t anAISIO = anAIS->impl(); } if (anAIS.get() != NULL) { - Handle(AIS_InteractiveObject) anAISIO = anAIS->impl(); + anAISIO = anAIS->impl(); if (!anAISIO.IsNull()) { - Handle(AIS_Dimension) aDim = Handle(AIS_Dimension)::DownCast(anAISIO); + Handle(PrsDim_Dimension) aDim = Handle(PrsDim_Dimension)::DownCast(anAISIO); if (!aDim.IsNull()) { gp_Pnt aPosition = aDim->GetTextPosition(); @@ -1391,6 +1723,7 @@ bool PartSet_SketcherMgr::setDistanceValueByPreselection(ModuleBase_Operation* t } anEditor->setCursorPosition(aX, anY); isValueAccepted = anEditor->showPopupEditor(false); + theCanCommitOperation = true; } } } @@ -1399,54 +1732,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, @@ -1457,10 +1742,9 @@ void PartSet_SketcherMgr::getSelectionOwners(const FeaturePtr& theFeature, return; FeatureToSelectionMap::const_iterator anIt = theSelection.find(theFeature); - std::set aSelectedAttributes = anIt.value().first; - std::set aSelectedResults = anIt.value().second; - - ModuleBase_IViewer* aViewer = theWorkshop->viewer(); + SelectionInfo anInfo = anIt.value(); + std::map aSelectedAttributes = anInfo.myAttributes; + std::set aSelectedResults = anInfo.myResults; XGUI_ModuleConnector* aConnector = dynamic_cast(theWorkshop); XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); @@ -1482,52 +1766,88 @@ void PartSet_SketcherMgr::getSelectionOwners(const FeaturePtr& theFeature, // 2. found the feature results's owners std::list aResults = theFeature->results(); std::list::const_iterator aIt; - for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) - { + + bool isSameShape = false; + if (aResults.size() > 0) { + ResultPtr aFirstResult = theFeature->firstResult(); + if (aFirstResult.get() && aFirstResult->shape().get()) { + TopoDS_Shape aFirstShape = aFirstResult->shape()->impl(); + isSameShape = aFirstShape.IsEqual(anInfo.myFirstResultShape); + } + } + 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(); + AISObjectPtr aResAISObj = aDisplayer->getAISObject(aResult); + if (aResAISObj.get() == NULL) + continue; + Handle(AIS_InteractiveObject) anAISIO = aResAISObj->impl(); - SelectMgr_IndexedMapOfOwner aSelectedOwners; + SelectMgr_IndexedMapOfOwner aSelectedOwners; aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners); + bool aFoundLocalShape = false; for ( Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++ ) { - Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast(aSelectedOwners(i)); - if ( anOwner.IsNull() || !anOwner->HasShape() ) + Handle(StdSelect_BRepOwner) anOwner = + Handle(StdSelect_BRepOwner)::DownCast(aSelectedOwners(i)); + if ( anOwner.IsNull() || !anOwner->HasShape() || theOwnersToSelect.FindIndex(anOwner)) continue; const TopoDS_Shape& aShape = anOwner->Shape(); TopAbs_ShapeEnum aShapeType = aShape.ShapeType(); if (aShapeType == TopAbs_VERTEX) { - AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(theFeature, aShape, theSketch); - if (aPntAttr.get() != NULL && - aSelectedAttributes.find(aPntAttr) != aSelectedAttributes.end()) { + std::pair aPntAttrIndex = + PartSet_Tools::findAttributeBy2dPoint(theFeature, aShape, theSketch); + if (aPntAttrIndex.first.get() != NULL && + aSelectedAttributes.find(aPntAttrIndex.first) != aSelectedAttributes.end()) + theOwnersToSelect.Add(anOwner); + else if (isSameShape && anInfo.myLocalSelectedShapes.Contains(aShape)) { theOwnersToSelect.Add(anOwner); } } else if (aShapeType == TopAbs_EDGE) { - bool aFound = aSelectedResults.find(aResult) != aSelectedResults.end(); - if (aSelectedResults.find(aResult) != aSelectedResults.end() && - theOwnersToSelect.FindIndex(anOwner) <= 0) + if (isSameShape && anInfo.myLocalSelectedShapes.Contains(aShape)) { + // try to restore local selection on Shape result + // we can do this only if the shape was not changed theOwnersToSelect.Add(anOwner); + aFoundLocalShape = true; + break; + } + } + } + if (!aFoundLocalShape) { + // result owners are put in the list of selection only if local selected shapes were not + // found + if (aSelectedResults.find(aResult) != aSelectedResults.end()) { + for (Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++ ) { + Handle(StdSelect_BRepOwner) anOwner = + Handle(StdSelect_BRepOwner)::DownCast(aSelectedOwners(i)); + if (anOwner.IsNull() || !anOwner->HasShape() || theOwnersToSelect.FindIndex(anOwner)) + continue; + // select whole result + theOwnersToSelect.Add(anOwner); + } } } } } -void PartSet_SketcherMgr::connectToPropertyPanel(ModuleBase_ModelWidget* theWidget, const bool isToConnect) +void PartSet_SketcherMgr::connectToPropertyPanel(ModuleBase_ModelWidget* theWidget, + const bool isToConnect) { + //Temporary commented as we do not modify values in property panel if (isToConnect) { - connect(theWidget, SIGNAL(beforeValuesChanged()), - this, SLOT(onBeforeValuesChangedInPropertyPanel())); + //connect(theWidget, SIGNAL(beforeValuesChanged()), + // this, SLOT(onBeforeValuesChangedInPropertyPanel())); + //connect(theWidget, SIGNAL(afterValuesChanged()), + // this, SLOT(onAfterValuesChangedInPropertyPanel())); connect(theWidget, SIGNAL(afterValuesChanged()), - this, SLOT(onAfterValuesChangedInPropertyPanel())); + myModule->sketchReentranceMgr(), SLOT(onAfterValuesChangedInPropertyPanel())); } else { - disconnect(theWidget, SIGNAL(beforeValuesChanged()), - this, SLOT(onBeforeValuesChangedInPropertyPanel())); + //disconnect(theWidget, SIGNAL(beforeValuesChanged()), + // this, SLOT(onBeforeValuesChangedInPropertyPanel())); + //disconnect(theWidget, SIGNAL(afterValuesChanged()), + // this, SLOT(onAfterValuesChangedInPropertyPanel())); disconnect(theWidget, SIGNAL(afterValuesChanged()), - this, SLOT(onAfterValuesChangedInPropertyPanel())); + myModule->sketchReentranceMgr(), SLOT(onAfterValuesChangedInPropertyPanel())); } } @@ -1536,8 +1856,8 @@ void PartSet_SketcherMgr::widgetStateChanged(int thePreviousState) ModuleBase_OperationFeature* aFOperation = dynamic_cast (getCurrentOperation()); if (aFOperation) { - if (PartSet_SketcherMgr::isSketchOperation(aFOperation) || - PartSet_SketcherMgr::isNestedSketchOperation(aFOperation) && + if ((PartSet_SketcherMgr::isSketchOperation(aFOperation) || + isNestedSketchOperation(aFOperation)) && thePreviousState == ModuleBase_ModelWidget::ModifiedInPP) { FeaturePtr aFeature = aFOperation->feature(); visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature)); @@ -1545,14 +1865,26 @@ 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))) - SketcherPrs_Tools::sendExpressionShownEvent(myIsConstraintsShown[PartSet_Tools::Expressions]); -} +//void PartSet_SketcherMgr::customisePresentation(const ObjectPtr& theObject) +//{ +// ModuleBase_OperationFeature* aFOperation = dynamic_cast +// (getCurrentOperation()); +// if (aFOperation && (PartSet_SketcherMgr::isSketchOperation(aFOperation) || +// isNestedSketchOperation(aFOperation))) +// SketcherPrs_Tools::sendExpressionShownEvent(myIsConstraintsShown[PartSet_Tools::Expressions]); +// +// // update entities selection priorities +// FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); +// if (aFeature.get() && PartSet_SketcherMgr::isEntity(aFeature->getKind())) { +// // update priority for feature +// updateSelectionPriority(aFeature, aFeature); +// // update priority for results of the feature +// std::list aResults = aFeature->results(); +// std::list::const_iterator anIt = aResults.begin(), aLastIt = aResults.end(); +// for (; anIt != aLastIt; anIt++) +// updateSelectionPriority(*anIt, aFeature); +// } +//} ModuleBase_Operation* PartSet_SketcherMgr::getCurrentOperation() const { @@ -1584,9 +1916,6 @@ void PartSet_SketcherMgr::visualizeFeature(const FeaturePtr& theFeature, if (isEditOperation || !theFeature.get()) return; - ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); - XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); - // 1. change visibility of the object itself, here the presentable object is processed, // e.g. constraints features //FeaturePtr aFeature = aFOperation->feature(); @@ -1610,52 +1939,97 @@ void PartSet_SketcherMgr::visualizeFeature(const FeaturePtr& theFeature, Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); } -void PartSet_SketcherMgr::storeSelection(const bool theHighlightedOnly) +void PartSet_SketcherMgr::storeSelection(const SelectionType theType, + PartSet_SketcherMgr::FeatureToSelectionMap& theCurrentSelection) { if (!myCurrentSketch.get()) return; ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); ModuleBase_ISelection* aSelect = aWorkshop->selection(); - QList aHighlighted = aSelect->getHighlighted(); + QList aStoredPrs; - QList aFeatureList; - if (theHighlightedOnly) { - fillFeatureList(aHighlighted, myCurrentSketch, aFeatureList); - } - else { - fillFeatureList(aHighlighted, myCurrentSketch, aFeatureList); + if (theType == ST_HighlightType || theType == ST_SelectAndHighlightType) + aStoredPrs = aSelect->getHighlighted(); - QList aSelected = aSelect->getSelected(ModuleBase_ISelection::AllControls); - fillFeatureList(aSelected, myCurrentSketch, aFeatureList); + QList aFeatureList; + if (theType == ST_SelectAndHighlightType || theType == ST_SelectType) { + 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(); + theCurrentSelection.clear(); + + 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); + + if (!aFeature.get()) + continue; + + std::set aSelectedAttributes; + std::set aSelectedResults; + SelectionInfo anInfo; + if (theCurrentSelection.find(aFeature) != theCurrentSelection.end()) + anInfo = theCurrentSelection.find(aFeature).value(); + + TopoDS_Shape aFirstShape; + ResultPtr aFirstResult = aFeature->firstResult(); + if (aFirstResult.get() && aFirstResult->shape().get()) + aFirstShape = aFirstResult->shape()->impl(); + anInfo.myFirstResultShape = aFirstShape; + Handle(SelectMgr_EntityOwner) anOwner = aPrs->owner(); + if (aResult.get()) { + getAttributesOrResults(anOwner, aFeature, aSketch, aResult, + anInfo.myAttributes, anInfo.myResults, anInfo.myLocalSelectedShapes); + } + else { + std::list aResults = aFeature->results(); + std::list::const_iterator aIt; + for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { + ResultPtr aCurResult = *aIt; + getAttributesOrResults(anOwner, aFeature, aSketch, aCurResult, + anInfo.myAttributes, anInfo.myResults, anInfo.myLocalSelectedShapes); + } + } + theCurrentSelection[aFeature] = anInfo; } - //qDebug(QString(" storeSelection: %1").arg(myCurrentSelection.size()).toStdString().c_str()); + //qDebug(QString(" storeSelection: %1").arg(theCurrentSelection.size()).toStdString().c_str()); } -void PartSet_SketcherMgr::restoreSelection() +void PartSet_SketcherMgr::restoreSelection( + PartSet_SketcherMgr::FeatureToSelectionMap& theCurrentSelection) { if (!myCurrentSketch.get()) return; - //qDebug(QString("restoreSelection: %1").arg(myCurrentSelection.size()).toStdString().c_str()); + //qDebug(QString("restoreSelection: %1").arg(theCurrentSelection.size()).toStdString().c_str()); ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); - FeatureToSelectionMap::const_iterator aSIt = myCurrentSelection.begin(), - aSLast = myCurrentSelection.end(); + FeatureToSelectionMap::const_iterator aSIt = theCurrentSelection.begin(), + aSLast = theCurrentSelection.end(); SelectMgr_IndexedMapOfOwner anOwnersToSelect; + anOwnersToSelect.Clear(); for (; aSIt != aSLast; aSIt++) { - anOwnersToSelect.Clear(); - getSelectionOwners(aSIt.key(), myCurrentSketch, aWorkshop, myCurrentSelection, - anOwnersToSelect); - aConnector->workshop()->selector()->setSelectedOwners(anOwnersToSelect, false); + getSelectionOwners(aSIt.key(), myCurrentSketch, aWorkshop, theCurrentSelection, + anOwnersToSelect); } + aConnector->workshop()->selector()->setSelectedOwners(anOwnersToSelect, false); } void PartSet_SketcherMgr::onShowConstraintsToggle(int theType, bool theState) @@ -1663,6 +2037,7 @@ void PartSet_SketcherMgr::onShowConstraintsToggle(int theType, bool theState) PartSet_Tools::ConstraintVisibleState aType = (PartSet_Tools::ConstraintVisibleState)theType; updateBySketchParameters(aType, theState); + myModule->workshop()->viewer()->update(); } void PartSet_SketcherMgr::updateBySketchParameters( @@ -1679,9 +2054,8 @@ void PartSet_SketcherMgr::updateBySketchParameters( 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++) { + int aNumberOfSubs = myCurrentSketch->numberOfSubs(); + for (int i = 0; i < aNumberOfSubs; i++) { FeaturePtr aSubFeature = myCurrentSketch->subFeature(i); bool aProcessed = false; bool aConstraintDisplayed = canDisplayConstraint(aSubFeature, theType, aProcessed); @@ -1693,12 +2067,67 @@ 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 + SketcherPrs_Tools::ParameterStyle aStyle = myIsConstraintsShown[PartSet_Tools::Expressions] + ? SketcherPrs_Tools::ParameterText : SketcherPrs_Tools::ParameterValue; + SketcherPrs_Tools::setParameterStyle(aStyle); + Events_ID anEventId = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); + PartSet_Tools::sendSubFeaturesEvent(myCurrentSketch, anEventId); + } } break; + default: // [to avoid compilation warning] + 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); + } + } } } @@ -1714,3 +2143,274 @@ XGUI_OperationMgr* PartSet_SketcherMgr::operationMgr() const return workshop()->operationMgr(); } +void PartSet_SketcherMgr::onShowPoints(bool toShow) +{ + if (!myCurrentSketch.get()) + return; + ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); + ModuleBase_IViewer* aViewer = aWorkshop->viewer(); + Handle(AIS_InteractiveContext) aContext = aViewer->AISContext(); + + bool aToUpdate = false; + if (toShow) { + std::list aFreePoints = SketcherPrs_Tools::getFreePoints(myCurrentSketch); + + // Delete obsolete presentations + std::list aDelList; + foreach(ResultPtr aObj, myPointsHighlight.keys()) { + bool aFound = (std::find(aFreePoints.begin(), aFreePoints.end(), aObj) != aFreePoints.end()); + if (!aFound) + aDelList.push_back(aObj); + } + foreach(ResultPtr aObj, aDelList) { + aContext->Remove(myPointsHighlight[aObj], false); + aToUpdate = true; + myPointsHighlight.remove(aObj); + } + + // Display new objects + QList aKeysList = myPointsHighlight.keys(); + std::list::const_iterator aIt; + for (aIt = aFreePoints.cbegin(); aIt != aFreePoints.cend(); aIt++) { + if (!aKeysList.contains(*aIt)) { + GeomShapePtr aShapePtr = (*aIt)->shape(); + TopoDS_Shape aShape = aShapePtr->impl(); + Handle(AIS_Shape) aShapePrs = new AIS_Shape(aShape); + aShapePrs->SetColor(Quantity_NOC_BLUE1); + aShapePrs->SetZLayer(Graphic3d_ZLayerId_Top); + Handle(Prs3d_Drawer) aDrawer = aShapePrs->Attributes(); + if (aDrawer->HasOwnPointAspect()) { + aDrawer->PointAspect()->SetTypeOfMarker(Aspect_TOM_O_STAR); + aDrawer->PointAspect()->SetColor(Quantity_NOC_BLUE1); + aDrawer->PointAspect()->SetScale(2); + } + else + aDrawer->SetPointAspect(new Prs3d_PointAspect(Aspect_TOM_O_STAR, Quantity_NOC_BLUE1, 2)); + aContext->Display(aShapePrs, false); + aContext->Deactivate(aShapePrs); + myPointsHighlight[*aIt] = aShapePrs; + aToUpdate = true; + } + } + } + else { + foreach(Handle(AIS_Shape) aPrs, myPointsHighlight.values()) { + aContext->Remove(aPrs, false); + aToUpdate = true; + } + myPointsHighlight.clear(); + } + if (aToUpdate) + aViewer->update(); +} + +void PartSet_SketcherMgr::processEvent(const std::shared_ptr& theMessage) +{ + if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOF_OBJECTS)) { + std::shared_ptr anUpdateMsg = + std::dynamic_pointer_cast(theMessage); + std::set aObjects = anUpdateMsg->objects(); + std::set::const_iterator aIt; + QList aPrsList; + for (aIt = aObjects.cbegin(); aIt != aObjects.cend(); aIt++) { + FeaturePtr aFeature = std::dynamic_pointer_cast(*aIt); + if (aFeature.get()) { + std::list aRes = aFeature->results(); + std::list::const_iterator aRIt; + for (aRIt = aRes.cbegin(); aRIt != aRes.cend(); ++aRIt) { + ModuleBase_ViewerPrsPtr aPrsPtr(new ModuleBase_ViewerPrs(*aRIt)); + aPrsList.append(aPrsPtr); + } + } + } + if (aPrsList.size() > 0) { + myModule->workshop()->setSelected(aPrsList); + } + } +} + +bool isExternal(const ObjectPtr& theObject) +{ + AttributeSelectionPtr aAttr = + theObject->data()->selection(SketchPlugin_SketchEntity::EXTERNAL_ID()); + if (aAttr) + return aAttr->context().get() != NULL && !aAttr->isInvalid(); + return false; +} + +bool isCopy(const ObjectPtr& theObject) +{ + AttributeBooleanPtr anAttr = theObject->data()->boolean(SketchPlugin_SketchEntity::COPY_ID()); + if (anAttr.get()) + return anAttr->value(); + return false; +} + +bool isIncludeToResult(const ObjectPtr& theObject) +{ + AttributeBooleanPtr anAttr; + std::set aRefsToMe = theObject->data()->refsToMe(); + std::set::const_iterator aIt; + for (aIt = aRefsToMe.cbegin(); aIt != aRefsToMe.cend(); ++aIt) { + if ((*aIt)->id() == SketchPlugin_Projection::PROJECTED_FEATURE_ID()) { + FeaturePtr aFeature = std::dynamic_pointer_cast((*aIt)->owner()); + if (aFeature.get() && !aFeature->isMacro()) { + anAttr = aFeature->data()->boolean(SketchPlugin_Projection::INCLUDE_INTO_RESULT()); + if (anAttr.get()) + return anAttr->value(); + } + } + } + return true; +} + +//************************************************************************************** +std::vector PartSet_SketcherMgr::colorOfObject(const ObjectPtr& theObject, + const FeaturePtr& theFeature, bool isConstruction) const +{ + PartSet_OverconstraintListener* aOCListener = myModule->overconstraintListener(); + std::string aKind = theFeature->getKind(); + + if (aOCListener->isConflictingObject(theObject)) { + return Config_PropManager::color("Visualization", "sketch_overconstraint_color"); + } + if (isDistanceKind(aKind)) { + return Config_PropManager::color("Visualization", "sketch_dimension_color"); + } + if (isExternal(theFeature)) + return Config_PropManager::color("Visualization", "sketch_external_color"); + + if (aOCListener->isFullyConstrained()) { + return Config_PropManager::color("Visualization", "sketch_fully_constrained_color"); + } + if (aKind == SketchPlugin_ConstraintCoincidence::ID()) + return std::vector(3, 0); + + if (isConstruction) + return Config_PropManager::color("Visualization", "sketch_auxiliary_color"); + + return Config_PropManager::color("Visualization", "sketch_entity_color"); +} + +//************************************************************************************** +void PartSet_SketcherMgr::customizeSketchPresentation(const ObjectPtr& theObject, + const AISObjectPtr& thePrs) const +{ + FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); + + // set color from preferences + std::shared_ptr anAuxiliaryAttr = + aFeature->data()->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID()); + bool isConstruction = anAuxiliaryAttr.get() != NULL && anAuxiliaryAttr->value(); + + std::vector aColor = colorOfObject(theObject, aFeature, isConstruction); + if (!aColor.empty()) { + // The code below causes redisplay again + if (ModelAPI_Session::get()->isOperation()) { + AttributeIntArrayPtr aColorAttr = theObject->data()->intArray(ModelAPI_Result::COLOR_ID()); + if (aColorAttr.get()) { + aColorAttr->setSize(3, false); + // Set the color attribute in order do not use default colors in the presentation object + for (int i = 0; i < 3; i++) + aColorAttr->setValue(i, aColor[i], false); + } + } + thePrs->setColor(aColor[0], aColor[1], aColor[2]); + } + + int aShapeType = thePrs->getShapeType(); + // a compound is processed like the edge because the + // arc feature uses the compound for presentable AIS + if (aShapeType != 6/*an edge*/ && aShapeType != 7/*a vertex*/ && aShapeType != 0/*compound*/) + return; + + int aWidth = Config_PropManager::integer("Visualization", "sketch_line_width"); + if (isExternal(aFeature)) { + thePrs->setWidth(isIncludeToResult(aFeature)? aWidth : 1); + return; + } + std::string aKind = aFeature->getKind(); + if (isDistanceKind(aKind)) + return; + + if (aShapeType == 6 || aShapeType == 0) { // if this is an edge or a compound + if (isConstruction) { + // Set axilliary line + thePrs->setWidth(SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH_AUXILIARY()); + thePrs->setLineStyle(SketchPlugin_SketchEntity::SKETCH_LINE_STYLE_AUXILIARY()); + } + else { + thePrs->setWidth(aWidth); + thePrs->setLineStyle(SketchPlugin_SketchEntity::SKETCH_LINE_STYLE()); + } + } + else if (aShapeType == 7) { // otherwise this is a vertex + // The width value do not have effect on the point presentation. + // It is defined in order to extend selection area of the object. + thePrs->setWidth(17); + // thePrs->setPointMarker(1, 1.); // Set point as a '+' symbol + } + if (isCopy(aFeature) || !isIncludeToResult(aFeature)) { + double aPrsWidth = thePrs->width(); + thePrs->setWidth(aPrsWidth / 2.5); + } + + double aDeflection = Config_PropManager::real("Visualization", "construction_deflection"); + thePrs->setDeflection(aDeflection); +} + +//************************************************************************************* +void PartSet_Fitter::fitAll(Handle(V3d_View) theView) +{ + CompositeFeaturePtr aSketch = mySketchMgr->activeSketch(); + + ModuleBase_IWorkshop* aWorkshop = mySketchMgr->module()->workshop(); + XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); + XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); + + Bnd_Box aBndBox; + int aNumberOfSubs = aSketch->numberOfSubs(); + double aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; + for (int i = 0; i < aNumberOfSubs; i++) { + FeaturePtr aFeature = aSketch->subFeature(i); + if (aDisplayer->isVisible(aFeature)) { + AISObjectPtr aAisPtr = aDisplayer->getAISObject(aFeature); + Handle(AIS_InteractiveObject) aAisObj = aAisPtr->impl(); + if (!aAisObj->IsInfinite()) { + Bnd_Box aBox; + aAisObj->BoundingBox(aBox); + aBndBox.Add(aBox); + } + } + else { + std::list aResults = aFeature->results(); + std::list::const_iterator aIt; + ResultPtr aRes; + for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { + aRes = (*aIt); + if (aRes->isDisplayed()) { + FeaturePtr aCurFeature = ModelAPI_Feature::feature(aRes); + if (aCurFeature.get()) { + std::shared_ptr aSPFeature = + std::dynamic_pointer_cast(aCurFeature); + if (aSPFeature.get()) { + bool isAxiliary = + aSPFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value(); + if (!(aSPFeature->isExternal() || isAxiliary)) { + GeomShapePtr aShape = aRes->shape(); + aShape->computeSize(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); + Bnd_Box aBox; + aBox.Update(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); + aBndBox.Add(aBox); + } + } + } + } + } + } + } + if (aBndBox.IsVoid()) + theView->FitAll(); + else + theView->FitAll(aBndBox, 0.01); +}