diff --git a/src/Mod/PartDesign/App/FeatureLinearPattern.cpp b/src/Mod/PartDesign/App/FeatureLinearPattern.cpp index fe862b5099..2ba1df02a2 100644 --- a/src/Mod/PartDesign/App/FeatureLinearPattern.cpp +++ b/src/Mod/PartDesign/App/FeatureLinearPattern.cpp @@ -51,25 +51,42 @@ PROPERTY_SOURCE(PartDesign::LinearPattern, PartDesign::Transformed) const App::PropertyIntegerConstraint::Constraints LinearPattern::intOccurrences = { 1, INT_MAX, 1 }; +const char* LinearPattern::ModeEnums[] = { "length", "offset", nullptr }; + LinearPattern::LinearPattern() { + auto initialMode = LinearPatternMode::length; + ADD_PROPERTY_TYPE(Direction,(nullptr),"LinearPattern",(App::PropertyType)(App::Prop_None),"Direction"); ADD_PROPERTY(Reversed,(0)); + ADD_PROPERTY(Mode, (long(initialMode))); ADD_PROPERTY(Length,(100.0)); + ADD_PROPERTY(Offset,(10.0)); ADD_PROPERTY(Occurrences,(3)); Occurrences.setConstraints(&intOccurrences); + Mode.setEnums(ModeEnums); + setReadWriteStatusForMode(initialMode); } short LinearPattern::mustExecute() const { if (Direction.isTouched() || Reversed.isTouched() || - Length.isTouched() || + Mode.isTouched() || + // Length and Offset are mutually exclusive, only one could be updated at once + Length.isTouched() || + Offset.isTouched() || Occurrences.isTouched()) return 1; return Transformed::mustExecute(); } +void LinearPattern::setReadWriteStatusForMode(LinearPatternMode mode) +{ + Length.setReadOnly(mode != LinearPatternMode::length); + Offset.setReadOnly(mode != LinearPatternMode::offset); +} + const std::list LinearPattern::getTransformations(const std::vector) { int occurrences = Occurrences.getValue(); @@ -173,7 +190,20 @@ const std::list LinearPattern::getTransformations(const std::vector(Mode.getValue())) { + case LinearPatternMode::length: + offset *= distance / (occurrences - 1); + break; + + case LinearPatternMode::offset: + offset *= Offset.getValue(); + break; + + default: + throw Base::ValueError("Invalid mode"); + } + if (reversed) offset.Reverse(); @@ -206,4 +236,24 @@ void LinearPattern::handleChangedPropertyType(Base::XMLReader& reader, const cha } } +void LinearPattern::onChanged(const App::Property* prop) +{ + auto mode = static_cast(Mode.getValue()); + + if (prop == &Mode) { + setReadWriteStatusForMode(mode); + } + + // Keep Length in sync with Offset + if (mode == LinearPatternMode::offset && prop == &Offset && !Length.testStatus(App::Property::Status::Immutable)) { + Length.setValue(Offset.getValue() * (Occurrences.getValue() - 1)); + } + + if (mode == LinearPatternMode::length && prop == &Length && !Offset.testStatus(App::Property::Status::Immutable)) { + Offset.setValue(Length.getValue() / (Occurrences.getValue() - 1)); + } + + Transformed::onChanged(prop); +} + } diff --git a/src/Mod/PartDesign/App/FeatureLinearPattern.h b/src/Mod/PartDesign/App/FeatureLinearPattern.h index 19e6d860be..8876f2646a 100644 --- a/src/Mod/PartDesign/App/FeatureLinearPattern.h +++ b/src/Mod/PartDesign/App/FeatureLinearPattern.h @@ -29,6 +29,10 @@ namespace PartDesign { +enum class LinearPatternMode { + length, + offset +}; class PartDesignExport LinearPattern : public PartDesign::Transformed { @@ -37,9 +41,11 @@ class PartDesignExport LinearPattern : public PartDesign::Transformed public: LinearPattern(); - App::PropertyLinkSub Direction; - App::PropertyBool Reversed; - App::PropertyLength Length; + App::PropertyLinkSub Direction; + App::PropertyBool Reversed; + App::PropertyEnumeration Mode; + App::PropertyLength Length; + App::PropertyLength Offset; App::PropertyIntegerConstraint Occurrences; /** @name methods override feature */ @@ -54,18 +60,32 @@ public: /** Create transformations * Returns a list of (Occurrences - 1) transformations since the first, untransformed instance - * is not counted. Each transformation will move the shape it is applied to by the distance - * (Length / (Occurrences - 1)) so that the transformations will cover the total Length. + * is not counted. + * + * Depending on Mode selection list will be constructed differently: + * 1. For "Overall Length" each transformation will move the shape it is applied to by the distance + * (Length / (Occurrences - 1)) so that the transformations will cover the total Length. + * 2. For "Spacing" each transformation will move the shape by the distance explicitly given in + * the Offset parameter. + * * If Direction contains a feature and a face name, then the transformation direction will be * the normal of the given face, which must be planar. If it contains an edge name, then the * transformation direction will be parallel to the given edge, which must be linear + * * If Reversed is true, the direction of transformation will be opposite */ const std::list getTransformations(const std::vector ) override; protected: void handleChangedPropertyType(Base::XMLReader& reader, const char* TypeName, App::Property* prop) override; + void onChanged(const App::Property* prop) override; + static const App::PropertyIntegerConstraint::Constraints intOccurrences; + +private: + static const char* ModeEnums[]; + + void setReadWriteStatusForMode(LinearPatternMode mode); }; } //namespace PartDesign diff --git a/src/Mod/PartDesign/App/FeaturePolarPattern.cpp b/src/Mod/PartDesign/App/FeaturePolarPattern.cpp index 66f5ad4dfb..c8436fc896 100644 --- a/src/Mod/PartDesign/App/FeaturePolarPattern.cpp +++ b/src/Mod/PartDesign/App/FeaturePolarPattern.cpp @@ -51,21 +51,34 @@ PROPERTY_SOURCE(PartDesign::PolarPattern, PartDesign::Transformed) const App::PropertyIntegerConstraint::Constraints PolarPattern::intOccurrences = { 1, INT_MAX, 1 }; const App::PropertyAngle::Constraints PolarPattern::floatAngle = { Base::toDegrees(Precision::Angular()), 360.0, 1.0 }; +const char* PolarPattern::ModeEnums[] = {"angle", "offset", nullptr}; + PolarPattern::PolarPattern() { + auto initialMode = PolarPatternMode::angle; + ADD_PROPERTY_TYPE(Axis, (nullptr), "PolarPattern", (App::PropertyType)(App::Prop_None), "Direction"); ADD_PROPERTY(Reversed, (0)); + ADD_PROPERTY(Mode, (long(initialMode))); + Mode.setEnums(PolarPattern::ModeEnums); ADD_PROPERTY(Angle, (360.0)); + ADD_PROPERTY(Offset, (120.0)); Angle.setConstraints(&floatAngle); + Offset.setConstraints(&floatAngle); ADD_PROPERTY(Occurrences, (3)); Occurrences.setConstraints(&intOccurrences); + + setReadWriteStatusForMode(initialMode); } short PolarPattern::mustExecute() const { if (Axis.isTouched() || Reversed.isTouched() || - Angle.isTouched() || + Mode.isTouched() || + // Angle and Offset are mutually exclusive, only one could be updated at once + Angle.isTouched() || + Offset.isTouched() || Occurrences.isTouched()) return 1; return Transformed::mustExecute(); @@ -80,17 +93,7 @@ const std::list PolarPattern::getTransformations(const std::vector(angle); - if (radians < Precision::Angular()) - throw Base::ValueError("Pattern angle too small"); - bool reversed = Reversed.getValue(); - double offset; - if (std::fabs(angle - 360.0) < Precision::Confusion()) - offset = radians / occurrences; // Because e.g. two occurrences in 360 degrees need to be 180 degrees apart - else - offset = radians / (occurrences - 1); App::DocumentObject* refObject = Axis.getValue(); if (!refObject) @@ -166,6 +169,32 @@ const std::list PolarPattern::getTransformations(const std::vector(Mode.getValue())) { + case PolarPatternMode::angle: + angle = Angle.getValue(); + + if (std::fabs(angle - 360.0) < Precision::Confusion()) + angle /= occurrences; // Because e.g. two occurrences in 360 degrees need to be 180 degrees apart + else + angle /= occurrences - 1; + + break; + + case PolarPatternMode::offset: + angle = Offset.getValue(); + break; + + default: + throw Base::ValueError("Invalid mode"); + } + + double offset = Base::toRadians(angle); + + if (offset < Precision::Angular()) + throw Base::ValueError("Pattern angle too small"); + std::list transformations; gp_Trsf trans; transformations.push_back(trans); @@ -195,4 +224,21 @@ void PolarPattern::handleChangedPropertyType(Base::XMLReader& reader, const char } } + +void PolarPattern::onChanged(const App::Property* prop) +{ + if (prop == &Mode) { + auto mode = static_cast(Mode.getValue()); + setReadWriteStatusForMode(mode); + } + + Transformed::onChanged(prop); +} + +void PolarPattern::setReadWriteStatusForMode(PolarPatternMode mode) +{ + Offset.setReadOnly(mode != PolarPatternMode::offset); + Angle.setReadOnly(mode != PolarPatternMode::angle); +} + } diff --git a/src/Mod/PartDesign/App/FeaturePolarPattern.h b/src/Mod/PartDesign/App/FeaturePolarPattern.h index 7362f311a5..f250820fec 100644 --- a/src/Mod/PartDesign/App/FeaturePolarPattern.h +++ b/src/Mod/PartDesign/App/FeaturePolarPattern.h @@ -31,6 +31,10 @@ namespace PartDesign { +enum class PolarPatternMode { + angle, + offset +}; class PartDesignExport PolarPattern : public PartDesign::Transformed { @@ -39,9 +43,11 @@ class PartDesignExport PolarPattern : public PartDesign::Transformed public: PolarPattern(); - App::PropertyLinkSub Axis; - App::PropertyBool Reversed; - App::PropertyAngle Angle; + App::PropertyLinkSub Axis; + App::PropertyBool Reversed; + App::PropertyEnumeration Mode; + App::PropertyAngle Angle; + App::PropertyAngle Offset; App::PropertyIntegerConstraint Occurrences; /** @name methods override feature */ @@ -55,21 +61,37 @@ public: //@} /** Create transformations + * * Returns a list of (Occurrences - 1) transformations since the first, untransformed instance - * is not counted. Each transformation will rotate the shape it is applied to by the angle - * (Angle / (Occurrences - 1)) so that the transformations will cover the total Angle. The only - * exception is Angle = 360 degrees in which case the transformation angle will be - * (Angle / Occurrences) so that the last transformed shape is not identical with the original shape + * is not counted. Each transformation will rotate the shape it is applied to by the supplied angle. + * + * Depending on Mode selection list will be constructed differently: + * 1. For "angle" mode each feature will be rotated by (Angle / (Occurrences - 1)) so + * that the transformations will cover the total Angle. The only exception is Angle = 360 degrees in + * which case the transformation angle will be (Angle / Occurrences) so that the last transformed shape + * is not identical with the original shape. + * 2. For "offset" mode each feature will be rotated using exact angle from Offset parameter. It can + * potentially result in transformation that extends beyond full rotation or results in overlapping shapes. + * This situations are considered as potential user errors and should be solved by user. + * * If Axis contains a feature and an edge name, then the transformation axis will be * the given edge, which must be linear. + * * If Reversed is true, the direction of rotation will be opposite. */ const std::list getTransformations(const std::vector) override; protected: void handleChangedPropertyType(Base::XMLReader& reader, const char* TypeName, App::Property* prop) override; + void onChanged(const App::Property* prop) override; + static const App::PropertyIntegerConstraint::Constraints intOccurrences; static const App::PropertyAngle::Constraints floatAngle; + +private: + static const char* ModeEnums[]; + + void setReadWriteStatusForMode(PolarPatternMode mode); }; } //namespace PartDesign diff --git a/src/Mod/PartDesign/Gui/TaskLinearPatternParameters.cpp b/src/Mod/PartDesign/Gui/TaskLinearPatternParameters.cpp index f28fcb9e5d..b0e6c13d64 100644 --- a/src/Mod/PartDesign/Gui/TaskLinearPatternParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskLinearPatternParameters.cpp @@ -127,8 +127,12 @@ void TaskLinearPatternParameters::connectSignals() this, &TaskLinearPatternParameters::onDirectionChanged); connect(ui->checkReverse, &QCheckBox::toggled, this, &TaskLinearPatternParameters::onCheckReverse); + connect(ui->comboMode, qOverload(&QComboBox::activated), + this, &TaskLinearPatternParameters::onModeChanged); connect(ui->spinLength, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskLinearPatternParameters::onLength); + connect(ui->spinOffset, qOverload(&Gui::QuantitySpinBox::valueChanged), + this, &TaskLinearPatternParameters::onOffset); connect(ui->spinOccurrences, &Gui::UIntSpinBox::unsignedChanged, this, &TaskLinearPatternParameters::onOccurrences); connect(ui->checkBoxUpdateView, &QCheckBox::toggled, @@ -153,16 +157,22 @@ void TaskLinearPatternParameters::setupUI() // --------------------- ui->spinLength->bind(pcLinearPattern->Length); + ui->spinOffset->bind(pcLinearPattern->Offset); ui->spinOccurrences->bind(pcLinearPattern->Occurrences); ui->spinOccurrences->setMaximum(pcLinearPattern->Occurrences.getMaximum()); ui->spinOccurrences->setMinimum(pcLinearPattern->Occurrences.getMinimum()); ui->comboDirection->setEnabled(true); ui->checkReverse->setEnabled(true); + ui->comboMode->setEnabled(true); ui->spinLength->blockSignals(true); ui->spinLength->setEnabled(true); ui->spinLength->setUnit(Base::Unit::Length); ui->spinLength->blockSignals(false); + ui->spinOffset->blockSignals(true); + ui->spinOffset->setEnabled(true); + ui->spinOffset->setUnit(Base::Unit::Length); + ui->spinOffset->blockSignals(false); ui->spinOccurrences->setEnabled(true); dirLinks.setCombo(*(ui->comboDirection)); @@ -187,7 +197,7 @@ void TaskLinearPatternParameters::setupUI() } } - updateUI(); + adaptVisibilityToMode(); connectSignals(); } @@ -198,9 +208,11 @@ void TaskLinearPatternParameters::updateUI() blockUpdate = true; PartDesign::LinearPattern* pcLinearPattern = static_cast(getObject()); + PartDesign::LinearPatternMode mode = static_cast(pcLinearPattern->Mode.getValue()); bool reverse = pcLinearPattern->Reversed.getValue(); double length = pcLinearPattern->Length.getValue(); + double offset = pcLinearPattern->Offset.getValue(); unsigned occurrences = pcLinearPattern->Occurrences.getValue(); if (dirLinks.setCurrentLink(pcLinearPattern->Direction) == -1){ @@ -210,15 +222,28 @@ void TaskLinearPatternParameters::updateUI() dirLinks.setCurrentLink(pcLinearPattern->Direction); } - // Note: These three lines would trigger onLength(), on Occurrences() and another updateUI() if we - // didn't check for blockUpdate + // Note: This block of code would trigger change signal handlers (e.g. onOccurrences()) + // and another updateUI() if we didn't check for blockUpdate ui->checkReverse->setChecked(reverse); + ui->comboMode->setCurrentIndex((long)mode); ui->spinLength->setValue(length); + ui->spinOffset->setValue(offset); ui->spinOccurrences->setValue(occurrences); blockUpdate = false; } +void TaskLinearPatternParameters::adaptVisibilityToMode() +{ + auto pcLinearPattern = static_cast(getObject()); + auto mode = static_cast(pcLinearPattern->Mode.getValue()); + + ui->lengthWrapper->setVisible(mode == PartDesign::LinearPatternMode::length); + ui->offsetWrapper->setVisible(mode == PartDesign::LinearPatternMode::offset); + + updateUI(); +} + void TaskLinearPatternParameters::onUpdateViewTimer() { setupTransaction(); @@ -294,6 +319,18 @@ void TaskLinearPatternParameters::onCheckReverse(const bool on) { kickUpdateViewTimer(); } +void TaskLinearPatternParameters::onModeChanged(const int mode) { + if (blockUpdate) + return; + PartDesign::LinearPattern* pcLinearPattern = static_cast(getObject()); + pcLinearPattern->Mode.setValue(mode); + + adaptVisibilityToMode(); + + exitSelectionMode(); + kickUpdateViewTimer(); +} + void TaskLinearPatternParameters::onLength(const double l) { if (blockUpdate) return; @@ -304,6 +341,16 @@ void TaskLinearPatternParameters::onLength(const double l) { kickUpdateViewTimer(); } +void TaskLinearPatternParameters::onOffset(const double o) { + if (blockUpdate) + return; + PartDesign::LinearPattern* pcLinearPattern = static_cast(getObject()); + pcLinearPattern->Offset.setValue(o); + + exitSelectionMode(); + kickUpdateViewTimer(); +} + void TaskLinearPatternParameters::onOccurrences(const uint n) { if (blockUpdate) return; @@ -352,6 +399,7 @@ void TaskLinearPatternParameters::onUpdateView(bool on) pcLinearPattern->Direction.setValue(obj,directions); pcLinearPattern->Reversed.setValue(getReverse()); pcLinearPattern->Length.setValue(getLength()); + pcLinearPattern->Offset.setValue(getOffset()); pcLinearPattern->Occurrences.setValue(getOccurrences()); recomputeFeature(); @@ -386,11 +434,21 @@ bool TaskLinearPatternParameters::getReverse() const return ui->checkReverse->isChecked(); } +int TaskLinearPatternParameters::getMode() const +{ + return ui->comboMode->currentIndex(); +} + double TaskLinearPatternParameters::getLength() const { return ui->spinLength->value().getValue(); } +double TaskLinearPatternParameters::getOffset() const +{ + return ui->spinOffset->value().getValue(); +} + unsigned TaskLinearPatternParameters::getOccurrences() const { return ui->spinOccurrences->value(); @@ -436,6 +494,7 @@ void TaskLinearPatternParameters::apply() FCMD_OBJ_CMD(tobj,"Reversed = " << getReverse()); ui->spinLength->apply(); + ui->spinOffset->apply(); ui->spinOccurrences->apply(); } diff --git a/src/Mod/PartDesign/Gui/TaskLinearPatternParameters.h b/src/Mod/PartDesign/Gui/TaskLinearPatternParameters.h index 7edc47f5d0..41cb67733e 100644 --- a/src/Mod/PartDesign/Gui/TaskLinearPatternParameters.h +++ b/src/Mod/PartDesign/Gui/TaskLinearPatternParameters.h @@ -59,7 +59,9 @@ private Q_SLOTS: void onUpdateViewTimer(); void onDirectionChanged(int num); void onCheckReverse(const bool on); + void onModeChanged(const int mode); void onLength(const double l); + void onOffset(const double o); void onOccurrences(const uint n); void onUpdateView(bool) override; void onFeatureDeleted() override; @@ -72,13 +74,16 @@ protected: void clearButtons() override; void getDirection(App::DocumentObject*& obj, std::vector& sub) const; bool getReverse() const; + int getMode() const; double getLength() const; + double getOffset() const; unsigned getOccurrences() const; private: void connectSignals(); void setupUI(); void updateUI(); + void adaptVisibilityToMode(); void kickUpdateViewTimer() const; private: diff --git a/src/Mod/PartDesign/Gui/TaskLinearPatternParameters.ui b/src/Mod/PartDesign/Gui/TaskLinearPatternParameters.ui index 751eccc4b0..7c97a94511 100644 --- a/src/Mod/PartDesign/Gui/TaskLinearPatternParameters.ui +++ b/src/Mod/PartDesign/Gui/TaskLinearPatternParameters.ui @@ -70,29 +70,106 @@ - + - + - Length + Mode - - - false - - - mm - - - 100.000000000000000 - + + + + Overall Length + + + + + Offset + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Length + + + + + + + false + + + mm + + + 100.000000000000000 + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Offset + + + + + + + false + + + mm + + + 10.000000000000000 + + + + + + diff --git a/src/Mod/PartDesign/Gui/TaskPolarPatternParameters.cpp b/src/Mod/PartDesign/Gui/TaskPolarPatternParameters.cpp index f3764ed5f8..92bdb55912 100644 --- a/src/Mod/PartDesign/Gui/TaskPolarPatternParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskPolarPatternParameters.cpp @@ -131,10 +131,14 @@ void TaskPolarPatternParameters::connectSignals() this, &TaskPolarPatternParameters::onUpdateViewTimer); connect(ui->comboAxis, qOverload(&QComboBox::activated), this, &TaskPolarPatternParameters::onAxisChanged); + connect(ui->comboMode, qOverload(&QComboBox::activated), + this, &TaskPolarPatternParameters::onModeChanged); connect(ui->checkReverse, &QCheckBox::toggled, this, &TaskPolarPatternParameters::onCheckReverse); connect(ui->polarAngle, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskPolarPatternParameters::onAngle); + connect(ui->angleOffset, qOverload(&Gui::QuantitySpinBox::valueChanged), + this, &TaskPolarPatternParameters::onOffset); connect(ui->spinOccurrences, &Gui::UIntSpinBox::unsignedChanged, this, &TaskPolarPatternParameters::onOccurrences); connect(ui->checkBoxUpdateView, &QCheckBox::toggled, @@ -159,11 +163,14 @@ void TaskPolarPatternParameters::setupUI() // --------------------- ui->polarAngle->bind(pcPolarPattern->Angle); + ui->angleOffset->bind(pcPolarPattern->Offset); + ui->spinOccurrences->bind(pcPolarPattern->Occurrences); ui->spinOccurrences->setMaximum(pcPolarPattern->Occurrences.getMaximum()); ui->spinOccurrences->setMinimum(pcPolarPattern->Occurrences.getMinimum()); ui->comboAxis->setEnabled(true); + ui->comboMode->setEnabled(true); ui->checkReverse->setEnabled(true); ui->polarAngle->setEnabled(true); ui->spinOccurrences->setEnabled(true); @@ -191,6 +198,7 @@ void TaskPolarPatternParameters::setupUI() } } + adaptVisibilityToMode(); updateUI(); connectSignals(); } @@ -203,20 +211,24 @@ void TaskPolarPatternParameters::updateUI() PartDesign::PolarPattern* pcPolarPattern = static_cast(getObject()); + PartDesign::PolarPatternMode mode = static_cast(pcPolarPattern->Mode.getValue()); bool reverse = pcPolarPattern->Reversed.getValue(); double angle = pcPolarPattern->Angle.getValue(); + double offset = pcPolarPattern->Offset.getValue(); unsigned occurrences = pcPolarPattern->Occurrences.getValue(); - if (axesLinks.setCurrentLink(pcPolarPattern->Axis) == -1){ + if (axesLinks.setCurrentLink(pcPolarPattern->Axis) == -1) { //failed to set current, because the link isn't in the list yet axesLinks.addLink(pcPolarPattern->Axis, getRefStr(pcPolarPattern->Axis.getValue(),pcPolarPattern->Axis.getSubValues())); axesLinks.setCurrentLink(pcPolarPattern->Axis); } - // Note: These three lines would trigger onLength(), on Occurrences() and another updateUI() if we - // didn't check for blockUpdate + // Note: This block of code would trigger change signal handlers (e.g. onOccurrences()) + // and another updateUI() if we didn't check for blockUpdate ui->checkReverse->setChecked(reverse); + ui->comboMode->setCurrentIndex((long)mode); ui->polarAngle->setValue(angle); + ui->angleOffset->setValue(offset); ui->spinOccurrences->setValue(occurrences); blockUpdate = false; @@ -233,6 +245,15 @@ void TaskPolarPatternParameters::kickUpdateViewTimer() const updateViewTimer->start(); } +void TaskPolarPatternParameters::adaptVisibilityToMode() +{ + auto pcLinearPattern = static_cast(getObject()); + auto mode = static_cast(pcLinearPattern->Mode.getValue()); + + ui->polarAngleWrapper->setVisible(mode == PartDesign::PolarPatternMode::angle); + ui->angleOffsetWrapper->setVisible(mode == PartDesign::PolarPatternMode::offset); +} + void TaskPolarPatternParameters::addObject(App::DocumentObject* obj) { QString label = QString::fromUtf8(obj->Label.getValue()); @@ -292,6 +313,18 @@ void TaskPolarPatternParameters::onCheckReverse(const bool on) { kickUpdateViewTimer(); } +void TaskPolarPatternParameters::onModeChanged(const int mode) { + if (blockUpdate) + return; + PartDesign::PolarPattern* pcPolarPattern = static_cast(getObject()); + pcPolarPattern->Mode.setValue(mode); + + adaptVisibilityToMode(); + + exitSelectionMode(); + kickUpdateViewTimer(); +} + void TaskPolarPatternParameters::onAngle(const double a) { if (blockUpdate) return; @@ -302,6 +335,16 @@ void TaskPolarPatternParameters::onAngle(const double a) { kickUpdateViewTimer(); } +void TaskPolarPatternParameters::onOffset(const double a) { + if (blockUpdate) + return; + PartDesign::PolarPattern* pcPolarPattern = static_cast(getObject()); + pcPolarPattern->Offset.setValue(a); + + exitSelectionMode(); + kickUpdateViewTimer(); +} + void TaskPolarPatternParameters::onOccurrences(const uint n) { if (blockUpdate) return; diff --git a/src/Mod/PartDesign/Gui/TaskPolarPatternParameters.h b/src/Mod/PartDesign/Gui/TaskPolarPatternParameters.h index 0408574993..b01121c23c 100644 --- a/src/Mod/PartDesign/Gui/TaskPolarPatternParameters.h +++ b/src/Mod/PartDesign/Gui/TaskPolarPatternParameters.h @@ -58,8 +58,10 @@ public: private Q_SLOTS: void onUpdateViewTimer(); void onAxisChanged(int num); + void onModeChanged(const int mode); void onCheckReverse(const bool on); void onAngle(const double a); + void onOffset(const double a); void onOccurrences(const uint n); void onUpdateView(bool) override; void onFeatureDeleted() override; @@ -82,6 +84,7 @@ private: void setupUI(); void updateUI(); void kickUpdateViewTimer() const; + void adaptVisibilityToMode(); private: std::unique_ptr ui; diff --git a/src/Mod/PartDesign/Gui/TaskPolarPatternParameters.ui b/src/Mod/PartDesign/Gui/TaskPolarPatternParameters.ui index 9e26831d5a..b95832289f 100644 --- a/src/Mod/PartDesign/Gui/TaskPolarPatternParameters.ui +++ b/src/Mod/PartDesign/Gui/TaskPolarPatternParameters.ui @@ -70,35 +70,118 @@ - + - + - Angle + Mode - - - false - - - deg - - - 0.000000000000000 - - - 360.000000000000000 - - - 360.000000000000000 - + + + + Overall Angle + + + + + Offset Angle + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Angle + + + + + + + false + + + deg + + + 0.000000000000000 + + + 360.000000000000000 + + + 360.000000000000000 + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Offset + + + + + + + false + + + deg + + + 0.000000000000000 + + + 360.000000000000000 + + + 360.000000000000000 + + + + + +