Reimplement footprint checking on top of DRC architecture.

This allows Import Netlist and Update PCB from Schematic to
share the same checking code, and expose it through the DRC
dialog.

Fixes: lp:1685516
* https://bugs.launchpad.net/kicad/+bug/1685516

Fixes: lp:1809293
* https://bugs.launchpad.net/kicad/+bug/1809293
This commit is contained in:
Jeff Young 2019-03-28 19:30:51 +00:00
parent 77f15eeeaf
commit a1c162e59f
12 changed files with 1330 additions and 649 deletions

View File

@ -79,6 +79,13 @@ public:
}
DRC_ITEM( int aErrorCode, const wxString& aMainText )
{
SetData( aErrorCode, aMainText, wxPoint() );
SetShowNoCoordinate();
}
/**
* Function SetData
* initialize all data in item

View File

@ -51,8 +51,9 @@
*/
// Keywords for read and write config
#define RefillZonesBeforeDrcKey wxT( "RefillZonesBeforeDrc" )
#define DrcTrackToZoneTestKey wxT( "DrcTrackToZoneTest" )
#define DrcRefillZonesKey wxT( "RefillZonesBeforeDrc" )
#define DrcTrackToZoneTestKey wxT( "DrcTrackToZoneTest" )
#define DrcTestFootprintsKey wxT( "DrcTestFootprints" )
DIALOG_DRC_CONTROL::DIALOG_DRC_CONTROL( DRC* aTester, PCB_EDIT_FRAME* aEditorFrame,
@ -76,7 +77,6 @@ DIALOG_DRC_CONTROL::DIALOG_DRC_CONTROL( DRC* aTester, PCB_EDIT_FRAME* aEditorFra
// We use a sdbSizer here to get the order right, which is platform-dependent
m_sdbSizer1OK->SetLabel( _( "Run DRC" ) );
m_sdbSizer1Apply->SetLabel( _( "List Unconnected" ) );
m_sdbSizer1Cancel->SetLabel( _( "Close" ) );
m_sizerButtons->Layout();
@ -93,6 +93,10 @@ DIALOG_DRC_CONTROL::DIALOG_DRC_CONTROL( DRC* aTester, PCB_EDIT_FRAME* aEditorFra
wxMouseEventHandler( DIALOG_DRC_CONTROL::OnLeftDClickUnconnected ), NULL, this );
m_UnconnectedListBox->Connect( ID_UNCONNECTED_LIST, wxEVT_RIGHT_UP,
wxMouseEventHandler( DIALOG_DRC_CONTROL::OnRightUpUnconnected ), NULL, this );
m_FootprintsListBox->Connect( ID_FOOTPRINTS_LIST, wxEVT_LEFT_DCLICK,
wxMouseEventHandler( DIALOG_DRC_CONTROL::OnLeftDClickFootprints ), NULL, this );
m_FootprintsListBox->Connect( ID_FOOTPRINTS_LIST, wxEVT_RIGHT_UP,
wxMouseEventHandler( DIALOG_DRC_CONTROL::OnRightUpFootprints ), NULL, this );
// Now all widgets have the size fixed, call FinishDialogSettings
FinishDialogSettings();
@ -101,8 +105,9 @@ DIALOG_DRC_CONTROL::DIALOG_DRC_CONTROL( DRC* aTester, PCB_EDIT_FRAME* aEditorFra
DIALOG_DRC_CONTROL::~DIALOG_DRC_CONTROL()
{
m_config->Write( RefillZonesBeforeDrcKey, m_cbRefillZones->GetValue() );
m_config->Write( DrcRefillZonesKey, m_cbRefillZones->GetValue() );
m_config->Write( DrcTrackToZoneTestKey, m_cbReportTracksToZonesErrors->GetValue() );
m_config->Write( DrcTestFootprintsKey, m_cbTestFootprints->GetValue() );
// Disconnect events
m_ClearanceListBox->Disconnect( ID_CLEARANCE_LIST, wxEVT_LEFT_DCLICK,
@ -110,9 +115,13 @@ DIALOG_DRC_CONTROL::~DIALOG_DRC_CONTROL()
m_ClearanceListBox->Disconnect( ID_CLEARANCE_LIST, wxEVT_RIGHT_UP,
wxMouseEventHandler( DIALOG_DRC_CONTROL::OnRightUpClearance ), NULL, this );
m_UnconnectedListBox->Disconnect( ID_UNCONNECTED_LIST, wxEVT_LEFT_DCLICK,
wxMouseEventHandler( DIALOG_DRC_CONTROL::OnLeftDClickUnconnected ), NULL, this );
wxMouseEventHandler( DIALOG_DRC_CONTROL::OnLeftDClickUnconnected ), NULL, this );
m_UnconnectedListBox->Disconnect( ID_UNCONNECTED_LIST, wxEVT_RIGHT_UP,
wxMouseEventHandler( DIALOG_DRC_CONTROL::OnRightUpUnconnected ), NULL, this );
wxMouseEventHandler( DIALOG_DRC_CONTROL::OnRightUpUnconnected ), NULL, this );
m_FootprintsListBox->Disconnect( ID_FOOTPRINTS_LIST, wxEVT_LEFT_DCLICK,
wxMouseEventHandler( DIALOG_DRC_CONTROL::OnLeftDClickFootprints ), NULL, this );
m_FootprintsListBox->Disconnect( ID_FOOTPRINTS_LIST, wxEVT_RIGHT_UP,
wxMouseEventHandler( DIALOG_DRC_CONTROL::OnRightUpFootprints ), NULL, this );
}
@ -149,6 +158,7 @@ void DIALOG_DRC_CONTROL::InitValues()
{
m_markersTitleTemplate = m_Notebook->GetPageText( 0 );
m_unconnectedTitleTemplate = m_Notebook->GetPageText( 1 );
m_footprintsTitleTemplate = m_Notebook->GetPageText( 2 );
m_DeleteCurrentMarkerButton->Enable( false );
@ -156,10 +166,12 @@ void DIALOG_DRC_CONTROL::InitValues()
// read options
bool value;
m_config->Read( RefillZonesBeforeDrcKey, &value, false );
m_config->Read( DrcRefillZonesKey, &value, false );
m_cbRefillZones->SetValue( value );
m_config->Read( DrcTrackToZoneTestKey, &value, false );
m_cbReportTracksToZonesErrors->SetValue( value );
m_config->Read( DrcTestFootprintsKey, &value, false );
m_cbTestFootprints->SetValue( value );
Layout(); // adding the units above expanded Clearance text, now resize.
@ -213,14 +225,13 @@ void DIALOG_DRC_CONTROL::OnStartdrcClick( wxCommandEvent& event )
}
SetDrcParmeters();
m_tester->SetSettings( true, // Pad to pad DRC test enabled
true, // unconnected pads DRC test enabled
// DRC test for zones enabled/disabled:
m_cbReportTracksToZonesErrors->GetValue(),
true, // DRC test for keepout areas enabled
m_cbRefillZones->GetValue(),
m_cbReportAllTrackErrors->GetValue(),
reportName, make_report );
m_tester->m_doZonesTest = m_cbReportTracksToZonesErrors->GetValue();
m_tester->m_rptFilename = reportName;
m_tester->m_doCreateRptFile = make_report;
m_tester->m_refillZones = m_cbRefillZones->GetValue();
m_tester->m_drcInLegacyRoutingMode = false;
m_tester->m_reportAllTrackErrors = m_cbReportAllTrackErrors->GetValue();
m_tester->m_testFootprints = m_cbTestFootprints->GetValue();
DelDRCMarkers();
@ -264,71 +275,6 @@ void DIALOG_DRC_CONTROL::OnDeleteAllClick( wxCommandEvent& event )
}
void DIALOG_DRC_CONTROL::OnListUnconnectedClick( wxCommandEvent& event )
{
wxString reportName, msg;
bool make_report = m_CreateRptCtrl->IsChecked();
if( make_report ) // Create a file rpt
{
reportName = m_RptFilenameCtrl->GetValue();
if( reportName.IsEmpty() )
{
wxCommandEvent junk;
OnButtonBrowseRptFileClick( junk );
}
if( !reportName.IsEmpty() )
reportName = makeValidFileNameReport();
}
SetDrcParmeters();
m_tester->SetSettings( true, // Pad to pad DRC test enabled
true, // unconnected pads DRC test enabled
true, // DRC test for zones enabled
true, // DRC test for keepout areas enabled
m_cbRefillZones->GetValue(),
m_cbReportAllTrackErrors->GetValue(),
reportName, make_report );
DelDRCMarkers();
wxBeginBusyCursor();
m_Messages->Clear();
m_tester->ListUnconnectedPads();
m_Notebook->ChangeSelection( 1 ); // display the "Unconnected" tab
// Generate the report
if( !reportName.IsEmpty() )
{
if( writeReport( reportName ) )
{
msg.Printf( _( "Report file \"%s\" created" ), GetChars( reportName ) );
wxMessageDialog popupWindow( this, msg, _( "Disk File Report Completed" ) );
popupWindow.ShowModal();
}
else
{
msg.Printf( _( "Unable to create report file \"%s\"" ), GetChars( reportName ) );
DisplayError( this, msg );
}
}
UpdateDisplayedCounts();
wxEndBusyCursor();
/* there is currently nothing visible on the DrawPanel for unconnected pads
* RedrawDrawPanel();
*/
}
void DIALOG_DRC_CONTROL::OnButtonBrowseRptFileClick( wxCommandEvent& )
{
wxFileName fn = m_brdEditor->GetBoard()->GetFileName();
@ -409,6 +355,17 @@ void DIALOG_DRC_CONTROL::OnLeftDClickClearance( wxMouseEvent& event )
}
void DIALOG_DRC_CONTROL::OnRightUpFootprints( wxMouseEvent& event )
{
// popup menu to go to either of the items listed in the DRC_ITEM.
int selection = m_FootprintsListBox->GetSelection();
if( selection != wxNOT_FOUND )
doSelectionMenu( m_FootprintsListBox->GetItem( selection ) );
}
void DIALOG_DRC_CONTROL::OnRightUpUnconnected( wxMouseEvent& event )
{
// popup menu to go to either of the items listed in the DRC_ITEM.
@ -447,6 +404,37 @@ void DIALOG_DRC_CONTROL::doSelectionMenu( const DRC_ITEM* aItem )
}
void DIALOG_DRC_CONTROL::OnLeftDClickFootprints( wxMouseEvent& event )
{
event.Skip();
int selection = m_FootprintsListBox->GetSelection();
if( selection != wxNOT_FOUND )
{
// Find the selected DRC_ITEM in the listbox, position cursor there.
// Then hide the dialog.
const DRC_ITEM* item = m_FootprintsListBox->GetItem( selection );
if( item )
{
// When selecting a item, center it on GAL and just move the graphic
// cursor in legacy mode gives the best result
bool center = m_brdEditor->IsGalCanvasActive() ? true : false;
m_brdEditor->FocusOnLocation( item->GetPointA(), true, center );
if( !IsModal() )
{
Show( false );
// We do not want the clarify selection popup when releasing the
// left button in the main window
m_brdEditor->SkipNextLeftButtonReleaseEvent();
}
}
}
}
void DIALOG_DRC_CONTROL::OnLeftDClickUnconnected( wxMouseEvent& event )
{
event.Skip();
@ -484,7 +472,8 @@ void DIALOG_DRC_CONTROL::OnLeftDClickUnconnected( wxMouseEvent& event )
void DIALOG_DRC_CONTROL::OnChangingMarkerList( wxNotebookEvent& event )
{
// Shouldn't be necessary, but is on at least OSX
m_Notebook->ChangeSelection( event.GetSelection() );
if( event.GetSelection() >= 0 )
m_Notebook->ChangeSelection( (unsigned) event.GetSelection() );
m_DeleteCurrentMarkerButton->Enable( false );
m_ClearanceListBox->SetSelection( -1 );
@ -548,6 +537,32 @@ void DIALOG_DRC_CONTROL::OnUnconnectedSelectionEvent( wxCommandEvent& event )
}
void DIALOG_DRC_CONTROL::OnFootprintsSelectionEvent( wxCommandEvent& event )
{
int selection = event.GetSelection();
if( selection != wxNOT_FOUND )
{
// until a MARKER is selected, this button is not enabled.
m_DeleteCurrentMarkerButton->Enable( true );
// Find the selected DRC_ITEM in the listbox, position cursor there.
const DRC_ITEM* item = m_FootprintsListBox->GetItem( selection );
if( item )
{
// When selecting a item, center it on GAL and just move the graphic
// cursor in legacy mode gives the best result
bool center = m_brdEditor->IsGalCanvasActive() ? true : false;
m_brdEditor->FocusOnLocation( item->GetPointA(), false, center );
RedrawDrawPanel();
}
}
event.Skip();
}
void DIALOG_DRC_CONTROL::RedrawDrawPanel()
{
WINDOW_THAWER thawer( m_brdEditor );
@ -667,10 +682,37 @@ void DIALOG_DRC_CONTROL::OnDeleteOneClick( wxCommandEvent& event )
void DIALOG_DRC_CONTROL::UpdateDisplayedCounts()
{
int marker_count = m_ClearanceListBox->GetItemCount();
int unconnected_count = m_UnconnectedListBox->GetItemCount();
wxString msg;
m_Notebook->SetPageText( 0, wxString::Format( m_markersTitleTemplate, marker_count ) );
m_Notebook->SetPageText( 1, wxString::Format( m_unconnectedTitleTemplate, unconnected_count ) );
if( m_tester->m_drcRun )
{
msg.sprintf( m_markersTitleTemplate, (int) m_ClearanceListBox->GetItemCount() );
m_Notebook->SetPageText( 0, msg );
msg.sprintf( m_unconnectedTitleTemplate, (int) m_UnconnectedListBox->GetItemCount() );
m_Notebook->SetPageText( 1, msg );
if( m_tester->m_footprintsTested )
msg.sprintf( m_footprintsTitleTemplate, (int) m_FootprintsListBox->GetItemCount() );
else
{
msg = m_footprintsTitleTemplate;
msg.Replace( wxT( "%d" ), _( "not run" ) );
}
m_Notebook->SetPageText( 2, msg );
}
else
{
msg = m_markersTitleTemplate;
msg.Replace( wxT( "(%d)" ), wxEmptyString );
m_Notebook->SetPageText( 0, msg );
msg = m_unconnectedTitleTemplate;
msg.Replace( wxT( "(%d)" ), wxEmptyString );
m_Notebook->SetPageText( 1, msg );
msg = m_footprintsTitleTemplate;
msg.Replace( wxT( "(%d)" ), wxEmptyString );
m_Notebook->SetPageText( 2, msg );
}
}

View File

@ -106,9 +106,6 @@ private:
/// wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_STARTDRC
void OnStartdrcClick( wxCommandEvent& event ) override;
/// wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_LIST_UNCONNECTED
void OnListUnconnectedClick( wxCommandEvent& event ) override;
/// wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_DELETE_ALL
void OnDeleteAllClick( wxCommandEvent& event ) override;
@ -127,6 +124,12 @@ private:
/// wxEVT_RIGHT_UP event handler for ID_UNCONNECTED_LIST
void OnRightUpUnconnected( wxMouseEvent& event ) override;
/// wxEVT_LEFT_DCLICK event handler for ID_FOOTPRINTS_LIST
void OnLeftDClickFootprints( wxMouseEvent& event ) override;
/// wxEVT_RIGHT_UP event handler for ID_FOOTPRINTS_LIST
void OnRightUpFootprints( wxMouseEvent& event ) override;
/// wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_CANCEL
void OnCancelClick( wxCommandEvent& event ) override;
@ -136,6 +139,7 @@ private:
void OnMarkerSelectionEvent( wxCommandEvent& event ) override;
void OnUnconnectedSelectionEvent( wxCommandEvent& event ) override;
void OnFootprintsSelectionEvent( wxCommandEvent& event ) override;
void OnChangingMarkerList( wxNotebookEvent& event ) override;
void DelDRCMarkers();
@ -152,6 +156,7 @@ private:
wxString m_markersTitleTemplate;
wxString m_unconnectedTitleTemplate;
wxString m_footprintsTitleTemplate;
UNIT_BINDER m_trackMinWidth;
UNIT_BINDER m_viaMinSize;

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Dec 1 2018)
// C++ code generated with wxFormBuilder (version Dec 30 2017)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -14,214 +14,215 @@
DIALOG_DRC_CONTROL_BASE::DIALOG_DRC_CONTROL_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
wxBoxSizer* m_MainSizer;
m_MainSizer = new wxBoxSizer( wxVERTICAL );
wxGridBagSizer* gbSizer1;
gbSizer1 = new wxGridBagSizer( 0, 10 );
gbSizer1->SetFlexibleDirection( wxBOTH );
gbSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
wxBoxSizer* bSizerOptions;
bSizerOptions = new wxBoxSizer( wxVERTICAL );
wxFlexGridSizer* fgMinValuesSizer;
fgMinValuesSizer = new wxFlexGridSizer( 4, 3, 0, 0 );
fgMinValuesSizer->AddGrowableCol( 1 );
fgMinValuesSizer->SetFlexibleDirection( wxHORIZONTAL );
fgMinValuesSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
m_ClearanceTitle = new wxStaticText( this, wxID_ANY, _("Clearance:"), wxDefaultPosition, wxDefaultSize, 0 );
m_ClearanceTitle->Wrap( -1 );
fgMinValuesSizer->Add( m_ClearanceTitle, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
m_SetClearance = new wxTextCtrl( this, wxID_ANY, _("by Netclass"), wxDefaultPosition, wxDefaultSize, 0 );
m_SetClearance->Enable( false );
fgMinValuesSizer->Add( m_SetClearance, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 3 );
fgMinValuesSizer->Add( 0, 0, 0, 0, 5 );
m_TrackMinWidthTitle = new wxStaticText( this, wxID_ANY, _("Minimum track width:"), wxDefaultPosition, wxDefaultSize, 0 );
m_TrackMinWidthTitle->Wrap( -1 );
m_TrackMinWidthTitle->SetToolTip( _("Enter the minimum acceptable value for a track width") );
fgMinValuesSizer->Add( m_TrackMinWidthTitle, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxLEFT, 5 );
m_SetTrackMinWidthCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgMinValuesSizer->Add( m_SetTrackMinWidthCtrl, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 3 );
m_TrackMinWidthUnit = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
m_TrackMinWidthUnit->Wrap( -1 );
m_TrackMinWidthUnit->SetToolTip( _("Enter the minimum acceptable value for a track width") );
fgMinValuesSizer->Add( m_TrackMinWidthUnit, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
m_ViaMinTitle = new wxStaticText( this, wxID_ANY, _("Minimum via size:"), wxDefaultPosition, wxDefaultSize, 0 );
m_ViaMinTitle->Wrap( -1 );
m_ViaMinTitle->SetHelpText( _("Enter the minimum acceptable diameter for a standard via") );
fgMinValuesSizer->Add( m_ViaMinTitle, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
m_SetViaMinSizeCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgMinValuesSizer->Add( m_SetViaMinSizeCtrl, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL, 3 );
m_ViaMinUnit = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
m_ViaMinUnit->Wrap( -1 );
m_ViaMinUnit->SetHelpText( _("Enter the minimum acceptable diameter for a standard via") );
fgMinValuesSizer->Add( m_ViaMinUnit, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
m_MicroViaMinTitle = new wxStaticText( this, wxID_ANY, _("Minimum uVia size:"), wxDefaultPosition, wxDefaultSize, 0 );
m_MicroViaMinTitle->Wrap( -1 );
m_MicroViaMinTitle->SetToolTip( _("Enter the minimum acceptable diameter for a micro via") );
fgMinValuesSizer->Add( m_MicroViaMinTitle, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
m_SetMicroViakMinSizeCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgMinValuesSizer->Add( m_SetMicroViakMinSizeCtrl, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 3 );
m_MicroViaMinUnit = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
m_MicroViaMinUnit->Wrap( -1 );
m_MicroViaMinUnit->SetToolTip( _("Enter the minimum acceptable diameter for a micro via") );
fgMinValuesSizer->Add( m_MicroViaMinUnit, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
bSizerOptions->Add( fgMinValuesSizer, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 );
wxBoxSizer* bSizerOptSettings;
bSizerOptSettings = new wxBoxSizer( wxVERTICAL );
m_cbRefillZones = new wxCheckBox( this, wxID_ANY, _("Refill all zones before performing DRC"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerOptSettings->Add( m_cbRefillZones, 0, wxALL, 5 );
m_cbReportAllTrackErrors = new wxCheckBox( this, wxID_ANY, _("Report all errors for tracks (slower)"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbReportAllTrackErrors->SetToolTip( _("If selected, all DRC violations for tracks will be reported. This can be slow for complicated designs.\n\nIf unselected, only the first DRC violation will be reported for each track connection.") );
bSizerOptSettings->Add( m_cbReportAllTrackErrors, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
m_cbReportTracksToZonesErrors = new wxCheckBox( this, wxID_ANY, _("Test tracks against filled copper areas (very slow)"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbReportTracksToZonesErrors->SetToolTip( _("If selected, tracks will be tested against copper zones. \nIf copper zones are up to date, this test should be not needed.\n\nThis test can be *very slow* for complicated designs.") );
bSizerOptSettings->Add( m_cbReportTracksToZonesErrors, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
m_cbTestFootprints = new wxCheckBox( this, wxID_ANY, _("Test footprints against schematic"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerOptSettings->Add( m_cbTestFootprints, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
bSizerOptions->Add( bSizerOptSettings, 1, wxEXPAND, 5 );
gbSizer1->Add( bSizerOptions, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
wxBoxSizer* bSizerMessages;
bSizerMessages = new wxBoxSizer( wxVERTICAL );
m_messagesLabel = new wxStaticText( this, wxID_ANY, _("Messages"), wxDefaultPosition, wxDefaultSize, 0 );
m_messagesLabel->Wrap( -1 );
bSizerMessages->Add( m_messagesLabel, 0, wxLEFT|wxRIGHT|wxTOP, 5 );
m_Messages = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxTE_MULTILINE|wxTE_READONLY );
m_Messages->SetMinSize( wxSize( 280,-1 ) );
bSizerMessages->Add( m_Messages, 1, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 2 );
gbSizer1->Add( bSizerMessages, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
wxFlexGridSizer* fgSizerRpt;
fgSizerRpt = new wxFlexGridSizer( 0, 3, 0, 0 );
fgSizerRpt->AddGrowableCol( 1 );
fgSizerRpt->SetFlexibleDirection( wxBOTH );
fgSizerRpt->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
m_CreateRptCtrl = new wxCheckBox( this, ID_CHECKBOX_RPT_FILE, _("Create report file:"), wxDefaultPosition, wxDefaultSize, 0 );
m_CreateRptCtrl->SetToolTip( _("Enable writing report to this file") );
fgSizerRpt->Add( m_CreateRptCtrl, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 10 );
m_RptFilenameCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_RptFilenameCtrl->SetToolTip( _("Enter the report filename") );
m_RptFilenameCtrl->SetMinSize( wxSize( 180,-1 ) );
fgSizerRpt->Add( m_RptFilenameCtrl, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxTOP|wxBOTTOM, 3 );
m_BrowseButton = new wxBitmapButton( this, ID_BUTTON_BROWSE_RPT_FILE, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
m_BrowseButton = new wxBitmapButton( this, ID_BUTTON_BROWSE_RPT_FILE, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
m_BrowseButton->SetMinSize( wxSize( 30,28 ) );
fgSizerRpt->Add( m_BrowseButton, 0, wxALIGN_CENTER_VERTICAL, 2 );
gbSizer1->Add( fgSizerRpt, wxGBPosition( 1, 0 ), wxGBSpan( 1, 3 ), wxEXPAND|wxTOP|wxRIGHT, 7 );
gbSizer1->AddGrowableCol( 0 );
gbSizer1->AddGrowableCol( 1 );
m_MainSizer->Add( gbSizer1, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
m_Notebook = new wxNotebook( this, ID_NOTEBOOK1, wxDefaultPosition, wxDefaultSize, 0 );
m_Notebook->SetMinSize( wxSize( 640,280 ) );
m_panelClearanceListBox = new wxPanel( m_Notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizeClearanceBox;
bSizeClearanceBox = new wxBoxSizer( wxVERTICAL );
m_ClearanceListBox = new DRCLISTBOX( m_panelClearanceListBox, ID_CLEARANCE_LIST, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 );
m_panelViolations = new wxPanel( m_Notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizerViolationsBox;
bSizerViolationsBox = new wxBoxSizer( wxVERTICAL );
m_ClearanceListBox = new DRCLISTBOX( m_panelViolations, ID_CLEARANCE_LIST, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 );
m_ClearanceListBox->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
m_ClearanceListBox->SetToolTip( _("Left-click to center on problem marker. Right-click to highlight items.") );
bSizeClearanceBox->Add( m_ClearanceListBox, 1, wxEXPAND|wxALL, 5 );
m_panelClearanceListBox->SetSizer( bSizeClearanceBox );
m_panelClearanceListBox->Layout();
bSizeClearanceBox->Fit( m_panelClearanceListBox );
m_Notebook->AddPage( m_panelClearanceListBox, _("Problems / Markers (%d)"), true );
m_panelUnconnectedBox = new wxPanel( m_Notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
bSizerViolationsBox->Add( m_ClearanceListBox, 1, wxEXPAND|wxALL, 5 );
m_panelViolations->SetSizer( bSizerViolationsBox );
m_panelViolations->Layout();
bSizerViolationsBox->Fit( m_panelViolations );
m_Notebook->AddPage( m_panelViolations, _("Violations / Markers (%d)"), true );
m_panelUnconnectedItems = new wxPanel( m_Notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizerUnconnectedBox;
bSizerUnconnectedBox = new wxBoxSizer( wxVERTICAL );
m_UnconnectedListBox = new DRCLISTBOX( m_panelUnconnectedBox, ID_UNCONNECTED_LIST, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 );
m_UnconnectedListBox = new DRCLISTBOX( m_panelUnconnectedItems, ID_UNCONNECTED_LIST, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 );
m_UnconnectedListBox->SetToolTip( _("Left-click to center on unconnected pair. Right-click to highlight unconnected items.") );
bSizerUnconnectedBox->Add( m_UnconnectedListBox, 1, wxALL|wxEXPAND, 5 );
m_panelUnconnectedBox->SetSizer( bSizerUnconnectedBox );
m_panelUnconnectedBox->Layout();
bSizerUnconnectedBox->Fit( m_panelUnconnectedBox );
m_Notebook->AddPage( m_panelUnconnectedBox, _("Unconnected Items (%d)"), false );
m_panelUnconnectedItems->SetSizer( bSizerUnconnectedBox );
m_panelUnconnectedItems->Layout();
bSizerUnconnectedBox->Fit( m_panelUnconnectedItems );
m_Notebook->AddPage( m_panelUnconnectedItems, _("Unconnected Items (%d)"), false );
m_panelFootprintWarnings = new wxPanel( m_Notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizerFootprintsBox;
bSizerFootprintsBox = new wxBoxSizer( wxVERTICAL );
m_FootprintsListBox = new DRCLISTBOX( m_panelFootprintWarnings, ID_FOOTPRINTS_LIST, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 );
bSizerFootprintsBox->Add( m_FootprintsListBox, 1, wxALL|wxEXPAND, 5 );
m_panelFootprintWarnings->SetSizer( bSizerFootprintsBox );
m_panelFootprintWarnings->Layout();
bSizerFootprintsBox->Fit( m_panelFootprintWarnings );
m_Notebook->AddPage( m_panelFootprintWarnings, _("Footprint Warnings (%d)"), false );
m_MainSizer->Add( m_Notebook, 1, wxEXPAND|wxLEFT|wxRIGHT, 5 );
m_sizerButtons = new wxBoxSizer( wxHORIZONTAL );
m_DeleteCurrentMarkerButton = new wxButton( this, wxID_ANY, _("Delete Marker"), wxDefaultPosition, wxDefaultSize, 0 );
m_sizerButtons->Add( m_DeleteCurrentMarkerButton, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 10 );
m_DeleteAllMarkersButton = new wxButton( this, wxID_ANY, _("Delete All Markers"), wxDefaultPosition, wxDefaultSize, 0 );
m_sizerButtons->Add( m_DeleteAllMarkersButton, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
m_sdbSizer1 = new wxStdDialogButtonSizer();
m_sdbSizer1OK = new wxButton( this, wxID_OK );
m_sdbSizer1->AddButton( m_sdbSizer1OK );
m_sdbSizer1Apply = new wxButton( this, wxID_APPLY );
m_sdbSizer1->AddButton( m_sdbSizer1Apply );
m_sdbSizer1Cancel = new wxButton( this, wxID_CANCEL );
m_sdbSizer1->AddButton( m_sdbSizer1Cancel );
m_sdbSizer1->Realize();
m_sizerButtons->Add( m_sdbSizer1, 1, wxEXPAND|wxALL, 5 );
m_MainSizer->Add( m_sizerButtons, 0, wxEXPAND|wxLEFT, 5 );
this->SetSizer( m_MainSizer );
this->Layout();
m_MainSizer->Fit( this );
// Connect Events
this->Connect( wxEVT_ACTIVATE, wxActivateEventHandler( DIALOG_DRC_CONTROL_BASE::OnActivateDlg ) );
m_CreateRptCtrl->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_DRC_CONTROL_BASE::OnReportCheckBoxClicked ), NULL, this );
@ -234,9 +235,11 @@ DIALOG_DRC_CONTROL_BASE::DIALOG_DRC_CONTROL_BASE( wxWindow* parent, wxWindowID i
m_UnconnectedListBox->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( DIALOG_DRC_CONTROL_BASE::OnLeftDClickUnconnected ), NULL, this );
m_UnconnectedListBox->Connect( wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler( DIALOG_DRC_CONTROL_BASE::OnUnconnectedSelectionEvent ), NULL, this );
m_UnconnectedListBox->Connect( wxEVT_RIGHT_UP, wxMouseEventHandler( DIALOG_DRC_CONTROL_BASE::OnRightUpUnconnected ), NULL, this );
m_FootprintsListBox->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( DIALOG_DRC_CONTROL_BASE::OnLeftDClickFootprints ), NULL, this );
m_FootprintsListBox->Connect( wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler( DIALOG_DRC_CONTROL_BASE::OnFootprintsSelectionEvent ), NULL, this );
m_FootprintsListBox->Connect( wxEVT_RIGHT_UP, wxMouseEventHandler( DIALOG_DRC_CONTROL_BASE::OnRightUpFootprints ), NULL, this );
m_DeleteCurrentMarkerButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_DRC_CONTROL_BASE::OnDeleteOneClick ), NULL, this );
m_DeleteAllMarkersButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_DRC_CONTROL_BASE::OnDeleteAllClick ), NULL, this );
m_sdbSizer1Apply->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_DRC_CONTROL_BASE::OnListUnconnectedClick ), NULL, this );
m_sdbSizer1Cancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_DRC_CONTROL_BASE::OnCancelClick ), NULL, this );
m_sdbSizer1OK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_DRC_CONTROL_BASE::OnStartdrcClick ), NULL, this );
}
@ -255,10 +258,12 @@ DIALOG_DRC_CONTROL_BASE::~DIALOG_DRC_CONTROL_BASE()
m_UnconnectedListBox->Disconnect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( DIALOG_DRC_CONTROL_BASE::OnLeftDClickUnconnected ), NULL, this );
m_UnconnectedListBox->Disconnect( wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler( DIALOG_DRC_CONTROL_BASE::OnUnconnectedSelectionEvent ), NULL, this );
m_UnconnectedListBox->Disconnect( wxEVT_RIGHT_UP, wxMouseEventHandler( DIALOG_DRC_CONTROL_BASE::OnRightUpUnconnected ), NULL, this );
m_FootprintsListBox->Disconnect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( DIALOG_DRC_CONTROL_BASE::OnLeftDClickFootprints ), NULL, this );
m_FootprintsListBox->Disconnect( wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler( DIALOG_DRC_CONTROL_BASE::OnFootprintsSelectionEvent ), NULL, this );
m_FootprintsListBox->Disconnect( wxEVT_RIGHT_UP, wxMouseEventHandler( DIALOG_DRC_CONTROL_BASE::OnRightUpFootprints ), NULL, this );
m_DeleteCurrentMarkerButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_DRC_CONTROL_BASE::OnDeleteOneClick ), NULL, this );
m_DeleteAllMarkersButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_DRC_CONTROL_BASE::OnDeleteAllClick ), NULL, this );
m_sdbSizer1Apply->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_DRC_CONTROL_BASE::OnListUnconnectedClick ), NULL, this );
m_sdbSizer1Cancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_DRC_CONTROL_BASE::OnCancelClick ), NULL, this );
m_sdbSizer1OK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_DRC_CONTROL_BASE::OnStartdrcClick ), NULL, this );
}

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,12 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Dec 1 2018)
// C++ code generated with wxFormBuilder (version Dec 30 2017)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __DIALOG_DRC_BASE_H__
#define __DIALOG_DRC_BASE_H__
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
@ -22,10 +23,10 @@ class DRCLISTBOX;
#include <wx/textctrl.h>
#include <wx/sizer.h>
#include <wx/checkbox.h>
#include <wx/bmpbuttn.h>
#include <wx/bitmap.h>
#include <wx/image.h>
#include <wx/icon.h>
#include <wx/bmpbuttn.h>
#include <wx/button.h>
#include <wx/gbsizer.h>
#include <wx/listbox.h>
@ -40,6 +41,7 @@ class DRCLISTBOX;
#define ID_NOTEBOOK1 1002
#define ID_CLEARANCE_LIST 1003
#define ID_UNCONNECTED_LIST 1004
#define ID_FOOTPRINTS_LIST 1005
///////////////////////////////////////////////////////////////////////////////
/// Class DIALOG_DRC_CONTROL_BASE
@ -47,10 +49,9 @@ class DRCLISTBOX;
class DIALOG_DRC_CONTROL_BASE : public DIALOG_SHIM
{
private:
wxPanel* m_panelUnconnectedBox;
wxPanel* m_panelUnconnectedItems;
protected:
wxStaticText* m_ClearanceTitle;
wxStaticText* m_TrackMinWidthTitle;
wxStaticText* m_TrackMinWidthUnit;
wxStaticText* m_ViaMinTitle;
@ -60,21 +61,22 @@ class DIALOG_DRC_CONTROL_BASE : public DIALOG_SHIM
wxCheckBox* m_cbRefillZones;
wxCheckBox* m_cbReportAllTrackErrors;
wxCheckBox* m_cbReportTracksToZonesErrors;
wxCheckBox* m_cbTestFootprints;
wxStaticText* m_messagesLabel;
wxTextCtrl* m_Messages;
wxCheckBox* m_CreateRptCtrl;
wxTextCtrl* m_RptFilenameCtrl;
wxBitmapButton* m_BrowseButton;
wxNotebook* m_Notebook;
wxPanel* m_panelClearanceListBox;
wxPanel* m_panelViolations;
wxPanel* m_panelFootprintWarnings;
wxBoxSizer* m_sizerButtons;
wxButton* m_DeleteCurrentMarkerButton;
wxButton* m_DeleteAllMarkersButton;
wxStdDialogButtonSizer* m_sdbSizer1;
wxButton* m_sdbSizer1OK;
wxButton* m_sdbSizer1Apply;
wxButton* m_sdbSizer1Cancel;
// Virtual event handlers, overide them in your derived class
virtual void OnActivateDlg( wxActivateEvent& event ) { event.Skip(); }
virtual void OnReportCheckBoxClicked( wxCommandEvent& event ) { event.Skip(); }
@ -87,23 +89,26 @@ class DIALOG_DRC_CONTROL_BASE : public DIALOG_SHIM
virtual void OnLeftDClickUnconnected( wxMouseEvent& event ) { event.Skip(); }
virtual void OnUnconnectedSelectionEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void OnRightUpUnconnected( wxMouseEvent& event ) { event.Skip(); }
virtual void OnLeftDClickFootprints( wxMouseEvent& event ) { event.Skip(); }
virtual void OnFootprintsSelectionEvent( wxCommandEvent& event ) { event.Skip(); }
virtual void OnRightUpFootprints( wxMouseEvent& event ) { event.Skip(); }
virtual void OnDeleteOneClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnDeleteAllClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnListUnconnectedClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnCancelClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnStartdrcClick( wxCommandEvent& event ) { event.Skip(); }
public:
wxTextCtrl* m_SetClearance;
wxTextCtrl* m_SetTrackMinWidthCtrl;
wxTextCtrl* m_SetViaMinSizeCtrl;
wxTextCtrl* m_SetMicroViakMinSizeCtrl;
DRCLISTBOX* m_ClearanceListBox;
DRCLISTBOX* m_UnconnectedListBox;
DIALOG_DRC_CONTROL_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("DRC Control"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
DRCLISTBOX* m_FootprintsListBox;
DIALOG_DRC_CONTROL_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("DRC Control"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~DIALOG_DRC_CONTROL_BASE();
};
#endif //__DIALOG_DRC_BASE_H__

View File

@ -48,6 +48,7 @@
#include <dialog_netlist.h>
#include <wx_html_report_panel.h>
#include <drc.h>
#define NETLIST_FILTER_MESSAGES_KEY wxT("NetlistReportFilterMsg")
#define NETLIST_UPDATEFOOTPRINTS_KEY wxT("NetlistUpdateFootprints")
@ -182,106 +183,44 @@ void DIALOG_NETLIST::OnTestFootprintsClick( wxCommandEvent& event )
return;
}
// Lists of duplicates, missing references and not in netlist footprints:
std::vector <MODULE*> duplicate;
wxArrayString missing;
std::vector <MODULE*> notInNetlist;
wxString netlistFilename = m_NetlistFilenameCtrl->GetValue();
wxString netlistFilename = m_NetlistFilenameCtrl->GetValue();
NETLIST_READER* netlistReader;
NETLIST netlist;
wxBusyCursor dummy; // Shows an hourglass while calculating.
if( !verifyFootprints( netlistFilename, wxEmptyString, duplicate, missing, notInNetlist ) )
try
{
netlistReader = NETLIST_READER::GetNetlistReader( &netlist, netlistFilename, "" );
if( netlistReader == NULL )
{
wxString msg = wxString::Format( _( "Cannot open netlist file \"%s\"." ),
netlistFilename );
wxMessageBox( msg, _( "Netlist Load Error." ), wxOK | wxICON_ERROR );
return;
}
std::unique_ptr< NETLIST_READER > nlr( netlistReader );
netlistReader->LoadNetlist();
m_parent->SetLastNetListRead( netlistFilename );
}
catch( const IO_ERROR& ioe )
{
wxString msg = wxString::Format( _( "Error loading netlist file:\n%s" ),
ioe.What().GetData() );
wxMessageBox( msg, _( "Netlist Load Error" ), wxOK | wxICON_ERROR );
return;
#define ERR_CNT_MAX 100 // Max number of errors to output in dialog
// to avoid a too long message list
wxString list; // The messages to display
m_parent->SetLastNetListRead( netlistFilename );
int err_cnt = 0;
// Search for duplicate footprints.
if( duplicate.size() == 0 )
list << wxT("<p><b>") << _( "No duplicate." ) << wxT("</b></p>");
else
{
list << wxT("<p><b>") << _( "Duplicates:" ) << wxT("</b></p>");
for( unsigned ii = 0; ii < duplicate.size(); ii++ )
{
MODULE* module = duplicate[ii];
if( module->GetReference().IsEmpty() )
list << wxT("<br>") << wxT("[noref)");
else
list << wxT("<br>") << module->GetReference();
list << wxT(" (<i>") << module->GetValue() << wxT("</i>)");
list << wxT(" @ ");
list << MessageTextFromValue( m_units, module->GetPosition().x ),
list << wxT(", ") << MessageTextFromValue( m_units, module->GetPosition().y ),
err_cnt++;
if( ERR_CNT_MAX < err_cnt )
break;
}
}
// Search for missing modules on board.
if( missing.size() == 0 )
list << wxT("<p><b>") << _( "No missing footprints." ) << wxT("</b></p>");
else
{
list << wxT("<p><b>") << _( "Missing:" ) << wxT("</b></p>");
for( unsigned ii = 0; ii < missing.size(); ii += 2 )
{
list << wxT("<br>") << missing[ii];
list << wxT(" (<i>") << missing[ii+1] << wxT("</i>)");
err_cnt++;
if( ERR_CNT_MAX < err_cnt )
break;
}
}
// Search for modules found on board but not in net list.
if( notInNetlist.size() == 0 )
list << wxT( "<p><b>" ) << _( "No extra footprints." ) << wxT( "</b></p>" );
else
{
list << wxT( "<p><b>" ) << _( "Not in Netlist:" ) << wxT( "</b></p>" );
for( unsigned ii = 0; ii < notInNetlist.size(); ii++ )
{
MODULE* module = notInNetlist[ii];
if( module->GetReference().IsEmpty() )
list << wxT( "<br>" ) << wxT( "[noref)" );
else
list << wxT( "<br>" ) << module->GetReference() ;
list << wxT( " (<i>" ) << module->GetValue() << wxT( "</i>)" );
list << wxT( " @ " );
list << MessageTextFromValue( m_units, module->GetPosition().x ),
list << wxT( ", " ) << MessageTextFromValue( m_units, module->GetPosition().y ),
err_cnt++;
if( ERR_CNT_MAX < err_cnt )
break;
}
}
if( ERR_CNT_MAX < err_cnt )
{
list << wxT( "<p><b>" )
<< _( "Too many errors: some are skipped" )
<< wxT( "</b></p>" );
}
HTML_MESSAGE_BOX dlg( this, _( "Check footprints" ) );
dlg.AddHTML_Text( list );
DRC_LIST drcItems;
DRC::TestFootprints( netlist, m_parent->GetBoard(), GetUserUnits(), drcItems );
for( DRC_ITEM* item : drcItems )
dlg.AddHTML_Text( item->ShowHtml( GetUserUnits() ) );
dlg.ShowModal();
}
@ -342,91 +281,6 @@ void DIALOG_NETLIST::OnUpdateUIValidNetlistFile( wxUpdateUIEvent& aEvent )
}
bool DIALOG_NETLIST::verifyFootprints( const wxString& aNetlistFilename,
const wxString & aCmpFilename,
std::vector< MODULE* >& aDuplicates,
wxArrayString& aMissing,
std::vector< MODULE* >& aNotInNetlist )
{
wxString msg;
MODULE* module;
MODULE* nextModule;
NETLIST netlist;
wxBusyCursor dummy; // Shows an hourglass while calculating.
NETLIST_READER* netlistReader;
COMPONENT* component;
try
{
netlistReader = NETLIST_READER::GetNetlistReader( &netlist, aNetlistFilename,
aCmpFilename );
if( netlistReader == NULL )
{
msg.Printf( _( "Cannot open netlist file \"%s\"." ), GetChars( aNetlistFilename ) );
wxMessageBox( msg, _( "Netlist Load Error." ), wxOK | wxICON_ERROR );
return false;
}
std::unique_ptr< NETLIST_READER > nlr( netlistReader );
netlistReader->LoadNetlist();
}
catch( const IO_ERROR& ioe )
{
msg.Printf( _( "Error loading netlist file:\n%s" ), ioe.What().GetData() );
wxMessageBox( msg, _( "Netlist Load Error" ), wxOK | wxICON_ERROR );
return false;
}
BOARD* pcb = m_parent->GetBoard();
// Search for duplicate footprints.
module = pcb->m_Modules;
for( ; module != NULL; module = module->Next() )
{
nextModule = module->Next();
for( ; nextModule != NULL; nextModule = nextModule->Next() )
{
if( module->GetReference().CmpNoCase( nextModule->GetReference() ) == 0 )
{
aDuplicates.push_back( module );
break;
}
}
}
// Search for component footprints in the netlist but not on the board.
for( unsigned ii = 0; ii < netlist.GetCount(); ii++ )
{
component = netlist.GetComponent( ii );
module = pcb->FindModuleByReference( component->GetReference() );
if( module == NULL )
{
aMissing.Add( component->GetReference() );
aMissing.Add( component->GetValue() );
}
}
// Search for component footprints found on board but not in netlist.
module = pcb->m_Modules;
for( ; module != NULL; module = module->Next() )
{
component = netlist.GetComponentByReference( module->GetReference() );
if( component == NULL )
aNotInNetlist.push_back( module );
}
return true;
}
void DIALOG_NETLIST::loadNetlist( bool aDryRun )
{
wxString netlistFileName = m_NetlistFilenameCtrl->GetValue();

View File

@ -50,27 +50,6 @@ public:
private:
void onFilenameChanged();
/**
* Function verifyFootprints
* compares the netlist to the board and builds a list of duplicate, missing, and
* extra footprints.
*
* @param aNetlistFilename the netlist filename.
* @param aCmpFilename the component link filename.
* @param aDuplicate the list of duplicate modules to populate
* @param aMissing the list of missing module references and values to populate. For
* each missing item, the first string is the reference designator and
* the second is the value.
* @param aNotInNetlist is the list of component footprint found in the netlist but not on
* the board.
* @return true if no errors occurred while reading the netlist. Otherwise false.
*/
bool verifyFootprints( const wxString& aNetlistFilename,
const wxString& aCmpFilename,
std::vector< MODULE* >& aDuplicate,
wxArrayString& aMissing,
std::vector< MODULE* >& aNotInNetlist );
void loadNetlist( bool aDryRun );
// Virtual event handlers:

View File

@ -49,8 +49,10 @@
#include <tool/tool_manager.h>
#include <tools/pcb_actions.h>
#include <kiface_i.h>
#include <pcbnew.h>
#include <drc.h>
#include <pcb_netlist.h>
#include <dialog_drc.h>
#include <wx/progdlg.h>
@ -144,8 +146,12 @@ DRC::DRC( PCB_EDIT_FRAME* aPcbWindow )
m_doKeepoutTest = true; // enable keepout areas to items clearance tests
m_refillZones = false; // Only fill zones if requested by user.
m_reportAllTrackErrors = false;
m_doCreateRptFile = false;
m_testFootprints = false;
m_drcRun = false;
m_footprintsTested = false;
m_doCreateRptFile = false;
// m_rptFilename set to empty by its constructor
m_currentMarker = NULL;
@ -164,9 +170,11 @@ DRC::DRC( PCB_EDIT_FRAME* aPcbWindow )
DRC::~DRC()
{
// maybe someday look at pointainer.h <- google for "pointainer.h"
for( unsigned i = 0; i<m_unconnected.size(); ++i )
delete m_unconnected[i];
for( DRC_ITEM* unconnectedItem : m_unconnected )
delete unconnectedItem;
for( DRC_ITEM* footprintItem : m_footprints )
delete footprintItem;
}
@ -509,7 +517,7 @@ void DRC::RunTests( wxTextCtrl* aMessages )
// find and gather vias, tracks, pads inside text boxes.
if( aMessages )
{
aMessages->AppendText( _( "Test texts...\n" ) );
aMessages->AppendText( _( "Text and graphic clearances...\n" ) );
wxSafeYield();
}
@ -528,6 +536,30 @@ void DRC::RunTests( wxTextCtrl* aMessages )
doFootprintOverlappingDrc();
}
for( DRC_ITEM* footprintItem : m_footprints )
delete footprintItem;
m_footprints.clear();
m_footprintsTested = false;
if( m_testFootprints && !Kiface().IsSingle() )
{
if( aMessages )
{
aMessages->AppendText( _( "Checking footprints against schematic...\n" ) );
aMessages->Refresh();
}
NETLIST netlist;
m_pcbEditorFrame->FetchNetlistFromSchematic( netlist, PCB_EDIT_FRAME::ANNOTATION_DIALOG );
if( m_drcDialog )
m_drcDialog->Raise();
TestFootprints( netlist, m_pcb, m_drcDialog->GetUserUnits(), m_footprints );
m_footprintsTested = true;
}
// Check if there are items on disabled layers
testDisabledLayers();
@ -537,6 +569,8 @@ void DRC::RunTests( wxTextCtrl* aMessages )
aMessages->Refresh();
}
m_drcRun = true;
// update the m_drcDialog listboxes
updatePointers();
@ -549,15 +583,6 @@ void DRC::RunTests( wxTextCtrl* aMessages )
}
void DRC::ListUnconnectedPads()
{
testUnconnected();
// update the m_drcDialog listboxes
updatePointers();
}
void DRC::updatePointers()
{
// update my pointers, m_pcbEditorFrame is the only unchangeable one
@ -569,6 +594,8 @@ void DRC::updatePointers()
m_pcbEditorFrame->GetUserUnits(), new DRC_LIST_MARKERS( m_pcb ) );
m_drcDialog->m_UnconnectedListBox->SetList(
m_pcbEditorFrame->GetUserUnits(), new DRC_LIST_GENERIC( &m_unconnected ) );
m_drcDialog->m_FootprintsListBox->SetList(
m_pcbEditorFrame->GetUserUnits(), new DRC_LIST_GENERIC( &m_footprints ) );
m_drcDialog->UpdateDisplayedCounts();
}
@ -1453,3 +1480,61 @@ void DRC::doFootprintOverlappingDrc()
drc_overlap.RunDRC( *m_pcb );
}
void DRC::TestFootprints( NETLIST& aNetlist, BOARD* aPCB, EDA_UNITS_T aUnits,
DRC_LIST& aDRCList )
{
MODULE* module;
MODULE* nextModule;
// Search for duplicate footprints.
for( module = aPCB->m_Modules; module != NULL; module = module->Next() )
{
nextModule = module->Next();
for( ; nextModule != NULL; nextModule = nextModule->Next() )
{
if( module->GetReference().CmpNoCase( nextModule->GetReference() ) == 0 )
{
aDRCList.emplace_back( new DRC_ITEM( aUnits, DRCE_DUPLICATE_FOOTPRINT,
module, module->GetPosition(),
nextModule, nextModule->GetPosition() ) );
break;
}
}
}
// Search for component footprints in the netlist but not on the board.
for( unsigned ii = 0; ii < aNetlist.GetCount(); ii++ )
{
COMPONENT* component = aNetlist.GetComponent( ii );
module = aPCB->FindModuleByReference( component->GetReference() );
if( module == NULL )
{
wxString msg = wxString::Format( wxT( "%s (%s)" ),
component->GetReference(),
component->GetValue() );
aDRCList.emplace_back( new DRC_ITEM( DRCE_MISSING_FOOTPRINT, msg ) );
}
}
// Search for component footprints found on board but not in netlist.
for( module = aPCB->m_Modules; module != NULL; module = module->Next() )
{
COMPONENT* component = aNetlist.GetComponentByReference( module->GetReference() );
if( component == NULL )
{
aDRCList.emplace_back( new DRC_ITEM( aUnits, DRCE_EXTRA_FOOTPRINT,
module, module->GetPosition(),
nullptr, wxPoint() ) );
}
}
}

View File

@ -99,6 +99,9 @@
#define DRCE_DRILLED_HOLES_TOO_CLOSE 51 ///< overlapping drilled holes break drill bits
#define DRCE_TRACK_NEAR_EDGE 53 ///< track too close to board edge
#define DRCE_INVALID_OUTLINE 54 ///< invalid board outline
#define DRCE_MISSING_FOOTPRINT 55 ///< footprint not found for netlist item
#define DRCE_DUPLICATE_FOOTPRINT 56 ///< more than one footprints found for netlist item
#define DRCE_EXTRA_FOOTPRINT 57 ///< netlist item not found for footprint
#define DRCE_SHORT 58
#define DRCE_REDUNDANT_VIA 59
@ -122,6 +125,7 @@ class DRC_ITEM;
class NETCLASS;
class EDA_TEXT;
class DRAWSEGMENT;
class NETLIST;
class wxWindow;
class wxString;
class wxTextCtrl;
@ -195,7 +199,7 @@ private:
bool m_doCreateRptFile; // enable creating a report file
bool m_refillZones; // refill zones if requested (by user).
bool m_reportAllTrackErrors; // Report all tracks errors (or only 4 first errors)
bool m_do;
bool m_testFootprints; // Test footprints against schematic
wxString m_rptFilename;
@ -239,6 +243,9 @@ private:
DRC_MARKER_FACTORY m_markerFactory; ///< Class that generates markers
DRC_LIST m_unconnected; ///< list of unconnected pads, as DRC_ITEMs
DRC_LIST m_footprints; ///< list of footprint warnings, as DRC_ITEMs
bool m_drcRun;
bool m_footprintsTested;
/**
@ -452,6 +459,13 @@ public:
*/
int TestZoneToZoneOutline( ZONE_CONTAINER* aZone, bool aCreateMarkers );
/**
* Test the board footprints against a netlist. Will report DRCE_MISSING_FOOTPRINT,
* DRCE_DUPLICATE_FOOTPRINT and DRCE_EXTRA_FOOTPRINT errors in aDRCList.
*/
static void TestFootprints( NETLIST& aNetlist, BOARD* aPCB, EDA_UNITS_T aUnits,
DRC_LIST& aDRCList );
/**
* Open a dialog and prompts the user, then if a test run button is
* clicked, runs the test(s) and creates the MARKERS. The dialog is only
@ -477,36 +491,6 @@ public:
*/
void DestroyDRCDialog( int aReason );
/**
* Save all the UI or test settings and may be called before running the tests.
*
* @param aPad2PadTest Tells whether to test pad to pad distances.
* @param aUnconnectedTest Tells whether to list unconnected pads.
* @param aZonesTest Tells whether to test zones.
* @param aRefillZones Refill zones before performing DRC.
* @param aKeepoutTest Tells whether to test keepout areas.
* @param aReportAllTrackErrors Tells whether or not to stop checking track connections after the first error.
* @param aReportName A string telling the disk file report name entered.
* @param aSaveReport A boolean telling whether to generate disk file report.
*/
void SetSettings( bool aPad2PadTest, bool aUnconnectedTest,
bool aZonesTest, bool aKeepoutTest, bool aRefillZones,
bool aReportAllTrackErrors,
const wxString& aReportName, bool aSaveReport )
{
m_doPad2PadTest = aPad2PadTest;
m_doUnconnectedTest = aUnconnectedTest;
m_doZonesTest = aZonesTest;
m_doKeepoutTest = aKeepoutTest;
m_rptFilename = aReportName;
m_doCreateRptFile = aSaveReport;
m_refillZones = aRefillZones;
m_drcInLegacyRoutingMode = false;
m_reportAllTrackErrors = aReportAllTrackErrors;
}
/**
* Run all the tests specified with a previous call to
* SetSettings()
@ -514,12 +498,6 @@ public:
*/
void RunTests( wxTextCtrl* aMessages = NULL );
/**
* Gather a list of all the unconnected pads and shows them in the
* dialog, and optionally prints a report of such.
*/
void ListUnconnectedPads();
/**
* @return a pointer to the current marker (last created marker
*/

View File

@ -143,6 +143,13 @@ wxString DRC_ITEM::GetErrorText() const
case DRCE_MALFORMED_COURTYARD_IN_FOOTPRINT:
return wxString( _( "Footprint has incorrect courtyard (not a closed shape)" ) );
case DRCE_DUPLICATE_FOOTPRINT:
return wxString( _( "Duplicate footprints" ) );
case DRCE_MISSING_FOOTPRINT:
return wxString( _( "Missing footprint" ) );
case DRCE_EXTRA_FOOTPRINT:
return wxString( _( "Extra footprint" ) );
case DRCE_SHORT:
return wxString( _( "Remove track shorting two nets" ) );
case DRCE_REDUNDANT_VIA:

View File

@ -713,12 +713,12 @@ void PCB_EDIT_FRAME::enableGALSpecificMenus()
ID_MENU_PCB_FLIP_VIEW
};
bool enbl = IsGalCanvasActive();
bool enable = IsGalCanvasActive();
for( unsigned ii = 0; ii < arrayDim( id_list ); ii++ )
for( auto& id : id_list )
{
if( GetMenuBar()->FindItem( id_list[ii] ) )
GetMenuBar()->FindItem( id_list[ii] )->Enable( enbl );
if( GetMenuBar()->FindItem( id ) )
GetMenuBar()->FindItem( id )->Enable( enable );
}
// Update settings for GAL menus
@ -1112,12 +1112,13 @@ void PCB_EDIT_FRAME::ToPlotter( wxCommandEvent& event )
switch( event.GetId() )
{
case ID_GEN_PLOT_GERBER: plotSettings.SetFormat( PLOT_FORMAT_GERBER ); break;
case ID_GEN_PLOT_DXF: plotSettings.SetFormat( PLOT_FORMAT_DXF ); break;
case ID_GEN_PLOT_HPGL: plotSettings.SetFormat( PLOT_FORMAT_HPGL ); break;
case ID_GEN_PLOT_PDF: plotSettings.SetFormat( PLOT_FORMAT_PDF ); break;
case ID_GEN_PLOT_PS: plotSettings.SetFormat( PLOT_FORMAT_POST ); break;
case ID_GEN_PLOT_SVG: wxFAIL_MSG( "Should have gone to ExportSVG()" ); break;
case ID_GEN_PLOT_GERBER: plotSettings.SetFormat( PLOT_FORMAT_GERBER ); break;
case ID_GEN_PLOT_DXF: plotSettings.SetFormat( PLOT_FORMAT_DXF ); break;
case ID_GEN_PLOT_HPGL: plotSettings.SetFormat( PLOT_FORMAT_HPGL ); break;
case ID_GEN_PLOT_PDF: plotSettings.SetFormat( PLOT_FORMAT_PDF ); break;
case ID_GEN_PLOT_PS: plotSettings.SetFormat( PLOT_FORMAT_POST ); break;
case ID_GEN_PLOT_SVG: wxFAIL_MSG( "Must be handled by ExportSVG()" ); break;
default: wxFAIL_MSG( "Unknown plot type" ); break;
}
SetPlotSettings( plotSettings );
@ -1183,20 +1184,20 @@ bool PCB_EDIT_FRAME::FetchNetlistFromSchematic( NETLIST& aNetlist, FETCH_NETLIST
wxFileName schfn( Prj().GetProjectPath(), Prj().GetProjectName(), SchematicFileExtension );
frame->OpenProjectFiles( std::vector<wxString>( 1, schfn.GetFullPath() ) );
// Because the schematic editor frame is not on screen, iconize it:
// However, another valid option is to do not iconize the schematic editor frame
// and show it
frame->Iconize( true );
// we show the schematic editor frame, because do not show is seen as
// a not yet opened schematic by Kicad manager, which is not the case
frame->Show( true );
// bring ourselves back to the front
Raise();
}
std::string payload;
if( aMode == NO_ANNOTATION )
payload = "no-annotate";
else if( aMode = QUIET_ANNOTATION )
else if( aMode == QUIET_ANNOTATION )
payload = "quiet-annotate";
Kiway().ExpressMail( FRAME_SCH, MAIL_SCH_GET_NETLIST, payload, this );