X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FPartSet%2FPartSet_WidgetPoint2d.cpp;h=8c7d1031b4d2a7c05410e47a27883d1bc65b8aaa;hb=32208dedf0b2b5bd50b5b86c464f37a8e0eb07d0;hp=61749d78fc0226a9d8bc19711a9edfd11f95daf6;hpb=c80b46cd0d67df6fbb1f9dc1aa43f50f1e8ae9e9;p=modules%2Fshaper.git diff --git a/src/PartSet/PartSet_WidgetPoint2d.cpp b/src/PartSet/PartSet_WidgetPoint2d.cpp index 61749d78f..8c7d1031b 100644 --- a/src/PartSet/PartSet_WidgetPoint2d.cpp +++ b/src/PartSet/PartSet_WidgetPoint2d.cpp @@ -7,19 +7,27 @@ #include "PartSet_WidgetPoint2d.h" #include #include -#include +#include + +#include +#include +#include #include #include #include #include #include +#include +#include +#include #include #include #include #include +#include #include #include @@ -27,8 +35,15 @@ #include #include +#include +#include + #include #include +#include +#include +#include +#include #include #include @@ -46,73 +61,145 @@ const double MaxCoordinate = 1e12; +static QStringList MyFeaturesForCoincedence; -PartSet_WidgetPoint2D::PartSet_WidgetPoint2D(QWidget* theParent, +PartSet_WidgetPoint2D::PartSet_WidgetPoint2D(QWidget* theParent, ModuleBase_IWorkshop* theWorkshop, - const Config_WidgetAPI* theData, - const std::string& theParentId) - : ModuleBase_ModelWidget(theParent, theData, theParentId), myWorkshop(theWorkshop) + const Config_WidgetAPI* theData) +: ModuleBase_ModelWidget(theParent, theData), myWorkshop(theWorkshop), + myValueIsCashed(false), myIsFeatureVisibleInCash(true), + myXValueInCash(0), myYValueInCash(0) { - myLockApplyMgr = new PartSet_LockApplyMgr(theParent, myWorkshop); + if (MyFeaturesForCoincedence.isEmpty()) { + MyFeaturesForCoincedence << SketchPlugin_Line::ID().c_str() + << SketchPlugin_Arc::ID().c_str() + << SketchPlugin_Point::ID().c_str() + << SketchPlugin_Circle::ID().c_str(); + } - // the control should accept the focus, so the boolen flag is corrected to be true + // the control should accept the focus, so the boolean flag is corrected to be true myIsObligatory = true; - //myOptionParam = theData->getProperty(PREVIOUS_FEATURE_PARAM); QString aPageName = QString::fromStdString(theData->getProperty(CONTAINER_PAGE_NAME)); myGroupBox = new QGroupBox(aPageName, theParent); myGroupBox->setFlat(false); + bool aAcceptVariables = theData->getBooleanAttribute(DOUBLE_WDG_ACCEPT_EXPRESSIONS, true); + QGridLayout* aGroupLay = new QGridLayout(myGroupBox); ModuleBase_Tools::adjustMargins(aGroupLay); aGroupLay->setSpacing(2); aGroupLay->setColumnStretch(1, 1); { QLabel* aLabel = new QLabel(myGroupBox); - aLabel->setText(tr("X ")); - aGroupLay->addWidget(aLabel, 0, 0); - myXSpin = new ModuleBase_ParamSpinBox(myGroupBox); - myXSpin->setMinimum(-DBL_MAX); - myXSpin->setMaximum(DBL_MAX); - myXSpin->setToolTip(tr("X")); + myXSpin = new ModuleBase_LabelValue(myGroupBox, tr("X")); + //ModuleBase_ParamSpinBox(myGroupBox); + //myXSpin->setAcceptVariables(aAcceptVariables); + //myXSpin->setMinimum(-DBL_MAX); + //myXSpin->setMaximum(DBL_MAX); + //myXSpin->setToolTip(tr("X")); aGroupLay->addWidget(myXSpin, 0, 1); - connect(myXSpin, SIGNAL(valueChanged(const QString&)), this, SLOT(onValuesChanged())); + //connect(myXSpin, SIGNAL(textChanged(const QString&)), this, SIGNAL(valuesModified())); + //myXSpin->setValueEnabled(isValueEnabled()); } { - QLabel* aLabel = new QLabel(myGroupBox); - aLabel->setText(tr("Y ")); - aGroupLay->addWidget(aLabel, 1, 0); - - myYSpin = new ModuleBase_ParamSpinBox(myGroupBox); - myYSpin->setMinimum(-DBL_MAX); - myYSpin->setMaximum(DBL_MAX); - myYSpin->setToolTip(tr("Y")); + //QLabel* aLabel = new QLabel(myGroupBox); + //aLabel->setText(tr("Y ")); + //aGroupLay->addWidget(aLabel, 1, 0); + + myYSpin = new ModuleBase_LabelValue(myGroupBox, tr("Y")); + //ModuleBase_ParamSpinBox(myGroupBox); + //myYSpin = new ModuleBase_ParamSpinBox(myGroupBox); + //myYSpin->setAcceptVariables(aAcceptVariables); + //myYSpin->setMinimum(-DBL_MAX); + //myYSpin->setMaximum(DBL_MAX); + //myYSpin->setToolTip(tr("Y")); aGroupLay->addWidget(myYSpin, 1, 1); - connect(myYSpin, SIGNAL(valueChanged(const QString&)), this, SLOT(onValuesChanged())); + //connect(myYSpin, SIGNAL(textChanged(const QString&)), this, SIGNAL(valuesModified())); + //myYSpin->setValueEnabled(isValueEnabled()); } QVBoxLayout* aLayout = new QVBoxLayout(this); ModuleBase_Tools::zeroMargins(aLayout); aLayout->addWidget(myGroupBox); setLayout(aLayout); + + myWidgetValidator = new ModuleBase_WidgetValidator(this, myWorkshop); +} + +bool PartSet_WidgetPoint2D::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr& theValue) +{ + bool aValid = true; + + PartSet_Module* aModule = dynamic_cast(myWorkshop->module()); + if (aModule->sketchReentranceMgr()->isInternalEditActive()) + return true; /// when internal edit is started a new feature is created. I has not results, AIS + + /// the selection is not possible if the current feature has no presentation for the current + /// attribute not in AIS not in results. If so, no object in current feature where make + /// coincidence, so selection is not necessary + bool aFoundPoint = false; + GeomShapePtr anAISShape; + GeomPresentablePtr aPrs = std::dynamic_pointer_cast(myFeature); + if (aPrs.get()) { + AISObjectPtr anAIS; + anAIS = aPrs->getAISObject(anAIS); + if (anAIS.get()) { + anAISShape = anAIS->getShape(); + } + } + const std::list >& aResults = myFeature->results(); + if (!anAISShape.get() && aResults.empty()) + return true; + + /// analysis of AIS + std::shared_ptr aData = myFeature->data(); + std::shared_ptr aPointAttr = std::dynamic_pointer_cast( + aData->attribute(attributeID())); + std::shared_ptr aPoint = aPointAttr->pnt(); + if (anAISShape.get()) + aFoundPoint = shapeContainsPoint(anAISShape, aPoint, mySketch); + + /// analysis of results + std::list >::const_iterator aRIter = aResults.cbegin(); + for (; aRIter != aResults.cend() && !aFoundPoint; aRIter++) { + ResultPtr aResult = *aRIter; + if (aResult.get() && aResult->shape().get()) { + GeomShapePtr aShape = aResult->shape(); + aFoundPoint = shapeContainsPoint(aShape, aPoint, mySketch); + } + } + return aFoundPoint; } -bool PartSet_WidgetPoint2D::reset() +bool PartSet_WidgetPoint2D::resetCustom() { bool aDone = false; - if (!isUseReset() || isComputedDefault() || myXSpin->hasVariable() || myYSpin->hasVariable()) { + if (!isUseReset() || isComputedDefault() + /*|| myXSpin->hasVariable() || myYSpin->hasVariable()*/) { aDone = false; } else { - bool isOk; - double aDefValue = QString::fromStdString(getDefaultValue()).toDouble(&isOk); - // it is important to block the spin box control in order to do not through out the - // locking of the validating state. - ModuleBase_Tools::setSpinValue(myXSpin, isOk ? aDefValue : 0.0); - ModuleBase_Tools::setSpinValue(myYSpin, isOk ? aDefValue : 0.0); - storeValueCustom(); - aDone = true; + if (myValueIsCashed) { + // if the restored value should be hidden, aDone = true to set + // reset state for the widget in the parent + aDone = restoreCurentValue(); + emit objectUpdated(); + } + else { + bool isOk; + double aDefValue = QString::fromStdString(getDefaultValue()).toDouble(&isOk); + // it is important to block the spin box control in order to do not through out the + // locking of the validating state. + myXSpin->setValue(isOk ? aDefValue : 0.0); + myYSpin->setValue(isOk ? aDefValue : 0.0); + + //ModuleBase_Tools::setSpinValue(myXSpin, isOk ? aDefValue : 0.0); + //ModuleBase_Tools::setSpinValue(myYSpin, isOk ? aDefValue : 0.0); + storeValueCustom(); + aDone = true; + } } return aDone; } @@ -121,24 +208,32 @@ PartSet_WidgetPoint2D::~PartSet_WidgetPoint2D() { } -bool PartSet_WidgetPoint2D::setSelection(QList& theValues, +bool PartSet_WidgetPoint2D::setSelection(QList& theValues, const bool theToValidate) { - if (theValues.empty()) - return false; - - ModuleBase_ViewerPrs aValue = theValues.takeFirst(); - - Handle(V3d_View) aView = myWorkshop->viewer()->activeView(); bool isDone = false; - TopoDS_Shape aShape = aValue.shape(); - double aX, aY; - if (getPoint2d(aView, aShape, aX, aY)) { - isDone = setPoint(aX, aY); + if (theValues.empty()) + return isDone; + + ModuleBase_ViewerPrsPtr aValue = theValues.takeFirst(); + GeomShapePtr aShape = aValue->shape(); + if (aShape.get() && !aShape->isNull()) { + Handle(V3d_View) aView = myWorkshop->viewer()->activeView(); + double aX, aY; + const TopoDS_Shape& aTDShape = aShape->impl(); + if (getPoint2d(aView, aTDShape, aX, aY)) { + isDone = setPoint(aX, aY); + PartSet_Tools::setConstraints(mySketch, feature(), attributeID(), aX, aY); + } } return isDone; } +void PartSet_WidgetPoint2D::selectContent() +{ + // myXSpin->selectAll(); +} + bool PartSet_WidgetPoint2D::setPoint(double theX, double theY) { if (fabs(theX) >= MaxCoordinate) @@ -146,14 +241,17 @@ bool PartSet_WidgetPoint2D::setPoint(double theX, double theY) if (fabs(theY) >= MaxCoordinate) return false; - ModuleBase_Tools::setSpinValue(myXSpin, theX); - ModuleBase_Tools::setSpinValue(myYSpin, theY); + myXSpin->setValue(theX); + myYSpin->setValue(theY); + + //ModuleBase_Tools::setSpinValue(myXSpin, theX); + //ModuleBase_Tools::setSpinValue(myYSpin, theY); storeValue(); return true; } -bool PartSet_WidgetPoint2D::storeValueCustom() const +bool PartSet_WidgetPoint2D::storeValueCustom() { std::shared_ptr aData = myFeature->data(); if (!aData) // can be on abort of sketcher element @@ -167,10 +265,11 @@ bool PartSet_WidgetPoint2D::storeValueCustom() const // if text is not empty then setValue will be ignored // so we should set the text at first - aPoint->setText(myXSpin->hasVariable() ? myXSpin->text().toStdString() : "", - myYSpin->hasVariable() ? myYSpin->text().toStdString() : ""); - aPoint->setValue(!myXSpin->hasVariable() ? myXSpin->value() : aPoint->x(), - !myYSpin->hasVariable() ? myYSpin->value() : aPoint->y()); + //aPoint->setText(myXSpin->hasVariable() ? myXSpin->text().toStdString() : "", + // myYSpin->hasVariable() ? myYSpin->text().toStdString() : ""); + //aPoint->setValue(!myXSpin->hasVariable() ? myXSpin->value() : aPoint->x(), + // !myYSpin->hasVariable() ? myYSpin->value() : aPoint->y()); + aPoint->setValue(myXSpin->value(), myYSpin->value()); // after movement the solver will call the update event: optimization moveObject(myFeature); @@ -185,39 +284,53 @@ bool PartSet_WidgetPoint2D::restoreValueCustom() std::shared_ptr aData = myFeature->data(); std::shared_ptr aPoint = std::dynamic_pointer_cast( aData->attribute(attributeID())); - QString aTextX = QString::fromStdString(aPoint->textX()); - QString aTextY = QString::fromStdString(aPoint->textY()); - - bool isDouble = false; - double aVal = 0; - if (aTextX.isEmpty()) { - ModuleBase_Tools::setSpinValue(myXSpin, aPoint->x()); - } else { - aVal = aTextX.toDouble(&isDouble); - if (isDouble) - ModuleBase_Tools::setSpinValue(myXSpin, aVal); - else - ModuleBase_Tools::setSpinText(myXSpin, aTextX); - } - if (aTextY.isEmpty()) { - ModuleBase_Tools::setSpinValue(myYSpin, aPoint->y()); - } else { - aVal = aTextY.toDouble(&isDouble); - if (isDouble) - ModuleBase_Tools::setSpinValue(myYSpin, aVal); - else - ModuleBase_Tools::setSpinText(myYSpin, aTextY); - } - //if (aTextX.empty() || aTextY.empty()) { - // ModuleBase_Tools::setSpinValue(myXSpin, aPoint->x()); - // ModuleBase_Tools::setSpinValue(myYSpin, aPoint->y()); - //} else { - // ModuleBase_Tools::setSpinText(myXSpin, QString::fromStdString(aTextX)); - // ModuleBase_Tools::setSpinText(myYSpin, QString::fromStdString(aTextY)); - //} + double aValueX = aPoint->isInitialized() ? aPoint->x() : 0.; + double aValueY = aPoint->isInitialized() ? aPoint->y() : 0.; + myXSpin->setValue(aValueX); + myYSpin->setValue(aValueY); + return true; } +void PartSet_WidgetPoint2D::storeCurentValue() +{ + // do not use cash if a variable is used + //if (myXSpin->hasVariable() || myYSpin->hasVariable()) + // return; + + myValueIsCashed = true; + myIsFeatureVisibleInCash = XGUI_Displayer::isVisible( + XGUI_Tools::workshop(myWorkshop)->displayer(), myFeature); + myXValueInCash = myXSpin->value(); + myYValueInCash = myYSpin->value(); +} + +bool PartSet_WidgetPoint2D::restoreCurentValue() +{ + bool aRestoredAndHidden = true; + + bool isVisible = myIsFeatureVisibleInCash; + // fill the control widgets by the cashed value + + myValueIsCashed = false; + myIsFeatureVisibleInCash = true; + myXSpin->setValue(myXValueInCash); + myYSpin->setValue(myYValueInCash); + //ModuleBase_Tools::setSpinValue(myXSpin, myXValueInCash); + //ModuleBase_Tools::setSpinValue(myYSpin, myYValueInCash); + + // store value to the model + storeValueCustom(); + if (isVisible) { + setValueState(Stored); + aRestoredAndHidden = false; + } + else + aRestoredAndHidden = true; + + return aRestoredAndHidden; +} + QList PartSet_WidgetPoint2D::getControls() const { QList aControls; @@ -229,35 +342,38 @@ QList PartSet_WidgetPoint2D::getControls() const void PartSet_WidgetPoint2D::activateCustom() { - ModuleBase_IViewer* aViewer = myWorkshop->viewer(); - connect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)), - this, SLOT(onMouseMove(ModuleBase_IViewWindow*, QMouseEvent*))); - connect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)), - this, SLOT(onMouseRelease(ModuleBase_IViewWindow*, QMouseEvent*))); - QIntList aModes; aModes << TopAbs_VERTEX; aModes << TopAbs_EDGE; myWorkshop->activateSubShapesSelection(aModes); - myLockApplyMgr->activate(); + if (!isEditingMode()) { + FeaturePtr aFeature = feature(); + if (aFeature.get() && aFeature->getKind() == SketchPlugin_Point::ID()) + storeValue(); + } } -void PartSet_WidgetPoint2D::deactivate() +void PartSet_WidgetPoint2D::setHighlighted(bool isHighlighted) { - ModuleBase_IViewer* aViewer = myWorkshop->viewer(); - disconnect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)), - this, SLOT(onMouseMove(ModuleBase_IViewWindow*, QMouseEvent*))); - disconnect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)), - this, SLOT(onMouseRelease(ModuleBase_IViewWindow*, QMouseEvent*))); +} +void PartSet_WidgetPoint2D::deactivate() +{ + // the value of the control should be stored to model if it was not + // initialized yet. It is important when we leave this control by Tab key. + // It should not be performed by the widget activation as the preview + // is visualized with default value. Line point is moved to origin. + AttributePtr anAttribute = myFeature->data()->attribute(attributeID()); + if (anAttribute && !anAttribute->isInitialized()) + storeValue(); + + ModuleBase_ModelWidget::deactivate(); myWorkshop->deactivateSubShapesSelection(); - - myLockApplyMgr->deactivate(); } -bool PartSet_WidgetPoint2D::getPoint2d(const Handle(V3d_View)& theView, - const TopoDS_Shape& theShape, +bool PartSet_WidgetPoint2D::getPoint2d(const Handle(V3d_View)& theView, + const TopoDS_Shape& theShape, double& theX, double& theY) const { if (!theShape.IsNull()) { @@ -274,53 +390,80 @@ bool PartSet_WidgetPoint2D::getPoint2d(const Handle(V3d_View)& theView, return false; } -void PartSet_WidgetPoint2D::setConstraintWith(const ObjectPtr& theObject) +bool PartSet_WidgetPoint2D::setConstraintWith(const ObjectPtr& theObject) { + std::shared_ptr aFeaturePoint; + if (feature()->isMacro()) { + AttributePtr aThisAttr = feature()->data()->attribute(attributeID()); + std::shared_ptr anAttrPoint = + std::dynamic_pointer_cast(aThisAttr); + if (anAttrPoint.get()) { + // the macro feature will be removed after the operation is stopped, so we need to build + // coicidence to possible sub-features + aFeaturePoint = PartSet_Tools::findFirstEqualPointInArgumentFeatures(feature(), + anAttrPoint->pnt()); + } + } + else { + AttributePtr aThisAttr = feature()->data()->attribute(attributeID()); + aFeaturePoint = std::dynamic_pointer_cast(aThisAttr); + } + if (!aFeaturePoint.get()) + return false; + // Create point-edge coincedence FeaturePtr aFeature = mySketch->addFeature(SketchPlugin_ConstraintCoincidence::ID()); std::shared_ptr aData = aFeature->data(); std::shared_ptr aRef1 = std::dynamic_pointer_cast< ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_A())); - AttributePtr aThisAttr = feature()->data()->attribute(attributeID()); - std::shared_ptr aThisPoint = - std::dynamic_pointer_cast(aThisAttr); - aRef1->setAttr(aThisPoint); + + aRef1->setAttr(aFeaturePoint); std::shared_ptr aRef2 = std::dynamic_pointer_cast< ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_B())); aRef2->setObject(theObject); - aFeature->execute(); + // we need to flush created signal in order to coincidence is processed by solver + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED)); + + return true; } -void PartSet_WidgetPoint2D::onMouseRelease(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) +void PartSet_WidgetPoint2D::mouseReleased(ModuleBase_IViewWindow* theWindow, QMouseEvent* theEvent) { // the contex menu release by the right button should not be processed by this widget if (theEvent->button() != Qt::LeftButton) return; ModuleBase_ISelection* aSelection = myWorkshop->selection(); - Handle(V3d_View) aView = theWnd->v3dView(); - // TODO: This fragment doesn't work because bug in OCC Viewer. It can be used after fixing. - NCollection_List aShapes; - std::list aObjects; - aSelection->selectedShapes(aShapes, aObjects); - // if we have selection - if (aShapes.Extent() > 0) { - TopoDS_Shape aShape = aShapes.First(); - ObjectPtr aObject = aObjects.front(); + Handle(V3d_View) aView = theWindow->v3dView(); + + QList aList = aSelection->getSelected(ModuleBase_ISelection::Viewer); + ModuleBase_ViewerPrsPtr aFirstValue = + aList.size() > 0 ? aList.first() : ModuleBase_ViewerPrsPtr(); + if (!aFirstValue.get() && myPreSelected.get()) { + aFirstValue = myPreSelected; + } + // if we have selection and use it + if (aFirstValue.get() && isValidSelectionCustom(aFirstValue) && + aFirstValue->shape().get()) { /// Trihedron Axis may be selected, but shape is empty + GeomShapePtr aGeomShape = aFirstValue->shape(); + TopoDS_Shape aShape = aGeomShape->impl(); + ObjectPtr aObject = aFirstValue->object(); + FeaturePtr aSelectedFeature = ModelAPI_Feature::feature(aObject); bool anExternal = false; - if (aSelectedFeature.get() != NULL) { - std::shared_ptr aSPFeature = - std::dynamic_pointer_cast(aSelectedFeature); - if ((!aSPFeature) && (!aShape.IsNull())) { + std::shared_ptr aSPFeature; + if (aSelectedFeature.get() != NULL) + aSPFeature = std::dynamic_pointer_cast(aSelectedFeature); + if ((!aSPFeature && !aShape.IsNull()) || + (aSPFeature.get() && aSPFeature->isExternal())) { + ResultPtr aFixedObject; anExternal = true; - ResultPtr aFixedObject = PartSet_Tools::findFixedObjectByExternal(aShape, aObject, mySketch); + aFixedObject = PartSet_Tools::findFixedObjectByExternal(aShape, aObject, mySketch); if (!aFixedObject.get()) - aObject = PartSet_Tools::createFixedObjectByExternal(aShape, aObject, mySketch); - + aFixedObject = PartSet_Tools::createFixedObjectByExternal(aShape, aObject, mySketch); double aX, aY; if (getPoint2d(aView, aShape, aX, aY) && isFeatureContainsPoint(myFeature, aX, aY)) { // do not create a constraint to the point, which already used by the feature @@ -328,12 +471,46 @@ void PartSet_WidgetPoint2D::onMouseRelease(ModuleBase_IViewWindow* theWnd, QMous setPoint(aX, aY); } else { - setConstraintWith(aObject); - emit vertexSelected(); + if (getPoint2d(aView, aShape, aX, aY)) + setPoint(aX, aY); + else + setValueState(Stored); // in case of edge selection, Apply state should also be updated + bool anOrphanPoint = aShape.ShapeType() == TopAbs_VERTEX || + isOrphanPoint(aSelectedFeature, mySketch, aX, aY); + if (anExternal) { + // we should not stop reentrant operation on external objects because + anOrphanPoint = true; + // they are not participate in the contour creation excepting external vertices + if (aShape.ShapeType() == TopAbs_VERTEX) { + FeaturePtr aFixedFeature = ModelAPI_Feature::feature(aFixedObject); + if (aFixedFeature.get() && aFixedFeature->getKind() == SketchPlugin_Point::ID()) { + anOrphanPoint = isOrphanPoint(aFixedFeature, mySketch, aX, aY); + } + } + else { + // point is taken from mouse event and set in attribute. + // It should be done before setting + // coinident constraint to the external line. If a point is created, it should be + // in the mouse clicked point + gp_Pnt aPoint = + PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView()); + double aX, anY; + PartSet_Tools::convertTo2D(aPoint, mySketch, aView, aX, anY); + setPoint(aX, anY); + } + } + if (aFixedObject.get()) + setConstraintWith(aFixedObject); + // fignal updated should be flushed in order to visualize possible created + // external objects e.g. selection of trihedron axis when input end arc point + updateObject(feature()); + + if (!anOrphanPoint) + emit vertexSelected(); // it stops the reentrant operation + emit focusOutWidget(this); } } - } if (!anExternal) { double aX, aY; bool isProcessed = false; @@ -343,22 +520,36 @@ void PartSet_WidgetPoint2D::onMouseRelease(ModuleBase_IViewWindow* theWnd, QMous setPoint(aX, aY); } else { + bool anOrphanPoint = isOrphanPoint(aSelectedFeature, mySketch, aX, aY); // do not set a coincidence constraint in the attribute if the feature contains a point // with the same coordinates. It is important for line creation in order to do not set // the same constraints for the same points, oterwise the result line has zero length. - if (getPoint2d(aView, aShape, aX, aY)) + bool isAuxiliaryFeature = false; + if (getPoint2d(aView, aShape, aX, aY)) { + setPoint(aX, aY); + feature()->execute(); PartSet_Tools::setConstraints(mySketch, feature(), attributeID(), aX, aY); - else if (aShape.ShapeType() == TopAbs_EDGE) + } + else if (aShape.ShapeType() == TopAbs_EDGE) { + // point is taken from mouse event and set in attribute. It should be done before setting + // coinident constraint to the external line. If a point is created, it should be in + // the mouse clicked point + gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView()); + PartSet_Tools::convertTo2D(aPoint, mySketch, aView, aX, aY); + setPoint(aX, aY); setConstraintWith(aObject); - - // it is important to perform updateObject() in order to the current value is + setValueState(Stored); // in case of edge selection, Apply state should also be updated + isAuxiliaryFeature = PartSet_Tools::isAuxiliarySketchEntity(aObject); + } + // it is important to perform updateObject() in order to the current value is // processed by Sketch Solver. Test case: line is created from a previous point // to some distance, but in the area of the highlighting of the point. Constraint // coincidence is created, after the solver is performed, the distance between the // points of the line becomes less than the tolerance. Validator of the line returns // false, the line will be aborted, but sketch stays valid. updateObject(feature()); - emit vertexSelected(); + if (!anOrphanPoint && !anExternal && !isAuxiliaryFeature) + emit vertexSelected(); emit focusOutWidget(this); } } @@ -366,7 +557,7 @@ void PartSet_WidgetPoint2D::onMouseRelease(ModuleBase_IViewWindow* theWnd, QMous // End of Bug dependent fragment else { // A case when point is taken from mouse event - gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWnd->v3dView()); + gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView()); double aX, anY; PartSet_Tools::convertTo2D(aPoint, mySketch, aView, aX, anY); @@ -381,7 +572,7 @@ void PartSet_WidgetPoint2D::onMouseRelease(ModuleBase_IViewWindow* theWnd, QMous //aIgnore.append(feature()); //double aTolerance = aView->Convert(7); - //std::shared_ptr aAttrPnt = + //std::shared_ptr aAttrPnt = // PartSet_Tools::findAttributePoint(mySketch, aX, anY, aTolerance, aIgnore); //if (aAttrPnt.get() != NULL) { // aFeaturePoint->setValue(aAttrPnt->pnt()); @@ -393,17 +584,30 @@ void PartSet_WidgetPoint2D::onMouseRelease(ModuleBase_IViewWindow* theWnd, QMous } } +void PartSet_WidgetPoint2D::setPreSelection( + const std::shared_ptr& thePreSelected) +{ + myPreSelected = thePreSelected; +} -void PartSet_WidgetPoint2D::onMouseMove(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) +void PartSet_WidgetPoint2D::mouseMoved(ModuleBase_IViewWindow* theWindow, QMouseEvent* theEvent) { - if (isEditingMode()) + PartSet_Module* aModule = dynamic_cast(myWorkshop->module()); + + if (isEditingMode() || aModule->sketchReentranceMgr()->isInternalEditStarted()) return; - gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWnd->v3dView()); + gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView()); double aX, anY; - PartSet_Tools::convertTo2D(aPoint, mySketch, theWnd->v3dView(), aX, anY); + PartSet_Tools::convertTo2D(aPoint, mySketch, theWindow->v3dView(), aX, anY); + if (myState != ModifiedInViewer) + storeCurentValue(); + // we need to block the value state change + bool isBlocked = blockValueState(true); setPoint(aX, anY); + blockValueState(isBlocked); + setValueState(ModifiedInViewer); } double PartSet_WidgetPoint2D::x() const @@ -421,27 +625,125 @@ bool PartSet_WidgetPoint2D::isFeatureContainsPoint(const FeaturePtr& theFeature, double theX, double theY) { bool aPointIsFound = false; + + if (feature()->getKind() != SketchPlugin_Line::ID()) + return aPointIsFound; + AttributePtr aWidgetAttribute = myFeature->attribute(attributeID()); - std::shared_ptr aPnt2d = + std::shared_ptr aPnt2d = std::shared_ptr(new GeomAPI_Pnt2d(theX, theY)); std::list anAttributes = myFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); std::list::iterator anIter = anAttributes.begin(); - for(; anIter != anAttributes.end(); anIter++) { + for(; anIter != anAttributes.end() && !aPointIsFound; anIter++) { AttributePoint2DPtr aPoint2DAttribute = std::dynamic_pointer_cast(*anIter); if (aPoint2DAttribute == aWidgetAttribute) continue; - if (aPoint2DAttribute.get()) { + if (aPoint2DAttribute.get() && aPoint2DAttribute->isInitialized()) { aPointIsFound = aPoint2DAttribute->pnt()->isEqual(aPnt2d); } } return aPointIsFound; } -void PartSet_WidgetPoint2D::onValuesChanged() +void PartSet_WidgetPoint2D::initializeValueByActivate() +{ +} + +/*void PartSet_WidgetPoint2D::onValuesChanged() { - myLockApplyMgr->valuesChanged(); emit valuesChanged(); +}*/ + +bool PartSet_WidgetPoint2D::processEnter() +{ + return false; + /*bool isModified = getValueState() == ModifiedInPP; + if (isModified) { + bool isXModified = myXSpin->hasFocus(); + emit valuesChanged(); + if (isXModified) + myXSpin->selectAll(); + else + myYSpin->selectAll(); + } + return isModified;*/ +} + +bool PartSet_WidgetPoint2D::useSelectedShapes() const +{ + return true; +} + +bool PartSet_WidgetPoint2D::isOrphanPoint(const FeaturePtr& theFeature, + const CompositeFeaturePtr& theSketch, + double theX, double theY) +{ + bool anOrphanPoint = false; + if (theFeature.get()) { + std::shared_ptr aPointAttr; + std::string aFeatureKind = theFeature->getKind(); + if (aFeatureKind == SketchPlugin_Point::ID()) + aPointAttr = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Point::COORD_ID())); + else if (aFeatureKind == SketchPlugin_Circle::ID()) + aPointAttr = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Circle::CENTER_ID())); + + else if (aFeatureKind == SketchPlugin_Arc::ID()) + aPointAttr = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Arc::CENTER_ID())); + + /// check that the geometry point with the given coordinates is the checked point + /// e.g. in arc the (x,y) point can not coicide to the center point and it automatically + /// means that this point is not an orphant one. + if (aPointAttr.get()) { + std::shared_ptr aCheckedPoint = std::shared_ptr( + new GeomAPI_Pnt2d(theX, theY)); + if (!aCheckedPoint->isEqual(aPointAttr->pnt())) + return anOrphanPoint; + } + + if (aPointAttr.get()) { + std::shared_ptr aPoint = aPointAttr->pnt(); + // we need to find coincidence features in results also, because external object(point) + // uses refs to me in another feature. + FeaturePtr aCoincidence = PartSet_Tools::findFirstCoincidence(theFeature, aPoint); + anOrphanPoint = true; + // if there is at least one concident line to the point, the point is not an orphant + if (aCoincidence.get()) { + QList aCoinsideLines; + QList aCoins; + PartSet_Tools::findCoincidences(aCoincidence, aCoinsideLines, aCoins, + SketchPlugin_ConstraintCoincidence::ENTITY_A()); + PartSet_Tools::findCoincidences(aCoincidence, aCoinsideLines, aCoins, + SketchPlugin_ConstraintCoincidence::ENTITY_B()); + QList::const_iterator anIt = aCoinsideLines.begin(), + aLast = aCoinsideLines.end(); + for (; anIt != aLast && anOrphanPoint; anIt++) { + anOrphanPoint = (*anIt)->getKind() != SketchPlugin_Line::ID(); + } + } + } + } + return anOrphanPoint; +} + +bool PartSet_WidgetPoint2D::shapeContainsPoint(const GeomShapePtr& theShape, + const std::shared_ptr& thePoint, + const CompositeFeaturePtr& theSketch) +{ + std::shared_ptr aPoint = PartSet_Tools::point3D(thePoint, theSketch); + + bool aContainPoint = false; + GeomAPI_ShapeExplorer anExp(theShape, GeomAPI_Shape::VERTEX); + for(; anExp.more() && !aContainPoint; anExp.next()) { + std::shared_ptr aVertexInCompSolid = anExp.current(); + std::shared_ptr aVertex(new GeomAPI_Vertex(aVertexInCompSolid)); + if (aVertex.get()) + aContainPoint = aPoint->isEqual(aVertex->point()); + } + return aContainPoint; }