Show collisions preventing routing from starting.

Also introduces a callback to the infobar so that the view can be
cleaned up when the timer expires.

Fixes https://gitlab.com/kicad/code/kicad/issues/6930
This commit is contained in:
Jeff Young 2021-01-04 17:51:50 +00:00
parent 1ddd0e53bb
commit 648c42f643
7 changed files with 96 additions and 10 deletions

View File

@ -722,6 +722,21 @@ void EDA_BASE_FRAME::ShowInfoBarError( const wxString& aErrorMsg, bool aShowClos
} }
void EDA_BASE_FRAME::ShowInfoBarError( const wxString& aErrorMsg, bool aShowCloseButton,
std::function<void(void)> aCallback )
{
m_infoBar->RemoveAllButtons();
if( aShowCloseButton )
m_infoBar->AddCloseButton();
if( aCallback )
m_infoBar->SetCallback( aCallback );
GetInfoBar()->ShowMessageFor( aErrorMsg, 8000, wxICON_ERROR );
}
void EDA_BASE_FRAME::ShowInfoBarWarning( const wxString& aWarningMsg, bool aShowCloseButton ) void EDA_BASE_FRAME::ShowInfoBarWarning( const wxString& aWarningMsg, bool aShowCloseButton )
{ {
m_infoBar->RemoveAllButtons(); m_infoBar->RemoveAllButtons();

View File

@ -153,6 +153,9 @@ void WX_INFOBAR::Dismiss()
if( m_auiManager ) if( m_auiManager )
updateAuiLayout( false ); updateAuiLayout( false );
if( m_callback )
(*m_callback)();
m_updateLock = false; m_updateLock = false;
} }

View File

@ -215,16 +215,33 @@ public:
WX_INFOBAR* GetInfoBar() { return m_infoBar; } WX_INFOBAR* GetInfoBar() { return m_infoBar; }
/** /**
* Show the #WX_INFOBAR displayed on the top of the canvas with a message * Show the #WX_INFOBAR displayed on the top of the canvas with a message and an error
* and a error icon on the left of the infobar. * icon on the left of the infobar, and an optional closebox to the right.
* *
* The infobar will be closed after a timeout. * The infobar will be closed after a timeout.
* *
* @param aErrorMsg is the message to display * @param aErrorMsg is the message to display.
* @param aShowCloseButton true to show a close button on the right of the #WX_INFOBAR. * @param aShowCloseButton true to show a close button on the right of the #WX_INFOBAR.
*/ */
void ShowInfoBarError( const wxString& aErrorMsg, bool aShowCloseButton = false ); void ShowInfoBarError( const wxString& aErrorMsg, bool aShowCloseButton = false );
/**
* Show the #WX_INFOBAR displayed on the top of the canvas with a message and an error
* icon on the left of the infobar, and an optional closebox to the right.
*
* The infobar will be closed after a timeout.
*
* This version accepts a callback which will be called when the infobar is dismissed
* (either as a result of user action or a timeout). This can be useful when the caller
* wants to make other decorations in the canvas to highlight the error.
*
* @param aErrorMsg is the message to display.
* @param aShowCloseButton true to show a close button on the right of the #WX_INFOBAR.
* @param aCallback a callback to be called when the infobar is dismissed.
*/
void ShowInfoBarError( const wxString& aErrorMsg, bool aShowCloseButton,
std::function<void(void)> aCallback );
/** /**
* Show the #WX_INFOBAR displayed on the top of the canvas with a message and a warning * Show the #WX_INFOBAR displayed on the top of the canvas with a message and a warning
* icon on the left of the infobar. * icon on the left of the infobar.

View File

@ -21,6 +21,7 @@
#ifndef INFOBAR_H_ #ifndef INFOBAR_H_
#define INFOBAR_H_ #define INFOBAR_H_
#include <core/optional.h>
#include <wx/event.h> #include <wx/event.h>
#include <wx/infobar.h> #include <wx/infobar.h>
#include <wx/wx.h> #include <wx/wx.h>
@ -129,6 +130,16 @@ public:
*/ */
void RemoveAllButtons(); void RemoveAllButtons();
/**
* Provide a callback to be called when the infobar is dismissed (either by user action
* or timer).
* @param aCallback
*/
void SetCallback( std::function<void(void)> aCallback )
{
m_callback = aCallback;
}
/** /**
* Show the infobar with the provided message and icon for a specific period * Show the infobar with the provided message and icon for a specific period
* of time. * of time.
@ -214,6 +225,8 @@ protected:
wxTimer* m_showTimer; ///< The timer counting the autoclose period wxTimer* m_showTimer; ///< The timer counting the autoclose period
wxAuiManager* m_auiManager; ///< The AUI manager that contains this infobar wxAuiManager* m_auiManager; ///< The AUI manager that contains this infobar
OPT<std::function<void(void)>> m_callback; ///< Optional callback made when closing infobar
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };

View File

@ -185,14 +185,30 @@ bool ROUTER::isStartingPointRoutable( const VECTOR2I& aWhere, ITEM* aStartItem,
if( m_mode == PNS_MODE_ROUTE_SINGLE && aStartItem ) if( m_mode == PNS_MODE_ROUTE_SINGLE && aStartItem )
{ {
VECTOR2I startPoint = aStartItem->Anchor( 0 ); VECTOR2I startPoint = aStartItem->Anchor( 0 );
SEGMENT dummyStartSeg( SEG( startPoint, startPoint ), aStartItem->Net() ); SHAPE_LINE_CHAIN dummyStartSeg;
LINE dummyStartLine;
dummyStartSeg.SetWidth( m_sizes.TrackWidth() ); dummyStartSeg.Append( startPoint );
dummyStartSeg.SetLayer( aLayer ); dummyStartSeg.Append( startPoint, true );
dummyStartLine.SetShape( dummyStartSeg );
dummyStartLine.SetLayer( aLayer );
dummyStartLine.SetNet( aStartItem->Net() );
dummyStartLine.SetWidth( m_sizes.TrackWidth() );
if( m_world->CheckColliding( &dummyStartLine, ITEM::ANY_T ) )
{
ITEM_SET dummyStartSet( &dummyStartLine );
NODE::ITEM_VECTOR highlightedItems;
markViolations( m_world.get(), dummyStartSet, highlightedItems );
for( ITEM* item : highlightedItems )
m_iface->HideItem( item );
if( m_world->CheckColliding( &dummyStartSeg, ITEM::ANY_T ) )
return false; return false;
}
} }
else if( m_mode == PNS_MODE_ROUTE_DIFF_PAIR && aStartItem ) else if( m_mode == PNS_MODE_ROUTE_DIFF_PAIR && aStartItem )
{ {
@ -204,7 +220,7 @@ bool ROUTER::isStartingPointRoutable( const VECTOR2I& aWhere, ITEM* aStartItem,
bool ROUTER::StartRouting( const VECTOR2I& aP, ITEM* aStartItem, int aLayer ) bool ROUTER::StartRouting( const VECTOR2I& aP, ITEM* aStartItem, int aLayer )
{ {
if( ! isStartingPointRoutable( aP, aStartItem, aLayer ) ) if( !isStartingPointRoutable( aP, aStartItem, aLayer ) )
{ {
SetFailureReason( _( "The routing start point violates DRC." ) ); SetFailureReason( _( "The routing start point violates DRC." ) );
return false; return false;
@ -519,6 +535,12 @@ void ROUTER::StopRouting()
} }
void ROUTER::ClearViewDecorations()
{
m_iface->EraseView();
}
void ROUTER::FlipPosture() void ROUTER::FlipPosture()
{ {
if( m_state == ROUTE_TRACK ) if( m_state == ROUTE_TRACK )

View File

@ -150,6 +150,7 @@ public:
void UndoLastSegment(); void UndoLastSegment();
void CommitRouting(); void CommitRouting();
void StopRouting(); void StopRouting();
void ClearViewDecorations();
NODE* GetWorld() const NODE* GetWorld() const
{ {

View File

@ -969,8 +969,18 @@ bool ROUTER_TOOL::prepareInteractive()
if( !m_router->StartRouting( m_startSnapPoint, m_startItem, routingLayer ) ) if( !m_router->StartRouting( m_startSnapPoint, m_startItem, routingLayer ) )
{ {
frame()->ShowInfoBarError( m_router->FailureReason() ); // It would make more sense to leave the net highlighted as the higher-contrast mode
// makes the router clearances more visible. However, since we just started routing
// the conversion of the screen from low contrast to high contrast is a bit jarring and
// makes the infobar coming up less noticable.
highlightNet( false ); highlightNet( false );
frame()->ShowInfoBarError( m_router->FailureReason(), true,
[&]()
{
m_router->ClearViewDecorations();
} );
controls()->SetAutoPan( false ); controls()->SetAutoPan( false );
return false; return false;
} }
@ -1000,6 +1010,8 @@ bool ROUTER_TOOL::finishInteractive()
void ROUTER_TOOL::performRouting() void ROUTER_TOOL::performRouting()
{ {
m_router->ClearViewDecorations();
if( !prepareInteractive() ) if( !prepareInteractive() )
return; return;
@ -1298,6 +1310,7 @@ int ROUTER_TOOL::MainLoop( const TOOL_EVENT& aEvent )
// Store routing settings till the next invocation // Store routing settings till the next invocation
m_savedSizes = m_router->Sizes(); m_savedSizes = m_router->Sizes();
m_router->ClearViewDecorations();
return 0; return 0;
} }
@ -1305,6 +1318,8 @@ int ROUTER_TOOL::MainLoop( const TOOL_EVENT& aEvent )
void ROUTER_TOOL::performDragging( int aMode ) void ROUTER_TOOL::performDragging( int aMode )
{ {
m_router->ClearViewDecorations();
VIEW_CONTROLS* ctls = getViewControls(); VIEW_CONTROLS* ctls = getViewControls();
if( m_startItem && m_startItem->IsLocked() ) if( m_startItem && m_startItem->IsLocked() )