diff --git a/pcbnew/dialogs/dialog_pad_properties.cpp b/pcbnew/dialogs/dialog_pad_properties.cpp index 02979b09e9..f1c5589c46 100644 --- a/pcbnew/dialogs/dialog_pad_properties.cpp +++ b/pcbnew/dialogs/dialog_pad_properties.cpp @@ -468,6 +468,72 @@ void DIALOG_PAD_PROPERTIES::onCornerRadiusChange( wxCommandEvent& event ) } +double DIALOG_PAD_PROPERTIES::getMaxChamferRatio() const +{ + // The maximum chamfer ratio is 50% of the smallest pad side if adjacent sides + // are selected, or 100% of the smallest pad side if only one side is selected. + double baseline = 1.0; + + auto considerCheckboxes = [&]( const std::vector& checkBoxes ) + { + for( size_t ii : { 0, 1, 2, 3 } ) + { + if( !checkBoxes[ii]->IsChecked() ) + continue; + + if( checkBoxes[( ii + 1 ) % 4]->IsChecked() || checkBoxes[( ii - 1 ) % 4]->IsChecked() ) + { + // If two adjacent corners are selected, the maximum chamfer ratio is 50% + baseline = std::max( baseline, 0.5 ); + break; + } + } + }; + + + baseline = 1.0 - m_previewPad->GetRoundRectRadiusRatio( m_editLayer ); + considerCheckboxes( { m_cbTopLeft1, m_cbTopRight1, m_cbBottomRight1, m_cbBottomLeft1 } ); + considerCheckboxes( { m_cbTopLeft, m_cbTopRight, m_cbBottomRight, m_cbBottomLeft } ); + + // If only one corner is selected, the maximum chamfer ratio is 100% + return baseline; +} + + +double DIALOG_PAD_PROPERTIES::getMaxCornerRadius() const +{ + return 1.0 - m_previewPad->GetChamferRectRatio( m_editLayer ); +} + + +void DIALOG_PAD_PROPERTIES::updateAllowedPadChamferCorners() +{ + auto updateCheckBoxes = []( const std::vector& aCheckBoxes ) + { + for( size_t ii : { 0, 1, 2, 3 } ) + { + bool disable = aCheckBoxes[( ii + 1 ) % 4]->IsChecked() + || aCheckBoxes[( ii + 3 ) % 4]->IsChecked(); + + aCheckBoxes[ii]->Enable( !disable ); + + if( disable ) + aCheckBoxes[ii]->SetValue( false ); + } + }; + + if( m_mixedChamferRatio.GetDoubleValue() > 50.0 ) + { + updateCheckBoxes( { m_cbTopLeft1, m_cbTopRight1, m_cbBottomRight1, m_cbBottomLeft1 } ); + } + + if( m_chamferRatio.GetDoubleValue() > 50.0 ) + { + updateCheckBoxes( { m_cbTopLeft, m_cbTopRight, m_cbBottomRight, m_cbBottomLeft } ); + } +} + + void DIALOG_PAD_PROPERTIES::onCornerSizePercentChange( wxCommandEvent& event ) { if( m_previewPad->GetShape( m_editLayer ) != PAD_SHAPE::ROUNDRECT @@ -487,15 +553,17 @@ void DIALOG_PAD_PROPERTIES::onCornerSizePercentChange( wxCommandEvent& event ) if( value.ToDouble( &ratioPercent ) ) { // Clamp ratioPercent to acceptable value (0.0 to 50.0) + double maxRatio = getMaxCornerRadius(); + if( ratioPercent < 0.0 ) { m_cornerRatio.SetDoubleValue( 0.0 ); m_mixedCornerRatio.SetDoubleValue( 0.0 ); } - else if( ratioPercent > 50.0 ) + else if( ratioPercent > maxRatio * 100.0 ) { - m_cornerRatio.SetDoubleValue( 50.0 ); - m_mixedCornerRatio.SetDoubleValue( 50.0 ); + m_cornerRatio.SetDoubleValue( maxRatio * 100.0 ); + m_mixedCornerRatio.SetDoubleValue( maxRatio * 100.0 ); } if( ctrl == m_cornerRatioCtrl ) @@ -512,16 +580,17 @@ void DIALOG_PAD_PROPERTIES::onCornerSizePercentChange( wxCommandEvent& event ) if( value.ToDouble( &ratioPercent ) ) { - // Clamp ratioPercent to acceptable value (0.0 to 50.0) + double maxRatio = getMaxChamferRatio(); + // Clamp ratioPercent to acceptable value (0.0 to maxRatio) if( ratioPercent < 0.0 ) { m_chamferRatio.SetDoubleValue( 0.0 ); m_mixedChamferRatio.SetDoubleValue( 0.0 ); } - else if( ratioPercent > 50.0 ) + else if( ratioPercent > maxRatio * 100.0 ) { - m_chamferRatio.SetDoubleValue( 50.0 ); - m_mixedChamferRatio.SetDoubleValue( 50.0 ); + m_chamferRatio.SetDoubleValue( maxRatio * 100.0 ); + m_mixedChamferRatio.SetDoubleValue( maxRatio * 100.0 ); } if( ctrl == m_chamferRatioCtrl ) @@ -529,6 +598,8 @@ void DIALOG_PAD_PROPERTIES::onCornerSizePercentChange( wxCommandEvent& event ) else m_chamferRatioCtrl->ChangeValue( value ); + updateAllowedPadChamferCorners(); + changed = true; } } @@ -2107,6 +2178,7 @@ void DIALOG_PAD_PROPERTIES::OnValuesChanged( wxCommandEvent& event ) return; // If the pad size has changed, update the displayed values for rounded rect pads. + updateAllowedPadChamferCorners(); updateRoundRectCornerValues(); redraw(); diff --git a/pcbnew/dialogs/dialog_pad_properties.h b/pcbnew/dialogs/dialog_pad_properties.h index 58a2db18e0..88ffe120a7 100644 --- a/pcbnew/dialogs/dialog_pad_properties.h +++ b/pcbnew/dialogs/dialog_pad_properties.h @@ -125,6 +125,14 @@ private: void onModify( wxCommandEvent& aEvent ) override; void onModify( wxSpinDoubleEvent& aEvent ) override; + // Return the largest chamfer ratio allowed by the current pad shape + double getMaxChamferRatio() const; + + // Return the largest corner radius allowed by the current pad shape + double getMaxCornerRadius() const; + + void updateAllowedPadChamferCorners(); + private: PCB_BASE_FRAME* m_parent; PAD* m_currentPad; // pad currently being edited diff --git a/pcbnew/pad.cpp b/pcbnew/pad.cpp index f6137f2bbd..49314ec417 100644 --- a/pcbnew/pad.cpp +++ b/pcbnew/pad.cpp @@ -506,7 +506,7 @@ int PAD::GetFrontRoundRectRadiusSize() const void PAD::SetChamferRectRatio( PCB_LAYER_ID aLayer, double aChamferScale ) { - m_padStack.SetChamferRatio( std::clamp( aChamferScale, 0.0, 0.5 ), aLayer ); + m_padStack.SetChamferRatio( aChamferScale, aLayer ); SetDirty(); }