Merge pull request #10377 from kadet1090/lp-offset
PartDesign: Add offset modes for patterns
This commit is contained in:
@@ -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<gp_Trsf> LinearPattern::getTransformations(const std::vector<App::DocumentObject*>)
|
||||
{
|
||||
int occurrences = Occurrences.getValue();
|
||||
@@ -173,7 +190,20 @@ const std::list<gp_Trsf> LinearPattern::getTransformations(const std::vector<App
|
||||
dir.Transform(invObjLoc.Transformation());
|
||||
|
||||
gp_Vec offset(dir.X(), dir.Y(), dir.Z());
|
||||
offset *= distance / (occurrences - 1);
|
||||
|
||||
switch (static_cast<LinearPatternMode>(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<LinearPatternMode>(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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<gp_Trsf> getTransformations(const std::vector<App::DocumentObject*> ) 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
|
||||
|
||||
@@ -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<double>(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<gp_Trsf> PolarPattern::getTransformations(const std::vector<App:
|
||||
if (occurrences == 1)
|
||||
return {gp_Trsf()};
|
||||
|
||||
double angle = Angle.getValue();
|
||||
double radians = Base::toRadians<double>(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<gp_Trsf> PolarPattern::getTransformations(const std::vector<App:
|
||||
if (reversed)
|
||||
axis.SetDirection(axis.Direction().Reversed());
|
||||
|
||||
double angle;
|
||||
|
||||
switch (static_cast<PolarPatternMode>(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<double>(angle);
|
||||
|
||||
if (offset < Precision::Angular())
|
||||
throw Base::ValueError("Pattern angle too small");
|
||||
|
||||
std::list<gp_Trsf> 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<PolarPatternMode>(Mode.getValue());
|
||||
setReadWriteStatusForMode(mode);
|
||||
}
|
||||
|
||||
Transformed::onChanged(prop);
|
||||
}
|
||||
|
||||
void PolarPattern::setReadWriteStatusForMode(PolarPatternMode mode)
|
||||
{
|
||||
Offset.setReadOnly(mode != PolarPatternMode::offset);
|
||||
Angle.setReadOnly(mode != PolarPatternMode::angle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<gp_Trsf> getTransformations(const std::vector<App::DocumentObject*>) 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
|
||||
|
||||
@@ -127,8 +127,12 @@ void TaskLinearPatternParameters::connectSignals()
|
||||
this, &TaskLinearPatternParameters::onDirectionChanged);
|
||||
connect(ui->checkReverse, &QCheckBox::toggled,
|
||||
this, &TaskLinearPatternParameters::onCheckReverse);
|
||||
connect(ui->comboMode, qOverload<int>(&QComboBox::activated),
|
||||
this, &TaskLinearPatternParameters::onModeChanged);
|
||||
connect(ui->spinLength, qOverload<double>(&Gui::QuantitySpinBox::valueChanged),
|
||||
this, &TaskLinearPatternParameters::onLength);
|
||||
connect(ui->spinOffset, qOverload<double>(&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<PartDesign::LinearPattern*>(getObject());
|
||||
PartDesign::LinearPatternMode mode = static_cast<PartDesign::LinearPatternMode>(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<PartDesign::LinearPattern*>(getObject());
|
||||
auto mode = static_cast<PartDesign::LinearPatternMode>(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<PartDesign::LinearPattern*>(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<PartDesign::LinearPattern*>(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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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<std::string>& 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:
|
||||
|
||||
@@ -70,29 +70,106 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<layout class="QHBoxLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<widget class="QLabel" name="labelMode">
|
||||
<property name="text">
|
||||
<string>Length</string>
|
||||
<string>Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::QuantitySpinBox" name="spinLength">
|
||||
<property name="keyboardTracking">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">mm</string>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
<widget class="QComboBox" name="comboMode">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Overall Length</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Offset</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="lengthWrapper" native="true">
|
||||
<layout class="QHBoxLayout" name="_3">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelLength">
|
||||
<property name="text">
|
||||
<string>Length</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::QuantitySpinBox" name="spinLength" native="true">
|
||||
<property name="keyboardTracking" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">mm</string>
|
||||
</property>
|
||||
<property name="value" stdset="0">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="offsetWrapper" native="true">
|
||||
<layout class="QHBoxLayout" name="_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelOffset">
|
||||
<property name="text">
|
||||
<string>Offset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::QuantitySpinBox" name="spinOffset" native="true">
|
||||
<property name="keyboardTracking" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">mm</string>
|
||||
</property>
|
||||
<property name="value" stdset="0">
|
||||
<double>10.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
|
||||
@@ -131,10 +131,14 @@ void TaskPolarPatternParameters::connectSignals()
|
||||
this, &TaskPolarPatternParameters::onUpdateViewTimer);
|
||||
connect(ui->comboAxis, qOverload<int>(&QComboBox::activated),
|
||||
this, &TaskPolarPatternParameters::onAxisChanged);
|
||||
connect(ui->comboMode, qOverload<int>(&QComboBox::activated),
|
||||
this, &TaskPolarPatternParameters::onModeChanged);
|
||||
connect(ui->checkReverse, &QCheckBox::toggled,
|
||||
this, &TaskPolarPatternParameters::onCheckReverse);
|
||||
connect(ui->polarAngle, qOverload<double>(&Gui::QuantitySpinBox::valueChanged),
|
||||
this, &TaskPolarPatternParameters::onAngle);
|
||||
connect(ui->angleOffset, qOverload<double>(&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<PartDesign::PolarPattern*>(getObject());
|
||||
|
||||
PartDesign::PolarPatternMode mode = static_cast<PartDesign::PolarPatternMode>(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<PartDesign::PolarPattern*>(getObject());
|
||||
auto mode = static_cast<PartDesign::PolarPatternMode>(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<PartDesign::PolarPattern*>(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<PartDesign::PolarPattern*>(getObject());
|
||||
pcPolarPattern->Offset.setValue(a);
|
||||
|
||||
exitSelectionMode();
|
||||
kickUpdateViewTimer();
|
||||
}
|
||||
|
||||
void TaskPolarPatternParameters::onOccurrences(const uint n) {
|
||||
if (blockUpdate)
|
||||
return;
|
||||
|
||||
@@ -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_TaskPolarPatternParameters> ui;
|
||||
|
||||
@@ -70,35 +70,118 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<layout class="QHBoxLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Angle</string>
|
||||
<string>Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::QuantitySpinBox" name="polarAngle">
|
||||
<property name="keyboardTracking">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">deg</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>360.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>360.000000000000000</double>
|
||||
</property>
|
||||
<widget class="QComboBox" name="comboMode">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Overall Angle</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Offset Angle</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="polarAngleWrapper" native="true">
|
||||
<layout class="QHBoxLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Angle</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::QuantitySpinBox" name="polarAngle" native="true">
|
||||
<property name="keyboardTracking" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">deg</string>
|
||||
</property>
|
||||
<property name="minimum" stdset="0">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum" stdset="0">
|
||||
<double>360.000000000000000</double>
|
||||
</property>
|
||||
<property name="value" stdset="0">
|
||||
<double>360.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="angleOffsetWrapper" native="true">
|
||||
<layout class="QHBoxLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Offset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::QuantitySpinBox" name="angleOffset" native="true">
|
||||
<property name="keyboardTracking" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">deg</string>
|
||||
</property>
|
||||
<property name="minimum" stdset="0">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum" stdset="0">
|
||||
<double>360.000000000000000</double>
|
||||
</property>
|
||||
<property name="value" stdset="0">
|
||||
<double>360.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
|
||||
Reference in New Issue
Block a user