Inform user of bad DRC rules when filling zones.

ADDED: facility for hypertext links in infobar.

Also made use of this for via constraint errors when routing.

Fixes https://gitlab.com/kicad/code/kicad/issues/5800
This commit is contained in:
Jeff Young 2020-10-16 12:20:37 +01:00
parent 834c7bbe05
commit eea7957e16
11 changed files with 89 additions and 25 deletions

View File

@ -26,6 +26,7 @@
#include <wx/infobar.h> #include <wx/infobar.h>
#include <wx/sizer.h> #include <wx/sizer.h>
#include <wx/timer.h> #include <wx/timer.h>
#include <wx/hyperlink.h>
wxDEFINE_EVENT( KIEVT_SHOW_INFOBAR, wxCommandEvent ); wxDEFINE_EVENT( KIEVT_SHOW_INFOBAR, wxCommandEvent );
@ -199,6 +200,19 @@ void WX_INFOBAR::AddButton( wxButton* aButton )
} }
void WX_INFOBAR::AddButton( wxHyperlinkCtrl* aHypertextButton )
{
wxSizer* sizer = GetSizer();
wxASSERT( aHypertextButton );
sizer->Add( aHypertextButton, wxSizerFlags().Centre().Border( wxRIGHT ) );
if( IsShown() )
sizer->Layout();
}
void WX_INFOBAR::AddCloseButton( const wxString& aTooltip ) void WX_INFOBAR::AddCloseButton( const wxString& aTooltip )
{ {
wxBitmapButton* button = wxBitmapButton::NewCloseButton( this, ID_CLOSE_INFOBAR ); wxBitmapButton* button = wxBitmapButton::NewCloseButton( this, ID_CLOSE_INFOBAR );

View File

@ -25,7 +25,9 @@
#include <wx/infobar.h> #include <wx/infobar.h>
#include <wx/wx.h> #include <wx/wx.h>
class wxAuiManager; class wxAuiManager;
class wxHyperlinkCtrl;
enum enum
@ -105,6 +107,14 @@ public:
*/ */
void AddButton( wxButton* aButton ); void AddButton( wxButton* aButton );
/**
* Add an already created hypertext link to the infobar.
* New buttons are added in the right-most position.
*
* @param aHypertextButton is the button to add
*/
void AddButton( wxHyperlinkCtrl* aHypertextButton );
/** /**
* Add a button with the provided ID and text. * Add a button with the provided ID and text.
* The new button is created on the right-most positon. * The new button is created on the right-most positon.

View File

@ -210,8 +210,7 @@ void DIALOG_DRC::OnRunDRCClick( wxCommandEvent& aEvent )
// issues (on at least OSX) if we don't. // issues (on at least OSX) if we don't.
drcTool->DestroyDRCDialog(); drcTool->DestroyDRCDialog();
m_brdEditor->ShowBoardSetupDialog( _( "Rules" ), pe.What(), ID_RULES_EDITOR, m_brdEditor->ShowBoardSetupDialog( _( "Rules" ) );
pe.lineNumber, pe.byteIndex );
return; return;
} }

View File

@ -386,6 +386,9 @@ bool PANEL_SETUP_RULES::TransferDataToWindow()
ConvertSmartQuotesAndDashes( &str ); ConvertSmartQuotesAndDashes( &str );
m_textEditor->AddText( str << '\n' ); m_textEditor->AddText( str << '\n' );
} }
wxCommandEvent dummy;
OnCompile( dummy );
} }
} }

View File

@ -406,7 +406,7 @@ void DRC_ENGINE::loadRules( const wxFileName& aPath )
} }
bool DRC_ENGINE::CompileRules() void DRC_ENGINE::compileRules()
{ {
ReportAux( wxString::Format( "Compiling Rules (%d rules, %d conditions): ", ReportAux( wxString::Format( "Compiling Rules (%d rules, %d conditions): ",
(int) m_rules.size(), (int) m_rules.size(),
@ -477,8 +477,6 @@ bool DRC_ENGINE::CompileRules()
} }
} }
} }
return true;
} }
@ -497,14 +495,17 @@ void DRC_ENGINE::InitEngine( const wxFileName& aRulePath )
m_ruleConditions.clear(); m_ruleConditions.clear();
m_rules.clear(); m_rules.clear();
m_rulesValid = false;
loadImplicitRules(); loadImplicitRules();
loadRules( aRulePath ); loadRules( aRulePath );
CompileRules(); compileRules();
for( int ii = DRCE_FIRST; ii < DRCE_LAST; ++ii ) for( int ii = DRCE_FIRST; ii < DRCE_LAST; ++ii )
m_errorLimits[ ii ] = INT_MAX; m_errorLimits[ ii ] = INT_MAX;
m_rulesValid = true;
} }

View File

@ -164,7 +164,7 @@ public:
bool GetReportAllTrackErrors() const { return m_reportAllTrackErrors; } bool GetReportAllTrackErrors() const { return m_reportAllTrackErrors; }
bool GetTestFootprints() const { return m_testFootprints; } bool GetTestFootprints() const { return m_testFootprints; }
bool CompileRules(); bool RulesValid() { return m_rulesValid; }
void ReportViolation( const std::shared_ptr<DRC_ITEM>& aItem, wxPoint aPos ); void ReportViolation( const std::shared_ptr<DRC_ITEM>& aItem, wxPoint aPos );
bool ReportProgress( double aProgress ); bool ReportProgress( double aProgress );
@ -193,7 +193,7 @@ private:
*/ */
void loadRules( const wxFileName& aPath ); void loadRules( const wxFileName& aPath );
void freeCompiledRules(); void compileRules();
struct CONSTRAINT_WITH_CONDITIONS struct CONSTRAINT_WITH_CONDITIONS
{ {
@ -215,6 +215,7 @@ protected:
std::vector<DRC_RULE_CONDITION*> m_ruleConditions; std::vector<DRC_RULE_CONDITION*> m_ruleConditions;
std::vector<DRC_RULE*> m_rules; std::vector<DRC_RULE*> m_rules;
bool m_rulesValid;
std::vector<DRC_TEST_PROVIDER*> m_testProviders; std::vector<DRC_TEST_PROVIDER*> m_testProviders;
EDA_UNITS m_userUnits; EDA_UNITS m_userUnits;

View File

@ -876,8 +876,7 @@ void PCB_EDIT_FRAME::ActivateGalCanvas()
} }
void PCB_EDIT_FRAME::ShowBoardSetupDialog( const wxString& aInitialPage, const wxString& aErrorMsg, void PCB_EDIT_FRAME::ShowBoardSetupDialog( const wxString& aInitialPage )
int aErrorCtrlId, int aErrorLine, int aErrorCol )
{ {
// Make sure everything's up-to-date // Make sure everything's up-to-date
GetBoard()->BuildListOfNets(); GetBoard()->BuildListOfNets();
@ -887,9 +886,6 @@ void PCB_EDIT_FRAME::ShowBoardSetupDialog( const wxString& aInitialPage, const w
if( !aInitialPage.IsEmpty() ) if( !aInitialPage.IsEmpty() )
dlg.SetInitialPage( aInitialPage, wxEmptyString ); dlg.SetInitialPage( aInitialPage, wxEmptyString );
if( !aErrorMsg.IsEmpty() )
dlg.SetError( aErrorMsg, aInitialPage, aErrorCtrlId, aErrorLine, aErrorCol );
if( dlg.ShowQuasiModal() == wxID_OK ) if( dlg.ShowQuasiModal() == wxID_OK )
{ {
Prj().GetProjectFile().NetSettings().ResolveNetClassAssignments( true ); Prj().GetProjectFile().NetSettings().ResolveNetClassAssignments( true );

View File

@ -475,9 +475,7 @@ public:
/** /**
* Function ShowBoardSetupDialog * Function ShowBoardSetupDialog
*/ */
void ShowBoardSetupDialog( const wxString& aInitialPage = wxEmptyString, void ShowBoardSetupDialog( const wxString& aInitialPage = wxEmptyString );
const wxString& aErrorMsg = wxEmptyString, int aErrorCtrlId = -1,
int aErrorLine = -1, int aErrorCol = -1 );
/* toolbars update UI functions: */ /* toolbars update UI functions: */

View File

@ -19,7 +19,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <wx/numdlg.h> #include <wx/hyperlink.h>
#include <functional> #include <functional>
using namespace std::placeholders; using namespace std::placeholders;
#include <class_board.h> #include <class_board.h>
@ -32,6 +32,7 @@ using namespace std::placeholders;
#include <dialogs/dialog_pns_settings.h> #include <dialogs/dialog_pns_settings.h>
#include <dialogs/dialog_pns_diff_pair_dimensions.h> #include <dialogs/dialog_pns_diff_pair_dimensions.h>
#include <dialogs/dialog_track_via_size.h> #include <dialogs/dialog_track_via_size.h>
#include <widgets/infobar.h>
#include <confirm.h> #include <confirm.h>
#include <bitmaps.h> #include <bitmaps.h>
#include <tool/action_menu.h> #include <tool/action_menu.h>
@ -717,15 +718,39 @@ int ROUTER_TOOL::onViaCommand( const TOOL_EVENT& aEvent )
// Cannot place microvias or blind vias if not allowed (obvious) // Cannot place microvias or blind vias if not allowed (obvious)
if( ( viaType == VIATYPE::BLIND_BURIED ) && ( !bds.m_BlindBuriedViaAllowed ) ) if( ( viaType == VIATYPE::BLIND_BURIED ) && ( !bds.m_BlindBuriedViaAllowed ) )
{ {
frame()->ShowInfoBarError( _( "Blind/buried vias have to be enabled in " WX_INFOBAR* infobar = frame()->GetInfoBar();
"Board Setup > Design Rules > Constraints." ) ); wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY,
_("Show board setup"), wxEmptyString );
button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
[&]( wxHyperlinkEvent& aEvent )
{
getEditFrame<PCB_EDIT_FRAME>()->ShowBoardSetupDialog( _( "Constraints" ) );
} ) );
infobar->ShowMessageFor( _( "Blind/buried vias have to be enabled in "
"Board Setup > Design Rules > Constraints." ),
10000, wxICON_ERROR );
infobar->AddButton( button );
return false; return false;
} }
if( ( viaType == VIATYPE::MICROVIA ) && ( !bds.m_MicroViasAllowed ) ) if( ( viaType == VIATYPE::MICROVIA ) && ( !bds.m_MicroViasAllowed ) )
{ {
frame()->ShowInfoBarError( _( "Microvias have to be enabled in " WX_INFOBAR* infobar = frame()->GetInfoBar();
"Board Setup > Design Rules > Constraints." ) ); wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY,
_("Show board setup"), wxEmptyString );
button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
[&]( wxHyperlinkEvent& aEvent )
{
getEditFrame<PCB_EDIT_FRAME>()->ShowBoardSetupDialog( _( "Constraints" ) );
} ) );
infobar->ShowMessageFor( _( "Microvias have to be enabled in "
"Board Setup > Design Rules > Constraints." ),
10000, wxICON_ERROR );
infobar->AddButton( button );
return false; return false;
} }

View File

@ -197,8 +197,7 @@ void PCB_INSPECTION_TOOL::reportClearance( DRC_CONSTRAINT_TYPE_T aClearanceType,
} }
catch( PARSE_ERROR& pe ) catch( PARSE_ERROR& pe )
{ {
m_frame->ShowBoardSetupDialog( _( "Rules" ), pe.What(), ID_RULES_EDITOR, m_frame->ShowBoardSetupDialog( _( "Rules" ) );
pe.lineNumber, pe.byteIndex );
return; return;
} }
@ -390,8 +389,7 @@ int PCB_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent )
} }
catch( PARSE_ERROR& pe ) catch( PARSE_ERROR& pe )
{ {
m_frame->ShowBoardSetupDialog( _( "Rules" ), pe.What(), ID_RULES_EDITOR, m_frame->ShowBoardSetupDialog( _( "Rules" ) );
pe.lineNumber, pe.byteIndex );
return 1; return 1;
} }

View File

@ -28,7 +28,9 @@
#include <connectivity/connectivity_data.h> #include <connectivity/connectivity_data.h>
#include <board_commit.h> #include <board_commit.h>
#include <widgets/progress_reporter.h> #include <widgets/progress_reporter.h>
#include <widgets/infobar.h>
#include <wx/event.h> #include <wx/event.h>
#include <wx/hyperlink.h>
#include <tool/tool_manager.h> #include <tool/tool_manager.h>
#include "pcb_actions.h" #include "pcb_actions.h"
#include "zone_filler_tool.h" #include "zone_filler_tool.h"
@ -102,6 +104,23 @@ void ZONE_FILLER_TOOL::FillAllZones( wxWindow* aCaller, PROGRESS_REPORTER* aRepo
ZONE_FILLER filler( board(), &commit ); ZONE_FILLER filler( board(), &commit );
if( !board()->GetDesignSettings().m_DRCEngine->RulesValid() )
{
WX_INFOBAR* infobar = frame()->GetInfoBar();
wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY, _("Show DRC rules"),
wxEmptyString );
button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
[&]( wxHyperlinkEvent& aEvent )
{
getEditFrame<PCB_EDIT_FRAME>()->ShowBoardSetupDialog( _( "Rules" ) );
} ) );
infobar->ShowMessageFor( _( "Zone fills may be inaccurate. DRC rules contain errors." ),
10000, wxICON_WARNING );
infobar->AddButton( button );
}
if( aReporter ) if( aReporter )
filler.SetProgressReporter( aReporter ); filler.SetProgressReporter( aReporter );
else else