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:
parent
1ddd0e53bb
commit
648c42f643
|
@ -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();
|
||||
|
|
|
@ -153,6 +153,9 @@ void WX_INFOBAR::Dismiss()
|
|||
if( m_auiManager )
|
||||
updateAuiLayout( false );
|
||||
|
||||
if( m_callback )
|
||||
(*m_callback)();
|
||||
|
||||
m_updateLock = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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()
|
||||
};
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -150,6 +150,7 @@ public:
|
|||
void UndoLastSegment();
|
||||
void CommitRouting();
|
||||
void StopRouting();
|
||||
void ClearViewDecorations();
|
||||
|
||||
NODE* GetWorld() const
|
||||
{
|
||||
|
|
|
@ -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() )
|
||||
|
|
Loading…
Reference in New Issue