mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-03-30 05:26:55 +00:00
Use std::optional for pad connection overrides.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/19555
This commit is contained in:
parent
1ebcd24944
commit
dd7c076bc9
common
include
pcbnew
qa/pcbnew_utils
@ -555,9 +555,17 @@ wxString PGPROPERTY_ANGLE::ValueToString( wxVariant& aVariant,
|
||||
wxString PGPROPERTY_ANGLE::ValueToString( wxVariant& aVariant, int aArgFlags ) const
|
||||
#endif
|
||||
{
|
||||
if( aVariant.GetType() == wxPG_VARIANT_TYPE_DOUBLE )
|
||||
if( aVariant.GetType() == wxT( "std::optional<double>" ) )
|
||||
{
|
||||
auto* variantData = static_cast<STD_OPTIONAL_DOUBLE_VARIANT_DATA*>( aVariant.GetData() );
|
||||
|
||||
if( variantData->Value().has_value() )
|
||||
return wxString::Format( wxS( "%g\u00B0" ), variantData->Value().value() / m_scale );
|
||||
else
|
||||
return wxEmptyString;
|
||||
}
|
||||
else if( aVariant.GetType() == wxPG_VARIANT_TYPE_DOUBLE )
|
||||
{
|
||||
// TODO(JE) Is this still needed?
|
||||
return wxString::Format( wxS( "%g\u00B0" ), aVariant.GetDouble() / m_scale );
|
||||
}
|
||||
else if( aVariant.GetType() == wxS( "EDA_ANGLE" ) )
|
||||
|
@ -655,15 +655,20 @@ bool UNIT_BINDER::IsIndeterminate() const
|
||||
|
||||
bool UNIT_BINDER::IsNull() const
|
||||
{
|
||||
wxTextEntry* te = dynamic_cast<wxTextEntry*>( m_valueCtrl );
|
||||
|
||||
if( te )
|
||||
if( wxTextEntry* te = dynamic_cast<wxTextEntry*>( m_valueCtrl ) )
|
||||
return te->GetValue().IsEmpty();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void UNIT_BINDER::SetNull()
|
||||
{
|
||||
if( wxTextEntry* te = dynamic_cast<wxTextEntry*>( m_valueCtrl ) )
|
||||
return te->SetValue( wxEmptyString );
|
||||
}
|
||||
|
||||
|
||||
void UNIT_BINDER::SetLabel( const wxString& aLabel )
|
||||
{
|
||||
m_label->SetLabel( aLabel );
|
||||
|
@ -112,9 +112,16 @@ public:
|
||||
int val = 0;
|
||||
|
||||
if( aValue.CheckType<int>() )
|
||||
{
|
||||
val = aValue.As<int>();
|
||||
}
|
||||
else if( aValue.CheckType<std::optional<int>>() )
|
||||
val = aValue.As<std::optional<int>>().value_or( 0 );
|
||||
{
|
||||
if( aValue.As<std::optional<int>>().has_value() )
|
||||
val = aValue.As<std::optional<int>>().value();
|
||||
else
|
||||
return std::nullopt; // no value for a std::optional is always valid
|
||||
}
|
||||
|
||||
if( val > Max )
|
||||
return std::make_unique<VALIDATION_ERROR_TOO_LARGE<int>>( val, Max );
|
||||
@ -132,9 +139,16 @@ public:
|
||||
int val = 0;
|
||||
|
||||
if( aValue.CheckType<int>() )
|
||||
{
|
||||
val = aValue.As<int>();
|
||||
}
|
||||
else if( aValue.CheckType<std::optional<int>>() )
|
||||
val = aValue.As<std::optional<int>>().value_or( 0 );
|
||||
{
|
||||
if( aValue.As<std::optional<int>>().has_value() )
|
||||
val = aValue.As<std::optional<int>>().value();
|
||||
else
|
||||
return std::nullopt; // no value for a std::optional is always valid
|
||||
}
|
||||
|
||||
if( val < 0 )
|
||||
return std::make_unique<VALIDATION_ERROR_TOO_SMALL<int>>( val, 0 );
|
||||
|
@ -157,6 +157,7 @@ public:
|
||||
* Return true if the control holds no value (ie: empty string, **not** 0).
|
||||
*/
|
||||
bool IsNull() const;
|
||||
void SetNull();
|
||||
|
||||
/**
|
||||
* Validate the control against the given range, informing the user of any errors found.
|
||||
|
@ -672,9 +672,17 @@ void DIALOG_PAD_PROPERTIES::initValues()
|
||||
else
|
||||
m_pasteMarginRatio.ChangeValue( wxEmptyString );
|
||||
|
||||
m_spokeWidth.ChangeValue( m_previewPad->GetThermalSpokeWidth() );
|
||||
if( m_previewPad->GetLocalThermalSpokeWidthOverride().has_value() )
|
||||
m_spokeWidth.ChangeValue( m_previewPad->GetLocalThermalSpokeWidthOverride().value() );
|
||||
else
|
||||
m_spokeWidth.SetNull();
|
||||
|
||||
if( m_previewPad->GetLocalThermalGapOverride().has_value() )
|
||||
m_thermalGap.ChangeValue( m_previewPad->GetLocalThermalGapOverride().value() );
|
||||
else
|
||||
m_thermalGap.SetNull();
|
||||
|
||||
m_spokeAngle.ChangeAngleValue( m_previewPad->GetThermalSpokeAngle() );
|
||||
m_thermalGap.ChangeValue( m_previewPad->GetThermalGap() );
|
||||
m_pad_orientation.ChangeAngleValue( m_previewPad->GetOrientation() );
|
||||
|
||||
m_cbTeardrops->SetValue( m_previewPad->GetTeardropParams().m_Enabled );
|
||||
@ -1734,9 +1742,13 @@ bool DIALOG_PAD_PROPERTIES::transferDataToPad( PAD* aPad )
|
||||
else
|
||||
aPad->SetLocalSolderPasteMarginRatio( m_pasteMarginRatio.GetDoubleValue() / 100.0 );
|
||||
|
||||
aPad->SetThermalSpokeWidth( m_spokeWidth.GetIntValue() );
|
||||
if( !m_spokeWidth.IsNull() )
|
||||
aPad->SetLocalThermalSpokeWidthOverride( m_spokeWidth.GetIntValue() );
|
||||
|
||||
if( !m_thermalGap.IsNull() )
|
||||
aPad->SetLocalThermalGapOverride( m_thermalGap.GetIntValue() );
|
||||
|
||||
aPad->SetThermalSpokeAngle( m_spokeAngle.GetAngleValue() );
|
||||
aPad->SetThermalGap( m_thermalGap.GetIntValue() );
|
||||
|
||||
// And rotation
|
||||
aPad->SetOrientation( m_pad_orientation.GetAngleValue() );
|
||||
|
@ -233,13 +233,15 @@ bool padHasOverrides( const PAD* a, const PAD* b, REPORTER& aReporter )
|
||||
REPORT_MSG( _( "%s has zone connection override." ), PAD_DESC( a ) );
|
||||
}
|
||||
|
||||
if( a->GetThermalGap() != b->GetThermalGap() )
|
||||
if( a->GetLocalThermalGapOverride().has_value()
|
||||
&& a->GetThermalGap() != b->GetThermalGap() )
|
||||
{
|
||||
diff = true;
|
||||
REPORT_MSG( _( "%s has thermal relief gap override." ), PAD_DESC( a ) );
|
||||
}
|
||||
|
||||
if( a->GetThermalSpokeWidth() != b->GetThermalSpokeWidth() )
|
||||
if( a->GetLocalThermalSpokeWidthOverride().has_value()
|
||||
&& a->GetLocalThermalSpokeWidthOverride() != b->GetLocalThermalSpokeWidthOverride() )
|
||||
{
|
||||
diff = true;
|
||||
REPORT_MSG( _( "%s has thermal relief spoke width override." ), PAD_DESC( a ) );
|
||||
|
@ -1265,7 +1265,7 @@ int PAD::GetLocalThermalGapOverride( wxString* aSource ) const
|
||||
if( m_padStack.ThermalGap().has_value() && aSource )
|
||||
*aSource = _( "pad" );
|
||||
|
||||
return m_padStack.ThermalGap().value_or( 0 );
|
||||
return GetLocalThermalGapOverride().value_or( 0 );
|
||||
}
|
||||
|
||||
|
||||
@ -1877,9 +1877,9 @@ void PAD::ImportSettingsFrom( const PAD& aMasterPad )
|
||||
SetLocalSolderPasteMarginRatio( aMasterPad.GetLocalSolderPasteMarginRatio() );
|
||||
|
||||
SetLocalZoneConnection( aMasterPad.GetLocalZoneConnection() );
|
||||
SetThermalSpokeWidth( aMasterPad.GetThermalSpokeWidth() );
|
||||
SetLocalThermalSpokeWidthOverride( aMasterPad.GetLocalThermalSpokeWidthOverride() );
|
||||
SetThermalSpokeAngle( aMasterPad.GetThermalSpokeAngle() );
|
||||
SetThermalGap( aMasterPad.GetThermalGap() );
|
||||
SetLocalThermalGapOverride( aMasterPad.GetLocalThermalGapOverride() );
|
||||
|
||||
SetCustomShapeInZoneOpt( aMasterPad.GetCustomShapeInZoneOpt() );
|
||||
|
||||
@ -2720,17 +2720,20 @@ static struct PAD_DESC
|
||||
|
||||
constexpr int minZoneWidth = pcbIUScale.mmToIU( ZONE_THICKNESS_MIN_VALUE_MM );
|
||||
|
||||
propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Thermal Relief Spoke Width" ),
|
||||
&PAD::SetThermalSpokeWidth, &PAD::GetThermalSpokeWidth,
|
||||
propMgr.AddProperty( new PROPERTY<PAD, std::optional<int>>(
|
||||
_HKI( "Thermal Relief Spoke Width" ),
|
||||
&PAD::SetLocalThermalSpokeWidthOverride, &PAD::GetLocalThermalSpokeWidthOverride,
|
||||
PROPERTY_DISPLAY::PT_SIZE ), groupOverrides )
|
||||
.SetValidator( PROPERTY_VALIDATORS::RangeIntValidator<minZoneWidth, INT_MAX> );
|
||||
|
||||
propMgr.AddProperty( new PROPERTY<PAD, double>( _HKI( "Thermal Relief Spoke Angle" ),
|
||||
propMgr.AddProperty( new PROPERTY<PAD, double>(
|
||||
_HKI( "Thermal Relief Spoke Angle" ),
|
||||
&PAD::SetThermalSpokeAngleDegrees, &PAD::GetThermalSpokeAngleDegrees,
|
||||
PROPERTY_DISPLAY::PT_DEGREE ), groupOverrides );
|
||||
|
||||
propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Thermal Relief Gap" ),
|
||||
&PAD::SetThermalGap, &PAD::GetThermalGap,
|
||||
propMgr.AddProperty( new PROPERTY<PAD, std::optional<int>>(
|
||||
_HKI( "Thermal Relief Gap" ),
|
||||
&PAD::SetLocalThermalGapOverride, &PAD::GetLocalThermalGapOverride,
|
||||
PROPERTY_DISPLAY::PT_SIZE ), groupOverrides )
|
||||
.SetValidator( PROPERTY_VALIDATORS::PositiveIntValidator );
|
||||
|
||||
|
21
pcbnew/pad.h
21
pcbnew/pad.h
@ -594,8 +594,14 @@ public:
|
||||
* Set the width of the thermal spokes connecting the pad to a zone. If != 0 this will
|
||||
* override similar settings in the parent footprint and zone.
|
||||
*/
|
||||
void SetThermalSpokeWidth( int aWidth ) { m_padStack.ThermalSpokeWidth() = aWidth; }
|
||||
int GetThermalSpokeWidth() const { return m_padStack.ThermalSpokeWidth().value_or( 0 ); }
|
||||
void SetLocalThermalSpokeWidthOverride( std::optional<int> aWidth )
|
||||
{
|
||||
m_padStack.ThermalSpokeWidth() = aWidth;
|
||||
}
|
||||
std::optional<int> GetLocalThermalSpokeWidthOverride() const
|
||||
{
|
||||
return m_padStack.ThermalSpokeWidth();
|
||||
}
|
||||
|
||||
int GetLocalSpokeWidthOverride( wxString* aSource = nullptr ) const;
|
||||
|
||||
@ -626,7 +632,16 @@ public:
|
||||
void SetThermalGap( int aGap ) { m_padStack.ThermalGap() = aGap; }
|
||||
int GetThermalGap() const { return m_padStack.ThermalGap().value_or( 0 ); }
|
||||
|
||||
int GetLocalThermalGapOverride( wxString* aSource = nullptr ) const;
|
||||
int GetLocalThermalGapOverride( wxString* aSource ) const;
|
||||
|
||||
std::optional<int> GetLocalThermalGapOverride() const
|
||||
{
|
||||
return m_padStack.ThermalGap();
|
||||
}
|
||||
void SetLocalThermalGapOverride( const std::optional<int>& aOverride )
|
||||
{
|
||||
m_padStack.ThermalGap() = aOverride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Has meaning only for rounded rectangle pads.
|
||||
|
@ -40,9 +40,9 @@ PADSTACK::PADSTACK( BOARD_ITEM* aParent ) :
|
||||
{
|
||||
m_copperProps[PADSTACK::ALL_LAYERS].shape = SHAPE_PROPS();
|
||||
m_copperProps[PADSTACK::ALL_LAYERS].zone_connection = ZONE_CONNECTION::INHERITED;
|
||||
m_copperProps[PADSTACK::ALL_LAYERS].thermal_spoke_width = 0;
|
||||
m_copperProps[PADSTACK::ALL_LAYERS].thermal_spoke_width = std::nullopt;
|
||||
m_copperProps[PADSTACK::ALL_LAYERS].thermal_spoke_angle = ANGLE_45;
|
||||
m_copperProps[PADSTACK::ALL_LAYERS].thermal_gap = 0;
|
||||
m_copperProps[PADSTACK::ALL_LAYERS].thermal_gap = std::nullopt;
|
||||
|
||||
m_drill.shape = PAD_DRILL_SHAPE::CIRCLE;
|
||||
m_drill.start = F_Cu;
|
||||
@ -247,8 +247,8 @@ bool PADSTACK::Deserialize( const google::protobuf::Any& aContainer )
|
||||
else
|
||||
{
|
||||
CopperLayer( ALL_LAYERS ).zone_connection = ZONE_CONNECTION::INHERITED;
|
||||
CopperLayer( ALL_LAYERS ).thermal_gap = 0;
|
||||
CopperLayer( ALL_LAYERS ).thermal_spoke_width = 0;
|
||||
CopperLayer( ALL_LAYERS ).thermal_gap = std::nullopt;
|
||||
CopperLayer( ALL_LAYERS ).thermal_spoke_width = std::nullopt;
|
||||
CopperLayer( ALL_LAYERS ).thermal_spoke_angle = DefaultThermalSpokeAngleForShape( F_Cu );
|
||||
}
|
||||
|
||||
|
@ -1236,7 +1236,7 @@ PAD* CADSTAR_PCB_ARCHIVE_LOADER::getKiCadPad( const COMPONENT_PAD& aCadstarPad,
|
||||
pad->SetThermalGap( getKiCadLength( csPadcode.ReliefClearance ) );
|
||||
|
||||
if( csPadcode.ReliefWidth != UNDEFINED_VALUE )
|
||||
pad->SetThermalSpokeWidth( getKiCadLength( csPadcode.ReliefWidth ) );
|
||||
pad->SetLocalThermalSpokeWidthOverride( getKiCadLength( csPadcode.ReliefWidth ) );
|
||||
|
||||
if( csPadcode.DrillDiameter != UNDEFINED_VALUE )
|
||||
{
|
||||
|
@ -1567,12 +1567,12 @@ void PCB_IO_KICAD_LEGACY::loadPAD( FOOTPRINT* aFootprint )
|
||||
else if( TESTLINE( ".ThermalWidth" ) )
|
||||
{
|
||||
BIU tmp = biuParse( line + SZ( ".ThermalWidth" ) );
|
||||
pad->SetThermalSpokeWidth( tmp );
|
||||
pad->SetLocalThermalSpokeWidthOverride( tmp );
|
||||
}
|
||||
else if( TESTLINE( ".ThermalGap" ) )
|
||||
{
|
||||
BIU tmp = biuParse( line + SZ( ".ThermalGap" ) );
|
||||
pad->SetThermalGap( tmp );
|
||||
pad->SetLocalThermalGapOverride( tmp );
|
||||
}
|
||||
else if( TESTLINE( "$EndPAD" ) )
|
||||
{
|
||||
|
@ -1668,10 +1668,10 @@ void PCB_IO_KICAD_SEXPR::format( const PAD* aPad ) const
|
||||
static_cast<int>( aPad->GetLocalZoneConnection() ) );
|
||||
}
|
||||
|
||||
if( aPad->GetThermalSpokeWidth() != 0 )
|
||||
if( aPad->GetLocalThermalSpokeWidthOverride().has_value() )
|
||||
{
|
||||
m_out->Print( "(thermal_bridge_width %s)",
|
||||
formatInternalUnits( aPad->GetThermalSpokeWidth() ).c_str() );
|
||||
formatInternalUnits( aPad->GetLocalThermalSpokeWidthOverride().value() ).c_str() );
|
||||
}
|
||||
|
||||
EDA_ANGLE defaultThermalSpokeAngle = ANGLE_90;
|
||||
@ -1689,10 +1689,10 @@ void PCB_IO_KICAD_SEXPR::format( const PAD* aPad ) const
|
||||
EDA_UNIT_UTILS::FormatAngle( aPad->GetThermalSpokeAngle() ).c_str() );
|
||||
}
|
||||
|
||||
if( aPad->GetThermalGap() != 0 )
|
||||
if( aPad->GetLocalThermalGapOverride().has_value() )
|
||||
{
|
||||
m_out->Print( "(thermal_gap %s)",
|
||||
formatInternalUnits( aPad->GetThermalGap() ).c_str() );
|
||||
formatInternalUnits( aPad->GetLocalThermalGapOverride().value() ).c_str() );
|
||||
}
|
||||
|
||||
auto anchorShape =
|
||||
|
@ -5235,7 +5235,7 @@ PAD* PCB_IO_KICAD_SEXPR_PARSER::parsePAD( FOOTPRINT* aParent )
|
||||
|
||||
case T_thermal_width: // legacy token
|
||||
case T_thermal_bridge_width:
|
||||
pad->SetThermalSpokeWidth( parseBoardUnits( token ) );
|
||||
pad->SetLocalThermalSpokeWidthOverride( parseBoardUnits( token ) );
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
|
@ -550,8 +550,8 @@ void PCB_SHAPE::SetIsProxyItem( bool aIsProxy )
|
||||
{
|
||||
if( GetShape() == SHAPE_T::SEGMENT )
|
||||
{
|
||||
if( parentPad && parentPad->GetThermalSpokeWidth() )
|
||||
SetWidth( parentPad->GetThermalSpokeWidth() );
|
||||
if( parentPad && parentPad->GetLocalThermalSpokeWidthOverride().has_value() )
|
||||
SetWidth( parentPad->GetLocalThermalSpokeWidthOverride().value() );
|
||||
else
|
||||
SetWidth( pcbIUScale.mmToIU( ZONE_THERMAL_RELIEF_COPPER_WIDTH_MM ) );
|
||||
}
|
||||
|
@ -896,8 +896,8 @@ void PAD_TOOL::explodePad( PAD* aPad, PCB_LAYER_ID* aLayer, BOARD_COMMIT& aCommi
|
||||
|
||||
if( shape->IsProxyItem() && shape->GetShape() == SHAPE_T::SEGMENT )
|
||||
{
|
||||
if( aPad->GetThermalSpokeWidth() )
|
||||
shape->SetWidth( aPad->GetThermalSpokeWidth() );
|
||||
if( aPad->GetLocalThermalSpokeWidthOverride().has_value() )
|
||||
shape->SetWidth( aPad->GetLocalThermalSpokeWidthOverride().value() );
|
||||
else
|
||||
shape->SetWidth( pcbIUScale.mmToIU( ZONE_THERMAL_RELIEF_COPPER_WIDTH_MM ) );
|
||||
}
|
||||
|
@ -367,7 +367,8 @@ void CheckFpPad( const PAD* expected, const PAD* pad )
|
||||
BOOST_CHECK_EQUAL( expected->GetLocalClearance().value_or( 0 ),
|
||||
pad->GetLocalClearance().value_or( 0 ) );
|
||||
CHECK_ENUM_CLASS_EQUAL( expected->GetLocalZoneConnection(), pad->GetLocalZoneConnection() );
|
||||
BOOST_CHECK_EQUAL( expected->GetThermalSpokeWidth(), pad->GetThermalSpokeWidth() );
|
||||
BOOST_CHECK_EQUAL( expected->GetLocalThermalSpokeWidthOverride().value_or( 0 ),
|
||||
pad->GetLocalThermalSpokeWidthOverride().value_or( 0 ) );
|
||||
BOOST_CHECK_EQUAL( expected->GetThermalSpokeAngle(), pad->GetThermalSpokeAngle() );
|
||||
BOOST_CHECK_EQUAL( expected->GetThermalGap(), pad->GetThermalGap() );
|
||||
BOOST_CHECK_EQUAL( expected->GetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS ),
|
||||
|
Loading…
Reference in New Issue
Block a user