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 )
{
m_infoBar->RemoveAllButtons();

View File

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

View File

@ -215,16 +215,33 @@ public:
WX_INFOBAR* GetInfoBar() { return m_infoBar; }
/**
* Show the #WX_INFOBAR displayed on the top of the canvas with a message
* and a error icon on the left of the infobar.
* 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.
*
* @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.
*/
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
* icon on the left of the infobar.

View File

@ -21,6 +21,7 @@
#ifndef INFOBAR_H_
#define INFOBAR_H_
#include <core/optional.h>
#include <wx/event.h>
#include <wx/infobar.h>
#include <wx/wx.h>
@ -129,6 +130,16 @@ public:
*/
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
* of time.
@ -214,6 +225,8 @@ protected:
wxTimer* m_showTimer; ///< The timer counting the autoclose period
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()
};

View File

@ -185,14 +185,30 @@ bool ROUTER::isStartingPointRoutable( const VECTOR2I& aWhere, ITEM* aStartItem,
if( m_mode == PNS_MODE_ROUTE_SINGLE && aStartItem )
{
VECTOR2I startPoint = aStartItem->Anchor( 0 );
SEGMENT dummyStartSeg( SEG( startPoint, startPoint ), aStartItem->Net() );
VECTOR2I startPoint = aStartItem->Anchor( 0 );
SHAPE_LINE_CHAIN dummyStartSeg;
LINE dummyStartLine;
dummyStartSeg.SetWidth( m_sizes.TrackWidth() );
dummyStartSeg.SetLayer( aLayer );
dummyStartSeg.Append( startPoint );
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;
}
}
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 )
{
if( ! isStartingPointRoutable( aP, aStartItem, aLayer ) )
if( !isStartingPointRoutable( aP, aStartItem, aLayer ) )
{
SetFailureReason( _( "The routing start point violates DRC." ) );
return false;
@ -519,6 +535,12 @@ void ROUTER::StopRouting()
}
void ROUTER::ClearViewDecorations()
{
m_iface->EraseView();
}
void ROUTER::FlipPosture()
{
if( m_state == ROUTE_TRACK )

View File

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

View File

@ -969,8 +969,18 @@ bool ROUTER_TOOL::prepareInteractive()
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 );
frame()->ShowInfoBarError( m_router->FailureReason(), true,
[&]()
{
m_router->ClearViewDecorations();
} );
controls()->SetAutoPan( false );
return false;
}
@ -1000,6 +1010,8 @@ bool ROUTER_TOOL::finishInteractive()
void ROUTER_TOOL::performRouting()
{
m_router->ClearViewDecorations();
if( !prepareInteractive() )
return;
@ -1298,6 +1310,7 @@ int ROUTER_TOOL::MainLoop( const TOOL_EVENT& aEvent )
// Store routing settings till the next invocation
m_savedSizes = m_router->Sizes();
m_router->ClearViewDecorations();
return 0;
}
@ -1305,6 +1318,8 @@ int ROUTER_TOOL::MainLoop( const TOOL_EVENT& aEvent )
void ROUTER_TOOL::performDragging( int aMode )
{
m_router->ClearViewDecorations();
VIEW_CONTROLS* ctls = getViewControls();
if( m_startItem && m_startItem->IsLocked() )