From fc1665ff2832537461dc1d37a1709a3a2cb6ead5 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Thu, 10 Sep 2020 20:58:05 +0100 Subject: [PATCH] ADDED Clearance Inspector. --- pcbnew/board_connected_item.cpp | 16 ++- pcbnew/board_connected_item.h | 5 +- pcbnew/drc/drc_rule.cpp | 92 +++++++++--- pcbnew/drc/drc_rule.h | 18 +-- pcbnew/drc/drc_rule_parser.cpp | 3 +- pcbnew/menubar_pcb_editor.cpp | 1 + pcbnew/tools/edit_tool.cpp | 22 ++- pcbnew/tools/pcb_actions.cpp | 6 + pcbnew/tools/pcb_actions.h | 1 + pcbnew/tools/pcb_editor_control.cpp | 5 +- pcbnew/tools/pcb_inspection_tool.cpp | 205 ++++++++++++++++++++++++++- pcbnew/tools/pcb_inspection_tool.h | 8 +- 12 files changed, 335 insertions(+), 47 deletions(-) diff --git a/pcbnew/board_connected_item.cpp b/pcbnew/board_connected_item.cpp index 54e43756ce..ba1895d10d 100644 --- a/pcbnew/board_connected_item.cpp +++ b/pcbnew/board_connected_item.cpp @@ -81,7 +81,7 @@ NETCLASS* BOARD_CONNECTED_ITEM::GetEffectiveNetclass() const * LEVEL 3: Accumulated local settings, netclass settings, & board design settings */ int BOARD_CONNECTED_ITEM::GetClearance( PCB_LAYER_ID aLayer, BOARD_ITEM* aItem, - wxString* aSource ) const + wxString* aSource, REPORTER* aReporter ) const { BOARD* board = GetBoard(); int clearance = 0; @@ -111,7 +111,7 @@ int BOARD_CONNECTED_ITEM::GetClearance( PCB_LAYER_ID aLayer, BOARD_ITEM* aItem, // LEVEL 2: Rules // - if( GetRuleClearance( aItem, aLayer, &clearance, aSource ) ) + if( GetRuleClearance( aItem, aLayer, &clearance, aSource, aReporter ) ) return clearance; // LEVEL 3: Accumulated local settings, netclass settings, & board design settings @@ -153,10 +153,11 @@ int BOARD_CONNECTED_ITEM::GetClearance( PCB_LAYER_ID aLayer, BOARD_ITEM* aItem, bool BOARD_CONNECTED_ITEM::GetRuleClearance( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer, - int* aClearance, wxString* aSource ) const + int* aClearance, wxString* aSource, + REPORTER* aReporter ) const { const DRC_CONSTRAINT* constraint = GetConstraint( this, aItem, DRC_RULE_ID_CLEARANCE, aLayer, - aSource ); + aSource, aReporter ); if( constraint ) { @@ -164,6 +165,13 @@ bool BOARD_CONNECTED_ITEM::GetRuleClearance( BOARD_ITEM* aItem, PCB_LAYER_ID aLa *aSource = wxString::Format( _( "'%s' rule" ), *aSource ); *aClearance = constraint->m_Value.Min(); + + if( aReporter ) + { + wxString clearance = StringFromValue( aReporter->GetUnits(), *aClearance, true ); + aReporter->Report( wxString::Format( _( "Clearance: %s." ), clearance ) ); + } + return true; } diff --git a/pcbnew/board_connected_item.h b/pcbnew/board_connected_item.h index 1f1bb3a7a0..23ccad0d2f 100644 --- a/pcbnew/board_connected_item.h +++ b/pcbnew/board_connected_item.h @@ -28,6 +28,7 @@ #include #include +#include #include class NETCLASS; @@ -167,7 +168,7 @@ public: * @return int - the clearance in internal units. */ virtual int GetClearance( PCB_LAYER_ID aLayer, BOARD_ITEM* aItem = nullptr, - wxString* aSource = nullptr ) const; + wxString* aSource = nullptr, REPORTER* aReporter = nullptr ) const; /** * Function GetRuleClearance @@ -178,7 +179,7 @@ public: * @return true if a rule was fired */ virtual bool GetRuleClearance( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer, int* aClearance, - wxString* aSource ) const; + wxString* aSource, REPORTER* aReporter = nullptr ) const; /** * Function GetLocalClearanceOverrides diff --git a/pcbnew/drc/drc_rule.cpp b/pcbnew/drc/drc_rule.cpp index 7acbc3fecf..8d56367aec 100644 --- a/pcbnew/drc/drc_rule.cpp +++ b/pcbnew/drc/drc_rule.cpp @@ -31,42 +31,86 @@ const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem, - int aConstraint, PCB_LAYER_ID aLayer, wxString* aRuleName ) + int aConstraint, PCB_LAYER_ID aLayer, wxString* aRuleName, + REPORTER* aReporter ) { - BOARD* board = aItem->GetBoard(); + BOARD* board = aItem->GetBoard(); if( !board ) return nullptr; for( DRC_RULE* rule : board->GetDesignSettings().m_DRCRules ) { - if( !rule->m_LayerCondition.test( aLayer ) ) - continue; - - for( const DRC_CONSTRAINT& constraint : rule->m_Constraints ) + if( aReporter ) { - if( constraint.m_Type != aConstraint ) - continue; + aReporter->Report( wxString::Format( _( "Checking rule \"%s\"." ), + rule->m_Name ) ); + } - if( !rule->m_LayerCondition.test( aLayer ) ) - continue; + if( !rule->m_LayerCondition.test( aLayer ) ) + { + if( aReporter ) + { + aReporter->Report( wxString::Format( _( "Rule layer \"%s\" not matched." ), + rule->m_LayerSource ) ); + aReporter->Report( "Rule not applied." ); + } + + continue; + } + + const DRC_CONSTRAINT* constraint = nullptr; + + for( const DRC_CONSTRAINT& candidate : rule->m_Constraints ) + { + if( candidate.m_Type == aConstraint ) + { + constraint = &candidate; + break; + } + } + + if( aReporter && !constraint ) + { + aReporter->Report( _( "Rule contains no applicable constraints." ) ); + aReporter->Report( _( "Rule not applied." ) ); + } + else + { + if( aReporter ) + { + aReporter->Report( wxString::Format( _( "Checking rule condition \"%s\"." ), + rule->m_Condition.m_Expression ) ); + } if( rule->m_Condition.EvaluateFor( aItem, bItem, aLayer ) ) { + if( aReporter ) + aReporter->Report( "Rule applied." ); + if( aRuleName ) *aRuleName = rule->m_Name; - return &constraint; + return constraint; } if( bItem && rule->m_Condition.EvaluateFor( bItem, aItem, aLayer ) ) { + if( aReporter ) + aReporter->Report( "Rule applied." ); + if( aRuleName ) *aRuleName = rule->m_Name; - return &constraint; + return constraint; } + + if( aReporter ) + aReporter->Report( "Condition not satisfied; rule not applied." ); } + + if( aReporter ) + aReporter->Report( "" ); } return nullptr; @@ -97,21 +141,37 @@ DRC_RULE_CONDITION::~DRC_RULE_CONDITION() bool DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB, - PCB_LAYER_ID aLayer ) + PCB_LAYER_ID aLayer, REPORTER* aReporter ) { - // An unconditional rule is always true if( m_Expression.IsEmpty() ) - return true; + { + if( aReporter ) + aReporter->Report( _( "Unconditional constraint." ) ); + + return true; + } + + if( aReporter ) + aReporter->Report( _( "Evaluating expression \"" + m_Expression + "\"." ) ); - // A rule which failed to compile is always false if( !m_ucode ) + { + if( aReporter ) + aReporter->Report( _( "ERROR in expression." ) ); + return false; + } BOARD_ITEM* a = const_cast( aItemA ); BOARD_ITEM* b = aItemB ? const_cast( aItemB ) : DELETED_BOARD_ITEM::GetInstance(); PCB_EXPR_CONTEXT ctx( aLayer ); ctx.SetItems( a, b ); + ctx.SetErrorCallback( [&]( const wxString& aMessage, int aOffset ) + { + if( aReporter ) + aReporter->Report( _( "ERROR: " ) + aMessage ); + } ); return m_ucode->Run( &ctx )->AsDouble() != 0.0; } diff --git a/pcbnew/drc/drc_rule.h b/pcbnew/drc/drc_rule.h index f39a3a496e..67ef5b6800 100644 --- a/pcbnew/drc/drc_rule.h +++ b/pcbnew/drc/drc_rule.h @@ -88,8 +88,7 @@ class DRC_CONSTRAINT public: DRC_CONSTRAINT() : m_Type( DRC_RULE_ID_UNKNOWN ), - m_DisallowFlags( 0 ), - m_LayerCondition( LSET::AllLayersMask() ) + m_DisallowFlags( 0 ) {} const MINOPTMAX& GetValue() const { return m_Value; } @@ -97,9 +96,8 @@ public: public: DRC_CONSTRAINT_TYPE_T m_Type; - MINOPTMAX m_Value; - int m_DisallowFlags; - LSET m_LayerCondition; + MINOPTMAX m_Value; + int m_DisallowFlags; }; @@ -109,14 +107,15 @@ public: DRC_RULE_CONDITION(); ~DRC_RULE_CONDITION(); - bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB, PCB_LAYER_ID aLayer ); + bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB, PCB_LAYER_ID aLayer, + REPORTER* aReporter = nullptr ); bool Compile( REPORTER* aReporter, int aSourceLine, int aSourceOffset ); public: wxString m_Expression; private: - PCB_EXPR_UCODE* m_ucode; + PCB_EXPR_UCODE* m_ucode; }; @@ -128,6 +127,7 @@ public: public: wxString m_Name; + wxString m_LayerSource; LSET m_LayerCondition; wxString m_TestProviderName; DRC_RULE_CONDITION m_Condition; @@ -136,7 +136,9 @@ public: const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem, - int aConstraint, PCB_LAYER_ID aLayer, wxString* aRuleName ); + int aConstraint, PCB_LAYER_ID aLayer, + wxString* aRuleName = nullptr, + REPORTER* aReporter = nullptr ); #endif // DRC_RULE_H diff --git a/pcbnew/drc/drc_rule_parser.cpp b/pcbnew/drc/drc_rule_parser.cpp index ce367534e2..e46e9f9c11 100644 --- a/pcbnew/drc/drc_rule_parser.cpp +++ b/pcbnew/drc/drc_rule_parser.cpp @@ -215,6 +215,7 @@ DRC_RULE* DRC_RULES_PARSER::parseDRC_RULE() break; case T_layer: + rule->m_LayerSource = FromUTF8(); rule->m_LayerCondition = parseLayer(); break; @@ -453,7 +454,7 @@ LSET DRC_RULES_PARSER::parseLayer() } if( !retVal.any() ) - reportError( wxString::Format( _( "Unrecognized layer '%s' " ), layerName ) ); + reportError( wxString::Format( _( "Unrecognized layer '%s'." ), layerName ) ); } if( (int) NextTok() != DSN_RIGHT ) diff --git a/pcbnew/menubar_pcb_editor.cpp b/pcbnew/menubar_pcb_editor.cpp index 8a1f53fd1f..80b8ee5ef7 100644 --- a/pcbnew/menubar_pcb_editor.cpp +++ b/pcbnew/menubar_pcb_editor.cpp @@ -372,6 +372,7 @@ void PCB_EDIT_FRAME::ReCreateMenuBar() inspectMenu->AppendSeparator(); inspectMenu->Add( PCB_ACTIONS::runDRC ); + inspectMenu->Add( PCB_ACTIONS::inspectClearance ); //-- Tools menu ---------------------------------------------------------- diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index abbf08d130..18cfd70040 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -204,23 +204,21 @@ bool EDIT_TOOL::Init() auto specialToolsSubMenu = std::make_shared( this ); menu.AddSeparator(); m_selectionTool->GetToolMenu().AddSubMenu( specialToolsSubMenu ); - menu.AddMenu( specialToolsSubMenu.get(), SELECTION_CONDITIONS::NotEmpty ); + menu.AddMenu( specialToolsSubMenu.get(), SELECTION_CONDITIONS::NotEmpty, 100 ); - menu.AddSeparator(); - menu.AddItem( ACTIONS::cut, SELECTION_CONDITIONS::NotEmpty ); - menu.AddItem( ACTIONS::copy, SELECTION_CONDITIONS::NotEmpty ); + menu.AddSeparator( 150 ); + menu.AddItem( ACTIONS::cut, SELECTION_CONDITIONS::NotEmpty, 150 ); + menu.AddItem( ACTIONS::copy, SELECTION_CONDITIONS::NotEmpty, 150 ); // Selection tool handles the context menu for some other tools, such as the Picker. // Don't add things like Paste when another tool is active. - menu.AddItem( ACTIONS::paste, noActiveToolCondition ); - - menu.AppendSeparator(); - menu.AddItem( ACTIONS::selectAll, noItemsCondition ); + menu.AddItem( ACTIONS::paste, noActiveToolCondition, 150 ); + menu.AddItem( ACTIONS::selectAll, noItemsCondition, 150 ); // Footprint actions - menu.AddSeparator(); - menu.AddItem( PCB_ACTIONS::editFpInFpEditor, singleModuleCondition ); - menu.AddItem( PCB_ACTIONS::updateFootprint, singleModuleCondition ); - menu.AddItem( PCB_ACTIONS::changeFootprint, singleModuleCondition ); + menu.AddSeparator( 150 ); + menu.AddItem( PCB_ACTIONS::editFpInFpEditor, singleModuleCondition, 150 ); + menu.AddItem( PCB_ACTIONS::updateFootprint, singleModuleCondition, 150 ); + menu.AddItem( PCB_ACTIONS::changeFootprint, singleModuleCondition, 150 ); return true; } diff --git a/pcbnew/tools/pcb_actions.cpp b/pcbnew/tools/pcb_actions.cpp index a8b145c7ff..4968986d3c 100644 --- a/pcbnew/tools/pcb_actions.cpp +++ b/pcbnew/tools/pcb_actions.cpp @@ -1025,6 +1025,12 @@ TOOL_ACTION PCB_ACTIONS::boardStatistics( "pcbnew.InspectionTool.ShowStatisticsD _( "Show Board Statistics" ), _( "Shows board statistics" ), pcbnew_xpm ); +TOOL_ACTION PCB_ACTIONS::inspectClearance( "pcbnew.InspectionTool.InspectClearance", + AS_GLOBAL, 0, "", + _( "Clearance Resolution..." ), + _( "Show clearance resolution for the active layer between two selected objects" ), + mw_add_gap_xpm ); + //Geographic re-annotation tool TOOL_ACTION PCB_ACTIONS::boardReannotate( "pcbnew.ReannotateTool.ShowReannotateDialog", AS_GLOBAL, 0, "", diff --git a/pcbnew/tools/pcb_actions.h b/pcbnew/tools/pcb_actions.h index 76a189b4bb..9aad1231eb 100644 --- a/pcbnew/tools/pcb_actions.h +++ b/pcbnew/tools/pcb_actions.h @@ -417,6 +417,7 @@ public: static TOOL_ACTION boardStatistics; static TOOL_ACTION boardReannotate; static TOOL_ACTION repairBoard; + static TOOL_ACTION inspectClearance; // Appearance controls static TOOL_ACTION clearHighlight; diff --git a/pcbnew/tools/pcb_editor_control.cpp b/pcbnew/tools/pcb_editor_control.cpp index 0a3139bfe1..74a47a1bbb 100644 --- a/pcbnew/tools/pcb_editor_control.cpp +++ b/pcbnew/tools/pcb_editor_control.cpp @@ -243,9 +243,10 @@ bool PCB_EDITOR_CONTROL::Init() toolMenu.AddSubMenu( lockMenu ); toolMenu.AddSubMenu( groupMenu ); + menu.AddMenu( groupMenu.get(), SELECTION_CONDITIONS::NotEmpty, 100 ); + menu.AddMenu( lockMenu.get(), SELECTION_CONDITIONS::OnlyTypes( GENERAL_COLLECTOR::LockableItems ), 100 ); + menu.AddMenu( zoneMenu.get(), SELECTION_CONDITIONS::OnlyType( PCB_ZONE_AREA_T ), 200 ); - menu.AddMenu( lockMenu.get(), SELECTION_CONDITIONS::OnlyTypes( GENERAL_COLLECTOR::LockableItems ), 200 ); - menu.AddMenu( groupMenu.get(), SELECTION_CONDITIONS::NotEmpty, 200 ); } DRAWING_TOOL* drawingTool = m_toolMgr->GetTool(); diff --git a/pcbnew/tools/pcb_inspection_tool.cpp b/pcbnew/tools/pcb_inspection_tool.cpp index 84e2bc4612..c54412a6bc 100644 --- a/pcbnew/tools/pcb_inspection_tool.cpp +++ b/pcbnew/tools/pcb_inspection_tool.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include "pcb_inspection_tool.h" @@ -77,7 +78,9 @@ bool PCB_INSPECTION_TOOL::Init() CONDITIONAL_MENU& menu = selectionTool->GetToolMenu().GetMenu(); selectionTool->GetToolMenu().AddSubMenu( netSubMenu ); - menu.AddMenu( netSubMenu.get(), SELECTION_CONDITIONS::OnlyTypes( connectedTypes ) ); + + menu.AddMenu( netSubMenu.get(), SELECTION_CONDITIONS::OnlyTypes( connectedTypes ), 200 ); + menu.AddItem( PCB_ACTIONS::inspectClearance, SELECTION_CONDITIONS::Count( 2 ), 200 ); return true; } @@ -97,6 +100,195 @@ int PCB_INSPECTION_TOOL::ShowStatisticsDialog( const TOOL_EVENT& aEvent ) } +void reportZoneConnection( ZONE_CONTAINER* aZone, D_PAD* aPad, REPORTER* r ) +{ + ENUM_MAP connectionEnum = ENUM_MAP::Instance(); + wxString source; + ZONE_CONNECTION connection = aZone->GetPadConnection( aPad, &source ); + + r->Report( "" ); + + r->Report( wxString::Format( _( "Zone connection type: %s." ), + connectionEnum.ToString( aZone->GetPadConnection() ) ) ); + + if( source != _( "zone" ) ) + { + r->Report( wxString::Format( _( "Overridden by %s; connection type: %s." ), + source, + connectionEnum.ToString( connection ) ) ); + } + + // Resolve complex connection types into simple types + if( connection == ZONE_CONNECTION::THT_THERMAL ) + { + if( aPad->GetAttribute() == PAD_ATTRIB_STANDARD ) + { + connection = ZONE_CONNECTION::THERMAL; + } + else + { + connection = ZONE_CONNECTION::FULL; + r->Report( wxString::Format( _( "Pad is not a PTH pad; connection will be: %s." ), + connectionEnum.ToString( ZONE_CONNECTION::FULL ) ) ); + } + } + + r->Report( "" ); + + // Process simple connection types + if( connection == ZONE_CONNECTION::THERMAL ) + { + int gap = aZone->GetThermalReliefGap(); + + r->Report( wxString::Format( _( "Zone thermal relief: %s." ), + StringFromValue( r->GetUnits(), gap, true ) ) ); + + gap = aZone->GetThermalReliefGap( aPad, &source ); + + if( source != _( "zone" ) ) + { + r->Report( wxString::Format( _( "Overridden by %s; thermal relief: %s." ), + source, + StringFromValue( r->GetUnits(), gap, true ) ) ); + } + } + else if( connection == ZONE_CONNECTION::NONE ) + { + int clearance = aZone->GetLocalClearance(); + + r->Report( wxString::Format( _( "Zone clearance: %s." ), + StringFromValue( r->GetUnits(), clearance, true ) ) ); + + if( aZone->GetThermalReliefGap( aPad ) > clearance ) + { + clearance = aZone->GetThermalReliefGap( aPad, &source ); + + if( source != _( "zone" ) ) + { + r->Report( wxString::Format( _( "Overridden by larger thermal relief from %s;" + "clearance: %s." ), + source, + StringFromValue( r->GetUnits(), clearance, true ) ) ); + } + } + } + else + { + r->Report( _( "Clearance is 0." ) ); + } +} + + +void reportCopperClearance( PCB_LAYER_ID aLayer, BOARD_CONNECTED_ITEM* aA, BOARD_ITEM* aB, + REPORTER* r ) +{ + wxString source; + + r->Report( "" ); + + // JEY TODO: hook this up to new DRC engine to get "classic" sources as well; right now + // we're just reporting on rules.... + aA->GetClearance( aLayer, aB, &source, r ); +} + + +int PCB_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent ) +{ + SELECTION_TOOL* selTool = m_toolMgr->GetTool(); + const PCBNEW_SELECTION& selection = selTool->GetSelection(); + PCB_LAYER_ID layer = m_frame->GetActiveLayer(); + + if( selection.Size() != 2 ) + { + m_frame->ShowInfoBarError( _( "Select two items for a clearance resolution report." ) ); + return 0; + } + + if( m_inspectClearanceDialog == nullptr ) + { + m_inspectClearanceDialog = std::make_unique( m_frame ); + m_inspectClearanceDialog->SetTitle( _( "Clearance Report" ) ); + + m_inspectClearanceDialog->Connect( wxEVT_CLOSE_WINDOW, + wxCommandEventHandler( PCB_INSPECTION_TOOL::onInspectClearanceDialogClosed ), + nullptr, this ); + } + + WX_HTML_REPORT_BOX* r = m_inspectClearanceDialog->m_Reporter; + r->SetUnits( m_frame->GetUserUnits() ); + r->Clear(); + + BOARD_ITEM* a = static_cast( selection.GetItem( 0 ) ); + BOARD_ITEM* b = static_cast( selection.GetItem( 1 ) ); + + if( a->Type() != PCB_ZONE_AREA_T && b->Type() == PCB_ZONE_AREA_T ) + std::swap( a, b ); + else if( !a->IsConnected() && b->IsConnected() ) + std::swap( a, b ); + + if( !IsCopperLayer( layer ) ) + { + r->Report( wxString::Format( _( "Active layer (%s) is not a copper layer. " + "No clearance defined." ), + m_frame->GetBoard()->GetLayerName( layer ) ) ); + } + else if( !a->GetLayerSet().test( layer ) ) + { + r->Report( wxString::Format( _( "%s not present on layer %s. No clearance defined." ), + a->GetSelectMenuText( r->GetUnits() ), + m_frame->GetBoard()->GetLayerName( layer ) ) ); + } + else if( !b->GetLayerSet().test( layer ) ) + { + r->Report( wxString::Format( _( "%s not present on layer %s. No clearance defined." ), + b->GetSelectMenuText( r->GetUnits() ), + m_frame->GetBoard()->GetLayerName( layer ) ) ); + } + else if( !a->IsConnected() ) + { + r->Report( _( "Items have no electrical connections. No clearance defined." ) ); + } + else + { + r->Report( _( "Clearance resolution for:" ) ); + + r->Report( wxString::Format( _( "
  • Layer %s
  • %s
  • %s
" ), + m_frame->GetBoard()->GetLayerName( layer ), + a->GetSelectMenuText( r->GetUnits() ), + b->GetSelectMenuText( r->GetUnits() ) ) ); + + BOARD_CONNECTED_ITEM* ac = dynamic_cast( a ); + BOARD_CONNECTED_ITEM* bc = dynamic_cast( b ); + + if( ac && bc && ac->GetNetCode() > 0 && ac->GetNetCode() == bc->GetNetCode() ) + { + // Same nets.... + + if( ac->Type() == PCB_ZONE_AREA_T && bc->Type() == PCB_PAD_T ) + { + reportZoneConnection( static_cast( ac ), + static_cast( bc ), r ); + } + else + { + r->Report( _( "Items belong to the same net. Clearance is 0." ) ); + } + } + else + { + // Different nets (or second unconnected).... + + reportCopperClearance( layer, ac, b, r ); + } + } + + r->Flush(); + + m_inspectClearanceDialog->Show( true ); + return 0; +} + + int PCB_INSPECTION_TOOL::CrossProbePcbToSch( const TOOL_EVENT& aEvent ) { // Don't get in an infinite loop PCB -> SCH -> PCB -> SCH -> ... @@ -537,6 +729,16 @@ void PCB_INSPECTION_TOOL::onListNetsDialogClosed( wxCommandEvent& event ) } +void PCB_INSPECTION_TOOL::onInspectClearanceDialogClosed( wxCommandEvent& event ) +{ + m_inspectClearanceDialog->Disconnect( wxEVT_CLOSE_WINDOW, + wxCommandEventHandler( PCB_INSPECTION_TOOL::onListNetsDialogClosed ), nullptr, this ); + + m_inspectClearanceDialog->Destroy(); + m_inspectClearanceDialog.release(); +} + + int PCB_INSPECTION_TOOL::HideNet( const TOOL_EVENT& aEvent ) { doHideNet( aEvent.Parameter(), true ); @@ -595,6 +797,7 @@ void PCB_INSPECTION_TOOL::setTransitions() Go( &PCB_INSPECTION_TOOL::ListNets, PCB_ACTIONS::listNets.MakeEvent() ); Go( &PCB_INSPECTION_TOOL::ShowStatisticsDialog, PCB_ACTIONS::boardStatistics.MakeEvent() ); + Go( &PCB_INSPECTION_TOOL::InspectClearance, PCB_ACTIONS::inspectClearance.MakeEvent() ); Go( &PCB_INSPECTION_TOOL::HighlightNet, PCB_ACTIONS::highlightNet.MakeEvent() ); Go( &PCB_INSPECTION_TOOL::HighlightNet, PCB_ACTIONS::highlightNetSelection.MakeEvent() ); diff --git a/pcbnew/tools/pcb_inspection_tool.h b/pcbnew/tools/pcb_inspection_tool.h index f40c855bc8..a25d190c61 100644 --- a/pcbnew/tools/pcb_inspection_tool.h +++ b/pcbnew/tools/pcb_inspection_tool.h @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -89,6 +90,9 @@ public: ///> Show the ratsnest for a given net int ShowNet( const TOOL_EVENT& aEvent ); + ///> Show the clearance resolution for two selected items + int InspectClearance( const TOOL_EVENT& aEvent ); + private: ///> Event handler to recalculate dynamic ratsnest void ratsnestTimer( wxTimerEvent& aEvent ); @@ -103,7 +107,8 @@ private: ///> Bind handlers to corresponding TOOL_ACTIONs void setTransitions() override; - void onListNetsDialogClosed( wxCommandEvent& event ); + void onListNetsDialogClosed( wxCommandEvent& aEvent ); + void onInspectClearanceDialogClosed( wxCommandEvent& aEvent ); private: PCB_EDIT_FRAME* m_frame; // Pointer to the currently used edit frame. @@ -116,6 +121,7 @@ private: std::unique_ptr m_listNetsDialog; DIALOG_SELECT_NET_FROM_LIST::SETTINGS m_listNetsDialogSettings; + std::unique_ptr m_inspectClearanceDialog; }; #endif //__BOARD_STATISTICS_TOOL_H