Be more discerning about dirtying zones for auto-refill.

In particular, record which children caused a parent footprint to be
added to the commit so we can determine if they have intersecting
bounding boxes and/or layers.

Fixes https://gitlab.com/kicad/code/kicad/issues/13512
This commit is contained in:
Jeff Young 2023-01-13 19:07:52 +00:00
parent f358749b28
commit ea4c3a267b
3 changed files with 31 additions and 19 deletions

View File

@ -29,8 +29,7 @@
#include <cstdint>
// These define are used for the .m_flags and .m_UndoRedoStatus member of the
// class EDA_ITEM
// These define are used for the .m_flags member of the class EDA_ITEM
//
// NB: DO NOT ADD FLAGS ANYWHERE BUT AT THE END: THE FLAG-SET IS STORED AS AN INTEGER IN FILES.
//
@ -65,8 +64,8 @@
#define SHOW_ELEC_TYPE (1 << 25) ///< Show pin electrical type. Shared with IS_ROLLOVER.
#define BRIGHTENED (1 << 26) ///< item is drawn with a bright contour
#define DP_COUPLED (1 << 27) ///< item is coupled with another item making a differential pair
///< (applies to segments only)
#define IS_MODIFIED_CHILD (1 << 27)///< when a child is promoted to its parent for a COMMIT, this
///< flag indicates the modified child
#define UR_TRANSIENT (1 << 28) ///< indicates the item is owned by the undo/redo stack
#define IS_DANGLING (1 << 29) ///< indicates a pin is dangling

View File

@ -79,14 +79,26 @@ BOARD* BOARD_COMMIT::GetBoard() const
COMMIT& BOARD_COMMIT::Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType )
{
// if aItem belongs a footprint, the full footprint will be saved
// because undo/redo does not handle "sub items" modifications
if( aItem && aItem->Type() != PCB_FOOTPRINT_T && aChangeType == CHT_MODIFY )
{
EDA_ITEM* item = aItem->GetParent();
aItem->ClearFlags( IS_MODIFIED_CHILD );
if( item && item->Type() == PCB_FOOTPRINT_T ) // means aItem belongs a footprint
aItem = item;
// If aItem belongs a footprint, the full footprint will be saved because undo/redo does
// not handle "sub items" modifications. This has implications for auto-zone-refill, so
// we need to store a bit more information.
if( aItem && aChangeType == CHT_MODIFY )
{
if( aItem->Type() == PCB_FOOTPRINT_T )
{
static_cast<FOOTPRINT*>( aItem )->RunOnChildren(
[&]( BOARD_ITEM* child )
{
child->SetFlags( IS_MODIFIED_CHILD );
} );
}
else if( FOOTPRINT* fp = dynamic_cast<FOOTPRINT*>( aItem->GetParent() ) )
{
aItem->SetFlags( IS_MODIFIED_CHILD );
aItem = fp;
}
}
return COMMIT::Stage( aItem, aChangeType );
@ -105,7 +117,7 @@ COMMIT& BOARD_COMMIT::Stage( const PICKED_ITEMS_LIST& aItems, UNDO_REDO aModFlag
}
void BOARD_COMMIT::dirtyIntersectingZones( BOARD_ITEM* item )
void BOARD_COMMIT::dirtyIntersectingZones( BOARD_ITEM* item, int aChangeType )
{
wxCHECK( item, /* void */ );
@ -119,7 +131,8 @@ void BOARD_COMMIT::dirtyIntersectingZones( BOARD_ITEM* item )
static_cast<FOOTPRINT*>( item )->RunOnChildren(
[&]( BOARD_ITEM* child )
{
dirtyIntersectingZones( child );
if( aChangeType != CHT_MODIFY || ( child->GetFlags() & IS_MODIFIED_CHILD ) )
dirtyIntersectingZones( child, aChangeType );
} );
}
else if( item->Type() == PCB_GROUP_T )
@ -127,7 +140,7 @@ void BOARD_COMMIT::dirtyIntersectingZones( BOARD_ITEM* item )
static_cast<PCB_GROUP*>( item )->RunOnChildren(
[&]( BOARD_ITEM* child )
{
dirtyIntersectingZones( child );
dirtyIntersectingZones( child, aChangeType );
} );
}
else
@ -295,7 +308,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
}
if( autofillZones && boardItem->Type() != PCB_MARKER_T )
dirtyIntersectingZones( boardItem );
dirtyIntersectingZones( boardItem, changeType );
if( view && boardItem->Type() != PCB_NETINFO_T )
view->Add( boardItem );
@ -322,7 +335,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
parentGroup->RemoveItem( boardItem );
if( autofillZones )
dirtyIntersectingZones( boardItem );
dirtyIntersectingZones( boardItem, changeType );
switch( boardItem->Type() )
{
@ -462,8 +475,8 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
if( autofillZones )
{
dirtyIntersectingZones( static_cast<BOARD_ITEM*>( ent.m_copy )); // before
dirtyIntersectingZones( boardItem ); // after
dirtyIntersectingZones( static_cast<BOARD_ITEM*>( ent.m_copy ), changeType ); // before
dirtyIntersectingZones( boardItem, changeType ); // after
}
if( view )

View File

@ -77,7 +77,7 @@ private:
EDA_ITEM* makeImage( EDA_ITEM* aItem ) const override;
void dirtyIntersectingZones( BOARD_ITEM* item );
void dirtyIntersectingZones( BOARD_ITEM* item, int aChangeType );
private:
TOOL_MANAGER* m_toolMgr;