diff --git a/common/bitmap_info.cpp b/common/bitmap_info.cpp index 7d33458ccb..bc50e6d73d 100644 --- a/common/bitmap_info.cpp +++ b/common/bitmap_info.cpp @@ -5036,6 +5036,9 @@ void BuildBitmapInfo( std::unordered_map>& aBi aBitmapInfoCache[BITMAPS::constraint_hole_to_hole_distance].emplace_back( BITMAPS::constraint_hole_to_hole_distance, wxT( "constraint_hole_to_hole_distance.png" ), -1, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::constraint_length].emplace_back( BITMAPS::constraint_length, wxT( "constraint_length.png" ), -1, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::constraint_matched_length_diff_pair].emplace_back( BITMAPS::constraint_matched_length_diff_pair, wxT( "constraint_matched_length_diff_pair.png" ), -1, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::constraint_matched_length_diff_pair_v2].emplace_back( + BITMAPS::constraint_matched_length_diff_pair_v2, wxT( "constraint_matched_length_diff_pair_v2.png" ), -1, + wxT( "light" ) ); aBitmapInfoCache[BITMAPS::constraint_maximum_allowed_deviation].emplace_back( BITMAPS::constraint_maximum_allowed_deviation, wxT( "constraint_maximum_allowed_deviation.png" ), -1, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::constraint_maximum_via_count].emplace_back( BITMAPS::constraint_maximum_via_count, wxT( "constraint_maximum_via_count.png" ), -1, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::constraint_minimum_angular_ring].emplace_back( BITMAPS::constraint_minimum_angular_ring, wxT( "constraint_minimum_angular_ring.png" ), -1, wxT( "light" ) ); @@ -5071,6 +5074,9 @@ void BuildBitmapInfo( std::unordered_map>& aBi aBitmapInfoCache[BITMAPS::constraint_hole_to_hole_distance].emplace_back( BITMAPS::constraint_hole_to_hole_distance, wxT( "constraint_hole_to_hole_distance_dark.png" ), -1, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::constraint_length].emplace_back( BITMAPS::constraint_length, wxT( "constraint_length_dark.png" ), -1, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::constraint_matched_length_diff_pair].emplace_back( BITMAPS::constraint_matched_length_diff_pair, wxT( "constraint_matched_length_diff_pair_dark.png" ), -1, wxT( "dark" ) ); + aBitmapInfoCache[BITMAPS::constraint_matched_length_diff_pair_v2].emplace_back( + BITMAPS::constraint_matched_length_diff_pair_v2, wxT( "constraint_matched_length_diff_pair_v2_dark.png" ), + -1, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::constraint_maximum_allowed_deviation].emplace_back( BITMAPS::constraint_maximum_allowed_deviation, wxT( "constraint_maximum_allowed_deviation_dark.png" ), -1, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::constraint_maximum_via_count].emplace_back( BITMAPS::constraint_maximum_via_count, wxT( "constraint_maximum_via_count_dark.png" ), -1, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::constraint_minimum_angular_ring].emplace_back( BITMAPS::constraint_minimum_angular_ring, wxT( "constraint_minimum_angular_ring_dark.png" ), -1, wxT( "dark" ) ); diff --git a/include/bitmaps/bitmaps_list.h b/include/bitmaps/bitmaps_list.h index 728b220bec..e27ba43522 100644 --- a/include/bitmaps/bitmaps_list.h +++ b/include/bitmaps/bitmaps_list.h @@ -717,6 +717,7 @@ enum class BITMAPS : unsigned int constraint_maximum_allowed_deviation, constraint_minimum_angular_ring, constraint_matched_length_diff_pair, + constraint_matched_length_diff_pair_v2, constraint_routing_diff_pair, constraint_routing_width, constraint_clearance, diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 8947107248..7d25a59f67 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -333,6 +333,7 @@ set( PCBNEW_DRC_SRCS drc/rule_editor/drc_re_rtg_diff_pair_overlay_panel.cpp drc/rule_editor/drc_re_min_txt_ht_th_overlay_panel.cpp drc/rule_editor/drc_re_abs_length_two_overlay_panel.cpp + drc/rule_editor/drc_re_matched_length_diff_pair_overlay_panel.cpp drc/rule_editor/drc_re_via_style_overlay_panel.cpp drc/rule_editor/drc_re_numeric_input_overlay_panel.cpp drc/rule_editor/drc_re_bool_input_overlay_panel.cpp diff --git a/pcbnew/drc/rule_editor/drc_re_abs_length_two_constraint_data.h b/pcbnew/drc/rule_editor/drc_re_abs_length_two_constraint_data.h index 0655e4e4ee..a553e0640d 100644 --- a/pcbnew/drc/rule_editor/drc_re_abs_length_two_constraint_data.h +++ b/pcbnew/drc/rule_editor/drc_re_abs_length_two_constraint_data.h @@ -157,14 +157,19 @@ class DRC_RE_MATCHED_LENGTH_DIFF_PAIR_CONSTRAINT_DATA : public DRC_RE_ABSOLUTE_L public: using DRC_RE_ABSOLUTE_LENGTH_TWO_CONSTRAINT_DATA::DRC_RE_ABSOLUTE_LENGTH_TWO_CONSTRAINT_DATA; - BITMAPS GetOverlayBitmap() const override { return BITMAPS::constraint_matched_length_diff_pair; } + BITMAPS GetOverlayBitmap() const override { return BITMAPS::constraint_matched_length_diff_pair_v2; } std::vector GetFieldPositions() const override { return { - { 335 + DRC_RE_OVERLAY_XO, 365 + DRC_RE_OVERLAY_XO, 33 + DRC_RE_OVERLAY_YO, 1, wxS( "mm" ), LABEL_POSITION::RIGHT }, // min_length - { 335 + DRC_RE_OVERLAY_XO, 365 + DRC_RE_OVERLAY_XO, 103 + DRC_RE_OVERLAY_YO, 2, wxS( "mm" ), LABEL_POSITION::RIGHT }, // opt_length - { 335 + DRC_RE_OVERLAY_XO, 365 + DRC_RE_OVERLAY_XO, 173 + DRC_RE_OVERLAY_YO, 3, wxS( "mm" ), LABEL_POSITION::RIGHT }, // max_length + { 527 + DRC_RE_OVERLAY_XO, 567 + DRC_RE_OVERLAY_XO, 133 + DRC_RE_OVERLAY_YO, 1, wxS( "mm" ), + LABEL_POSITION::RIGHT }, // min_length + { 670 + DRC_RE_OVERLAY_XO, 710 + DRC_RE_OVERLAY_XO, 162 + DRC_RE_OVERLAY_YO, 2, wxS( "mm" ), + LABEL_POSITION::RIGHT }, // opt_length + { 817 + DRC_RE_OVERLAY_XO, 857 + DRC_RE_OVERLAY_XO, 190 + DRC_RE_OVERLAY_YO, 3, wxS( "mm" ), + LABEL_POSITION::RIGHT }, // max_length + { 777 + DRC_RE_OVERLAY_XO, 815 + DRC_RE_OVERLAY_XO, -3 + DRC_RE_OVERLAY_YO, 4, wxS( "mm" ), + LABEL_POSITION::RIGHT }, // max_skew }; } @@ -196,6 +201,16 @@ public: m_maxSkew = source.m_maxSkew; } + VALIDATION_RESULT Validate() const override + { + VALIDATION_RESULT result = DRC_RE_ABSOLUTE_LENGTH_TWO_CONSTRAINT_DATA::Validate(); + + if( m_maxSkew < 0 ) + result.AddError( _( "Maximum Skew must be greater than or equal to 0" ) ); + + return result; + } + private: double m_maxSkew{ 0 }; }; diff --git a/pcbnew/drc/rule_editor/drc_re_matched_length_diff_pair_overlay_panel.cpp b/pcbnew/drc/rule_editor/drc_re_matched_length_diff_pair_overlay_panel.cpp new file mode 100644 index 0000000000..db73390c22 --- /dev/null +++ b/pcbnew/drc/rule_editor/drc_re_matched_length_diff_pair_overlay_panel.cpp @@ -0,0 +1,172 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "drc_re_matched_length_diff_pair_overlay_panel.h" +#include "drc_re_abs_length_two_constraint_data.h" +#include "drc_rule_editor_utils.h" +#include "drc_re_validator_numeric_ctrl.h" + +#include +#include +#include + +#include +#include + +DRC_RE_MATCHED_LENGTH_DIFF_PAIR_OVERLAY_PANEL::DRC_RE_MATCHED_LENGTH_DIFF_PAIR_OVERLAY_PANEL( + wxWindow* aParent, DRC_RE_MATCHED_LENGTH_DIFF_PAIR_CONSTRAINT_DATA* aData, EDA_UNITS aUnits ) : + DRC_RE_BITMAP_OVERLAY_PANEL( aParent ), + m_data( aData ), + m_unitsProvider( pcbIUScale, aUnits ) +{ + SetBackgroundBitmap( aData->GetOverlayBitmap() ); + + std::vector positions = m_data->GetFieldPositions(); + + wxWindow* eventSource = nullptr; + + for( wxWindow* win = aParent; win; win = win->GetParent() ) + { + if( dynamic_cast( win ) ) + { + eventSource = win; + break; + } + } + + // Create min length field + auto* minLengthField = AddField( wxS( "min_length" ), positions[0], wxTE_CENTRE | wxTE_PROCESS_ENTER ); + m_minLengthBinder = + std::make_unique( &m_unitsProvider, eventSource, nullptr, minLengthField->GetControl(), + minLengthField->GetLabel(), false, false ); + minLengthField->SetUnitBinder( m_minLengthBinder.get() ); + minLengthField->GetControl()->SetValidator( VALIDATOR_NUMERIC_CTRL( false, false ) ); + + // Create opt length field + auto* optLengthField = AddField( wxS( "opt_length" ), positions[1], wxTE_CENTRE | wxTE_PROCESS_ENTER ); + m_optLengthBinder = + std::make_unique( &m_unitsProvider, eventSource, nullptr, optLengthField->GetControl(), + optLengthField->GetLabel(), false, false ); + optLengthField->SetUnitBinder( m_optLengthBinder.get() ); + optLengthField->GetControl()->SetValidator( VALIDATOR_NUMERIC_CTRL( false, false ) ); + + // Create max length field + auto* maxLengthField = AddField( wxS( "max_length" ), positions[2], wxTE_CENTRE | wxTE_PROCESS_ENTER ); + m_maxLengthBinder = + std::make_unique( &m_unitsProvider, eventSource, nullptr, maxLengthField->GetControl(), + maxLengthField->GetLabel(), false, false ); + maxLengthField->SetUnitBinder( m_maxLengthBinder.get() ); + maxLengthField->GetControl()->SetValidator( VALIDATOR_NUMERIC_CTRL( false, false ) ); + + // Create max skew field + auto* maxSkewField = AddField( wxS( "max_skew" ), positions[3], wxTE_CENTRE | wxTE_PROCESS_ENTER ); + m_maxSkewBinder = std::make_unique( &m_unitsProvider, eventSource, nullptr, maxSkewField->GetControl(), + maxSkewField->GetLabel(), false, false ); + maxSkewField->SetUnitBinder( m_maxSkewBinder.get() ); + maxSkewField->GetControl()->SetValidator( VALIDATOR_NUMERIC_CTRL( false, false ) ); + + auto notifyModified = [this]( wxCommandEvent& ) + { + RULE_EDITOR_DIALOG_BASE* dlg = RULE_EDITOR_DIALOG_BASE::GetDialog( this ); + if( dlg ) + dlg->SetModified(); + }; + + minLengthField->GetControl()->Bind( wxEVT_TEXT, notifyModified ); + optLengthField->GetControl()->Bind( wxEVT_TEXT, notifyModified ); + maxLengthField->GetControl()->Bind( wxEVT_TEXT, notifyModified ); + maxSkewField->GetControl()->Bind( wxEVT_TEXT, notifyModified ); + + auto notifySave = [this]( wxCommandEvent& aEvent ) + { + RULE_EDITOR_DIALOG_BASE* dlg = RULE_EDITOR_DIALOG_BASE::GetDialog( this ); + if( dlg ) + dlg->OnSave( aEvent ); + }; + + minLengthField->GetControl()->Bind( wxEVT_TEXT_ENTER, notifySave ); + optLengthField->GetControl()->Bind( wxEVT_TEXT_ENTER, notifySave ); + maxLengthField->GetControl()->Bind( wxEVT_TEXT_ENTER, notifySave ); + maxSkewField->GetControl()->Bind( wxEVT_TEXT_ENTER, notifySave ); + + // Position all fields and update the panel layout + PositionFields(); + TransferDataToWindow(); +} + + +bool DRC_RE_MATCHED_LENGTH_DIFF_PAIR_OVERLAY_PANEL::TransferDataToWindow() +{ + if( !m_data ) + return false; + + m_minLengthBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetMinimumLength() ) ); + m_optLengthBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetOptimumLength() ) ); + m_maxLengthBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetMaximumLength() ) ); + m_maxSkewBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetMaxSkew() ) ); + + return true; +} + + +bool DRC_RE_MATCHED_LENGTH_DIFF_PAIR_OVERLAY_PANEL::TransferDataFromWindow() +{ + if( !m_data ) + return false; + + m_data->SetMinimumLength( pcbIUScale.IUTomm( m_minLengthBinder->GetDoubleValue() ) ); + m_data->SetOptimumLength( pcbIUScale.IUTomm( m_optLengthBinder->GetDoubleValue() ) ); + m_data->SetMaximumLength( pcbIUScale.IUTomm( m_maxLengthBinder->GetDoubleValue() ) ); + m_data->SetMaxSkew( pcbIUScale.IUTomm( m_maxSkewBinder->GetDoubleValue() ) ); + + return true; +} + + +bool DRC_RE_MATCHED_LENGTH_DIFF_PAIR_OVERLAY_PANEL::ValidateInputs( int* aErrorCount, wxString* aValidationMessage ) +{ + TransferDataFromWindow(); + + VALIDATION_RESULT result = m_data->Validate(); + + if( !result.isValid ) + { + *aErrorCount = result.errors.size(); + + for( size_t i = 0; i < result.errors.size(); i++ ) + *aValidationMessage += DRC_RULE_EDITOR_UTILS::FormatErrorMessage( i + 1, result.errors[i] ); + + return false; + } + + return true; +} + + +wxString DRC_RE_MATCHED_LENGTH_DIFF_PAIR_OVERLAY_PANEL::GenerateRule( const RULE_GENERATION_CONTEXT& aContext ) +{ + if( !m_data ) + return wxEmptyString; + + return m_data->GenerateRule( aContext ); +} diff --git a/pcbnew/drc/rule_editor/drc_re_matched_length_diff_pair_overlay_panel.h b/pcbnew/drc/rule_editor/drc_re_matched_length_diff_pair_overlay_panel.h new file mode 100644 index 0000000000..742d07a1d9 --- /dev/null +++ b/pcbnew/drc/rule_editor/drc_re_matched_length_diff_pair_overlay_panel.h @@ -0,0 +1,65 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef DRC_RE_MATCHED_LENGTH_DIFF_PAIR_OVERLAY_PANEL_H +#define DRC_RE_MATCHED_LENGTH_DIFF_PAIR_OVERLAY_PANEL_H + +#include + +#include + +#include "drc_re_bitmap_overlay_panel.h" + +enum class EDA_UNITS; + +class DRC_RE_MATCHED_LENGTH_DIFF_PAIR_CONSTRAINT_DATA; +class UNIT_BINDER; + + +class DRC_RE_MATCHED_LENGTH_DIFF_PAIR_OVERLAY_PANEL : public DRC_RE_BITMAP_OVERLAY_PANEL +{ +public: + DRC_RE_MATCHED_LENGTH_DIFF_PAIR_OVERLAY_PANEL( wxWindow* aParent, + DRC_RE_MATCHED_LENGTH_DIFF_PAIR_CONSTRAINT_DATA* aData, + EDA_UNITS aUnits ); + + ~DRC_RE_MATCHED_LENGTH_DIFF_PAIR_OVERLAY_PANEL() override = default; + + bool TransferDataToWindow() override; + bool TransferDataFromWindow() override; + + bool ValidateInputs( int* aErrorCount, wxString* aValidationMessage ) override; + wxString GenerateRule( const RULE_GENERATION_CONTEXT& aContext ) override; + +private: + DRC_RE_MATCHED_LENGTH_DIFF_PAIR_CONSTRAINT_DATA* m_data; + + UNITS_PROVIDER m_unitsProvider; + + std::unique_ptr m_minLengthBinder; + std::unique_ptr m_optLengthBinder; + std::unique_ptr m_maxLengthBinder; + std::unique_ptr m_maxSkewBinder; +}; + +#endif // DRC_RE_MATCHED_LENGTH_DIFF_PAIR_OVERLAY_PANEL_H diff --git a/pcbnew/drc/rule_editor/panel_drc_rule_editor.cpp b/pcbnew/drc/rule_editor/panel_drc_rule_editor.cpp index 6ca28b7704..aefdb39a9a 100644 --- a/pcbnew/drc/rule_editor/panel_drc_rule_editor.cpp +++ b/pcbnew/drc/rule_editor/panel_drc_rule_editor.cpp @@ -61,6 +61,7 @@ #include "drc_re_numeric_input_overlay_panel.h" #include "drc_re_bool_input_overlay_panel.h" #include "drc_re_allowed_orientation_overlay_panel.h" +#include "drc_re_matched_length_diff_pair_overlay_panel.h" #include "drc_re_vias_under_smd_overlay_panel.h" #include "drc_re_permitted_layers_overlay_panel.h" @@ -382,6 +383,11 @@ PANEL_DRC_RULE_EDITOR::getConstraintPanel( wxWindow* aParent, const DRC_RULE_EDI aParent, dynamic_pointer_cast( m_constraintData ) ); case MATCHED_LENGTH_DIFF_PAIR: + return new DRC_RE_MATCHED_LENGTH_DIFF_PAIR_OVERLAY_PANEL( + aParent, + dynamic_pointer_cast( m_constraintData ).get(), + units ); + case ABSOLUTE_LENGTH: return new DRC_RE_ABS_LENGTH_TWO_OVERLAY_PANEL( aParent, diff --git a/resources/bitmaps_png/CMakeLists.txt b/resources/bitmaps_png/CMakeLists.txt index 5e1ca82e60..a73ffe0a70 100644 --- a/resources/bitmaps_png/CMakeLists.txt +++ b/resources/bitmaps_png/CMakeLists.txt @@ -730,6 +730,7 @@ set( BMAPS_CONSTRAINTS hole-to-hole-distance length matched-length-diff-pair + matched-length-diff-pair-v2 maximum-allowed-deviation maximum-via-count minimum-angular-ring diff --git a/resources/bitmaps_png/generate_themed_constraints.py b/resources/bitmaps_png/generate_themed_constraints.py index 325c8b4a4b..a0a1639e8f 100644 --- a/resources/bitmaps_png/generate_themed_constraints.py +++ b/resources/bitmaps_png/generate_themed_constraints.py @@ -52,6 +52,7 @@ CONSTRAINT_FILES = { 'solderpaste-expansion.svg': 'solderpaste-expansion.svg', 'maximum_allowed_deviation.svg': 'maximum-allowed-deviation.svg', 'matched-lenght-diff-pair.svg': 'matched-length-diff-pair.svg', + "matched-length-diff-pair-v2.svg": "matched-length-diff-pair-v2.svg", } diff --git a/resources/bitmaps_png/png/constraint_matched_length_diff_pair_v2.png b/resources/bitmaps_png/png/constraint_matched_length_diff_pair_v2.png new file mode 100644 index 0000000000..5e81422e0d Binary files /dev/null and b/resources/bitmaps_png/png/constraint_matched_length_diff_pair_v2.png differ diff --git a/resources/bitmaps_png/png/constraint_matched_length_diff_pair_v2_dark.png b/resources/bitmaps_png/png/constraint_matched_length_diff_pair_v2_dark.png new file mode 100644 index 0000000000..5e81422e0d Binary files /dev/null and b/resources/bitmaps_png/png/constraint_matched_length_diff_pair_v2_dark.png differ diff --git a/resources/bitmaps_png/sources/constraints/matched-length-diff-pair-v2.svg b/resources/bitmaps_png/sources/constraints/matched-length-diff-pair-v2.svg new file mode 100644 index 0000000000..d61a7d22f0 --- /dev/null +++ b/resources/bitmaps_png/sources/constraints/matched-length-diff-pair-v2.svg @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/bitmaps_png/sources/dark/constraints/matched-length-diff-pair-v2.svg b/resources/bitmaps_png/sources/dark/constraints/matched-length-diff-pair-v2.svg new file mode 100644 index 0000000000..9873acd10a --- /dev/null +++ b/resources/bitmaps_png/sources/dark/constraints/matched-length-diff-pair-v2.svg @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/bitmaps_png/sources/light/constraints/matched-length-diff-pair-v2.svg b/resources/bitmaps_png/sources/light/constraints/matched-length-diff-pair-v2.svg new file mode 100644 index 0000000000..d61a7d22f0 --- /dev/null +++ b/resources/bitmaps_png/sources/light/constraints/matched-length-diff-pair-v2.svg @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +