diff --git a/pcbnew/generators/pcb_tuning_pattern.cpp b/pcbnew/generators/pcb_tuning_pattern.cpp index 46d576049a..bfb924ca82 100644 --- a/pcbnew/generators/pcb_tuning_pattern.cpp +++ b/pcbnew/generators/pcb_tuning_pattern.cpp @@ -1309,7 +1309,10 @@ void PCB_TUNING_PATTERN::EditPush( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_C if( router->RoutingInProgress() ) { - router->FixRoute( m_end, nullptr, true ); + bool forceFinish = true; + bool forceCommit = false; + + router->FixRoute( m_end, nullptr, forceFinish, forceCommit ); router->StopRouting(); } diff --git a/pcbnew/router/CMakeLists.txt b/pcbnew/router/CMakeLists.txt index 7500ecfe89..b6c3f2166a 100644 --- a/pcbnew/router/CMakeLists.txt +++ b/pcbnew/router/CMakeLists.txt @@ -44,6 +44,7 @@ set( PCBNEW_PNS_SRCS pns_via.cpp pns_walkaround.cpp router_preview_item.cpp + router_status_view_item.cpp router_tool.cpp ) diff --git a/pcbnew/router/pns_component_dragger.cpp b/pcbnew/router/pns_component_dragger.cpp index b1d2025a11..42d409dde2 100644 --- a/pcbnew/router/pns_component_dragger.cpp +++ b/pcbnew/router/pns_component_dragger.cpp @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013-2020 CERN - * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2021-2024 KiCad Developers, see AUTHORS.txt for contributors. * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -244,13 +244,13 @@ bool COMPONENT_DRAGGER::Drag( const VECTOR2I& aP ) } -bool COMPONENT_DRAGGER::FixRoute() +bool COMPONENT_DRAGGER::FixRoute( bool aForceCommit ) { NODE* node = CurrentNode(); if( node ) { - if( Settings().AllowDRCViolations() || !node->CheckColliding( m_draggedItems ) ) + if( Settings().AllowDRCViolations() || aForceCommit || !node->CheckColliding( m_draggedItems ) ) { Router()->CommitRouting( node ); return true; diff --git a/pcbnew/router/pns_component_dragger.h b/pcbnew/router/pns_component_dragger.h index a9d6f1246a..c542065f5f 100644 --- a/pcbnew/router/pns_component_dragger.h +++ b/pcbnew/router/pns_component_dragger.h @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013-2020 CERN - * Copyright (C) 2013-2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2013-2024 KiCad Developers, see AUTHORS.txt for contributors. * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -66,7 +66,7 @@ public: * and eventually commits it to the world. * @return true, if dragging finished with success. */ - bool FixRoute() override; + bool FixRoute( bool aForceCommit ) override; /** * Function CurrentNode() @@ -110,6 +110,12 @@ public: return PNS::DM_COMPONENT; } + bool GetForceMarkObstaclesMode( bool* aDragStatus ) const override + { + *aDragStatus = m_dragStatus; + return false; + } + private: struct DRAGGED_CONNECTION { diff --git a/pcbnew/router/pns_drag_algo.h b/pcbnew/router/pns_drag_algo.h index ca4a7075e4..b0674efef3 100644 --- a/pcbnew/router/pns_drag_algo.h +++ b/pcbnew/router/pns_drag_algo.h @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013-2020 CERN - * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2024 KiCad Developers, see AUTHORS.txt for contributors. * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -86,7 +86,7 @@ public: * and eventually commits it to the world. * @return true, if dragging finished with success. */ - virtual bool FixRoute() = 0; + virtual bool FixRoute( bool aForceCommit ) = 0; /** * Function CurrentNode() @@ -120,6 +120,8 @@ public: virtual PNS::DRAG_MODE Mode() const = 0; + virtual bool GetForceMarkObstaclesMode( bool* aDragStatus ) const = 0; + protected: NODE* m_world; diff --git a/pcbnew/router/pns_dragger.cpp b/pcbnew/router/pns_dragger.cpp index ed20e4bcda..bad99cf114 100644 --- a/pcbnew/router/pns_dragger.cpp +++ b/pcbnew/router/pns_dragger.cpp @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013-2014 CERN - * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2024 KiCad Developers, see AUTHORS.txt for contributors. * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -116,7 +116,7 @@ bool DRAGGER::startDragSegment( const VECTOR2D& aP, SEGMENT* aSeg ) if ( m_world->CheckColliding( &m_draggedLine ) ) { // If we're already in a state that violates DRC then there's not much we can do but - // switch to mark obstacles mode (and ignore other DRC violation). + // switch to mark obstacles mode. m_forceMarkObstaclesMode = true; } @@ -162,7 +162,7 @@ bool DRAGGER::startDragArc( const VECTOR2D& aP, ARC* aArc ) if ( m_world->CheckColliding( &m_draggedLine ) ) { // If we're already in a state that violates DRC then there's not much we can do but - // switch to mark obstacles mode (and ignore other DRC violation). + // switch to mark obstacles mode. m_forceMarkObstaclesMode = true; } @@ -180,7 +180,7 @@ bool DRAGGER::startDragVia( VIA* aVia ) if ( m_world->CheckColliding( aVia ) ) { // If we're already in a state that violates DRC then there's not much we can do but - // switch to mark obstacles mode (and ignore other DRC violation). + // switch to mark obstacles mode. m_forceMarkObstaclesMode = true; } @@ -335,7 +335,7 @@ bool DRAGGER::dragMarkObstacles( const VECTOR2I& aP ) break; } - if( m_forceMarkObstaclesMode || Settings().AllowDRCViolations() ) + if( Settings().AllowDRCViolations() ) m_dragStatus = true; else m_dragStatus = !m_lastNode->CheckColliding( m_draggedItems ); @@ -704,29 +704,41 @@ bool DRAGGER::dragShove( const VECTOR2I& aP ) } -bool DRAGGER::FixRoute() +bool DRAGGER::FixRoute( bool aForceCommit ) { NODE* node = CurrentNode(); if( node ) { - // If collisions exist, we can fix in shove/smart mode because all tracks to be committed - // will be in valid positions (even if the current routing solution to the mouse cursor is - // invalid). In other modes, we can only commit if "Allow DRC violations" is enabled. - if( !m_dragStatus ) + if( m_dragStatus ) { + Router()->CommitRouting( node ); + return true; + } + else if( m_forceMarkObstaclesMode ) + { + if( aForceCommit ) + { + Router()->CommitRouting( node ); + return true; + } + + return false; + } + else + { + // If collisions exist, we can fix in shove/smart mode because all tracks to be + // committed will be in valid positions (even if the current routing solution to + // the mouse cursor is invalid). Drag( m_lastValidPoint ); node = CurrentNode(); - if( !node ) - return false; + if( node && m_dragStatus ) + { + Router()->CommitRouting( node ); + return true; + } } - - if( !m_dragStatus && !Settings().AllowDRCViolations() && !m_forceMarkObstaclesMode ) - return false; - - Router()->CommitRouting( node ); - return true; } return false; diff --git a/pcbnew/router/pns_dragger.h b/pcbnew/router/pns_dragger.h index 4f34e8f355..e3c11413ee 100644 --- a/pcbnew/router/pns_dragger.h +++ b/pcbnew/router/pns_dragger.h @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013-2014 CERN - * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2024 KiCad Developers, see AUTHORS.txt for contributors. * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -73,7 +73,7 @@ public: * and eventually commits it to the world. * @return true, if dragging finished with success. */ - bool FixRoute() override; + bool FixRoute( bool aForceCommit ) override; /** * Function CurrentNode() @@ -101,7 +101,7 @@ public: } const LINE& GetOriginalLine() -{ + { return m_draggedLine; } @@ -121,6 +121,12 @@ public: PNS::DRAG_MODE Mode() const override; + bool GetForceMarkObstaclesMode( bool* aDragStatus ) const override + { + *aDragStatus = m_dragStatus; + return m_forceMarkObstaclesMode; + } + private: const ITEM_SET findViaFanoutByHandle ( NODE *aNode, const VIA_HANDLE& handle ); diff --git a/pcbnew/router/pns_router.cpp b/pcbnew/router/pns_router.cpp index 8c0a6796e4..23943fc547 100644 --- a/pcbnew/router/pns_router.cpp +++ b/pcbnew/router/pns_router.cpp @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013-2014 CERN - * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2024 KiCad Developers, see AUTHORS.txt for contributors. * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -557,7 +557,12 @@ bool ROUTER::Finish() // If we've made it, fix the route and we're done if( moveResultPoint == otherEnd && otherEndLayers.Overlaps( GetCurrentLayer() ) ) - return FixRoute( otherEnd, otherEndItem, false ); + { + bool forceFinish = false; + bool allowViolations = false; + + return FixRoute( otherEnd, otherEndItem, forceFinish, allowViolations ); + } return false; } @@ -848,7 +853,7 @@ void ROUTER::CommitRouting( NODE* aNode ) } -bool ROUTER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish ) +bool ROUTER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish, bool aForceCommit ) { bool rv = false; @@ -863,7 +868,7 @@ bool ROUTER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish ) case DRAG_SEGMENT: case DRAG_COMPONENT: - rv = m_dragger->FixRoute(); + rv = m_dragger->FixRoute( aForceCommit ); break; default: diff --git a/pcbnew/router/pns_router.h b/pcbnew/router/pns_router.h index 0b8679a352..2b67720b4b 100644 --- a/pcbnew/router/pns_router.h +++ b/pcbnew/router/pns_router.h @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013-2014 CERN - * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2024 KiCad Developers, see AUTHORS.txt for contributors. * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -149,7 +149,7 @@ public: bool Move( const VECTOR2I& aP, ITEM* aItem ); bool Finish(); bool ContinueFromEnd( ITEM** aNewStartItem ); - bool FixRoute( const VECTOR2I& aP, ITEM* aItem, bool aForceFinish = false ); + bool FixRoute( const VECTOR2I& aP, ITEM* aItem, bool aForceFinish, bool aForceCommit ); void BreakSegment( ITEM *aItem, const VECTOR2I& aP ); std::optional UndoLastSegment(); diff --git a/pcbnew/router/router_status_view_item.cpp b/pcbnew/router/router_status_view_item.cpp new file mode 100644 index 0000000000..31b966a7d5 --- /dev/null +++ b/pcbnew/router/router_status_view_item.cpp @@ -0,0 +1,135 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include + +#include "preview_items/preview_utils.h" +#include "router_status_view_item.h" +#include "gr_text.h" + +using namespace KIGFX; + + +const BOX2I ROUTER_STATUS_VIEW_ITEM::ViewBBox() const +{ + BOX2I tmp; + + // this is an edit-time artefact; no reason to try and be smart with the bounding box + // (besides, we can't tell the text extents without a view to know what the scale is) + tmp.SetMaximum(); + return tmp; +} + +void ROUTER_STATUS_VIEW_ITEM::ViewGetLayers( int aLayers[], int& aCount ) const +{ + aLayers[0] = LAYER_UI_START; + aLayers[1] = LAYER_UI_START + 1; + aCount = 2; +} + +void ROUTER_STATUS_VIEW_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const +{ + KIGFX::GAL* gal = aView->GetGAL(); + bool viewFlipped = gal->IsFlippedX(); + bool drawingDropShadows = ( aLayer == LAYER_UI_START ); + + gal->Save(); + gal->Scale( { 1., 1. } ); + + KIGFX::PREVIEW::TEXT_DIMS textDims = KIGFX::PREVIEW::GetConstantGlyphHeight( gal, -1 ); + KIGFX::PREVIEW::TEXT_DIMS hintDims = KIGFX::PREVIEW::GetConstantGlyphHeight( gal, -2 ); + KIFONT::FONT* font = KIFONT::FONT::GetFont(); + const KIFONT::METRICS& fontMetrics = KIFONT::METRICS::Default(); + TEXT_ATTRIBUTES textAttrs; + int textWidth; + + textWidth = std::max( GRTextWidth( m_status, font, textDims.GlyphSize, textDims.StrokeWidth, + false, false, fontMetrics ), + GRTextWidth( m_hint, font, hintDims.GlyphSize, hintDims.StrokeWidth, + false, false, fontMetrics ) ); + + VECTOR2I margin( KiROUND( textDims.GlyphSize.x * 0.4 ), KiROUND( textDims.GlyphSize.y * 0.6 ) ); + VECTOR2I size( textWidth + margin.x, KiROUND( textDims.GlyphSize.y * 1.7 ) ); + VECTOR2I offset( margin.x * 5, -( size.y + margin.y * 5 ) ); + + if( !m_hint.IsEmpty() ) + size.y += KiROUND( hintDims.GlyphSize.y * 1.2 ); + + if( drawingDropShadows ) + { + gal->SetIsFill( true ); + gal->SetIsStroke( true ); + gal->SetLineWidth( gal->GetScreenWorldMatrix().GetScale().x * 2 ); + gal->SetStrokeColor( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNTEXT ) ); + KIGFX::COLOR4D bgColor( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + gal->SetFillColor( bgColor.WithAlpha( 0.9 ) ); + + gal->DrawRectangle( GetPosition() + offset - margin, + GetPosition() + offset + size + margin ); + gal->Restore(); + return; + } + + COLOR4D bg = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ); + COLOR4D normal = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNTEXT ); + COLOR4D red; + + if( viewFlipped ) + textAttrs.m_Halign = GR_TEXT_H_ALIGN_RIGHT; + else + textAttrs.m_Halign = GR_TEXT_H_ALIGN_LEFT; + + gal->SetIsFill( false ); + gal->SetIsStroke( true ); + gal->SetStrokeColor( normal ); + textAttrs.m_Halign = GR_TEXT_H_ALIGN_LEFT; + + // Prevent text flipping when view is flipped + if( gal->IsFlippedX() ) + { + textAttrs.m_Mirrored = true; + textAttrs.m_Halign = GR_TEXT_H_ALIGN_RIGHT; + } + + textAttrs.m_Size = textDims.GlyphSize; + textAttrs.m_StrokeWidth = textDims.StrokeWidth; + + VECTOR2I textPos = GetPosition() + offset + margin; + font->Draw( gal, m_status, textPos, textAttrs, KIFONT::METRICS::Default() ); + + if( !m_hint.IsEmpty() ) + { + textAttrs.m_Size = hintDims.GlyphSize; + textAttrs.m_StrokeWidth = hintDims.StrokeWidth; + + textPos.y += KiROUND( textDims.GlyphSize.y * 1.6 ); + font->Draw( gal, m_hint, textPos, textAttrs, KIFONT::METRICS::Default() ); + } + + gal->Restore(); +} + diff --git a/pcbnew/router/router_status_view_item.h b/pcbnew/router/router_status_view_item.h new file mode 100644 index 0000000000..1febd3d3d0 --- /dev/null +++ b/pcbnew/router/router_status_view_item.h @@ -0,0 +1,82 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef ROUTER_STATUS_VIEW_ITEM_H +#define ROUTER_STATUS_VIEW_ITEM_H + +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include + + +class ROUTER_STATUS_VIEW_ITEM : public EDA_ITEM +{ +public: + ROUTER_STATUS_VIEW_ITEM() : + EDA_ITEM( NOT_USED ) // Never added to anything - just a preview + { } + + wxString GetClass() const override { return wxT( "ROUTER_STATUS" ); } + +#if defined(DEBUG) + void Show( int nestLevel, std::ostream& os ) const override {} +#endif + + VECTOR2I GetPosition() const override { return m_pos; } + void SetPosition( const VECTOR2I& aPos ) override { m_pos = aPos; }; + + void SetMessage( const wxString& aStatus ) + { + m_status = aStatus; + } + + void SetHint( const wxString& aHint ) + { + m_hint = aHint; + } + + const BOX2I ViewBBox() const override; + void ViewGetLayers( int aLayers[], int& aCount ) const override; + void ViewDraw( int aLayer, KIGFX::VIEW* aView ) const override; + +protected: + VECTOR2I m_pos; + wxString m_status; + wxString m_hint; +}; + + + +#endif // ROUTER_STATUS_VIEW_ITEM_H diff --git a/pcbnew/router/router_tool.cpp b/pcbnew/router/router_tool.cpp index 3e3522e87b..5dad57c1f7 100644 --- a/pcbnew/router/router_tool.cpp +++ b/pcbnew/router/router_tool.cpp @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013-2017 CERN - * Copyright (C) 2017-2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2017-2024 KiCad Developers, see AUTHORS.txt for contributors. * * @author Tomasz Wlostowski * @@ -66,13 +66,12 @@ using namespace std::placeholders; #include #include "router_tool.h" -#include "pns_segment.h" +#include "router_status_view_item.h" #include "pns_router.h" #include "pns_itemset.h" #include "pns_logger.h" #include "pns_placement_algo.h" -#include "pns_line_placer.h" -#include "pns_topology.h" +#include "pns_drag_algo.h" #include "pns_kicad_iface.h" @@ -1391,13 +1390,16 @@ void ROUTER_TOOL::performRouting() frame()->ShowInfoBarError( m_router->FailureReason(), true ); } } - else if( evt->IsClick( BUT_LEFT ) || evt->IsDrag( BUT_LEFT ) || evt->IsAction( &PCB_ACTIONS::routeSingleTrack ) ) + else if( evt->IsClick( BUT_LEFT ) + || evt->IsDrag( BUT_LEFT ) + || evt->IsAction( &PCB_ACTIONS::routeSingleTrack ) ) { updateEndItem( *evt ); bool needLayerSwitch = m_router->IsPlacingVia(); bool forceFinish = evt->Modifier( MD_SHIFT ); + bool forceCommit = false; - if( m_router->FixRoute( m_endSnapPoint, m_endItem, forceFinish ) ) + if( m_router->FixRoute( m_endSnapPoint, m_endItem, forceFinish, forceCommit ) ) break; if( needLayerSwitch ) @@ -1437,7 +1439,10 @@ void ROUTER_TOOL::performRouting() else if( evt->IsAction( &ACTIONS::finishInteractive ) || evt->IsDblClick( BUT_LEFT ) ) { // Stop current routing: - m_router->FixRoute( m_endSnapPoint, m_endItem, true ); + bool forceFinish = true; + bool forceCommit = false; + + m_router->FixRoute( m_endSnapPoint, m_endItem, forceFinish, forceCommit ); break; } else if( evt->IsCancelInteractive() || evt->IsActivate() @@ -1848,6 +1853,9 @@ void ROUTER_TOOL::performDragging( int aMode ) { m_router->ClearViewDecorations(); + view()->ClearPreview(); + view()->InitPreview(); + VIEW_CONTROLS* ctls = getViewControls(); if( m_startItem && m_startItem->IsLocked() ) @@ -1900,10 +1908,36 @@ void ROUTER_TOOL::performDragging( int aMode ) { updateEndItem( *evt ); m_router->Move( m_endSnapPoint, m_endItem ); + + if( PNS::DRAG_ALGO* dragger = m_router->GetDragger() ) + { + bool dragStatus; + + if( dragger->GetForceMarkObstaclesMode( &dragStatus ) ) + { + view()->ClearPreview(); + + if( !dragStatus ) + { + wxString hint; + hint.Printf( _( "(%s to commit anyway.)" ), + KeyNameFromKeyCode( MD_CTRL + PSEUDO_WXK_CLICK ) ); + + ROUTER_STATUS_VIEW_ITEM* statusItem = new ROUTER_STATUS_VIEW_ITEM(); + statusItem->SetMessage( _( "Track violates DRC." ) ); + statusItem->SetHint( hint ); + statusItem->SetPosition( frame()->GetToolManager()->GetMousePosition() ); + view()->AddToPreview( statusItem ); + } + } + } } else if( evt->IsClick( BUT_LEFT ) ) { - if( m_router->FixRoute( m_endSnapPoint, m_endItem ) ) + bool forceFinish = false; + bool forceCommit = evt->Modifier( MD_CTRL ); + + if( m_router->FixRoute( m_endSnapPoint, m_endItem, forceFinish, forceCommit ) ) break; } else if( evt->IsClick( BUT_RIGHT ) ) @@ -1959,6 +1993,9 @@ void ROUTER_TOOL::performDragging( int aMode ) handleCommonEvents( *evt ); } + view()->ClearPreview(); + view()->ShowPreview( false ); + if( m_router->RoutingInProgress() ) m_router->StopRouting(); @@ -2283,13 +2320,13 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent ) updateEndItem( *evt ); m_router->Move( m_endSnapPoint, m_endItem ); + view()->ClearPreview(); + if( !footprints.empty() ) { VECTOR2I offset = m_endSnapPoint - p; BOARD_ITEM* previewItem; - view()->ClearPreview(); - for( FOOTPRINT* footprint : footprints ) { for( BOARD_ITEM* drawing : footprint->GraphicalItems() ) @@ -2347,11 +2384,35 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent ) lastOffset = offset; connectivityData->ComputeLocalRatsnest( dynamicItems, dynamicData.get(), offset ); } + + if( PNS::DRAG_ALGO* dragger = m_router->GetDragger() ) + { + bool dragStatus; + + if( dragger->GetForceMarkObstaclesMode( &dragStatus ) ) + { + if( !dragStatus ) + { + wxString hint; + hint.Printf( _( "(%s to commit anyway.)" ), + KeyNameFromKeyCode( MD_CTRL + PSEUDO_WXK_CLICK ) ); + + ROUTER_STATUS_VIEW_ITEM* statusItem = new ROUTER_STATUS_VIEW_ITEM(); + statusItem->SetMessage( _( "Track violates DRC." ) ); + statusItem->SetHint( hint ); + statusItem->SetPosition( frame()->GetToolManager()->GetMousePosition() ); + view()->AddToPreview( statusItem ); + } + } + } } else if( hasMouseMoved && ( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) ) { + bool forceFinish = false; + bool forceCommit = evt->Modifier( MD_CTRL ); + updateEndItem( *evt ); - m_router->FixRoute( m_endSnapPoint, m_endItem ); + m_router->FixRoute( m_endSnapPoint, m_endItem, forceFinish, forceCommit ); break; } else if( evt->IsUndoRedo() ) @@ -2407,12 +2468,12 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent ) view()->Hide( pad, false ); } - view()->ClearPreview(); - view()->ShowPreview( false ); - connectivityData->ClearLocalRatsnest(); } + view()->ClearPreview(); + view()->ShowPreview( false ); + // Clear temporary COURTYARD_CONFLICT flag and ensure the conflict shadow is cleared courtyardClearanceDRC.ClearConflicts( getView() ); diff --git a/qa/tools/pns/pns_log_player.cpp b/qa/tools/pns/pns_log_player.cpp index b51ec9fde4..f766309fe5 100644 --- a/qa/tools/pns/pns_log_player.cpp +++ b/qa/tools/pns/pns_log_player.cpp @@ -156,7 +156,7 @@ void PNS_LOG_PLAYER::ReplayLog( PNS_LOG_FILE* aLog, int aStartEventIndex, int aF m_debugDecorator->NewStage( "fix", 0, PNSLOGINFO ); m_viewTracker->SetStage( m_debugDecorator->GetStageCount() - 1 ); m_debugDecorator->Message( wxString::Format( "fix (%d, %d)", evt.p.x, evt.p.y ) ); - bool rv = m_router->FixRoute( evt.p, ritem ); + bool rv = m_router->FixRoute( evt.p, ritem, false, false ); printf( " fix -> (%d, %d) ret %d\n", evt.p.x, evt.p.y, rv ? 1 : 0 ); break; }