diff --git a/common/eda_base_frame.cpp b/common/eda_base_frame.cpp index ec230eab5d..a29add05ba 100644 --- a/common/eda_base_frame.cpp +++ b/common/eda_base_frame.cpp @@ -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 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(); diff --git a/common/widgets/infobar.cpp b/common/widgets/infobar.cpp index 0b1e278b2d..8cf4b48d1b 100644 --- a/common/widgets/infobar.cpp +++ b/common/widgets/infobar.cpp @@ -153,6 +153,9 @@ void WX_INFOBAR::Dismiss() if( m_auiManager ) updateAuiLayout( false ); + if( m_callback ) + (*m_callback)(); + m_updateLock = false; } diff --git a/include/eda_base_frame.h b/include/eda_base_frame.h index 782bf70e44..3dc6806ec7 100644 --- a/include/eda_base_frame.h +++ b/include/eda_base_frame.h @@ -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 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. diff --git a/include/widgets/infobar.h b/include/widgets/infobar.h index 11b3c48fa6..06ec37e081 100644 --- a/include/widgets/infobar.h +++ b/include/widgets/infobar.h @@ -21,6 +21,7 @@ #ifndef INFOBAR_H_ #define INFOBAR_H_ +#include #include #include #include @@ -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 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> m_callback; ///< Optional callback made when closing infobar + DECLARE_EVENT_TABLE() }; diff --git a/pcbnew/router/pns_router.cpp b/pcbnew/router/pns_router.cpp index aae90d1570..25e3287838 100644 --- a/pcbnew/router/pns_router.cpp +++ b/pcbnew/router/pns_router.cpp @@ -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 ) diff --git a/pcbnew/router/pns_router.h b/pcbnew/router/pns_router.h index f89116e7fd..27907c6fb7 100644 --- a/pcbnew/router/pns_router.h +++ b/pcbnew/router/pns_router.h @@ -150,6 +150,7 @@ public: void UndoLastSegment(); void CommitRouting(); void StopRouting(); + void ClearViewDecorations(); NODE* GetWorld() const { diff --git a/pcbnew/router/router_tool.cpp b/pcbnew/router/router_tool.cpp index c516ccdb4f..66716105a0 100644 --- a/pcbnew/router/router_tool.cpp +++ b/pcbnew/router/router_tool.cpp @@ -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() )