-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: PartSet_SketcherMgr.cpp
-// Created: 19 Dec 2014
-// Author: Vitaly SMETANNIKOV
-
-#include "PartSet_SketcherMgr.h"
-#include "PartSet_SketcherReetntrantMgr.h"
-#include "PartSet_Module.h"
-#include "PartSet_MouseProcessor.h"
-#include "PartSet_Tools.h"
-#include "PartSet_WidgetSketchLabel.h"
-#include "PartSet_WidgetEditor.h"
-#include "PartSet_ResultSketchPrs.h"
-
-#include <XGUI_ModuleConnector.h>
-#include <XGUI_Displayer.h>
-#include <XGUI_Workshop.h>
-#include <XGUI_ContextMenuMgr.h>
-#include <XGUI_Selection.h>
-#include <XGUI_SelectionMgr.h>
-#include <XGUI_ModuleConnector.h>
-#include <XGUI_PropertyPanel.h>
-#include <XGUI_ViewerProxy.h>
-#include <XGUI_OperationMgr.h>
-#include <XGUI_ErrorMgr.h>
-#include <XGUI_Tools.h>
-
-#include <ModuleBase_IPropertyPanel.h>
-#include <ModuleBase_ISelection.h>
-#include <ModuleBase_IViewer.h>
-#include <ModuleBase_IWorkshop.h>
-#include <ModuleBase_IViewWindow.h>
-#include <ModuleBase_ModelWidget.h>
-#include <ModuleBase_Operation.h>
-#include <ModuleBase_OperationFeature.h>
-#include <ModuleBase_Operation.h>
-#include <ModuleBase_WidgetEditor.h>
-#include <ModuleBase_ViewerPrs.h>
-#include <ModuleBase_Tools.h>
-#include <ModuleBase_ResultPrs.h>
-
-#include <GeomDataAPI_Point2D.h>
-
-#include <Events_Loop.h>
-
-#include <SketchPlugin_Line.h>
-#include <SketchPlugin_Sketch.h>
-#include <SketchPlugin_Point.h>
-#include <SketchPlugin_Arc.h>
-#include <SketchPlugin_Circle.h>
-#include <SketchPlugin_ConstraintLength.h>
-#include <SketchPlugin_ConstraintDistance.h>
-#include <SketchPlugin_ConstraintParallel.h>
-#include <SketchPlugin_ConstraintPerpendicular.h>
-#include <SketchPlugin_ConstraintRadius.h>
-#include <SketchPlugin_ConstraintRigid.h>
-#include <SketchPlugin_ConstraintHorizontal.h>
-#include <SketchPlugin_ConstraintVertical.h>
-#include <SketchPlugin_ConstraintEqual.h>
-#include <SketchPlugin_ConstraintTangent.h>
-#include <SketchPlugin_ConstraintCoincidence.h>
-#include <SketchPlugin_ConstraintFillet.h>
-#include <SketchPlugin_ConstraintMirror.h>
-#include <SketchPlugin_ConstraintAngle.h>
-#include <SketchPlugin_ConstraintCollinear.h>
-#include <SketchPlugin_ConstraintMiddle.h>
-#include <SketchPlugin_MultiRotation.h>
-#include <SketchPlugin_MultiTranslation.h>
-#include <SketchPlugin_IntersectionPoint.h>
-
-#include <SketcherPrs_Tools.h>
-
-#include <SelectMgr_IndexedMapOfOwner.hxx>
-#include <StdSelect_BRepOwner.hxx>
-
-//#include <AIS_DimensionSelectionMode.hxx>
-#include <AIS_Shape.hxx>
-#include <AIS_Dimension.hxx>
-
-#include <ModelAPI_Events.h>
-#include <ModelAPI_Session.h>
-#include <ModelAPI_AttributeString.h>
-
-#include <ModelAPI_Validator.h>
-#include <ModelAPI_Tools.h>
-
-#include <QMouseEvent>
-#include <QApplication>
-#include <QCursor>
-#include <QMessageBox>
-#include <QMainWindow>
-
-//#define DEBUG_DO_NOT_BY_ENTER
-//#define DEBUG_SKETCHER_ENTITIES
-//#define DEBUG_SKETCH_ENTITIES_ON_MOVE
-
-//#define DEBUG_CURSOR
-
-/// 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.
-/// \param theOwner a viewer selected owner
-/// \param theFeature a feature, where the attribute is searched
-/// \param theSketch a current sketch
-/// \param theSelectedAttribute an output list of attributes
-/// \param theSelectedResults an output list of edge results
-void getAttributesOrResults(const Handle(SelectMgr_EntityOwner)& theOwner,
- const FeaturePtr& theFeature, const FeaturePtr& theSketch,
- const ResultPtr& theResult,
- std::set<AttributePtr>& aSelectedAttributes,
- std::set<ResultPtr>& aSelectedResults)
-{
- Handle(StdSelect_BRepOwner) aBRepOwner = Handle(StdSelect_BRepOwner)::DownCast(theOwner);
- if (aBRepOwner.IsNull())
- return;
- Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast(
- aBRepOwner->Selectable());
- if (aBRepOwner->HasShape()) {
- const TopoDS_Shape& aShape = aBRepOwner->Shape();
- TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
- if (aShapeType == TopAbs_VERTEX) {
- AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(theFeature,
- aShape, theSketch);
- if (aPntAttr.get() != NULL)
- aSelectedAttributes.insert(aPntAttr);
- }
- else if (aShapeType == TopAbs_EDGE &&
- aSelectedResults.find(theResult) == aSelectedResults.end()) {
- aSelectedResults.insert(theResult);
- }
- }
-}
-
-PartSet_SketcherMgr::PartSet_SketcherMgr(PartSet_Module* theModule)
- : QObject(theModule), myModule(theModule), myIsDragging(false), myDragDone(false),
- myIsMouseOverWindow(false),
- myIsMouseOverViewProcessed(true), myPreviousUpdateViewerEnabled(true),
- myIsPopupMenuActive(false)
-{
- ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();
- ModuleBase_IViewer* aViewer = anIWorkshop->viewer();
-
- myPreviousDrawModeEnabled = true;//aViewer->isSelectionEnabled();
-
- connect(aViewer, SIGNAL(mousePress(ModuleBase_IViewWindow*, QMouseEvent*)),
- this, SLOT(onMousePressed(ModuleBase_IViewWindow*, QMouseEvent*)));
-
- connect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)),
- this, SLOT(onMouseReleased(ModuleBase_IViewWindow*, QMouseEvent*)));
-
- connect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)),
- this, SLOT(onMouseMoved(ModuleBase_IViewWindow*, QMouseEvent*)));
-
- connect(aViewer, SIGNAL(mouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*)),
- this, SLOT(onMouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*)));
-
- XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(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()
-{
- if (!myPlaneFilter.IsNull())
- myPlaneFilter.Nullify();
-}
-
-void PartSet_SketcherMgr::onEnterViewPort()
-{
- // 1. if the mouse over window, update the next flag. Do not perform update visibility of
- // created feature because it should be done in onMouseMove(). Some widgets watch
- // the mouse move and use the cursor position to update own values. If the presentaion is
- // redisplayed before this update, the feature presentation jumps from reset value to current.
- myIsMouseOverWindow = true;
-
- #ifdef DEBUG_DO_NOT_BY_ENTER
- 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
- }
- }
-
- if (!isNestedCreateOperation(getCurrentOperation(), activeSketch()))
- return;
-
- operationMgr()->onValidateOperation();
-
- // we need change displayed state of the current operation feature
- // if the feature is presentable, e.g. distance construction. It has no results, so workshop does
- // not accept a signal about the result created. Nothing is shown until mouse is moved out/in view
- // port. If the isDisplayed flag is true, the presentable feature is displayed as soon as the
- // presentation becomes valid and redisplay happens
- //ModuleBase_Operation* aOperation = getCurrentOperation();
- ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
- (getCurrentOperation());
- if (aFOperation) {
- FeaturePtr aFeature = aFOperation->feature();
- if (aFeature.get() && aFeature->data()->isValid()) {
- visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature), false);
- }
- }
-}
-
-void PartSet_SketcherMgr::onLeaveViewPort()
-{
- myIsMouseOverViewProcessed = false;
- myIsMouseOverWindow = false;
-
- #ifdef DEBUG_DO_NOT_BY_ENTER
- return;
- #endif
-
- if (canChangeCursor(getCurrentOperation())) {
- QApplication::restoreOverrideCursor();
-#ifdef DEBUG_CURSOR
- qDebug("onLeaveViewPort() : None");
-#endif
- }
-
- if (!isNestedCreateOperation(getCurrentOperation(), activeSketch()))
- return;
-
- // the method should be performed if the popup menu is called,
- // the reset of the current widget should not happen
- 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
- ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
- XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
- XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
- // disable the viewer update in order to avoid visualization of redisplayed feature in viewer
- // obtained after reset value
- bool isEnableUpdateViewer = aDisplayer->enableUpdateViewer(false);
- ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
- if (anActiveWidget)
- anActiveWidget->reset();
-
- // hides the presentation of the current operation feature
- // 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<ModuleBase_OperationFeature*>
- (getCurrentOperation());
- if (aFOperation) {
- FeaturePtr aFeature = aFOperation->feature();
- visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature));
- }
- // we should update viewer after the presentation are hidden in the viewer
- // otherwise the reset presentation(line) appears in the viewer(by quick move from viewer to PP)
- aDisplayer->enableUpdateViewer(isEnableUpdateViewer);
-}
-
-void PartSet_SketcherMgr::onBeforeValuesChangedInPropertyPanel()
-{
- 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();
-
- ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
- XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
- XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
- myPreviousUpdateViewerEnabled = aDisplayer->enableUpdateViewer(false);
-}
-
-void PartSet_SketcherMgr::onAfterValuesChangedInPropertyPanel()
-{
- 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();
-
- // 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();
- XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
- XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
- aDisplayer->enableUpdateViewer(myPreviousUpdateViewerEnabled);
- aDisplayer->updateViewer();
-
-
-}
-
-void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
-{
- 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;
-
- ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
- (getCurrentOperation());
- if (!aFOperation)
- return;
-
- if (aFOperation->isEditOperation()) {
- // If the current widget is a selector, do nothing, it processes the mouse press
- ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
- if(anActiveWidget && anActiveWidget->isViewerSelector()) {
- return;
- }
- }
-
- // Use only for sketch operations
- if (myCurrentSketch) {
- if (!PartSet_Tools::sketchPlane(myCurrentSketch))
- return;
-
- bool isSketcher = isSketchOperation(aFOperation);
- bool isSketchOpe = isNestedSketchOperation(aFOperation);
-
- // Avoid non-sketch operations
- if ((!isSketchOpe) && (!isSketcher))
- return;
-
- bool isEditing = aFOperation->isEditOperation();
-
- // Ignore creation sketch operation
- if ((!isSketcher) && (!isEditing))
- return;
-
- Handle(AIS_InteractiveContext) aContext = aViewer->AISContext();
- // Remember highlighted objects for editing
- ModuleBase_ISelection* aSelect = aWorkshop->selection();
-
- bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
- storeSelection(!aHasShift);
-
- if (myCurrentSelection.empty()) {
- if (isSketchOpe && (!isSketcher))
- // commit previous operation
- if (!aFOperation->commit())
- aFOperation->abort();
- return;
- }
- // Init flyout point for radius rotation
- FeaturePtr aFeature = myCurrentSelection.begin().key();
-
- if (isSketcher) {
- myIsDragging = true;
- get2dPoint(theWnd, theEvent, myCurrentPoint);
- myDragDone = false;
-
- myPreviousDrawModeEnabled = aViewer->enableDrawMode(false);
- // selection should be restored before edit operation start to process the
- // selected entities, e.g. selection of point(attribute on a line) should edit the point
- restoreSelection();
- launchEditing();
- if (aFeature.get() != NULL) {
- std::shared_ptr<SketchPlugin_Feature> aSPFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
- if (aSPFeature.get() && aSPFeature->getKind() == SketchPlugin_ConstraintRadius::ID()) {
- DataPtr aData = aSPFeature->data();
- AttributePtr aAttr = aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT());
- std::shared_ptr<GeomDataAPI_Point2D> aFPAttr =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(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);
- // 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();
- }
- }
-}
-
-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())
- return;
- ModuleBase_Operation* aOp = getCurrentOperation();
- if (aOp) {
- if (isNestedSketchOperation(aOp)) {
- // Only for sketcher operations
- if (myIsDragging) {
- if (myDragDone) {
- myCurrentSelection.clear();
- }
- }
- }
- }
-
- aWorkshop->viewer()->enableDrawMode(myPreviousDrawModeEnabled);
- myIsDragging = false;
-
- ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
- PartSet_MouseProcessor* aProcessor = dynamic_cast<PartSet_MouseProcessor*>(anActiveWidget);
- if (aProcessor)
- aProcessor->mouseReleased(theWnd, theEvent);
-}
-
-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(), 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 = myModule->activeWidget();
- PartSet_MouseProcessor* aProcessor = dynamic_cast<PartSet_MouseProcessor*>(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<ModuleBase_OperationFeature*>
- (getCurrentOperation());
- if (aFOperation) {
- FeaturePtr aFeature = aFOperation->feature();
- visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature));
- }
- }
- }
- //myClickedPoint.clear();
-
- if (myIsDragging) {
- // 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
-
- 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<XGUI_ModuleConnector*>(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
- // 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);
-
- 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();
- // 4. the features and attributes modification(move)
- bool isModified = false;
- for (; anIt != aLast; anIt++) {
- FeaturePtr aFeature = anIt.key();
-
- std::set<AttributePtr> anAttributes = anIt.value().first;
- // Process selection by attribute: the priority to the attribute
- if (!anAttributes.empty()) {
- std::set<AttributePtr>::const_iterator anAttIt = anAttributes.begin(),
- anAttLast = anAttributes.end();
- for (; anAttIt != anAttLast; anAttIt++) {
- AttributePtr anAttr = *anAttIt;
- if (anAttr.get() == NULL)
- continue;
- std::string aAttrId = anAttr->id();
- DataPtr aData = aFeature->data();
- if (aData->isValid()) {
- std::shared_ptr<GeomDataAPI_Point2D> aPoint =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(aAttrId));
- if (aPoint.get() != NULL) {
- bool isImmutable = aPoint->setImmutable(true);
- aPoint->move(dX, dY);
- isModified = true;
- ModelAPI_EventCreator::get()->sendUpdated(aFeature, aMoveEvent);
- aPoint->setImmutable(isImmutable);
- }
- }
- }
- } else {
- // Process selection by feature
- std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
- if (aSketchFeature) {
- aSketchFeature->move(dX, dY);
- isModified = true;
- ModelAPI_EventCreator::get()->sendUpdated(aSketchFeature, aMoveEvent);
- }
- }
- }
- // the modified state of the current operation should be updated if there are features, which
- // 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(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();
- // 6. restore the update viewer flag and call this update
- aDisplayer->enableUpdateViewer(isEnableUpdateViewer);
- aDisplayer->updateViewer();
-
- myDragDone = true;
- myCurrentPoint.setValue(aX, aY);
- }
-}
-
-void PartSet_SketcherMgr::onMouseDoubleClick(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
-{
- ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
- (getCurrentOperation());
- if (aFOperation && aFOperation->isEditOperation()) {
- std::string aId = aFOperation->id().toStdString();
- if (isDistanceOperation(aFOperation))
- {
- // Activate dimension value editing on double click
- ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel();
- QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();
- // Find corresponded widget to activate value editing
- foreach (ModuleBase_ModelWidget* aWgt, aWidgets) {
- if (aWgt->attributeID() == SketchPlugin_Constraint::VALUE() ||
- aWgt->attributeID() == SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()) {
- PartSet_WidgetEditor* anEditor = dynamic_cast<PartSet_WidgetEditor*>(aWgt);
- if (anEditor)
- anEditor->showPopupEditor();
- return;
- }
- }
- }
- }
-}
-
-void PartSet_SketcherMgr::onApplicationStarted()
-{
- ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();
- XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(anIWorkshop);
- XGUI_Workshop* aWorkshop = aConnector->workshop();
- PartSet_SketcherReetntrantMgr* aReentranceMgr = myModule->sketchReentranceMgr();
-
- XGUI_PropertyPanel* aPropertyPanel = aWorkshop->propertyPanel();
- if (aPropertyPanel) {
- //connect(aPropertyPanel, SIGNAL(beforeWidgetActivated(ModuleBase_ModelWidget*)),
- // this, SLOT(onBeforeWidgetActivated(ModuleBase_ModelWidget*)));
-
- connect(aPropertyPanel, SIGNAL(noMoreWidgets(const std::string&)),
- aReentranceMgr, SLOT(onNoMoreWidgets(const std::string&)));
- connect(aPropertyPanel, SIGNAL(widgetActivated(ModuleBase_ModelWidget*)),
- aReentranceMgr, SLOT(onWidgetActivated()));
- }
-
- XGUI_ViewerProxy* aViewerProxy = aWorkshop->viewer();
- connect(aViewerProxy, SIGNAL(enterViewPort()), this, SLOT(onEnterViewPort()));
- connect(aViewerProxy, SIGNAL(leaveViewPort()), this, SLOT(onLeaveViewPort()));
-
- XGUI_ContextMenuMgr* aContextMenuMgr = aWorkshop->contextMenuMgr();
- connect(aContextMenuMgr, SIGNAL(beforeContextMenu()), this, SLOT(onBeforeContextMenu()));
- connect(aContextMenuMgr, SIGNAL(afterContextMenu()), this, SLOT(onAfterContextMenu()));
-}
-
-//void PartSet_SketcherMgr::onBeforeWidgetActivated(ModuleBase_ModelWidget* theWidget)
-//{
- //if (!myClickedPoint.myIsInitialized)
- // return;
-
- //ModuleBase_Operation* aOperation = getCurrentOperation();
- // the distance constraint feature should not use the clickedd point
- // this is workaround in order to don't throw down the flyout point value,
- // set by execute() method of these type of features
- //if (isDistanceOperation(aOperation))
- // return;
-
- //PartSet_WidgetPoint2D* aPnt2dWgt = dynamic_cast<PartSet_WidgetPoint2D*>(theWidget);
- //if (aPnt2dWgt) {
- // aPnt2dWgt->setPoint(myClickedPoint.myCurX, myClickedPoint.myCurY);
- //}
-//}
-
-void PartSet_SketcherMgr::onBeforeContextMenu()
-{
- myIsPopupMenuActive = true;
-}
-
-void PartSet_SketcherMgr::onAfterContextMenu()
-{
- myIsPopupMenuActive = false;
-}
-
-void PartSet_SketcherMgr::get2dPoint(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent,
- Point& thePoint)
-{
- Handle(V3d_View) aView = theWnd->v3dView();
- gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);
- double aX, anY;
- PartSet_Tools::convertTo2D(aPoint, myCurrentSketch, aView, aX, anY);
- thePoint.setValue(aX, anY);
-}
-
-void PartSet_SketcherMgr::launchEditing()
-{
- if (!myCurrentSelection.empty()) {
- FeaturePtr aFeature = myCurrentSelection.begin().key();
- std::shared_ptr<SketchPlugin_Feature> aSPFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
- if (aSPFeature && (!aSPFeature->isExternal())) {
- myModule->editFeature(aSPFeature);
- }
- }
-}
-
-bool PartSet_SketcherMgr::sketchSolverError()
-{
- bool anError = false;
- CompositeFeaturePtr aSketch = activeSketch();
- if (aSketch.get()) {
- AttributeStringPtr aAttributeString = aSketch->string(SketchPlugin_Sketch::SOLVER_ERROR());
- anError = !aAttributeString->value().empty();
- }
- return anError;
-}
-
-QString PartSet_SketcherMgr::getFeatureError(const FeaturePtr& theFeature)
-{
- std::string anError = "";
- if (!theFeature.get() || !theFeature->data()->isValid())
- return anError.c_str();
-
- CompositeFeaturePtr aSketch = activeSketch();
- if (aSketch.get() && aSketch == theFeature) {
- AttributeStringPtr aAttributeString = aSketch->string(SketchPlugin_Sketch::SOLVER_ERROR());
- anError = aAttributeString->value();
- ModuleBase_Tools::translate(aSketch->getKind(), anError);
- }
- return anError.c_str();
-}
-
-void PartSet_SketcherMgr::clearClickedFlags()
-{
- //myClickedPoint.clear();
- myCurrentPoint.clear();
-}
-
-const QStringList& PartSet_SketcherMgr::replicationsIdList()
-{
- 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 aReplicationIds;
-}
-
-const QStringList& PartSet_SketcherMgr::constraintsIdList()
-{
- 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 aConstraintIds;
-}
-
-void PartSet_SketcherMgr::sketchSelectionModes(QIntList& theModes)
-{
- theModes.clear();
-
- theModes.append(SketcherPrs_Tools::Sel_Dimension_Text);
- theModes.append(SketcherPrs_Tools::Sel_Dimension_Line);
- theModes.append(SketcherPrs_Tools::Sel_Constraint);
- theModes.append(TopAbs_VERTEX);
- 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) const
-{
- bool aNestedSketch = false;
-
- FeaturePtr anActiveSketch = activeSketch();
- if (anActiveSketch.get() && theOperation) {
- ModuleBase_Operation* aSketchOperation = operationMgr()->findOperation(
- anActiveSketch->getKind().c_str());
- ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
- (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,
- const CompositeFeaturePtr& theSketch) const
-{
- ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
- (theOperation);
- return aFOperation && !aFOperation->isEditOperation() &&
- isNestedSketchOperation(aFOperation);
-}
-
-bool PartSet_SketcherMgr::isNestedEditOperation(ModuleBase_Operation* theOperation,
- const CompositeFeaturePtr& theSketch) const
-{
- ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
- (theOperation);
- return aFOperation && aFOperation->isEditOperation() &&
- isNestedSketchOperation(aFOperation);
-}
-
-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());
-}
-
-bool PartSet_SketcherMgr::isDistanceOperation(ModuleBase_Operation* theOperation)
-{
- std::string anId = theOperation ? theOperation->id().toStdString() : "";
-
- 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)
-{
- ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
- (getCurrentOperation());
- if (!aFOperation)
- return;
-
- myModule->onViewTransformed();
-
- // Display all sketcher sub-Objects
- myCurrentSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFOperation->feature());
- XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
-
- // Hide sketcher result
- std::list<ResultPtr> aResults = myCurrentSketch->results();
- std::list<ResultPtr>::const_iterator aIt;
- for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
- (*aIt)->setDisplayed(false);
- }
- myCurrentSketch->setDisplayed(false);
-
- // Remove invalid sketch entities
- std::set<FeaturePtr> 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<FeaturePtr, std::set<FeaturePtr> > aReferences;
- ModelAPI_Tools::findAllReferences(anInvalidFeatures, aReferences, false);
-
- std::set<FeaturePtr>::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<FeaturePtr> 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<ResultPtr> aResults = aFeature->results();
- std::list<ResultPtr>::const_iterator aIt;
- for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
- (*aIt)->setDisplayed(true);
- }
- 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<GeomAPI_Pln> aPln;
- aPln = PartSet_Tools::sketchPlane(myCurrentSketch);
- myPlaneFilter->setPlane(aPln);
-
- 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();
-}
-
-void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
-{
- myIsMouseOverWindow = false;
- myIsConstraintsShown[PartSet_Tools::Geometrical] = true;
- myIsConstraintsShown[PartSet_Tools::Dimensional] = true;
- myIsConstraintsShown[PartSet_Tools::Expressions] = false;
-
- XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
-
- 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);
-
- // Erase all sketcher objects
- QObjectPtrList aObjects = aDisplayer->displayedObjects();
- foreach (ObjectPtr aObj, aObjects) {
- DataPtr aObjData = aObj->data();
- if (!aObjData->isValid())
- aObj->setDisplayed(false);
- }
- }
- else {
- // Hide all sketcher sub-Objects
- for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {
- FeaturePtr aFeature = myCurrentSketch->subFeature(i);
- std::list<ResultPtr> aResults = aFeature->results();
- std::list<ResultPtr>::const_iterator aIt;
- for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
- (*aIt)->setDisplayed(false);
- }
- aFeature->setDisplayed(false);
- }
- // Display sketcher result
- std::list<ResultPtr> aResults = myCurrentSketch->results();
- std::list<ResultPtr>::const_iterator aIt;
- Events_Loop* aLoop = Events_Loop::loop();
- static Events_ID aDispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
-
- ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
- (theOperation);
- for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
- if (!aFOperation->isDisplayedOnStart(*aIt)) {
- (*aIt)->setDisplayed(true);
- // this display event is needed because sketch already may have "displayed" state,
- // but not displayed while it is still active (issue 613, abort of existing sketch)
- ModelAPI_EventCreator::get()->sendUpdated(*aIt, aDispEvent);
- }
- }
- if (!aFOperation->isDisplayedOnStart(myCurrentSketch))
- 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();
-}
-
-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
- }
- }
-}
-
-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
- workshop()->selector()->clearSelection();
-}
-
-void PartSet_SketcherMgr::commitNestedSketch(ModuleBase_Operation* theOperation)
-{
- if (isNestedCreateOperation(theOperation, activeSketch())) {
- ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
- (theOperation);
- if (aFOperation) {
- FeaturePtr aFeature = aFOperation->feature();
- // it is necessary to check the the feature data validity because
- // some kind of features are removed by an operation commit(the macro state of a feature)
- if (aFeature.get() && aFeature->data()->isValid()) {
- visualizeFeature(aFeature, aFOperation->isEditOperation(), true);
- }
- }
- }
-}
-
-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 && isNestedSketchOperation(anOperation)) {
- // 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<ModuleBase_OperationFeature*>
- (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(), activeSketch());
-}
-
-bool PartSet_SketcherMgr::canRedo() const
-{
- return isNestedCreateOperation(getCurrentOperation(), activeSketch());
-}
-
-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<ModelAPI_Result>(theObject);
- if (aResult.get()) {
- // Display sketcher objects
- for (int i = 0; i < myCurrentSketch->numberOfSubs() && aCanErase; i++) {
-
- FeaturePtr aFeature = myCurrentSketch->subFeature(i);
- std::list<ResultPtr> aResults = aFeature->results();
- std::list<ResultPtr>::const_iterator anIt;
- for (anIt = aResults.begin(); anIt != aResults.end() && aCanErase; ++anIt) {
- aCanErase = *anIt != aResult;
- }
- }
- }
- }
- return aCanErase;
-}
-
-bool PartSet_SketcherMgr::canDisplayObject(const ObjectPtr& theObject) const
-{
- bool aCanDisplay = true;
-
- 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
- // nested features can be visualized
- FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
- if (aFeature.get() != NULL && aFeature == activeSketch()) {
- aCanDisplay = false;
- }
- std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(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
- FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
- if (aFeature.get() != NULL) {
- std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
- if (aSketchFeature.get()) {
- aCanDisplay = false;
- }
- }
- }
-
- // 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
- if (aCanDisplay) {
- bool isObjectFound = false;
- ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
- (getCurrentOperation());
- if (aFOperation) {
- FeaturePtr aFeature = aFOperation->feature();
- if (aFeature.get()) {
- std::list<ResultPtr> aResults = aFeature->results();
- if (theObject == aFeature)
- isObjectFound = true;
- else {
- std::list<ResultPtr>::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<ModuleBase_WidgetEditor*>(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
- }
- }
-
- // 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;
- }
- }
-
- 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<ObjectPtr>& theObjects)
-{
- ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
- (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<ResultPtr> anOperationResultList = anOperationFeature->results();
- std::set<ResultPtr> anOperationResults;
- std::list<ResultPtr>::const_iterator aRIt = anOperationResultList.begin(),
- aRLast = anOperationResultList.end();
- for (; aRIt != aRLast; aRIt++)
- anOperationResults.insert(*aRIt);
-
- std::set<FeaturePtr> anObjectsToBeDeleted;
- QStringList anObjectsToBeDeletedNames;
- std::list<ObjectPtr>::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<ModelAPI_Result>(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<ResultPtr> aResults = aFeature->results();
- std::list<ResultPtr>::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<FeaturePtr>::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;
- if (!aCanDisplay) {
- ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
- if (anActiveWidget)
- aCanDisplay = anActiveWidget->getValueState() == ModuleBase_ModelWidget::Stored;
- }
- return aCanDisplay;
-}
-
-bool PartSet_SketcherMgr::canChangeCursor(ModuleBase_Operation* theOperation) const
-{
- return isNestedCreateOperation(theOperation, activeSketch()) ||
- myModule->sketchReentranceMgr()->isInternalEditActive();
-}
-
-const QMap<PartSet_Tools::ConstraintVisibleState, bool>& PartSet_SketcherMgr::showConstraintStates()
-{
- return myIsConstraintsShown;
-}
-
-bool PartSet_SketcherMgr::isObjectOfSketch(const ObjectPtr& theObject) const
-{
- bool isFoundObject = 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;
- }
- }
- return isFoundObject;
-}
-
-void PartSet_SketcherMgr::onPlaneSelected(const std::shared_ptr<GeomAPI_Pln>& thePln)
-{
- if (myPlaneFilter.IsNull())
- myPlaneFilter = new ModuleBase_ShapeInPlaneFilter();
-
- myPlaneFilter->setPlane(thePln);
-}
-
-bool PartSet_SketcherMgr::setDistanceValueByPreselection(ModuleBase_Operation* theOperation,
- ModuleBase_IWorkshop* theWorkshop,
- bool& theCanCommitOperation)
-{
- bool isValueAccepted = false;
- theCanCommitOperation = false;
-
- ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
- (theOperation);
- FeaturePtr aFeature = aFOperation->feature();
- // editor is shown only if all attribute references are filled by preseletion
- bool anAllRefAttrInitialized = true;
-
- std::list<AttributePtr> aRefAttrs = aFeature->data()->attributes(
- ModelAPI_AttributeRefAttr::typeId());
- std::list<AttributePtr>::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<ModuleBase_ModelWidget*> 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<PartSet_WidgetEditor*>(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<Handle(AIS_InteractiveObject)>();
- }
- if (anAIS.get() != NULL) {
- Handle(AIS_InteractiveObject) anAISIO = anAIS->impl<Handle(AIS_InteractiveObject)>();
-
- 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;
- }
- }
- }
- }
- }
- return isValueAccepted;
-}
-
-void PartSet_SketcherMgr::getSelectionOwners(const FeaturePtr& theFeature,
- const FeaturePtr& theSketch,
- ModuleBase_IWorkshop* theWorkshop,
- const FeatureToSelectionMap& theSelection,
- SelectMgr_IndexedMapOfOwner& theOwnersToSelect)
-{
- if (theFeature.get() == NULL)
- return;
-
- FeatureToSelectionMap::const_iterator anIt = theSelection.find(theFeature);
- std::set<AttributePtr> aSelectedAttributes = anIt.value().first;
- std::set<ResultPtr> aSelectedResults = anIt.value().second;
-
- ModuleBase_IViewer* aViewer = theWorkshop->viewer();
-
- XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWorkshop);
- XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
-
- // 1. found the feature's owners. Check the AIS objects of the constructions
- AISObjectPtr aAISObj = aDisplayer->getAISObject(theFeature);
- if (aAISObj.get() != NULL && aSelectedAttributes.empty() && aSelectedResults.empty()) {
- Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
-
- SelectMgr_IndexedMapOfOwner aSelectedOwners;
- aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners);
- for (Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++) {
- Handle(SelectMgr_EntityOwner) anOwner = aSelectedOwners(i);
- if (!anOwner.IsNull())
- theOwnersToSelect.Add(anOwner);
- }
- }
-
- // 2. found the feature results's owners
- std::list<ResultPtr> aResults = theFeature->results();
- std::list<ResultPtr>::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<Handle(AIS_InteractiveObject)>();
-
- SelectMgr_IndexedMapOfOwner aSelectedOwners;
- aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners);
- 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() )
- 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()) {
- 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)
- theOwnersToSelect.Add(anOwner);
- }
- }
- }
-}
-
-void PartSet_SketcherMgr::connectToPropertyPanel(ModuleBase_ModelWidget* theWidget, const bool isToConnect)
-{
- if (isToConnect) {
- connect(theWidget, SIGNAL(beforeValuesChanged()),
- this, SLOT(onBeforeValuesChangedInPropertyPanel()));
- connect(theWidget, SIGNAL(afterValuesChanged()),
- this, SLOT(onAfterValuesChangedInPropertyPanel()));
- }
- else {
- disconnect(theWidget, SIGNAL(beforeValuesChanged()),
- this, SLOT(onBeforeValuesChangedInPropertyPanel()));
- disconnect(theWidget, SIGNAL(afterValuesChanged()),
- this, SLOT(onAfterValuesChangedInPropertyPanel()));
- }
-}
-
-void PartSet_SketcherMgr::widgetStateChanged(int thePreviousState)
-{
- ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
- (getCurrentOperation());
- if (aFOperation) {
- if (PartSet_SketcherMgr::isSketchOperation(aFOperation) ||
- isNestedSketchOperation(aFOperation) &&
- thePreviousState == ModuleBase_ModelWidget::ModifiedInPP) {
- FeaturePtr aFeature = aFOperation->feature();
- visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature));
- }
- }
-}
-
-void PartSet_SketcherMgr::customizePresentation(const ObjectPtr& theObject)
-{
- ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
- (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<ResultPtr> aResults = aFeature->results();
- std::list<ResultPtr>::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();
-}
-
-//**************************************************************
-ModuleBase_ModelWidget* PartSet_SketcherMgr::getActiveWidget() const
-{
- ModuleBase_ModelWidget* aWidget = 0;
- ModuleBase_Operation* anOperation = getCurrentOperation();
- if (anOperation) {
- ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel();
- if (aPanel)
- aWidget = aPanel->activeWidget();
- }
- return aWidget;
-}
-
-void PartSet_SketcherMgr::visualizeFeature(const FeaturePtr& theFeature,
- const bool isEditOperation,
- const bool isToDisplay,
- const bool isFlushRedisplay)
-{
- #ifdef DEBUG_DO_NOT_BY_ENTER
- return;
- #endif
-
- if (isEditOperation || !theFeature.get())
- return;
-
- ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
- XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
-
- // 1. change visibility of the object itself, here the presentable object is processed,
- // e.g. constraints features
- //FeaturePtr aFeature = aFOperation->feature();
- std::list<ResultPtr> aResults = theFeature->results();
- if (isToDisplay)
- theFeature->setDisplayed(true);
- else
- theFeature->setDisplayed(false);
-
- // change visibility of the object results, e.g. non-constraint features
- std::list<ResultPtr>::const_iterator aIt;
- for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
- if (isToDisplay) {
- (*aIt)->setDisplayed(true);
- }
- else {
- (*aIt)->setDisplayed(false);
- }
- }
- if (isFlushRedisplay)
- Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
-}
-
-void PartSet_SketcherMgr::storeSelection(const bool theHighlightedOnly)
-{
- if (!myCurrentSketch.get())
- return;
-
- ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
- ModuleBase_ISelection* aSelect = aWorkshop->selection();
- QList<ModuleBase_ViewerPrsPtr> aStoredPrs = aSelect->getHighlighted();
-
- QList<FeaturePtr> aFeatureList;
- if (!theHighlightedOnly) {
- QList<ModuleBase_ViewerPrsPtr> 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<ModuleBase_ViewerPrsPtr>::const_iterator anIt = aStoredPrs.begin(), aLast = aStoredPrs.end();
-
- CompositeFeaturePtr aSketch = activeSketch();
- for (; anIt != aLast; anIt++) {
- ModuleBase_ViewerPrsPtr aPrs = *anIt;
- ObjectPtr anObject = aPrs->object();
- if (!anObject.get())
- continue;
-
- ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
- FeaturePtr aFeature;
- if (aResult.get())
- aFeature = ModelAPI_Feature::feature(aResult);
- else
- aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
-
-
- std::set<AttributePtr> aSelectedAttributes;
- std::set<ResultPtr> aSelectedResults;
- if (myCurrentSelection.find(aFeature) != myCurrentSelection.end()) {
- std::pair<std::set<AttributePtr>, std::set<ResultPtr> > 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<ResultPtr> aResults = aFeature->results();
- std::list<ResultPtr>::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<XGUI_ModuleConnector*>(aWorkshop);
- FeatureToSelectionMap::const_iterator aSIt = myCurrentSelection.begin(),
- aSLast = myCurrentSelection.end();
- SelectMgr_IndexedMapOfOwner anOwnersToSelect;
- for (; aSIt != aSLast; aSIt++) {
- anOwnersToSelect.Clear();
- getSelectionOwners(aSIt.key(), myCurrentSketch, aWorkshop, myCurrentSelection,
- anOwnersToSelect);
- aConnector->workshop()->selector()->setSelectedOwners(anOwnersToSelect, false);
- }
-}
-
-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 (myCurrentSketch.get() == NULL)
- return;
-
- 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<XGUI_ModuleConnector*>(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;
- }
-}
-
-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<Handle(AIS_InteractiveObject)>();
- }
-
- if (!anAISIO.IsNull()) { // the presentation for the object is visualized
- int anAdditionalPriority = 0;
- // current feature
- std::shared_ptr<SketchPlugin_Feature> aSPFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
- if (aSPFeature.get() != NULL) {
- // 1. Vertices
- // 2. Simple segments
- // 3. External objects (violet color)
- // 4. Auxiliary segments (dotted)
- // StdSelect_BRepSelectionTool::Load uses priority calculating:
- // Standard_Integer aPriority = (thePriority == -1) ? GetStandardPriority (theShape, theType) : thePriority;
- // Priority of Vertex is 8, edge(segment) is 7.
- // It might be not corrected as provides the condition above.
- bool isExternal = aSPFeature->isExternal();
- bool isAuxiliary = PartSet_Tools::isAuxiliarySketchEntity(aSPFeature);
- // current feature
- if (!isExternal && !isAuxiliary)
- anAdditionalPriority = 30;
- // external feature
- if (isExternal)
- anAdditionalPriority = 20;
- // auxiliary feature
- if (isAuxiliary) {
- anAdditionalPriority = 10; /// auxiliary objects should have less priority that
- // edges/vertices of local selection on not-sketch objects
- }
- Handle(ModuleBase_ResultPrs) aResult = Handle(ModuleBase_ResultPrs)::DownCast(anAISIO);
- if (!aResult.IsNull()) {
- aResult->setAdditionalSelectionPriority(anAdditionalPriority);
- }
- }
- }
-}
-
-XGUI_Workshop* PartSet_SketcherMgr::workshop() const
-{
- ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();
- XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(anIWorkshop);
- return aConnector->workshop();
-}
-
-XGUI_OperationMgr* PartSet_SketcherMgr::operationMgr() const
-{
- return workshop()->operationMgr();
-}
-
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D\r
+\r
+// File: PartSet_SketcherMgr.cpp\r
+// Created: 19 Dec 2014\r
+// Author: Vitaly SMETANNIKOV\r
+\r
+#include "PartSet_SketcherMgr.h"\r
+#include "PartSet_SketcherReetntrantMgr.h"\r
+#include "PartSet_Module.h"\r
+#include "PartSet_MouseProcessor.h"\r
+#include "PartSet_Tools.h"\r
+#include "PartSet_WidgetSketchLabel.h"\r
+#include "PartSet_WidgetEditor.h"\r
+#include "PartSet_ResultSketchPrs.h"\r
+\r
+#include <XGUI_ModuleConnector.h>\r
+#include <XGUI_Displayer.h>\r
+#include <XGUI_Workshop.h>\r
+#include <XGUI_ContextMenuMgr.h>\r
+#include <XGUI_Selection.h>\r
+#include <XGUI_SelectionMgr.h>\r
+#include <XGUI_ModuleConnector.h>\r
+#include <XGUI_PropertyPanel.h>\r
+#include <XGUI_ViewerProxy.h>\r
+#include <XGUI_OperationMgr.h>\r
+#include <XGUI_ErrorMgr.h>\r
+#include <XGUI_Tools.h>\r
+\r
+#include <ModuleBase_IPropertyPanel.h>\r
+#include <ModuleBase_ISelection.h>\r
+#include <ModuleBase_IViewer.h>\r
+#include <ModuleBase_IWorkshop.h>\r
+#include <ModuleBase_IViewWindow.h>\r
+#include <ModuleBase_ModelWidget.h>\r
+#include <ModuleBase_Operation.h>\r
+#include <ModuleBase_OperationFeature.h>\r
+#include <ModuleBase_Operation.h>\r
+#include <ModuleBase_WidgetEditor.h>\r
+#include <ModuleBase_ViewerPrs.h>\r
+#include <ModuleBase_Tools.h>\r
+#include <ModuleBase_ResultPrs.h>\r
+\r
+#include <GeomDataAPI_Point2D.h>\r
+\r
+#include <Events_Loop.h>\r
+\r
+#include <SketchPlugin_Line.h>\r
+#include <SketchPlugin_Sketch.h>\r
+#include <SketchPlugin_Point.h>\r
+#include <SketchPlugin_Arc.h>\r
+#include <SketchPlugin_Circle.h>\r
+#include <SketchPlugin_ConstraintLength.h>\r
+#include <SketchPlugin_ConstraintDistance.h>\r
+#include <SketchPlugin_ConstraintParallel.h>\r
+#include <SketchPlugin_ConstraintPerpendicular.h>\r
+#include <SketchPlugin_ConstraintRadius.h>\r
+#include <SketchPlugin_ConstraintRigid.h>\r
+#include <SketchPlugin_ConstraintHorizontal.h>\r
+#include <SketchPlugin_ConstraintVertical.h>\r
+#include <SketchPlugin_ConstraintEqual.h>\r
+#include <SketchPlugin_ConstraintTangent.h>\r
+#include <SketchPlugin_ConstraintCoincidence.h>\r
+#include <SketchPlugin_ConstraintFillet.h>\r
+#include <SketchPlugin_ConstraintMirror.h>\r
+#include <SketchPlugin_ConstraintAngle.h>\r
+#include <SketchPlugin_ConstraintCollinear.h>\r
+#include <SketchPlugin_ConstraintMiddle.h>\r
+#include <SketchPlugin_MultiRotation.h>\r
+#include <SketchPlugin_MultiTranslation.h>\r
+#include <SketchPlugin_IntersectionPoint.h>\r
+\r
+#include <SketcherPrs_Tools.h>\r
+\r
+#include <SelectMgr_IndexedMapOfOwner.hxx>\r
+#include <StdSelect_BRepOwner.hxx>\r
+\r
+//#include <AIS_DimensionSelectionMode.hxx>\r
+#include <AIS_Shape.hxx>\r
+#include <AIS_Dimension.hxx>\r
+\r
+#include <ModelAPI_Events.h>\r
+#include <ModelAPI_Session.h>\r
+#include <ModelAPI_AttributeString.h>\r
+\r
+#include <ModelAPI_Validator.h>\r
+#include <ModelAPI_Tools.h>\r
+\r
+#include <QMouseEvent>\r
+#include <QApplication>\r
+#include <QCursor>\r
+#include <QMessageBox>\r
+#include <QMainWindow>\r
+\r
+//#define DEBUG_DO_NOT_BY_ENTER\r
+//#define DEBUG_SKETCHER_ENTITIES\r
+//#define DEBUG_SKETCH_ENTITIES_ON_MOVE\r
+\r
+//#define DEBUG_CURSOR\r
+\r
+/// Fills attribute and result lists by the selected owner. In case if the attribute is found,\r
+/// by the owner shape, it is put to the list. Otherwise if type of owner shape is edge, put the function\r
+/// result as is to the list of results.\r
+/// \param theOwner a viewer selected owner\r
+/// \param theFeature a feature, where the attribute is searched\r
+/// \param theSketch a current sketch\r
+/// \param theSelectedAttribute an output list of attributes\r
+/// \param theSelectedResults an output list of edge results\r
+void getAttributesOrResults(const Handle(SelectMgr_EntityOwner)& theOwner,\r
+ const FeaturePtr& theFeature, const FeaturePtr& theSketch,\r
+ const ResultPtr& theResult,\r
+ std::set<AttributePtr>& aSelectedAttributes,\r
+ std::set<ResultPtr>& aSelectedResults)\r
+{\r
+ Handle(StdSelect_BRepOwner) aBRepOwner = Handle(StdSelect_BRepOwner)::DownCast(theOwner);\r
+ if (aBRepOwner.IsNull())\r
+ return;\r
+ Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast(\r
+ aBRepOwner->Selectable());\r
+ if (aBRepOwner->HasShape()) {\r
+ const TopoDS_Shape& aShape = aBRepOwner->Shape();\r
+ TopAbs_ShapeEnum aShapeType = aShape.ShapeType();\r
+ if (aShapeType == TopAbs_VERTEX) {\r
+ AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(theFeature,\r
+ aShape, theSketch);\r
+ if (aPntAttr.get() != NULL)\r
+ aSelectedAttributes.insert(aPntAttr);\r
+ }\r
+ else if (aShapeType == TopAbs_EDGE &&\r
+ aSelectedResults.find(theResult) == aSelectedResults.end()) {\r
+ aSelectedResults.insert(theResult);\r
+ }\r
+ }\r
+}\r
+\r
+PartSet_SketcherMgr::PartSet_SketcherMgr(PartSet_Module* theModule)\r
+ : QObject(theModule), myModule(theModule), myIsDragging(false), myDragDone(false),\r
+ myIsMouseOverWindow(false),\r
+ myIsMouseOverViewProcessed(true), myPreviousUpdateViewerEnabled(true),\r
+ myIsPopupMenuActive(false)\r
+{\r
+ ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();\r
+ ModuleBase_IViewer* aViewer = anIWorkshop->viewer();\r
+\r
+ myPreviousDrawModeEnabled = true;//aViewer->isSelectionEnabled();\r
+\r
+ connect(aViewer, SIGNAL(mousePress(ModuleBase_IViewWindow*, QMouseEvent*)),\r
+ this, SLOT(onMousePressed(ModuleBase_IViewWindow*, QMouseEvent*)));\r
+\r
+ connect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)),\r
+ this, SLOT(onMouseReleased(ModuleBase_IViewWindow*, QMouseEvent*)));\r
+\r
+ connect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)),\r
+ this, SLOT(onMouseMoved(ModuleBase_IViewWindow*, QMouseEvent*)));\r
+\r
+ connect(aViewer, SIGNAL(mouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*)),\r
+ this, SLOT(onMouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*)));\r
+\r
+ XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(anIWorkshop);\r
+ XGUI_Workshop* aWorkshop = aConnector->workshop();\r
+ connect(aWorkshop, SIGNAL(applicationStarted()), this, SLOT(onApplicationStarted()));\r
+\r
+ myIsConstraintsShown[PartSet_Tools::Geometrical] = true;\r
+ myIsConstraintsShown[PartSet_Tools::Dimensional] = true;\r
+ myIsConstraintsShown[PartSet_Tools::Expressions] = false;\r
+}\r
+\r
+PartSet_SketcherMgr::~PartSet_SketcherMgr()\r
+{\r
+ if (!myPlaneFilter.IsNull())\r
+ myPlaneFilter.Nullify();\r
+}\r
+\r
+void PartSet_SketcherMgr::onEnterViewPort()\r
+{\r
+ // 1. if the mouse over window, update the next flag. Do not perform update visibility of\r
+ // created feature because it should be done in onMouseMove(). Some widgets watch\r
+ // the mouse move and use the cursor position to update own values. If the presentaion is\r
+ // redisplayed before this update, the feature presentation jumps from reset value to current.\r
+ myIsMouseOverWindow = true;\r
+\r
+ #ifdef DEBUG_DO_NOT_BY_ENTER\r
+ return;\r
+ #endif\r
+\r
+ if (canChangeCursor(getCurrentOperation())) {\r
+ QCursor* aCurrentCursor = QApplication::overrideCursor();\r
+ if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) {\r
+ QApplication::setOverrideCursor(QCursor(Qt::CrossCursor));\r
+#ifdef DEBUG_CURSOR\r
+ qDebug("onEnterViewPort() : Qt::CrossCursor");\r
+#endif\r
+ }\r
+ }\r
+\r
+ if (!isNestedCreateOperation(getCurrentOperation(), activeSketch()))\r
+ return;\r
+\r
+ operationMgr()->onValidateOperation();\r
+\r
+ // we need change displayed state of the current operation feature\r
+ // if the feature is presentable, e.g. distance construction. It has no results, so workshop does\r
+ // not accept a signal about the result created. Nothing is shown until mouse is moved out/in view\r
+ // port. If the isDisplayed flag is true, the presentable feature is displayed as soon as the\r
+ // presentation becomes valid and redisplay happens\r
+ //ModuleBase_Operation* aOperation = getCurrentOperation();\r
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>\r
+ (getCurrentOperation());\r
+ if (aFOperation) {\r
+ FeaturePtr aFeature = aFOperation->feature();\r
+ if (aFeature.get() && aFeature->data()->isValid()) {\r
+ visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature), false);\r
+ }\r
+ }\r
+}\r
+\r
+void PartSet_SketcherMgr::onLeaveViewPort()\r
+{\r
+ myIsMouseOverViewProcessed = false;\r
+ myIsMouseOverWindow = false;\r
+\r
+ #ifdef DEBUG_DO_NOT_BY_ENTER\r
+ return;\r
+ #endif\r
+\r
+ if (canChangeCursor(getCurrentOperation())) {\r
+ QApplication::restoreOverrideCursor();\r
+#ifdef DEBUG_CURSOR\r
+ qDebug("onLeaveViewPort() : None");\r
+#endif\r
+ }\r
+\r
+ if (!isNestedCreateOperation(getCurrentOperation(), activeSketch()))\r
+ return;\r
+\r
+ // the method should be performed if the popup menu is called,\r
+ // the reset of the current widget should not happen\r
+ if (myIsPopupMenuActive)\r
+ return;\r
+\r
+ // it is important to validate operation here only if sketch entity create operation is active\r
+ // because at this operation we reacts to the mouse leave/enter view port\r
+ operationMgr()->onValidateOperation();\r
+\r
+ // 2. if the mouse IS NOT over window, reset the active widget value and hide the presentation\r
+ ModuleBase_IWorkshop* aWorkshop = myModule->workshop();\r
+ XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);\r
+ XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();\r
+ // disable the viewer update in order to avoid visualization of redisplayed feature in viewer\r
+ // obtained after reset value\r
+ bool isEnableUpdateViewer = aDisplayer->enableUpdateViewer(false);\r
+ ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();\r
+ if (anActiveWidget)\r
+ anActiveWidget->reset();\r
+\r
+ // hides the presentation of the current operation feature\r
+ // the feature is to be erased here, but it is correct to call canDisplayObject because\r
+ // there can be additional check (e.g. editor widget in distance constraint)\r
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>\r
+ (getCurrentOperation());\r
+ if (aFOperation) {\r
+ FeaturePtr aFeature = aFOperation->feature();\r
+ visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature));\r
+ }\r
+ // we should update viewer after the presentation are hidden in the viewer\r
+ // otherwise the reset presentation(line) appears in the viewer(by quick move from viewer to PP)\r
+ aDisplayer->enableUpdateViewer(isEnableUpdateViewer);\r
+}\r
+\r
+void PartSet_SketcherMgr::onBeforeValuesChangedInPropertyPanel()\r
+{\r
+ if (!isNestedEditOperation(getCurrentOperation(), myModule->sketchMgr()->activeSketch()) ||\r
+ myModule->sketchReentranceMgr()->isInternalEditActive())\r
+ return;\r
+ // it is necessary to save current selection in order to restore it after the values are modifed\r
+ storeSelection();\r
+\r
+ ModuleBase_IWorkshop* aWorkshop = myModule->workshop();\r
+ XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);\r
+ XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();\r
+ myPreviousUpdateViewerEnabled = aDisplayer->enableUpdateViewer(false);\r
+}\r
+\r
+void PartSet_SketcherMgr::onAfterValuesChangedInPropertyPanel()\r
+{\r
+ if (!isNestedEditOperation(getCurrentOperation(), myModule->sketchMgr()->activeSketch()) ||\r
+ myModule->sketchReentranceMgr()->isInternalEditActive()) {\r
+ myModule->sketchReentranceMgr()->updateInternalEditActiveState();\r
+ return;\r
+ }\r
+ // it is necessary to restore current selection in order to restore it after the values are modified\r
+ restoreSelection();\r
+ myCurrentSelection.clear();\r
+\r
+ // 3. the flag to disable the update viewer should be set in order to avoid blinking in the \r
+ // viewer happens by deselect/select the modified objects. The flag should be restored after\r
+ // the selection processing. The update viewer should be also called.\r
+ ModuleBase_IWorkshop* aWorkshop = myModule->workshop();\r
+ XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);\r
+ XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();\r
+ aDisplayer->enableUpdateViewer(myPreviousUpdateViewerEnabled);\r
+ aDisplayer->updateViewer();\r
+\r
+\r
+}\r
+\r
+void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)\r
+{\r
+ if (myModule->sketchReentranceMgr()->processMousePressed(theWnd, theEvent))\r
+ return;\r
+\r
+ //get2dPoint(theWnd, theEvent, myClickedPoint);\r
+\r
+ if (!(theEvent->buttons() & Qt::LeftButton))\r
+ return;\r
+\r
+ // Clear dragging mode\r
+ myIsDragging = false;\r
+\r
+ ModuleBase_IWorkshop* aWorkshop = myModule->workshop();\r
+ ModuleBase_IViewer* aViewer = aWorkshop->viewer();\r
+ if (!aViewer->canDragByMouse())\r
+ return;\r
+\r
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>\r
+ (getCurrentOperation());\r
+ if (!aFOperation)\r
+ return;\r
+\r
+ if (aFOperation->isEditOperation()) {\r
+ // If the current widget is a selector, do nothing, it processes the mouse press\r
+ ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();\r
+ if(anActiveWidget && anActiveWidget->isViewerSelector()) {\r
+ return;\r
+ }\r
+ }\r
+\r
+ // Use only for sketch operations\r
+ if (myCurrentSketch) {\r
+ if (!PartSet_Tools::sketchPlane(myCurrentSketch))\r
+ return;\r
+\r
+ bool isSketcher = isSketchOperation(aFOperation);\r
+ bool isSketchOpe = isNestedSketchOperation(aFOperation);\r
+\r
+ // Avoid non-sketch operations\r
+ if ((!isSketchOpe) && (!isSketcher))\r
+ return;\r
+\r
+ bool isEditing = aFOperation->isEditOperation();\r
+\r
+ // Ignore creation sketch operation\r
+ if ((!isSketcher) && (!isEditing))\r
+ return;\r
+\r
+ Handle(AIS_InteractiveContext) aContext = aViewer->AISContext();\r
+ // Remember highlighted objects for editing\r
+ ModuleBase_ISelection* aSelect = aWorkshop->selection();\r
+\r
+ bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);\r
+ storeSelection(!aHasShift);\r
+\r
+ if (myCurrentSelection.empty()) {\r
+ if (isSketchOpe && (!isSketcher))\r
+ // commit previous operation\r
+ if (!aFOperation->commit())\r
+ aFOperation->abort();\r
+ return;\r
+ }\r
+ // Init flyout point for radius rotation\r
+ FeaturePtr aFeature = myCurrentSelection.begin().key();\r
+\r
+ if (isSketcher) {\r
+ myIsDragging = true;\r
+ get2dPoint(theWnd, theEvent, myCurrentPoint);\r
+ myDragDone = false;\r
+\r
+ myPreviousDrawModeEnabled = aViewer->enableDrawMode(false);\r
+ // selection should be restored before edit operation start to process the\r
+ // selected entities, e.g. selection of point(attribute on a line) should edit the point\r
+ restoreSelection();\r
+ launchEditing();\r
+ if (aFeature.get() != NULL) {\r
+ std::shared_ptr<SketchPlugin_Feature> aSPFeature = \r
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);\r
+ if (aSPFeature.get() && aSPFeature->getKind() == SketchPlugin_ConstraintRadius::ID()) {\r
+ DataPtr aData = aSPFeature->data();\r
+ AttributePtr aAttr = aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT());\r
+ std::shared_ptr<GeomDataAPI_Point2D> aFPAttr = \r
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aAttr);\r
+ aFPAttr->setValue(myCurrentPoint.myCurX, myCurrentPoint.myCurY);\r
+ }\r
+ }\r
+ } else if (isSketchOpe && isEditing) {\r
+ // If selected another object commit current result\r
+ aFOperation->commit();\r
+\r
+ myIsDragging = true;\r
+ get2dPoint(theWnd, theEvent, myCurrentPoint);\r
+ myDragDone = false;\r
+\r
+ myPreviousDrawModeEnabled = aViewer->enableDrawMode(false);\r
+ // selection should be restored before edit operation start to process the\r
+ // selected entities, e.g. selection of point(attribute on a line) should edit the point\r
+ restoreSelection();\r
+ launchEditing();\r
+ restoreSelection();\r
+ }\r
+ }\r
+}\r
+\r
+void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)\r
+{\r
+ if (myModule->sketchReentranceMgr()->processMouseReleased(theWnd, theEvent))\r
+ return;\r
+\r
+ ModuleBase_IWorkshop* aWorkshop = myModule->workshop();\r
+ ModuleBase_IViewer* aViewer = aWorkshop->viewer();\r
+ if (!aViewer->canDragByMouse())\r
+ return;\r
+ ModuleBase_Operation* aOp = getCurrentOperation();\r
+ if (aOp) {\r
+ if (isNestedSketchOperation(aOp)) {\r
+ // Only for sketcher operations\r
+ if (myIsDragging) {\r
+ if (myDragDone) {\r
+ myCurrentSelection.clear();\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ aWorkshop->viewer()->enableDrawMode(myPreviousDrawModeEnabled);\r
+ myIsDragging = false;\r
+\r
+ ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();\r
+ PartSet_MouseProcessor* aProcessor = dynamic_cast<PartSet_MouseProcessor*>(anActiveWidget);\r
+ if (aProcessor)\r
+ aProcessor->mouseReleased(theWnd, theEvent);\r
+}\r
+\r
+void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)\r
+{\r
+#ifdef DEBUG_SKETCH_ENTITIES_ON_MOVE\r
+ CompositeFeaturePtr aSketch = activeSketch();\r
+ if (aSketch.get()) {\r
+ std::cout << "mouse move SKETCH FEATURES [" << aSketch->numberOfSubs() << "]:" << std::endl;\r
+ QStringList anInfo;\r
+ for (int i = 0, aNbSubs = aSketch->numberOfSubs(); i < aNbSubs; i++) {\r
+ //std::cout << getFeatureInfo(aSketch->subFeature(i), false) << std::endl;\r
+ anInfo.append(ModuleBase_Tools::objectInfo(aSketch->subFeature(i)));\r
+ }\r
+ QString anInfoStr = anInfo.join("\n");\r
+ qDebug(QString("%1").arg(anInfo.size()).arg(anInfoStr).toStdString().c_str());\r
+ }\r
+#endif\r
+\r
+ if (myModule->sketchReentranceMgr()->processMouseMoved(theWnd, theEvent))\r
+ return;\r
+\r
+ if (isNestedCreateOperation(getCurrentOperation(), activeSketch())) {\r
+ // 1. perform the widget mouse move functionality and display the presentation\r
+ // the mouse move should be processed in the widget, if it can in order to visualize correct\r
+ // presentation. These widgets correct the feature attribute according to the mouse position\r
+ ModuleBase_ModelWidget* anActiveWidget = myModule->activeWidget();\r
+ PartSet_MouseProcessor* aProcessor = dynamic_cast<PartSet_MouseProcessor*>(anActiveWidget);\r
+ if (aProcessor)\r
+ aProcessor->mouseMoved(theWnd, theEvent);\r
+ if (!myIsMouseOverViewProcessed) {\r
+ myIsMouseOverViewProcessed = true;\r
+\r
+ // the feature is to be erased here, but it is correct to call canDisplayObject because\r
+ // there can be additional check (e.g. editor widget in distance constraint)\r
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>\r
+ (getCurrentOperation());\r
+ if (aFOperation) {\r
+ FeaturePtr aFeature = aFOperation->feature();\r
+ visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature));\r
+ }\r
+ }\r
+ }\r
+ //myClickedPoint.clear();\r
+\r
+ if (myIsDragging) {\r
+ // 1. the current selection is saved in the mouse press method in order to restore it after moving\r
+ // 2. the enable selection in the viewer should be temporary switched off in order to ignore\r
+ // mouse press signal in the viewer(it call Select for AIS context and the dragged objects are\r
+ // deselected). This flag should be restored in the slot, processed the mouse release signal.\r
+\r
+ ModuleBase_Operation* aCurrentOperation = getCurrentOperation();\r
+ if (!aCurrentOperation)\r
+ return;\r
+ if (isSketchOperation(aCurrentOperation))\r
+ return; // No edit operation activated\r
+\r
+ Handle(V3d_View) aView = theWnd->v3dView();\r
+ gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);\r
+ double aX, aY;\r
+ PartSet_Tools::convertTo2D(aPoint, myCurrentSketch, aView, aX, aY);\r
+ double dX = aX - myCurrentPoint.myCurX;\r
+ double dY = aY - myCurrentPoint.myCurY;\r
+\r
+ ModuleBase_IWorkshop* aWorkshop = myModule->workshop();\r
+ XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);\r
+ XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();\r
+ // 3. the flag to disable the update viewer should be set in order to avoid blinking in the \r
+ // viewer happens by deselect/select the modified objects. The flag should be restored after\r
+ // the selection processing. The update viewer should be also called.\r
+ bool isEnableUpdateViewer = aDisplayer->enableUpdateViewer(false);\r
+\r
+ static Events_ID aMoveEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED);\r
+ //static Events_ID aUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);\r
+ FeatureToSelectionMap::const_iterator anIt = myCurrentSelection.begin(),\r
+ aLast = myCurrentSelection.end();\r
+ // 4. the features and attributes modification(move)\r
+ bool isModified = false;\r
+ for (; anIt != aLast; anIt++) {\r
+ FeaturePtr aFeature = anIt.key();\r
+\r
+ std::set<AttributePtr> anAttributes = anIt.value().first;\r
+ // Process selection by attribute: the priority to the attribute\r
+ if (!anAttributes.empty()) {\r
+ std::set<AttributePtr>::const_iterator anAttIt = anAttributes.begin(),\r
+ anAttLast = anAttributes.end();\r
+ for (; anAttIt != anAttLast; anAttIt++) {\r
+ AttributePtr anAttr = *anAttIt;\r
+ if (anAttr.get() == NULL)\r
+ continue;\r
+ std::string aAttrId = anAttr->id();\r
+ DataPtr aData = aFeature->data();\r
+ if (aData->isValid()) {\r
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint = \r
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(aAttrId));\r
+ if (aPoint.get() != NULL) {\r
+ bool isImmutable = aPoint->setImmutable(true);\r
+ aPoint->move(dX, dY);\r
+ isModified = true;\r
+ ModelAPI_EventCreator::get()->sendUpdated(aFeature, aMoveEvent);\r
+ aPoint->setImmutable(isImmutable);\r
+ }\r
+ }\r
+ }\r
+ } else {\r
+ // Process selection by feature\r
+ std::shared_ptr<SketchPlugin_Feature> aSketchFeature =\r
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);\r
+ if (aSketchFeature) {\r
+ aSketchFeature->move(dX, dY);\r
+ isModified = true;\r
+ ModelAPI_EventCreator::get()->sendUpdated(aSketchFeature, aMoveEvent);\r
+ }\r
+ }\r
+ }\r
+ // the modified state of the current operation should be updated if there are features, which\r
+ // were changed here\r
+ if (isModified) {\r
+ aCurrentOperation->onValuesChanged();\r
+ }\r
+ Events_Loop::loop()->flush(aMoveEvent); // up all move events - to be processed in the solver\r
+ //Events_Loop::loop()->flush(aUpdateEvent); // up update events - to redisplay presentations\r
+\r
+ // 5. it is necessary to save current selection in order to restore it after the features moving\r
+ restoreSelection();\r
+ // 6. restore the update viewer flag and call this update\r
+ aDisplayer->enableUpdateViewer(isEnableUpdateViewer);\r
+ aDisplayer->updateViewer();\r
+\r
+ myDragDone = true;\r
+ myCurrentPoint.setValue(aX, aY);\r
+ }\r
+}\r
+\r
+void PartSet_SketcherMgr::onMouseDoubleClick(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)\r
+{\r
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>\r
+ (getCurrentOperation());\r
+ if (aFOperation && aFOperation->isEditOperation()) {\r
+ std::string aId = aFOperation->id().toStdString();\r
+ if (isDistanceOperation(aFOperation))\r
+ {\r
+ // Activate dimension value editing on double click\r
+ ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel();\r
+ QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();\r
+ // Find corresponded widget to activate value editing\r
+ foreach (ModuleBase_ModelWidget* aWgt, aWidgets) {\r
+ if (aWgt->attributeID() == SketchPlugin_Constraint::VALUE() ||\r
+ aWgt->attributeID() == SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()) {\r
+ PartSet_WidgetEditor* anEditor = dynamic_cast<PartSet_WidgetEditor*>(aWgt);\r
+ if (anEditor)\r
+ anEditor->showPopupEditor();\r
+ return;\r
+ }\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+void PartSet_SketcherMgr::onApplicationStarted()\r
+{\r
+ ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();\r
+ XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(anIWorkshop);\r
+ XGUI_Workshop* aWorkshop = aConnector->workshop();\r
+ PartSet_SketcherReetntrantMgr* aReentranceMgr = myModule->sketchReentranceMgr();\r
+\r
+ XGUI_PropertyPanel* aPropertyPanel = aWorkshop->propertyPanel();\r
+ if (aPropertyPanel) {\r
+ //connect(aPropertyPanel, SIGNAL(beforeWidgetActivated(ModuleBase_ModelWidget*)),\r
+ // this, SLOT(onBeforeWidgetActivated(ModuleBase_ModelWidget*)));\r
+\r
+ connect(aPropertyPanel, SIGNAL(noMoreWidgets(const std::string&)),\r
+ aReentranceMgr, SLOT(onNoMoreWidgets(const std::string&)));\r
+ connect(aPropertyPanel, SIGNAL(widgetActivated(ModuleBase_ModelWidget*)),\r
+ aReentranceMgr, SLOT(onWidgetActivated()));\r
+ }\r
+\r
+ XGUI_ViewerProxy* aViewerProxy = aWorkshop->viewer();\r
+ connect(aViewerProxy, SIGNAL(enterViewPort()), this, SLOT(onEnterViewPort()));\r
+ connect(aViewerProxy, SIGNAL(leaveViewPort()), this, SLOT(onLeaveViewPort()));\r
+\r
+ XGUI_ContextMenuMgr* aContextMenuMgr = aWorkshop->contextMenuMgr();\r
+ connect(aContextMenuMgr, SIGNAL(beforeContextMenu()), this, SLOT(onBeforeContextMenu()));\r
+ connect(aContextMenuMgr, SIGNAL(afterContextMenu()), this, SLOT(onAfterContextMenu()));\r
+}\r
+\r
+//void PartSet_SketcherMgr::onBeforeWidgetActivated(ModuleBase_ModelWidget* theWidget)\r
+//{\r
+ //if (!myClickedPoint.myIsInitialized)\r
+ // return;\r
+\r
+ //ModuleBase_Operation* aOperation = getCurrentOperation();\r
+ // the distance constraint feature should not use the clickedd point\r
+ // this is workaround in order to don't throw down the flyout point value,\r
+ // set by execute() method of these type of features\r
+ //if (isDistanceOperation(aOperation))\r
+ // return;\r
+\r
+ //PartSet_WidgetPoint2D* aPnt2dWgt = dynamic_cast<PartSet_WidgetPoint2D*>(theWidget);\r
+ //if (aPnt2dWgt) {\r
+ // aPnt2dWgt->setPoint(myClickedPoint.myCurX, myClickedPoint.myCurY);\r
+ //}\r
+//}\r
+\r
+void PartSet_SketcherMgr::onBeforeContextMenu()\r
+{\r
+ myIsPopupMenuActive = true;\r
+}\r
+\r
+void PartSet_SketcherMgr::onAfterContextMenu()\r
+{\r
+ myIsPopupMenuActive = false;\r
+}\r
+\r
+void PartSet_SketcherMgr::get2dPoint(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent, \r
+ Point& thePoint)\r
+{\r
+ Handle(V3d_View) aView = theWnd->v3dView();\r
+ gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);\r
+ double aX, anY;\r
+ PartSet_Tools::convertTo2D(aPoint, myCurrentSketch, aView, aX, anY);\r
+ thePoint.setValue(aX, anY);\r
+}\r
+\r
+void PartSet_SketcherMgr::launchEditing()\r
+{\r
+ if (!myCurrentSelection.empty()) {\r
+ FeaturePtr aFeature = myCurrentSelection.begin().key();\r
+ std::shared_ptr<SketchPlugin_Feature> aSPFeature = \r
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);\r
+ if (aSPFeature && (!aSPFeature->isExternal())) {\r
+ myModule->editFeature(aSPFeature);\r
+ }\r
+ }\r
+}\r
+\r
+bool PartSet_SketcherMgr::sketchSolverError()\r
+{\r
+ bool anError = false;\r
+ CompositeFeaturePtr aSketch = activeSketch();\r
+ if (aSketch.get()) {\r
+ AttributeStringPtr aAttributeString = aSketch->string(SketchPlugin_Sketch::SOLVER_ERROR());\r
+ anError = !aAttributeString->value().empty();\r
+ }\r
+ return anError;\r
+}\r
+\r
+QString PartSet_SketcherMgr::getFeatureError(const FeaturePtr& theFeature)\r
+{\r
+ std::string anError = "";\r
+ if (!theFeature.get() || !theFeature->data()->isValid())\r
+ return anError.c_str();\r
+\r
+ CompositeFeaturePtr aSketch = activeSketch();\r
+ if (aSketch.get() && aSketch == theFeature) {\r
+ AttributeStringPtr aAttributeString = aSketch->string(SketchPlugin_Sketch::SOLVER_ERROR());\r
+ anError = aAttributeString->value();\r
+ ModuleBase_Tools::translate(aSketch->getKind(), anError);\r
+ }\r
+ return anError.c_str();\r
+}\r
+\r
+void PartSet_SketcherMgr::clearClickedFlags()\r
+{\r
+ //myClickedPoint.clear();\r
+ myCurrentPoint.clear();\r
+}\r
+\r
+const QStringList& PartSet_SketcherMgr::replicationsIdList()\r
+{\r
+ static QStringList aReplicationIds;\r
+ if (aReplicationIds.size() == 0) {\r
+ aReplicationIds << SketchPlugin_ConstraintMirror::ID().c_str();\r
+ aReplicationIds << SketchPlugin_MultiRotation::ID().c_str();\r
+ aReplicationIds << SketchPlugin_MultiTranslation::ID().c_str();\r
+ }\r
+ return aReplicationIds;\r
+}\r
+\r
+const QStringList& PartSet_SketcherMgr::constraintsIdList()\r
+{\r
+ static QStringList aConstraintIds;\r
+ if (aConstraintIds.size() == 0) {\r
+ aConstraintIds << SketchPlugin_ConstraintLength::ID().c_str();\r
+ aConstraintIds << SketchPlugin_ConstraintDistance::ID().c_str();\r
+ aConstraintIds << SketchPlugin_ConstraintRigid::ID().c_str();\r
+ aConstraintIds << SketchPlugin_ConstraintRadius::ID().c_str();\r
+ aConstraintIds << SketchPlugin_ConstraintPerpendicular::ID().c_str();\r
+ aConstraintIds << SketchPlugin_ConstraintParallel::ID().c_str();\r
+ aConstraintIds << SketchPlugin_ConstraintHorizontal::ID().c_str();\r
+ aConstraintIds << SketchPlugin_ConstraintVertical::ID().c_str();\r
+ aConstraintIds << SketchPlugin_ConstraintEqual::ID().c_str();\r
+ aConstraintIds << SketchPlugin_ConstraintTangent::ID().c_str();\r
+ aConstraintIds << SketchPlugin_ConstraintCoincidence::ID().c_str();\r
+ aConstraintIds << SketchPlugin_ConstraintAngle::ID().c_str();\r
+ aConstraintIds << SketchPlugin_ConstraintCollinear::ID().c_str();\r
+ aConstraintIds << SketchPlugin_ConstraintMiddle::ID().c_str();\r
+ }\r
+ return aConstraintIds;\r
+}\r
+\r
+void PartSet_SketcherMgr::sketchSelectionModes(QIntList& theModes)\r
+{\r
+ theModes.clear();\r
+\r
+ theModes.append(SketcherPrs_Tools::Sel_Dimension_Text);\r
+ theModes.append(SketcherPrs_Tools::Sel_Dimension_Line);\r
+ theModes.append(SketcherPrs_Tools::Sel_Constraint);\r
+ theModes.append(TopAbs_VERTEX);\r
+ theModes.append(TopAbs_EDGE);\r
+}\r
+\r
+Handle(AIS_InteractiveObject) PartSet_SketcherMgr::createPresentation(const ResultPtr& theResult)\r
+{\r
+ Handle(AIS_InteractiveObject) aPrs;\r
+\r
+ FeaturePtr aFeature = ModelAPI_Feature::feature(theResult);\r
+ if (aFeature.get() && aFeature->getKind() == SketchPlugin_Sketch::ID()) {\r
+ aPrs = new PartSet_ResultSketchPrs(theResult);\r
+ }\r
+ return aPrs;\r
+}\r
+\r
+bool PartSet_SketcherMgr::isSketchOperation(ModuleBase_Operation* theOperation)\r
+{\r
+ return theOperation && theOperation->id().toStdString() == SketchPlugin_Sketch::ID();\r
+}\r
+\r
+bool PartSet_SketcherMgr::isNestedSketchOperation(ModuleBase_Operation* theOperation) const\r
+{\r
+ bool aNestedSketch = false;\r
+\r
+ FeaturePtr anActiveSketch = activeSketch();\r
+ if (anActiveSketch.get() && theOperation) {\r
+ ModuleBase_Operation* aSketchOperation = operationMgr()->findOperation(\r
+ anActiveSketch->getKind().c_str());\r
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>\r
+ (theOperation);\r
+ if (aSketchOperation && aFOperation) {\r
+ FeaturePtr aFeature = aFOperation->feature();\r
+ if (aFeature.get()) {\r
+ QStringList aGrantedOpIds = aSketchOperation->grantedOperationIds();\r
+ aNestedSketch = aGrantedOpIds.contains(aFeature->getKind().c_str());\r
+ }\r
+ }\r
+ }\r
+ return aNestedSketch;\r
+}\r
+\r
+bool PartSet_SketcherMgr::isNestedCreateOperation(ModuleBase_Operation* theOperation,\r
+ const CompositeFeaturePtr& theSketch) const\r
+{\r
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>\r
+ (theOperation);\r
+ return aFOperation && !aFOperation->isEditOperation() &&\r
+ isNestedSketchOperation(aFOperation);\r
+}\r
+\r
+bool PartSet_SketcherMgr::isNestedEditOperation(ModuleBase_Operation* theOperation,\r
+ const CompositeFeaturePtr& theSketch) const\r
+{\r
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>\r
+ (theOperation);\r
+ return aFOperation && aFOperation->isEditOperation() &&\r
+ isNestedSketchOperation(aFOperation);\r
+}\r
+\r
+bool PartSet_SketcherMgr::isEntity(const std::string& theId)\r
+{\r
+ return (theId == SketchPlugin_Line::ID()) ||\r
+ (theId == SketchPlugin_Point::ID()) ||\r
+ (theId == SketchPlugin_Arc::ID()) ||\r
+ (theId == SketchPlugin_Circle::ID());\r
+}\r
+\r
+bool PartSet_SketcherMgr::isDistanceOperation(ModuleBase_Operation* theOperation)\r
+{\r
+ std::string anId = theOperation ? theOperation->id().toStdString() : "";\r
+\r
+ return isDistanceKind(anId);\r
+}\r
+\r
+bool PartSet_SketcherMgr::isDistanceKind(std::string& theKind)\r
+{\r
+ return (theKind == SketchPlugin_ConstraintLength::ID()) ||\r
+ (theKind == SketchPlugin_ConstraintDistance::ID()) ||\r
+ (theKind == SketchPlugin_ConstraintRadius::ID()) ||\r
+ (theKind == SketchPlugin_ConstraintAngle::ID());\r
+}\r
+\r
+void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)\r
+{\r
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>\r
+ (getCurrentOperation());\r
+ if (!aFOperation)\r
+ return;\r
+\r
+ myModule->onViewTransformed();\r
+\r
+ // Display all sketcher sub-Objects\r
+ myCurrentSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFOperation->feature());\r
+ XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());\r
+\r
+ // Hide sketcher result\r
+ std::list<ResultPtr> aResults = myCurrentSketch->results();\r
+ std::list<ResultPtr>::const_iterator aIt;\r
+ for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {\r
+ (*aIt)->setDisplayed(false);\r
+ }\r
+ myCurrentSketch->setDisplayed(false);\r
+\r
+ // Remove invalid sketch entities\r
+ std::set<FeaturePtr> anInvalidFeatures;\r
+ ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();\r
+ for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {\r
+ FeaturePtr aFeature = myCurrentSketch->subFeature(i);\r
+ if (aFeature.get()) {\r
+ if (!aFactory->validate(aFeature))\r
+ anInvalidFeatures.insert(aFeature);\r
+ }\r
+ }\r
+ if (!anInvalidFeatures.empty()) {\r
+ std::map<FeaturePtr, std::set<FeaturePtr> > aReferences;\r
+ ModelAPI_Tools::findAllReferences(anInvalidFeatures, aReferences, false);\r
+\r
+ std::set<FeaturePtr>::const_iterator anIt = anInvalidFeatures.begin(),\r
+ aLast = anInvalidFeatures.end();\r
+ // separate features to references to parameter features and references to others\r
+ QStringList anInvalidFeatureNames;\r
+ for (; anIt != aLast; anIt++) {\r
+ FeaturePtr aFeature = *anIt;\r
+ if (aFeature.get())\r
+ anInvalidFeatureNames.append(aFeature->name().c_str());\r
+ }\r
+ std::string aPrefixInfo = QString("Invalid features of the sketch will be deleted: %1.\n\n").\r
+ arg(anInvalidFeatureNames.join(", ")).toStdString().c_str();\r
+ std::set<FeaturePtr> aFeatureRefsToDelete;\r
+ if (ModuleBase_Tools::askToDelete(anInvalidFeatures, aReferences, aConnector->desktop(),\r
+ aFeatureRefsToDelete, aPrefixInfo)) {\r
+ if (!aFeatureRefsToDelete.empty())\r
+ anInvalidFeatures.insert(aFeatureRefsToDelete.begin(), aFeatureRefsToDelete.end());\r
+ ModelAPI_Tools::removeFeatures(anInvalidFeatures, true);\r
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));\r
+ // TODO: call the next method in the XGUI_OperationMgr::onOperationStarted().\r
+ workshop()->errorMgr()->updateAcceptAllAction(myCurrentSketch);\r
+ }\r
+ }\r
+\r
+ // Display sketcher objects\r
+ QStringList anInfo;\r
+ for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {\r
+ FeaturePtr aFeature = myCurrentSketch->subFeature(i);\r
+#ifdef DEBUG_SKETCHER_ENTITIES\r
+ anInfo.append(ModuleBase_Tools::objectInfo(aFeature));\r
+#endif\r
+ std::list<ResultPtr> aResults = aFeature->results();\r
+ std::list<ResultPtr>::const_iterator aIt;\r
+ for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {\r
+ (*aIt)->setDisplayed(true);\r
+ }\r
+ aFeature->setDisplayed(true);\r
+ }\r
+#ifdef DEBUG_SKETCHER_ENTITIES\r
+ QString anInfoStr = anInfo.join(";\t");\r
+ qDebug(QString("startSketch: %1, %2").arg(anInfo.size()).arg(anInfoStr).toStdString().c_str());\r
+#endif\r
+\r
+ if(myCirclePointFilter.IsNull()) {\r
+ myCirclePointFilter = new PartSet_CirclePointFilter(myModule->workshop());\r
+ }\r
+\r
+ myModule->workshop()->viewer()->addSelectionFilter(myCirclePointFilter);\r
+\r
+ if (myPlaneFilter.IsNull()) \r
+ myPlaneFilter = new ModuleBase_ShapeInPlaneFilter();\r
+\r
+ myModule->workshop()->viewer()->addSelectionFilter(myPlaneFilter);\r
+ bool aHasPlane = false;\r
+ std::shared_ptr<GeomAPI_Pln> aPln;\r
+ aPln = PartSet_Tools::sketchPlane(myCurrentSketch);\r
+ myPlaneFilter->setPlane(aPln);\r
+\r
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));\r
+ // all displayed objects should be activated in current selection modes according to switched\r
+ // plane filter\r
+ if (aPln.get())\r
+ aConnector->activateModuleSelectionModes();\r
+}\r
+\r
+void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)\r
+{\r
+ myIsMouseOverWindow = false;\r
+ myIsConstraintsShown[PartSet_Tools::Geometrical] = true;\r
+ myIsConstraintsShown[PartSet_Tools::Dimensional] = true;\r
+ myIsConstraintsShown[PartSet_Tools::Expressions] = false;\r
+\r
+ XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());\r
+\r
+ DataPtr aData = myCurrentSketch->data();\r
+ if (!aData->isValid()) {\r
+ XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();\r
+ // The sketch was aborted\r
+ myCurrentSketch = CompositeFeaturePtr();\r
+ // TODO: move this outside of if-else\r
+ myModule->workshop()->viewer()->removeSelectionFilter(myCirclePointFilter);\r
+ myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter);\r
+\r
+ // Erase all sketcher objects\r
+ QObjectPtrList aObjects = aDisplayer->displayedObjects();\r
+ foreach (ObjectPtr aObj, aObjects) {\r
+ DataPtr aObjData = aObj->data();\r
+ if (!aObjData->isValid())\r
+ aObj->setDisplayed(false);\r
+ }\r
+ }\r
+ else {\r
+ // Hide all sketcher sub-Objects\r
+ for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {\r
+ FeaturePtr aFeature = myCurrentSketch->subFeature(i);\r
+ std::list<ResultPtr> aResults = aFeature->results();\r
+ std::list<ResultPtr>::const_iterator aIt;\r
+ for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {\r
+ (*aIt)->setDisplayed(false);\r
+ }\r
+ aFeature->setDisplayed(false);\r
+ }\r
+ // Display sketcher result\r
+ std::list<ResultPtr> aResults = myCurrentSketch->results();\r
+ std::list<ResultPtr>::const_iterator aIt;\r
+ Events_Loop* aLoop = Events_Loop::loop();\r
+ static Events_ID aDispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);\r
+\r
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>\r
+ (theOperation);\r
+ for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {\r
+ if (!aFOperation->isDisplayedOnStart(*aIt)) {\r
+ (*aIt)->setDisplayed(true);\r
+ // this display event is needed because sketch already may have "displayed" state,\r
+ // but not displayed while it is still active (issue 613, abort of existing sketch)\r
+ ModelAPI_EventCreator::get()->sendUpdated(*aIt, aDispEvent);\r
+ }\r
+ }\r
+ if (!aFOperation->isDisplayedOnStart(myCurrentSketch))\r
+ myCurrentSketch->setDisplayed(true);\r
+ \r
+ myCurrentSketch = CompositeFeaturePtr();\r
+\r
+ myModule->workshop()->viewer()->removeSelectionFilter(myCirclePointFilter);\r
+ myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter);\r
+\r
+ Events_Loop::loop()->flush(aDispEvent);\r
+ }\r
+ // restore the module selection modes, which were changed on startSketch\r
+ aConnector->activateModuleSelectionModes();\r
+}\r
+\r
+void PartSet_SketcherMgr::startNestedSketch(ModuleBase_Operation* theOperation)\r
+{\r
+ if (canChangeCursor(theOperation) && myIsMouseOverWindow) {\r
+ QCursor* aCurrentCursor = QApplication::overrideCursor();\r
+ if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) {\r
+ QApplication::setOverrideCursor(QCursor(Qt::CrossCursor));\r
+#ifdef DEBUG_CURSOR\r
+ qDebug("startNestedSketch() : Qt::CrossCursor");\r
+#endif\r
+ }\r
+ }\r
+}\r
+\r
+void PartSet_SketcherMgr::stopNestedSketch(ModuleBase_Operation* theOperation)\r
+{\r
+ myIsMouseOverViewProcessed = true;\r
+ operationMgr()->onValidateOperation();\r
+ // when sketch nested operation is stopped the cursor should be restored unconditionally\r
+ //if (canChangeCursor(theOperation)) {\r
+ QApplication::restoreOverrideCursor();\r
+#ifdef DEBUG_CURSOR\r
+ qDebug("stopNestedSketch() : None");\r
+#endif\r
+ //}\r
+ /// improvement to deselect automatically all eventual selected objects, when\r
+ // returning to the neutral point of the Sketcher\r
+ workshop()->selector()->clearSelection();\r
+}\r
+\r
+void PartSet_SketcherMgr::commitNestedSketch(ModuleBase_Operation* theOperation)\r
+{\r
+ if (isNestedCreateOperation(theOperation, activeSketch())) {\r
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>\r
+ (theOperation);\r
+ if (aFOperation) {\r
+ FeaturePtr aFeature = aFOperation->feature();\r
+ // it is necessary to check the the feature data validity because\r
+ // some kind of features are removed by an operation commit(the macro state of a feature)\r
+ if (aFeature.get() && aFeature->data()->isValid()) {\r
+ visualizeFeature(aFeature, aFOperation->isEditOperation(), true);\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+void PartSet_SketcherMgr::activatePlaneFilter(const bool& toActivate)\r
+{\r
+ if (toActivate)\r
+ myModule->workshop()->viewer()->addSelectionFilter(myPlaneFilter);\r
+ else\r
+ myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter);\r
+}\r
+\r
+bool PartSet_SketcherMgr::operationActivatedByPreselection()\r
+{\r
+ bool isOperationStopped = false;\r
+ ModuleBase_Operation* anOperation = getCurrentOperation();\r
+ if(anOperation && isNestedSketchOperation(anOperation)) {\r
+ // Set final definitions if they are necessary\r
+ //propertyPanelDefined(aOperation);\r
+ /// Commit sketcher operations automatically\r
+ /// distance operation are able to show popup editor to modify the distance value\r
+ /// after entering the value, the operation should be committed/aborted(by Esc key)\r
+ bool aCanCommitOperation = true;\r
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>\r
+ (anOperation);\r
+ if (aFOperation && PartSet_SketcherMgr::isDistanceOperation(aFOperation)) {\r
+ bool aValueAccepted = setDistanceValueByPreselection(anOperation, myModule->workshop(),\r
+ aCanCommitOperation);\r
+ if (!aValueAccepted)\r
+ return isOperationStopped;\r
+ }\r
+\r
+ if (aCanCommitOperation)\r
+ isOperationStopped = anOperation->commit();\r
+ else {\r
+ anOperation->abort();\r
+ isOperationStopped = true;\r
+ }\r
+ }\r
+ return isOperationStopped;\r
+}\r
+\r
+bool PartSet_SketcherMgr::canUndo() const\r
+{\r
+ return isNestedCreateOperation(getCurrentOperation(), activeSketch());\r
+}\r
+\r
+bool PartSet_SketcherMgr::canRedo() const\r
+{\r
+ return isNestedCreateOperation(getCurrentOperation(), activeSketch());\r
+}\r
+\r
+bool PartSet_SketcherMgr::canEraseObject(const ObjectPtr& theObject) const\r
+{\r
+ bool aCanErase = true;\r
+ // when the sketch operation is active, results of sketch sub-feature can not be hidden\r
+ if (myCurrentSketch.get()) {\r
+ ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);\r
+ if (aResult.get()) {\r
+ // Display sketcher objects\r
+ for (int i = 0; i < myCurrentSketch->numberOfSubs() && aCanErase; i++) {\r
+\r
+ FeaturePtr aFeature = myCurrentSketch->subFeature(i);\r
+ std::list<ResultPtr> aResults = aFeature->results();\r
+ std::list<ResultPtr>::const_iterator anIt;\r
+ for (anIt = aResults.begin(); anIt != aResults.end() && aCanErase; ++anIt) {\r
+ aCanErase = *anIt != aResult;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return aCanErase;\r
+}\r
+\r
+bool PartSet_SketcherMgr::canDisplayObject(const ObjectPtr& theObject) const\r
+{\r
+ bool aCanDisplay = true;\r
+\r
+ bool aHasActiveSketch = activeSketch().get() != NULL;\r
+ if (aHasActiveSketch) {\r
+ // 1. the sketch feature should not be displayed during the sketch active operation\r
+ // it is hidden by a sketch operation start and shown by a sketch stop, just the sketch \r
+ // nested features can be visualized\r
+ FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);\r
+ if (aFeature.get() != NULL && aFeature == activeSketch()) {\r
+ aCanDisplay = false;\r
+ }\r
+ std::shared_ptr<SketchPlugin_Feature> aSketchFeature =\r
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);\r
+ /// some sketch entities should be never shown, e.g. projection feature\r
+ if (aSketchFeature.get())\r
+ aCanDisplay = aSketchFeature->canBeDisplayed();\r
+ }\r
+ else { // there are no an active sketch\r
+ // 2. sketch sub-features should not be visualized if the sketch operation is not active\r
+ FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);\r
+ if (aFeature.get() != NULL) {\r
+ std::shared_ptr<SketchPlugin_Feature> aSketchFeature =\r
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);\r
+ if (aSketchFeature.get()) {\r
+ aCanDisplay = false;\r
+ }\r
+ }\r
+ }\r
+\r
+ // 3. the method should not filter the objects, which are not related to the current operation.\r
+ // The object is filtered just if it is a current operation feature or this feature result\r
+ if (aCanDisplay) {\r
+ bool isObjectFound = false;\r
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>\r
+ (getCurrentOperation());\r
+ if (aFOperation) {\r
+ FeaturePtr aFeature = aFOperation->feature();\r
+ if (aFeature.get()) {\r
+ std::list<ResultPtr> aResults = aFeature->results();\r
+ if (theObject == aFeature)\r
+ isObjectFound = true;\r
+ else {\r
+ std::list<ResultPtr>::const_iterator anIt = aResults.begin(), aLast = aResults.end();\r
+ for (; anIt != aLast && !isObjectFound; anIt++) {\r
+ isObjectFound = *anIt == theObject;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ if (isObjectFound) {\r
+ // 4. For created nested feature operation do not display the created feature if\r
+ // the mouse curstor leaves the OCC window.\r
+ // The correction cases, which ignores this condition:\r
+ // a. the property panel values modification\r
+ // b. the popup menu activated\r
+ // c. widget editor control\r
+ #ifndef DEBUG_DO_NOT_BY_ENTER\r
+ if (isNestedCreateOperation(getCurrentOperation(), activeSketch())) {\r
+ ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();\r
+ ModuleBase_WidgetEditor* anEditorWdg = anActiveWidget ? dynamic_cast<ModuleBase_WidgetEditor*>(anActiveWidget) : 0;\r
+ // the active widget editor should not influence here. The presentation should be visible always\r
+ // when this widget is active.\r
+ if (!anEditorWdg && !myIsPopupMenuActive) {\r
+ // during a nested create operation, the feature is redisplayed only if the mouse over view\r
+ // of there was a value modified in the property panel after the mouse left the view\r
+ aCanDisplay = canDisplayCurrentCreatedFeature();\r
+ }\r
+ }\r
+ #endif\r
+ }\r
+ }\r
+\r
+ // checks the sketcher constraints visibility according to active sketch check box states\r
+ if (aCanDisplay) {\r
+ bool aProcessed = false;\r
+ FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);\r
+ if (aFeature.get()) {\r
+ bool aConstraintDisplayed = canDisplayConstraint(aFeature, PartSet_Tools::Any, aProcessed);\r
+ if (aProcessed)\r
+ aCanDisplay = aConstraintDisplayed;\r
+ }\r
+ }\r
+\r
+ return aCanDisplay;\r
+}\r
+\r
+bool PartSet_SketcherMgr::canDisplayConstraint(const FeaturePtr& theFeature,\r
+ const PartSet_Tools::ConstraintVisibleState& theState,\r
+ bool& isProcessed) const\r
+{\r
+ bool aSwitchedOn = true;\r
+\r
+ const QStringList& aConstrIds = constraintsIdList();\r
+\r
+ std::string aKind = theFeature->getKind();\r
+ if (aConstrIds.contains(QString(aKind.c_str()))) {\r
+ bool isTypedConstraint = false;\r
+\r
+ switch (theState) {\r
+ case PartSet_Tools::Dimensional: {\r
+ bool isDistance = isDistanceKind(aKind);\r
+ if (isDistance) {\r
+ isProcessed = true;\r
+ aSwitchedOn = myIsConstraintsShown[theState];\r
+ }\r
+ }\r
+ break;\r
+ case PartSet_Tools::Geometrical: {\r
+ bool isGeometrical = !isDistanceKind(aKind);\r
+ if (isGeometrical) {\r
+ isProcessed = true;\r
+ aSwitchedOn = myIsConstraintsShown[theState];\r
+ }\r
+ }\r
+ break;\r
+ case PartSet_Tools::Any: {\r
+ isProcessed = true;\r
+ bool isDistance = isDistanceKind(aKind);\r
+ if (isDistance)\r
+ aSwitchedOn = myIsConstraintsShown[PartSet_Tools::Dimensional];\r
+ else\r
+ aSwitchedOn = myIsConstraintsShown[PartSet_Tools::Geometrical];\r
+ }\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+ return aSwitchedOn;\r
+}\r
+\r
+/*void PartSet_SketcherMgr::processHiddenObject(const std::list<ObjectPtr>& theObjects)\r
+{\r
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>\r
+ (getCurrentOperation());\r
+ if (aFOperation && myCurrentSketch.get()) {\r
+ // find results of the current operation\r
+ // these results should not be proposed to be deleted\r
+ FeaturePtr anOperationFeature = aFOperation->feature();\r
+ std::list<ResultPtr> anOperationResultList = anOperationFeature->results();\r
+ std::set<ResultPtr> anOperationResults;\r
+ std::list<ResultPtr>::const_iterator aRIt = anOperationResultList.begin(),\r
+ aRLast = anOperationResultList.end();\r
+ for (; aRIt != aRLast; aRIt++)\r
+ anOperationResults.insert(*aRIt);\r
+\r
+ std::set<FeaturePtr> anObjectsToBeDeleted;\r
+ QStringList anObjectsToBeDeletedNames;\r
+ std::list<ObjectPtr>::const_iterator anIt = theObjects.begin(), aLast = theObjects.end();\r
+ for (; anIt != aLast; anIt++) {\r
+ ObjectPtr anObject = *anIt;\r
+ bool aCanErase = true;\r
+ // when the sketch operation is active, results of sketch sub-feature can not be hidden\r
+ ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);\r
+ // the result is found between current feature results\r
+ if (anOperationResults.find(aResult) != anOperationResults.end())\r
+ continue;\r
+\r
+ if (aResult.get()) {\r
+ // Display sketcher objects\r
+ for (int i = 0; i < myCurrentSketch->numberOfSubs() && aCanErase; i++) {\r
+ FeaturePtr aFeature = myCurrentSketch->subFeature(i);\r
+ std::list<ResultPtr> aResults = aFeature->results();\r
+ std::list<ResultPtr>::const_iterator anIt;\r
+ for (anIt = aResults.begin(); anIt != aResults.end() && aCanErase; ++anIt) {\r
+ aCanErase = *anIt != aResult;\r
+ }\r
+ }\r
+ }\r
+ if (!aCanErase) {\r
+ FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);\r
+ if (aFeature.get() && anObjectsToBeDeleted.find(aFeature) == anObjectsToBeDeleted.end()) {\r
+ anObjectsToBeDeleted.insert(aFeature);\r
+ anObjectsToBeDeletedNames.append(aFeature->name().c_str());\r
+ }\r
+ }\r
+ }\r
+ if (!anObjectsToBeDeleted.empty()) {\r
+ QString aFeatureNames = anObjectsToBeDeletedNames.join(", ");\r
+ QString aMessage = tr("The following features have incorrect presentation and \\r
+will be hidden: %1. Would you like to delete them?")\r
+ .arg(aFeatureNames);\r
+ int anAnswer = QMessageBox::question(qApp->activeWindow(), tr("Features hide"),\r
+ aMessage, QMessageBox::Ok | QMessageBox::Cancel,\r
+ QMessageBox::Cancel);\r
+ if (anAnswer == QMessageBox::Ok) {\r
+ QObjectPtrList anObjects;\r
+ std::set<FeaturePtr>::const_iterator anIt = anObjectsToBeDeleted.begin(),\r
+ aLast = anObjectsToBeDeleted.end();\r
+ for (; anIt != aLast; anIt++)\r
+ anObjects.append(*anIt);\r
+ SessionPtr aMgr = ModelAPI_Session::get();\r
+ DocumentPtr aDoc = aMgr->activeDocument();\r
+ bool aIsOp = aMgr->isOperation();\r
+ if (!aIsOp)\r
+ aMgr->startOperation();\r
+ workshop()->deleteFeatures(anObjects);\r
+ //static Events_ID aDeletedEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);\r
+ //static Events_ID aRedispEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);\r
+ //Events_Loop::loop()->flush(aDeletedEvent);\r
+ //Events_Loop::loop()->flush(aRedispEvent);\r
+\r
+ if (!aIsOp)\r
+ aMgr->finishOperation();\r
+ }\r
+ }\r
+ }\r
+}*/\r
+\r
+bool PartSet_SketcherMgr::canDisplayCurrentCreatedFeature() const\r
+{\r
+ bool aCanDisplay = myIsMouseOverWindow;\r
+ if (!aCanDisplay) {\r
+ ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();\r
+ if (anActiveWidget)\r
+ aCanDisplay = anActiveWidget->getValueState() == ModuleBase_ModelWidget::Stored;\r
+ }\r
+ return aCanDisplay;\r
+}\r
+\r
+bool PartSet_SketcherMgr::canChangeCursor(ModuleBase_Operation* theOperation) const\r
+{\r
+ return isNestedCreateOperation(theOperation, activeSketch()) ||\r
+ myModule->sketchReentranceMgr()->isInternalEditActive();\r
+}\r
+\r
+const QMap<PartSet_Tools::ConstraintVisibleState, bool>& PartSet_SketcherMgr::showConstraintStates()\r
+{\r
+ return myIsConstraintsShown;\r
+}\r
+\r
+bool PartSet_SketcherMgr::isObjectOfSketch(const ObjectPtr& theObject) const\r
+{\r
+ bool isFoundObject = false;\r
+\r
+ FeaturePtr anObjectFeature = ModelAPI_Feature::feature(theObject);\r
+ if (anObjectFeature.get()) {\r
+ int aSize = myCurrentSketch->numberOfSubs();\r
+ for (int i = 0; i < myCurrentSketch->numberOfSubs() && !isFoundObject; i++) {\r
+ FeaturePtr aCurrentFeature = myCurrentSketch->subFeature(i);\r
+ isFoundObject = myCurrentSketch->subFeature(i) == anObjectFeature;\r
+ }\r
+ }\r
+ return isFoundObject;\r
+}\r
+\r
+void PartSet_SketcherMgr::onPlaneSelected(const std::shared_ptr<GeomAPI_Pln>& thePln)\r
+{\r
+ if (myPlaneFilter.IsNull()) \r
+ myPlaneFilter = new ModuleBase_ShapeInPlaneFilter();\r
+\r
+ myPlaneFilter->setPlane(thePln);\r
+}\r
+\r
+bool PartSet_SketcherMgr::setDistanceValueByPreselection(ModuleBase_Operation* theOperation,\r
+ ModuleBase_IWorkshop* theWorkshop,\r
+ bool& theCanCommitOperation)\r
+{\r
+ bool isValueAccepted = false;\r
+ theCanCommitOperation = false;\r
+\r
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>\r
+ (theOperation);\r
+ FeaturePtr aFeature = aFOperation->feature();\r
+ // editor is shown only if all attribute references are filled by preseletion\r
+ bool anAllRefAttrInitialized = true;\r
+\r
+ std::list<AttributePtr> aRefAttrs = aFeature->data()->attributes(\r
+ ModelAPI_AttributeRefAttr::typeId());\r
+ std::list<AttributePtr>::const_iterator anIt = aRefAttrs.begin(), aLast = aRefAttrs.end();\r
+ for (; anIt != aLast && anAllRefAttrInitialized; anIt++) {\r
+ anAllRefAttrInitialized = (*anIt)->isInitialized();\r
+ }\r
+ if (anAllRefAttrInitialized) {\r
+ // Activate dimension value editing on double click\r
+ ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel();\r
+ QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();\r
+ // Find corresponded widget to activate value editing\r
+ foreach (ModuleBase_ModelWidget* aWgt, aWidgets) {\r
+ if (aWgt->attributeID() == "ConstraintValue") {\r
+ // the featue should be displayed in order to find the AIS text position,\r
+ // the place where the editor will be shown\r
+ aFeature->setDisplayed(true);\r
+ /// the execute is necessary to perform in the feature compute for flyout position\r
+ aFeature->execute();\r
+\r
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));\r
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));\r
+\r
+ PartSet_WidgetEditor* anEditor = dynamic_cast<PartSet_WidgetEditor*>(aWgt);\r
+ if (anEditor) {\r
+ int aX = 0, anY = 0;\r
+\r
+ XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(theWorkshop);\r
+ XGUI_Displayer* aDisplayer = aWorkshop->displayer();\r
+ AISObjectPtr anAIS = aDisplayer->getAISObject(aFeature);\r
+ Handle(AIS_InteractiveObject) anAISIO;\r
+ if (anAIS.get() != NULL) {\r
+ anAISIO = anAIS->impl<Handle(AIS_InteractiveObject)>();\r
+ }\r
+ if (anAIS.get() != NULL) {\r
+ Handle(AIS_InteractiveObject) anAISIO = anAIS->impl<Handle(AIS_InteractiveObject)>();\r
+\r
+ if (!anAISIO.IsNull()) {\r
+ Handle(AIS_Dimension) aDim = Handle(AIS_Dimension)::DownCast(anAISIO);\r
+ if (!aDim.IsNull()) {\r
+ gp_Pnt aPosition = aDim->GetTextPosition();\r
+\r
+ ModuleBase_IViewer* aViewer = aWorkshop->viewer();\r
+ Handle(V3d_View) aView = aViewer->activeView();\r
+ int aCX, aCY;\r
+ aView->Convert(aPosition.X(), aPosition.Y(), aPosition.Z(), aCX, aCY);\r
+\r
+ QWidget* aViewPort = aViewer->activeViewPort();\r
+ QPoint aGlPoint = aViewPort->mapToGlobal(QPoint(aCX, aCY));\r
+ aX = aGlPoint.x();\r
+ anY = aGlPoint.y();\r
+ }\r
+ }\r
+ anEditor->setCursorPosition(aX, anY);\r
+ isValueAccepted = anEditor->showPopupEditor(false);\r
+ theCanCommitOperation = true;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return isValueAccepted;\r
+}\r
+\r
+void PartSet_SketcherMgr::getSelectionOwners(const FeaturePtr& theFeature,\r
+ const FeaturePtr& theSketch,\r
+ ModuleBase_IWorkshop* theWorkshop,\r
+ const FeatureToSelectionMap& theSelection,\r
+ SelectMgr_IndexedMapOfOwner& theOwnersToSelect)\r
+{\r
+ if (theFeature.get() == NULL)\r
+ return;\r
+\r
+ FeatureToSelectionMap::const_iterator anIt = theSelection.find(theFeature);\r
+ std::set<AttributePtr> aSelectedAttributes = anIt.value().first;\r
+ std::set<ResultPtr> aSelectedResults = anIt.value().second;\r
+\r
+ ModuleBase_IViewer* aViewer = theWorkshop->viewer();\r
+\r
+ XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWorkshop);\r
+ XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();\r
+\r
+ // 1. found the feature's owners. Check the AIS objects of the constructions\r
+ AISObjectPtr aAISObj = aDisplayer->getAISObject(theFeature);\r
+ if (aAISObj.get() != NULL && aSelectedAttributes.empty() && aSelectedResults.empty()) {\r
+ Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();\r
+\r
+ SelectMgr_IndexedMapOfOwner aSelectedOwners;\r
+ aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners);\r
+ for (Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++) {\r
+ Handle(SelectMgr_EntityOwner) anOwner = aSelectedOwners(i);\r
+ if (!anOwner.IsNull())\r
+ theOwnersToSelect.Add(anOwner);\r
+ }\r
+ }\r
+\r
+ // 2. found the feature results's owners\r
+ std::list<ResultPtr> aResults = theFeature->results();\r
+ std::list<ResultPtr>::const_iterator aIt;\r
+ for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt)\r
+ {\r
+ ResultPtr aResult = *aIt;\r
+ AISObjectPtr aAISObj = aDisplayer->getAISObject(aResult);\r
+ if (aAISObj.get() == NULL)\r
+ continue; \r
+ Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();\r
+\r
+ SelectMgr_IndexedMapOfOwner aSelectedOwners; \r
+ aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners);\r
+ for ( Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++ ) {\r
+ Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast(aSelectedOwners(i));\r
+ if ( anOwner.IsNull() || !anOwner->HasShape() )\r
+ continue;\r
+ const TopoDS_Shape& aShape = anOwner->Shape();\r
+ TopAbs_ShapeEnum aShapeType = aShape.ShapeType();\r
+ if (aShapeType == TopAbs_VERTEX) {\r
+ AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(theFeature, aShape, theSketch);\r
+ if (aPntAttr.get() != NULL &&\r
+ aSelectedAttributes.find(aPntAttr) != aSelectedAttributes.end()) {\r
+ theOwnersToSelect.Add(anOwner);\r
+ }\r
+ }\r
+ else if (aShapeType == TopAbs_EDGE) {\r
+ bool aFound = aSelectedResults.find(aResult) != aSelectedResults.end();\r
+ if (aSelectedResults.find(aResult) != aSelectedResults.end() &&\r
+ theOwnersToSelect.FindIndex(anOwner) <= 0)\r
+ theOwnersToSelect.Add(anOwner);\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+void PartSet_SketcherMgr::connectToPropertyPanel(ModuleBase_ModelWidget* theWidget, const bool isToConnect)\r
+{\r
+ if (isToConnect) {\r
+ connect(theWidget, SIGNAL(beforeValuesChanged()),\r
+ this, SLOT(onBeforeValuesChangedInPropertyPanel()));\r
+ connect(theWidget, SIGNAL(afterValuesChanged()),\r
+ this, SLOT(onAfterValuesChangedInPropertyPanel()));\r
+ }\r
+ else {\r
+ disconnect(theWidget, SIGNAL(beforeValuesChanged()),\r
+ this, SLOT(onBeforeValuesChangedInPropertyPanel()));\r
+ disconnect(theWidget, SIGNAL(afterValuesChanged()),\r
+ this, SLOT(onAfterValuesChangedInPropertyPanel()));\r
+ }\r
+}\r
+\r
+void PartSet_SketcherMgr::widgetStateChanged(int thePreviousState)\r
+{\r
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>\r
+ (getCurrentOperation());\r
+ if (aFOperation) {\r
+ if (PartSet_SketcherMgr::isSketchOperation(aFOperation) ||\r
+ isNestedSketchOperation(aFOperation) &&\r
+ thePreviousState == ModuleBase_ModelWidget::ModifiedInPP) {\r
+ FeaturePtr aFeature = aFOperation->feature();\r
+ visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature));\r
+ }\r
+ }\r
+}\r
+\r
+void PartSet_SketcherMgr::customizePresentation(const ObjectPtr& theObject)\r
+{\r
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>\r
+ (getCurrentOperation());\r
+ if (aFOperation && (PartSet_SketcherMgr::isSketchOperation(aFOperation) ||\r
+ isNestedSketchOperation(aFOperation)))\r
+ SketcherPrs_Tools::sendExpressionShownEvent(myIsConstraintsShown[PartSet_Tools::Expressions]);\r
+\r
+ // update entities selection priorities\r
+ FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);\r
+ if (aFeature.get() && PartSet_SketcherMgr::isEntity(aFeature->getKind())) {\r
+ // update priority for feature\r
+ updateSelectionPriority(aFeature, aFeature);\r
+ // update priority for results of the feature\r
+ std::list<ResultPtr> aResults = aFeature->results();\r
+ std::list<ResultPtr>::const_iterator anIt = aResults.begin(), aLastIt = aResults.end();\r
+ for (; anIt != aLastIt; anIt++)\r
+ updateSelectionPriority(*anIt, aFeature);\r
+ }\r
+}\r
+\r
+ModuleBase_Operation* PartSet_SketcherMgr::getCurrentOperation() const\r
+{\r
+ return myModule->workshop()->currentOperation();\r
+}\r
+\r
+//**************************************************************\r
+ModuleBase_ModelWidget* PartSet_SketcherMgr::getActiveWidget() const\r
+{\r
+ ModuleBase_ModelWidget* aWidget = 0;\r
+ ModuleBase_Operation* anOperation = getCurrentOperation();\r
+ if (anOperation) {\r
+ ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel();\r
+ if (aPanel)\r
+ aWidget = aPanel->activeWidget();\r
+ }\r
+ return aWidget;\r
+}\r
+\r
+void PartSet_SketcherMgr::visualizeFeature(const FeaturePtr& theFeature,\r
+ const bool isEditOperation,\r
+ const bool isToDisplay,\r
+ const bool isFlushRedisplay)\r
+{\r
+ #ifdef DEBUG_DO_NOT_BY_ENTER\r
+ return;\r
+ #endif\r
+\r
+ if (isEditOperation || !theFeature.get())\r
+ return;\r
+\r
+ ModuleBase_IWorkshop* aWorkshop = myModule->workshop();\r
+ XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);\r
+\r
+ // 1. change visibility of the object itself, here the presentable object is processed,\r
+ // e.g. constraints features\r
+ //FeaturePtr aFeature = aFOperation->feature();\r
+ std::list<ResultPtr> aResults = theFeature->results();\r
+ if (isToDisplay)\r
+ theFeature->setDisplayed(true);\r
+ else\r
+ theFeature->setDisplayed(false);\r
+\r
+ // change visibility of the object results, e.g. non-constraint features\r
+ std::list<ResultPtr>::const_iterator aIt;\r
+ for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {\r
+ if (isToDisplay) {\r
+ (*aIt)->setDisplayed(true);\r
+ }\r
+ else {\r
+ (*aIt)->setDisplayed(false);\r
+ }\r
+ }\r
+ if (isFlushRedisplay)\r
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));\r
+}\r
+\r
+void PartSet_SketcherMgr::storeSelection(const bool theHighlightedOnly)\r
+{\r
+ if (!myCurrentSketch.get())\r
+ return;\r
+\r
+ ModuleBase_IWorkshop* aWorkshop = myModule->workshop();\r
+ ModuleBase_ISelection* aSelect = aWorkshop->selection();\r
+ QList<ModuleBase_ViewerPrsPtr> aStoredPrs = aSelect->getHighlighted();\r
+\r
+ QList<FeaturePtr> aFeatureList;\r
+ if (!theHighlightedOnly) {\r
+ QList<ModuleBase_ViewerPrsPtr> aSelected = aSelect->getSelected(\r
+ ModuleBase_ISelection::AllControls);\r
+ aStoredPrs.append(aSelected);\r
+ }\r
+\r
+ // 1. it is necessary to save current selection in order to restore it after the features moving\r
+ myCurrentSelection.clear();\r
+\r
+ QList<ModuleBase_ViewerPrsPtr>::const_iterator anIt = aStoredPrs.begin(), aLast = aStoredPrs.end();\r
+\r
+ CompositeFeaturePtr aSketch = activeSketch();\r
+ for (; anIt != aLast; anIt++) {\r
+ ModuleBase_ViewerPrsPtr aPrs = *anIt;\r
+ ObjectPtr anObject = aPrs->object();\r
+ if (!anObject.get())\r
+ continue;\r
+\r
+ ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);\r
+ FeaturePtr aFeature;\r
+ if (aResult.get())\r
+ aFeature = ModelAPI_Feature::feature(aResult);\r
+ else\r
+ aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);\r
+\r
+\r
+ std::set<AttributePtr> aSelectedAttributes;\r
+ std::set<ResultPtr> aSelectedResults;\r
+ if (myCurrentSelection.find(aFeature) != myCurrentSelection.end()) {\r
+ std::pair<std::set<AttributePtr>, std::set<ResultPtr> > aPair = myCurrentSelection.find(aFeature).value();\r
+ aSelectedAttributes = aPair.first;\r
+ aSelectedResults = aPair.second;\r
+ }\r
+\r
+ Handle(SelectMgr_EntityOwner) anOwner = aPrs->owner();\r
+ if (aResult.get()) {\r
+ getAttributesOrResults(anOwner, aFeature, aSketch, aResult,\r
+ aSelectedAttributes, aSelectedResults);\r
+ }\r
+ else {\r
+ std::list<ResultPtr> aResults = aFeature->results();\r
+ std::list<ResultPtr>::const_iterator aIt;\r
+ for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {\r
+ ResultPtr aResult = *aIt;\r
+ getAttributesOrResults(anOwner, aFeature, aSketch, aResult,\r
+ aSelectedAttributes, aSelectedResults);\r
+ }\r
+ }\r
+ myCurrentSelection[aFeature] = std::make_pair(aSelectedAttributes, aSelectedResults);\r
+ }\r
+ //qDebug(QString(" storeSelection: %1").arg(myCurrentSelection.size()).toStdString().c_str());\r
+}\r
+\r
+void PartSet_SketcherMgr::restoreSelection()\r
+{\r
+ if (!myCurrentSketch.get())\r
+ return;\r
+\r
+ //qDebug(QString("restoreSelection: %1").arg(myCurrentSelection.size()).toStdString().c_str());\r
+ ModuleBase_IWorkshop* aWorkshop = myModule->workshop();\r
+ XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);\r
+ FeatureToSelectionMap::const_iterator aSIt = myCurrentSelection.begin(),\r
+ aSLast = myCurrentSelection.end();\r
+ SelectMgr_IndexedMapOfOwner anOwnersToSelect;\r
+ for (; aSIt != aSLast; aSIt++) {\r
+ anOwnersToSelect.Clear();\r
+ getSelectionOwners(aSIt.key(), myCurrentSketch, aWorkshop, myCurrentSelection,\r
+ anOwnersToSelect);\r
+ aConnector->workshop()->selector()->setSelectedOwners(anOwnersToSelect, false);\r
+ }\r
+}\r
+\r
+void PartSet_SketcherMgr::onShowConstraintsToggle(int theType, bool theState)\r
+{\r
+ PartSet_Tools::ConstraintVisibleState aType = (PartSet_Tools::ConstraintVisibleState)theType;\r
+\r
+ updateBySketchParameters(aType, theState);\r
+}\r
+\r
+void PartSet_SketcherMgr::updateBySketchParameters(\r
+ const PartSet_Tools::ConstraintVisibleState& theType,\r
+ bool theState)\r
+{\r
+ if (myCurrentSketch.get() == NULL)\r
+ return;\r
+\r
+ bool aPrevState = myIsConstraintsShown[theType];\r
+ myIsConstraintsShown[theType] = theState;\r
+\r
+ switch (theType) {\r
+ case PartSet_Tools::Geometrical:\r
+ case PartSet_Tools::Dimensional: {\r
+ if (aPrevState != theState) {\r
+ ModuleBase_IWorkshop* aWorkshop = myModule->workshop();\r
+ XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);\r
+ for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {\r
+ FeaturePtr aSubFeature = myCurrentSketch->subFeature(i);\r
+ bool aProcessed = false;\r
+ bool aConstraintDisplayed = canDisplayConstraint(aSubFeature, theType, aProcessed);\r
+ if (aProcessed)\r
+ aSubFeature->setDisplayed(aConstraintDisplayed);\r
+ }\r
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));\r
+ }\r
+ }\r
+ break;\r
+ case PartSet_Tools::Expressions: {\r
+ if (aPrevState != theState) {\r
+ /// call all sketch features redisplay, the expression state will be corrected in customize\r
+ /// of distance presentation\r
+ Events_ID anEventId = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);\r
+ PartSet_Tools::sendSubFeaturesEvent(myCurrentSketch, anEventId);\r
+ }\r
+ }\r
+ break;\r
+ }\r
+}\r
+\r
+void PartSet_SketcherMgr::updateSelectionPriority(ObjectPtr theObject,\r
+ FeaturePtr theFeature)\r
+{\r
+ if (!theObject.get() || !theFeature.get())\r
+ return;\r
+\r
+ AISObjectPtr anAIS = workshop()->displayer()->getAISObject(theObject);\r
+ Handle(AIS_InteractiveObject) anAISIO;\r
+ if (anAIS.get() != NULL) {\r
+ anAISIO = anAIS->impl<Handle(AIS_InteractiveObject)>();\r
+ }\r
+\r
+ if (!anAISIO.IsNull()) { // the presentation for the object is visualized\r
+ int anAdditionalPriority = 0;\r
+ // current feature\r
+ std::shared_ptr<SketchPlugin_Feature> aSPFeature =\r
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);\r
+ if (aSPFeature.get() != NULL) {\r
+ // 1. Vertices\r
+ // 2. Simple segments\r
+ // 3. External objects (violet color)\r
+ // 4. Auxiliary segments (dotted)\r
+ // StdSelect_BRepSelectionTool::Load uses priority calculating:\r
+ // Standard_Integer aPriority = (thePriority == -1) ? GetStandardPriority (theShape, theType) : thePriority;\r
+ // Priority of Vertex is 8, edge(segment) is 7.\r
+ // It might be not corrected as provides the condition above.\r
+ bool isExternal = aSPFeature->isExternal();\r
+ bool isAuxiliary = PartSet_Tools::isAuxiliarySketchEntity(aSPFeature);\r
+ // current feature\r
+ if (!isExternal && !isAuxiliary)\r
+ anAdditionalPriority = 30;\r
+ // external feature\r
+ if (isExternal)\r
+ anAdditionalPriority = 20;\r
+ // auxiliary feature\r
+ if (isAuxiliary) {\r
+ anAdditionalPriority = 10; /// auxiliary objects should have less priority that\r
+ // edges/vertices of local selection on not-sketch objects\r
+ }\r
+ Handle(ModuleBase_ResultPrs) aResult = Handle(ModuleBase_ResultPrs)::DownCast(anAISIO);\r
+ if (!aResult.IsNull()) {\r
+ aResult->setAdditionalSelectionPriority(anAdditionalPriority);\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+XGUI_Workshop* PartSet_SketcherMgr::workshop() const\r
+{\r
+ ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();\r
+ XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(anIWorkshop);\r
+ return aConnector->workshop();\r
+}\r
+\r
+XGUI_OperationMgr* PartSet_SketcherMgr::operationMgr() const\r
+{\r
+ return workshop()->operationMgr();\r
+}\r
+\r