X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FPartSet%2FPartSet_SketcherMgr.cpp;h=f3d5bfa320deb4f71dcd88151bbf8852f2f34089;hb=aea15db62bec148b6bfd5db468c682b1695c3449;hp=80fd683fef3c97a3d289cdb4cbced777e9b0fc52;hpb=9e10a25021a539ae9bb44e85e244a8e3fa8119ed;p=modules%2Fshaper.git diff --git a/src/PartSet/PartSet_SketcherMgr.cpp b/src/PartSet/PartSet_SketcherMgr.cpp index 80fd683fe..f3d5bfa32 100644 --- a/src/PartSet/PartSet_SketcherMgr.cpp +++ b/src/PartSet/PartSet_SketcherMgr.cpp @@ -7,16 +7,24 @@ #include "PartSet_SketcherMgr.h" #include "PartSet_Module.h" #include "PartSet_WidgetPoint2d.h" +#include "PartSet_WidgetPoint2dDistance.h" #include "PartSet_Tools.h" +#include "PartSet_WidgetSketchLabel.h" + +#include #include #include #include +#include #include #include #include #include #include +#include + +#include #include #include @@ -41,18 +49,31 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include #include //#include -//#include +#include #include +#include #include #include +//#define DEBUG_DO_NOT_BY_ENTER /// Returns list of unique objects by sum of objects from List1 and List2 /*QList getSumList(const QList& theList1, @@ -106,7 +127,10 @@ void fillFeature2Attribute(const QList& theList, PartSet_SketcherMgr::PartSet_SketcherMgr(PartSet_Module* theModule) - : QObject(theModule), myModule(theModule), myIsDragging(false), myDragDone(false) + : QObject(theModule), myModule(theModule), myIsDragging(false), myDragDone(false), + myIsPropertyPanelValueChanged(false), myIsMouseOverWindow(false), + myIsMouseOverViewProcessed(true), myPreviousUpdateViewerEnabled(true), + myIsPopupMenuActive(false), myIsConstraintsShown(true) { ModuleBase_IWorkshop* anIWorkshop = myModule->workshop(); ModuleBase_IViewer* aViewer = anIWorkshop->viewer(); @@ -136,6 +160,107 @@ PartSet_SketcherMgr::~PartSet_SketcherMgr() 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; + myIsPropertyPanelValueChanged = false; + + #ifdef DEBUG_DO_NOT_BY_ENTER + return; + #endif + //if (!isNestedCreateOperation(getCurrentOperation())) + // return; +} + +void PartSet_SketcherMgr::onLeaveViewPort() +{ + myIsMouseOverViewProcessed = false; + myIsMouseOverWindow = false; + myIsPropertyPanelValueChanged = false; + + #ifdef DEBUG_DO_NOT_BY_ENTER + return; + #endif + + if (!isNestedCreateOperation(getCurrentOperation())) + return; + // the method should be performed if the popup menu is called, + // the reset of the current widget should not happen + if (myIsPopupMenuActive) + return; + + // 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(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_Operation* aOperation = getCurrentOperation(); + ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); + ModuleBase_ModelWidget* aActiveWgt = aPanel->activeWidget(); + if (aActiveWgt) { + aActiveWgt->reset(); + } + aDisplayer->enableUpdateViewer(isEnableUpdateViewer); + + // hides the presentation of the current operation feature + //myIsPropertyPanelValueChanged = false; + // 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) + FeaturePtr aFeature = getCurrentOperation()->feature(); + visualizeFeature(aOperation, canDisplayObject(aFeature)); +} + +void PartSet_SketcherMgr::onBeforeValuesChangedInPropertyPanel() +{ + if (isNestedCreateOperation(getCurrentOperation())) + 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(aWorkshop); + XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); + myPreviousUpdateViewerEnabled = aDisplayer->enableUpdateViewer(false); +} + +void PartSet_SketcherMgr::onAfterValuesChangedInPropertyPanel() +{ + if (isNestedCreateOperation(getCurrentOperation())) + 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(aWorkshop); + XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); + aDisplayer->enableUpdateViewer(myPreviousUpdateViewerEnabled); + aDisplayer->updateViewer(); +} + +void PartSet_SketcherMgr::onValuesChangedInPropertyPanel() +{ + if (!isNestedCreateOperation(getCurrentOperation())) + return; + + // visualize the current operation feature + myIsPropertyPanelValueChanged = true; + ModuleBase_Operation* aOperation = getCurrentOperation(); + // 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) + FeaturePtr aFeature = getCurrentOperation()->feature(); + visualizeFeature(aOperation, canDisplayObject(aFeature)); +} + void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) { get2dPoint(theWnd, theEvent, myClickedPoint); @@ -151,7 +276,7 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE if (!aViewer->canDragByMouse()) return; - ModuleBase_Operation* aOperation = aWorkshop->currentOperation(); + ModuleBase_Operation* aOperation = getCurrentOperation(); if (aOperation && aOperation->isEditOperation()) { ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); ModuleBase_ModelWidget* aActiveWgt = aPanel->activeWidget(); @@ -166,8 +291,8 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE if (!PartSet_Tools::sketchPlane(myCurrentSketch)) return; - bool isSketcher = (aOperation->id().toStdString() == SketchPlugin_Sketch::ID()); - bool isSketchOpe = sketchOperationIdList().contains(aOperation->id()); + bool isSketcher = isSketchOperation(aOperation); + bool isSketchOpe = isNestedSketchOperation(aOperation); // Avoid non-sketch operations if ((!isSketchOpe) && (!isSketcher)) @@ -184,33 +309,36 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE // Remember highlighted objects for editing ModuleBase_ISelection* aSelect = aWorkshop->selection(); - QList aHighlighted = aSelect->getHighlighted(); - QList aSelected = aSelect->getSelected(); - myFeature2AttributeMap.clear(); bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier); - if (aHasShift) { - fillFeature2Attribute(aHighlighted, myFeature2AttributeMap, myCurrentSketch); - fillFeature2Attribute(aSelected, myFeature2AttributeMap, myCurrentSketch); - } - else { - fillFeature2Attribute(aHighlighted, myFeature2AttributeMap, myCurrentSketch); - } + storeSelection(!aHasShift); - if (myFeature2AttributeMap.empty()) { + if (myCurrentSelection.empty()) { if (isSketchOpe && (!isSketcher)) // commit previous operation if (!aOperation->commit()) aOperation->abort(); return; } + // Init flyout point for radius rotation + FeaturePtr aFeature = myCurrentSelection.begin().key(); if (isSketcher) { myIsDragging = true; get2dPoint(theWnd, theEvent, myCurrentPoint); myDragDone = false; launchEditing(); - + if (aFeature.get() != NULL) { + std::shared_ptr aSPFeature = + std::dynamic_pointer_cast(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 aFPAttr = + std::dynamic_pointer_cast(aAttr); + aFPAttr->setValue(myCurrentPoint.myCurX, myCurrentPoint.myCurY); + } + } } else if (isSketchOpe && isEditing) { // If selected another object commit current result aOperation->commit(); @@ -232,17 +360,16 @@ void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouse ModuleBase_IViewer* aViewer = aWorkshop->viewer(); if (!aViewer->canDragByMouse()) return; - ModuleBase_Operation* aOp = aWorkshop->currentOperation(); + ModuleBase_Operation* aOp = getCurrentOperation(); if (aOp) { - if (sketchOperationIdList().contains(aOp->id())) { - get2dPoint(theWnd, theEvent, myClickedPoint); + if (isNestedSketchOperation(aOp)) { + get2dPoint(theWnd, theEvent, myClickedPoint); // Only for sketcher operations if (myIsDragging) { if (myDragDone) { //aOp->commit(); - myFeature2AttributeMap.clear(); - + myCurrentSelection.clear(); // Reselect edited object /*aViewer->AISContext()->MoveTo(theEvent->x(), theEvent->y(), theWnd->v3dView()); if (theEvent->modifiers() & Qt::ShiftModifier) @@ -260,24 +387,43 @@ void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouse void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) { + if (isNestedCreateOperation(getCurrentOperation()) && !myIsMouseOverViewProcessed) { + myIsMouseOverViewProcessed = true; + // 1. perform the widget mouse move functionality and display the presentation + ModuleBase_Operation* aOperation = getCurrentOperation(); + ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); + ModuleBase_ModelWidget* anActiveWdg = aPanel->activeWidget(); + // 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 + PartSet_WidgetPoint2D* aPoint2DWdg = dynamic_cast(anActiveWdg); + if (aPoint2DWdg) { + aPoint2DWdg->onMouseMove(theWnd, theEvent); + } + PartSet_WidgetPoint2dDistance* aDistanceWdg = dynamic_cast + (anActiveWdg); + if (aDistanceWdg) { + aDistanceWdg->onMouseMove(theWnd, theEvent); + } + // the feature is to be erased here, but it is correct to call canDisplayObject because + // there can be additional check (e.g. editor widget in distance constraint) + FeaturePtr aFeature = getCurrentOperation()->feature(); + visualizeFeature(aOperation, canDisplayObject(aFeature)); + } + myClickedPoint.clear(); if (myIsDragging) { - ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); - // 1. it is necessary to save current selection in order to restore it after the features moving - FeatureToSelectionMap aCurrentSelection; - getCurrentSelection(myFeature2AttributeMap, myCurrentSketch, aWorkshop, aCurrentSelection); - + // 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_IViewer* aViewer = myModule->workshop()->viewer(); aViewer->enableSelection(false); - ModuleBase_Operation* aOperation = myModule->workshop()->currentOperation(); + ModuleBase_Operation* aOperation = getCurrentOperation(); if (!aOperation) return; - if (aOperation->id().toStdString() == SketchPlugin_Sketch::ID()) + if (isSketchOperation(aOperation)) return; // No edit operation activated Handle(V3d_View) aView = theWnd->v3dView(); @@ -287,6 +433,7 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve double dX = aX - myCurrentPoint.myCurX; double dY = aY - myCurrentPoint.myCurY; + ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); // 3. the flag to disable the update viewer should be set in order to avoid blinking in the @@ -296,17 +443,17 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve static Events_ID aMoveEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED); //static Events_ID aUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); - - FeatureToAttributesMap::const_iterator anIt = myFeature2AttributeMap.begin(), - aLast = myFeature2AttributeMap.end(); + FeatureToSelectionMap::const_iterator anIt = myCurrentSelection.begin(), + aLast = myCurrentSelection.end(); // 4. the features and attributes modification(move) for (; anIt != aLast; anIt++) { FeaturePtr aFeature = anIt.key(); - AttributeList anAttributes = anIt.value(); + std::set anAttributes = anIt.value().first; // Process selection by attribute: the priority to the attribute if (!anAttributes.empty()) { - AttributeList::const_iterator anAttIt = anAttributes.begin(), anAttLast = anAttributes.end(); + std::set::const_iterator anAttIt = anAttributes.begin(), + anAttLast = anAttributes.end(); for (; anAttIt != anAttLast; anAttIt++) { AttributePtr anAttr = *anAttIt; if (anAttr.get() == NULL) @@ -338,19 +485,11 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve //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 - FeatureToSelectionMap::const_iterator aSIt = aCurrentSelection.begin(), - aSLast = aCurrentSelection.end(); - SelectMgr_IndexedMapOfOwner anOwnersToSelect; - for (; aSIt != aSLast; aSIt++) { - anOwnersToSelect.Clear(); - getSelectionOwners(aSIt->first, myCurrentSketch, aWorkshop, aCurrentSelection, - anOwnersToSelect); - aConnector->workshop()->selector()->setSelectedOwners(anOwnersToSelect, false); - } - + restoreSelection(); // 6. restore the update viewer flag and call this update aDisplayer->enableUpdateViewer(isEnableUpdateViewer); aDisplayer->updateViewer(); + myDragDone = true; myCurrentPoint.setValue(aX, aY); } @@ -358,7 +497,7 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve void PartSet_SketcherMgr::onMouseDoubleClick(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) { - ModuleBase_Operation* aOperation = myModule->workshop()->currentOperation(); + ModuleBase_Operation* aOperation = getCurrentOperation(); if (aOperation && aOperation->isEditOperation()) { std::string aId = aOperation->id().toStdString(); if (isDistanceOperation(aOperation)) @@ -387,6 +526,14 @@ void PartSet_SketcherMgr::onApplicationStarted() connect(aPropertyPanel, SIGNAL(beforeWidgetActivated(ModuleBase_ModelWidget*)), this, SLOT(onBeforeWidgetActivated(ModuleBase_ModelWidget*))); } + + 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) @@ -394,7 +541,7 @@ void PartSet_SketcherMgr::onBeforeWidgetActivated(ModuleBase_ModelWidget* theWid if (!myClickedPoint.myIsInitialized) return; - ModuleBase_Operation* aOperation = myModule->workshop()->currentOperation(); + 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 @@ -407,13 +554,14 @@ void PartSet_SketcherMgr::onBeforeWidgetActivated(ModuleBase_ModelWidget* theWid } } -bool PartSet_SketcherMgr::isDistanceOperation(ModuleBase_Operation* theOperation) const +void PartSet_SketcherMgr::onBeforeContextMenu() { - std::string aId = theOperation ? theOperation->id().toStdString() : ""; + myIsPopupMenuActive = true; +} - return (aId == SketchPlugin_ConstraintLength::ID()) || - (aId == SketchPlugin_ConstraintDistance::ID()) || - (aId == SketchPlugin_ConstraintRadius::ID()); +void PartSet_SketcherMgr::onAfterContextMenu() +{ + myIsPopupMenuActive = false; } void PartSet_SketcherMgr::get2dPoint(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent, @@ -428,21 +576,12 @@ void PartSet_SketcherMgr::get2dPoint(ModuleBase_IViewWindow* theWnd, QMouseEvent void PartSet_SketcherMgr::launchEditing() { - // there should be activate the vertex selection mode because the edit can happens by the selected - // point - QIntList aModes; - aModes << TopAbs_VERTEX << TopAbs_EDGE; - // TODO: #391 - to be uncommented - /*aModes.append(AIS_DSM_Text); - aModes.append(AIS_DSM_Line); - aModes.append(AIS_Shape::SelectionMode((TopAbs_ShapeEnum) TopAbs_VERTEX)); - aModes.append(AIS_Shape::SelectionMode((TopAbs_ShapeEnum) TopAbs_EDGE));*/ + // there should be activate the sketch selection mode because the edit can happens + // by any sketch entity or consttant selected + activateObjectsInSketchMode(true); - XGUI_ModuleConnector* aConnector = dynamic_cast(myModule->workshop()); - aConnector->activateSubShapesSelection(aModes); - - if (!myFeature2AttributeMap.empty()) { - FeaturePtr aFeature = myFeature2AttributeMap.begin().key(); + if (!myCurrentSelection.empty()) { + FeaturePtr aFeature = myCurrentSelection.begin().key(); std::shared_ptr aSPFeature = std::dynamic_pointer_cast(aFeature); if (aSPFeature) { @@ -453,7 +592,7 @@ void PartSet_SketcherMgr::launchEditing() } -QStringList PartSet_SketcherMgr::sketchOperationIdList() +const QStringList& PartSet_SketcherMgr::sketchOperationIdList() { static QStringList aIds; if (aIds.size() == 0) { @@ -461,16 +600,78 @@ QStringList PartSet_SketcherMgr::sketchOperationIdList() aIds << SketchPlugin_Point::ID().c_str(); aIds << SketchPlugin_Arc::ID().c_str(); aIds << SketchPlugin_Circle::ID().c_str(); + aIds << SketchPlugin_ConstraintFillet::ID().c_str(); + aIds.append(constraintsIdList()); + } + return aIds; +} + +const QStringList& PartSet_SketcherMgr::constraintsIdList() +{ + static QStringList aIds; + if (aIds.size() == 0) { aIds << SketchPlugin_ConstraintLength::ID().c_str(); aIds << SketchPlugin_ConstraintDistance::ID().c_str(); aIds << SketchPlugin_ConstraintRigid::ID().c_str(); aIds << SketchPlugin_ConstraintRadius::ID().c_str(); aIds << SketchPlugin_ConstraintPerpendicular::ID().c_str(); aIds << SketchPlugin_ConstraintParallel::ID().c_str(); + aIds << SketchPlugin_ConstraintHorizontal::ID().c_str(); + aIds << SketchPlugin_ConstraintVertical::ID().c_str(); + aIds << SketchPlugin_ConstraintEqual::ID().c_str(); + aIds << SketchPlugin_ConstraintTangent::ID().c_str(); + aIds << SketchPlugin_ConstraintCoincidence::ID().c_str(); + aIds << SketchPlugin_ConstraintMirror::ID().c_str(); + aIds << SketchPlugin_MultiRotation::ID().c_str(); + aIds << SketchPlugin_MultiTranslation::ID().c_str(); } return aIds; } +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(AIS_Shape::SelectionMode((TopAbs_ShapeEnum) TopAbs_VERTEX)); + theModes.append(AIS_Shape::SelectionMode((TopAbs_ShapeEnum) TopAbs_EDGE)); +} + +bool PartSet_SketcherMgr::isSketchOperation(ModuleBase_Operation* theOperation) +{ + return theOperation && theOperation->id().toStdString() == SketchPlugin_Sketch::ID(); +} + +bool PartSet_SketcherMgr::isNestedSketchOperation(ModuleBase_Operation* theOperation) +{ + return theOperation && + PartSet_SketcherMgr::sketchOperationIdList().contains(theOperation->id()); +} + +bool PartSet_SketcherMgr::isNestedCreateOperation(ModuleBase_Operation* theOperation) +{ + return theOperation && !theOperation->isEditOperation() && isNestedSketchOperation(theOperation); +} + +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 aId = theOperation ? theOperation->id().toStdString() : ""; + + return (aId == SketchPlugin_ConstraintLength::ID()) || + (aId == SketchPlugin_ConstraintDistance::ID()) || + (aId == SketchPlugin_ConstraintRadius::ID()); +} + void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation) { // Display all sketcher sub-Objects @@ -507,10 +708,19 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation) myPlaneFilter->setPlane(aPln->impl()); } aDisplayer->updateViewer(); + // all sketch objects should be activated in the sketch selection modes by edit operation start + if (theOperation->isEditOperation()) + activateObjectsInSketchMode(true); } void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation) { + myIsMouseOverWindow = false; + myIsConstraintsShown = true; + // the objects activated in the sketch should be deactivated in order to do not have the specific + // sketch selection mode activated on objects in neutral point of the application(no started operation) + activateObjectsInSketchMode(false); + XGUI_ModuleConnector* aConnector = dynamic_cast(myModule->workshop()); XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); @@ -553,23 +763,135 @@ void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation) aDisplayer->updateViewer(); } +void PartSet_SketcherMgr::startNestedSketch(ModuleBase_Operation* theOperation) +{ + if (constraintsIdList().contains(theOperation->id())) { + // Show constraints if a constraint was created + onShowConstraintsToggle(true); + } + connectToPropertyPanel(true); +} -void PartSet_SketcherMgr::onPlaneSelected(const std::shared_ptr& thePln) +void PartSet_SketcherMgr::stopNestedSketch(ModuleBase_Operation* theOp) { - myPlaneFilter->setPlane(thePln->impl()); + connectToPropertyPanel(false); + myIsPropertyPanelValueChanged = false; + myIsMouseOverViewProcessed = true; + + // the sketch objects selection should be activated in order to select any sketch + // object + activateObjectsInSketchMode(true); } -void PartSet_SketcherMgr::getCurrentSelection(const FeatureToAttributesMap& theFeatureToAttributes, - const FeaturePtr& theSketch, - ModuleBase_IWorkshop* theWorkshop, - FeatureToSelectionMap& theSelection) +void PartSet_SketcherMgr::commitNestedSketch(ModuleBase_Operation* theOperation) { - FeatureToAttributesMap::const_iterator anIt = theFeatureToAttributes.begin(), - aLast = theFeatureToAttributes.end(); - for (; anIt != aLast; anIt++) { - FeaturePtr aFeature = anIt.key(); - getCurrentSelection(aFeature, theSketch, theWorkshop, theSelection); + if (isNestedCreateOperation(theOperation)) + visualizeFeature(theOperation, true); + +} + +bool PartSet_SketcherMgr::canUndo() const +{ + return isNestedCreateOperation(getCurrentOperation()); +} + +bool PartSet_SketcherMgr::canRedo() const +{ + return isNestedCreateOperation(getCurrentOperation()); +} + +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; + } + 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 aSketchFeature = + std::dynamic_pointer_cast(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 + bool isObjectFound = false; + ModuleBase_Operation* anOperation = getCurrentOperation(); + if (anOperation) { + FeaturePtr aFeature = anOperation->feature(); + if (aFeature.get()) { + std::list aResults = aFeature->results(); + if (theObject == aFeature) + isObjectFound = true; + else { + std::list::const_iterator anIt = aResults.begin(), aLast = aResults.end(); + for (; anIt != aLast; anIt++) { + isObjectFound = *anIt == theObject; + } + } + } + } + if (!isObjectFound) + return aCanDisplay; + + // 4. For created nested feature operation do not display the created feature if + // the mouse curstor leaves the OCC window. + // The correction cases, which ignores this condition: + // a. the property panel values modification + // b. the popup menu activated + // c. widget editor control + #ifndef DEBUG_DO_NOT_BY_ENTER + if (aCanDisplay && isNestedCreateOperation(getCurrentOperation())) { + ModuleBase_Operation* aOperation = getCurrentOperation(); + ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); + ModuleBase_ModelWidget* anActiveWdg = aPanel ? aPanel->activeWidget() : 0; + ModuleBase_WidgetEditor* anEditorWdg = anActiveWdg ? dynamic_cast(anActiveWdg) : 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 = myIsPropertyPanelValueChanged || myIsMouseOverWindow; + } + } + #endif + return aCanDisplay; +} + +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& thePln) +{ + myPlaneFilter->setPlane(thePln->impl()); + + // after the plane is selected in the sketch, the sketch selection should be activated + // it can not be performed in the sketch label widget because, we don't need to switch off + // the selection by any label deactivation, but need to switch it off by stop the sketch + activateObjectsInSketchMode(true); } void PartSet_SketcherMgr::getCurrentSelection(const FeaturePtr& theFeature, @@ -637,14 +959,29 @@ void PartSet_SketcherMgr::getSelectionOwners(const FeaturePtr& theFeature, return; FeatureToSelectionMap::const_iterator anIt = theSelection.find(theFeature); - std::set aSelectedAttributes = anIt->second.first; - std::set aSelectedResults = anIt->second.second; + std::set aSelectedAttributes = anIt.value().first; + std::set aSelectedResults = anIt.value().second; ModuleBase_IViewer* aViewer = theWorkshop->viewer(); Handle(AIS_InteractiveContext) aContext = aViewer->AISContext(); XGUI_ModuleConnector* aConnector = dynamic_cast(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(); + + 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()) + anOwnersToSelect.Add(anOwner); + } + } + + // 2. found the feature results's owners std::list aResults = theFeature->results(); std::list::const_iterator aIt; for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) @@ -679,3 +1016,153 @@ void PartSet_SketcherMgr::getSelectionOwners(const FeaturePtr& theFeature, } } } + +void PartSet_SketcherMgr::connectToPropertyPanel(const bool isToConnect) +{ + ModuleBase_IWorkshop* anIWorkshop = myModule->workshop(); + XGUI_ModuleConnector* aConnector = dynamic_cast(anIWorkshop); + XGUI_Workshop* aWorkshop = aConnector->workshop(); + XGUI_PropertyPanel* aPropertyPanel = aWorkshop->propertyPanel(); + if (aPropertyPanel) { + const QList& aWidgets = aPropertyPanel->modelWidgets(); + foreach (ModuleBase_ModelWidget* aWidget, aWidgets) { + if (isToConnect) { + connect(aWidget, SIGNAL(beforeValuesChanged()), + this, SLOT(onBeforeValuesChangedInPropertyPanel())); + connect(aWidget, SIGNAL(valuesChanged()), this, SLOT(onValuesChangedInPropertyPanel())); + connect(aWidget, SIGNAL(afterValuesChanged()), + this, SLOT(onAfterValuesChangedInPropertyPanel())); + } + else { + disconnect(aWidget, SIGNAL(beforeValuesChanged()), + this, SLOT(onBeforeValuesChangedInPropertyPanel())); + disconnect(aWidget, SIGNAL(valuesChanged()), this, SLOT(onValuesChangedInPropertyPanel())); + disconnect(aWidget, SIGNAL(afterValuesChanged()), + this, SLOT(onAfterValuesChangedInPropertyPanel())); + } + } + } +} + +ModuleBase_Operation* PartSet_SketcherMgr::getCurrentOperation() const +{ + return myModule->workshop()->currentOperation(); +} + +void PartSet_SketcherMgr::visualizeFeature(ModuleBase_Operation* theOperation, + const bool isToDisplay) +{ + #ifdef DEBUG_DO_NOT_BY_ENTER + return; + #endif + + if (!theOperation || theOperation->isEditOperation()) + return; + + ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); + XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); + XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); + + // 1. change visibility of the object itself, here the presentable object is processed, + // e.g. constraints features + FeaturePtr aFeature = theOperation->feature(); + std::list aResults = aFeature->results(); + if (isToDisplay) + aDisplayer->display(aFeature, false); + else + aDisplayer->erase(aFeature, false); + + // change visibility of the object results, e.g. non-constraint features + std::list::const_iterator aIt; + for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { + if (isToDisplay) { + aDisplayer->display(*aIt, false); + } + else { + aDisplayer->erase(*aIt, false); + } + } + aDisplayer->updateViewer(); +} + +void PartSet_SketcherMgr::activateObjectsInSketchMode(const bool isActive) +{ + ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); + XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); + XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); + + QIntList aModes; + if (isActive) + sketchSelectionModes(aModes); + aDisplayer->activateObjects(aModes); +} + +void PartSet_SketcherMgr::storeSelection(const bool theHighlightedOnly) +{ + ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); + ModuleBase_ISelection* aSelect = aWorkshop->selection(); + QList aHighlighted = aSelect->getHighlighted(); + + QMap > aFeature2AttributeMap; + if (theHighlightedOnly) { + fillFeature2Attribute(aHighlighted, aFeature2AttributeMap, myCurrentSketch); + } + else { + fillFeature2Attribute(aHighlighted, aFeature2AttributeMap, myCurrentSketch); + + QList aSelected = aSelect->getSelected(); + fillFeature2Attribute(aSelected, aFeature2AttributeMap, myCurrentSketch); + } + + // 1. it is necessary to save current selection in order to restore it after the features moving + myCurrentSelection.clear(); + QMap >::const_iterator anIt = aFeature2AttributeMap.begin(), + aLast = aFeature2AttributeMap.end(); + for (; anIt != aLast; anIt++) { + FeaturePtr aFeature = anIt.key(); + getCurrentSelection(aFeature, myCurrentSketch, aWorkshop, myCurrentSelection); + } + //qDebug(QString(" storeSelection: %1").arg(myCurrentSelection.size()).toStdString().c_str()); +} + +void PartSet_SketcherMgr::restoreSelection() +{ + //qDebug(QString("restoreSelection: %1").arg(myCurrentSelection.size()).toStdString().c_str()); + ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); + XGUI_ModuleConnector* aConnector = dynamic_cast(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(bool theOn) +{ + if (myIsConstraintsShown == theOn) + return; + if (myCurrentSketch.get() == NULL) + return; + + myIsConstraintsShown = theOn; + + ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); + XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); + XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); + + const QStringList& aConstrIds = constraintsIdList(); + for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) { + FeaturePtr aSubFeature = myCurrentSketch->subFeature(i); + if (aConstrIds.contains(QString(aSubFeature->getKind().c_str()))) { + if (myIsConstraintsShown) + aDisplayer->display(aSubFeature, false); + else + aDisplayer->erase(aSubFeature, false); + } + } + aDisplayer->updateViewer(); +}