Tighten lifecycle management of parent group pointers.
Also adds some debugging to try to catch dangling pointers. Also adds a cache for group bounding boxes (which will be expensive to calculate for large groups). Fixes https://gitlab.com/kicad/code/kicad/issues/12875
This commit is contained in:
parent
78b0c29875
commit
03ba14c6d3
|
@ -66,6 +66,8 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
~BOARD_ITEM();
|
||||
|
||||
void SetParentGroup( PCB_GROUP* aGroup ) { m_group = aGroup; }
|
||||
PCB_GROUP* GetParentGroup() const { return m_group; }
|
||||
|
||||
|
@ -229,7 +231,7 @@ public:
|
|||
*
|
||||
* @param aImage the item image which contains data to swap.
|
||||
*/
|
||||
virtual void SwapData( BOARD_ITEM* aImage );
|
||||
void SwapItemData( BOARD_ITEM* aImage );
|
||||
|
||||
/**
|
||||
* Test to see if this object is on the given layer.
|
||||
|
@ -321,6 +323,8 @@ protected:
|
|||
*/
|
||||
virtual wxString layerMaskDescribe() const;
|
||||
|
||||
virtual void swapData( BOARD_ITEM* aImage );
|
||||
|
||||
protected:
|
||||
PCB_LAYER_ID m_layer;
|
||||
bool m_isKnockout;
|
||||
|
|
|
@ -145,9 +145,6 @@ public:
|
|||
*/
|
||||
PCB_GROUP* DeepDuplicate() const;
|
||||
|
||||
///< @copydoc BOARD_ITEM::SwapData
|
||||
void SwapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
///< @copydoc BOARD_ITEM::IsOnLayer
|
||||
bool IsOnLayer( PCB_LAYER_ID aLayer ) const override;
|
||||
|
||||
|
@ -221,6 +218,10 @@ public:
|
|||
*/
|
||||
void RunOnDescendants( const std::function<void( BOARD_ITEM* )>& aFunction ) const;
|
||||
|
||||
protected:
|
||||
///< @copydoc BOARD_ITEM::swapData
|
||||
void swapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
private:
|
||||
std::unordered_set<BOARD_ITEM*> m_items; // Members of the group
|
||||
wxString m_name; // Optional group name
|
||||
|
|
|
@ -120,6 +120,13 @@ BOARD::BOARD() :
|
|||
|
||||
BOARD::~BOARD()
|
||||
{
|
||||
// Untangle group parents before doing any deleting
|
||||
for( PCB_GROUP* group : m_groups )
|
||||
{
|
||||
for( BOARD_ITEM* item : group->GetItems() )
|
||||
item->SetParentGroup( nullptr );
|
||||
}
|
||||
|
||||
// Clean up the owned elements
|
||||
DeleteMARKERs();
|
||||
|
||||
|
@ -219,6 +226,7 @@ void BOARD::IncrementTimeStamp()
|
|||
|
||||
{
|
||||
std::unique_lock<std::mutex> cacheLock( m_CachesMutex );
|
||||
|
||||
m_IntersectsAreaCache.clear();
|
||||
m_EnclosedByAreaCache.clear();
|
||||
m_IntersectsCourtyardCache.clear();
|
||||
|
@ -233,6 +241,7 @@ void BOARD::IncrementTimeStamp()
|
|||
m_CopperZoneRTreeCache.clear();
|
||||
m_CopperItemRTreeCache = std::make_unique<DRC_RTREE>();
|
||||
m_ZoneBBoxCache.clear();
|
||||
m_GroupBBoxCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1690,16 +1699,6 @@ void BOARD::GetSortedPadListByXthenYCoord( std::vector<PAD*>& aVector, int aNetC
|
|||
}
|
||||
|
||||
|
||||
void BOARD::PadDelete( PAD* aPad )
|
||||
{
|
||||
GetConnectivity()->Remove( aPad );
|
||||
|
||||
InvokeListeners( &BOARD_LISTENER::OnBoardItemRemoved, *this, aPad );
|
||||
|
||||
aPad->DeleteStructure();
|
||||
}
|
||||
|
||||
|
||||
std::tuple<int, double, double> BOARD::GetTrackLength( const PCB_TRACK& aTrack ) const
|
||||
{
|
||||
int count = 0;
|
||||
|
|
|
@ -1003,14 +1003,6 @@ public:
|
|||
*/
|
||||
PAD* GetPad( std::vector<PAD*>& aPadList, const VECTOR2I& aPosition, LSET aLayerMask ) const;
|
||||
|
||||
/**
|
||||
* Delete a given pad from the BOARD by removing it from its footprint and from the
|
||||
* m_NetInfo. Makes no UI calls.
|
||||
*
|
||||
* @param aPad is the pad to delete.
|
||||
*/
|
||||
void PadDelete( PAD* aPad );
|
||||
|
||||
/**
|
||||
* First empties then fills the vector with all pads and sorts them by increasing x
|
||||
* coordinate, and for increasing y coordinate for same values of x coordinates. The vector
|
||||
|
@ -1151,6 +1143,7 @@ public:
|
|||
std::unordered_map<ZONE*, std::unique_ptr<DRC_RTREE>> m_CopperZoneRTreeCache;
|
||||
std::unique_ptr<DRC_RTREE> m_CopperItemRTreeCache;
|
||||
mutable std::unordered_map<const ZONE*, BOX2I> m_ZoneBBoxCache;
|
||||
mutable std::unordered_map<const PCB_GROUP*, BOX2I> m_GroupBBoxCache;
|
||||
|
||||
// ------------ DRC caches -------------
|
||||
std::vector<ZONE*> m_DRCZones;
|
||||
|
|
|
@ -309,6 +309,9 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
|||
itemsDeselected = true;
|
||||
}
|
||||
|
||||
if( parentGroup && !( parentGroup->GetFlags() & STRUCT_DELETED ) )
|
||||
parentGroup->RemoveItem( boardItem );
|
||||
|
||||
if( autofillZones )
|
||||
dirtyIntersectingZones( boardItem );
|
||||
|
||||
|
@ -339,9 +342,6 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
|||
break;
|
||||
}
|
||||
|
||||
if( parentGroup && !( parentGroup->GetFlags() & STRUCT_DELETED ) )
|
||||
parentGroup->RemoveItem( boardItem );
|
||||
|
||||
if( view )
|
||||
view->Remove( boardItem );
|
||||
|
||||
|
@ -649,7 +649,7 @@ void BOARD_COMMIT::Revert()
|
|||
view->Remove( item );
|
||||
connectivity->Remove( item );
|
||||
|
||||
item->SwapData( copy );
|
||||
item->SwapItemData( copy );
|
||||
|
||||
view->Add( item );
|
||||
connectivity->Add( item );
|
||||
|
|
|
@ -34,6 +34,12 @@
|
|||
#include <pcb_group.h>
|
||||
|
||||
|
||||
BOARD_ITEM::~BOARD_ITEM()
|
||||
{
|
||||
wxASSERT( m_group == nullptr );
|
||||
}
|
||||
|
||||
|
||||
const BOARD* BOARD_ITEM::GetBoard() const
|
||||
{
|
||||
if( Type() == PCB_T )
|
||||
|
@ -152,11 +158,32 @@ void BOARD_ITEM::DeleteStructure()
|
|||
}
|
||||
|
||||
|
||||
void BOARD_ITEM::SwapData( BOARD_ITEM* aImage )
|
||||
void BOARD_ITEM::swapData( BOARD_ITEM* aImage )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void BOARD_ITEM::SwapItemData( BOARD_ITEM* aImage )
|
||||
{
|
||||
if( aImage == nullptr )
|
||||
return;
|
||||
|
||||
wxASSERT( Type() == aImage->Type() );
|
||||
wxASSERT( m_Uuid == aImage->m_Uuid );
|
||||
|
||||
EDA_ITEM* parent = GetParent();
|
||||
PCB_GROUP* group = GetParentGroup();
|
||||
|
||||
SetParentGroup( nullptr );
|
||||
aImage->SetParentGroup( nullptr );
|
||||
swapData( aImage );
|
||||
|
||||
// Restore pointers to be sure they are not broken
|
||||
SetParent( parent );
|
||||
SetParentGroup( group );
|
||||
}
|
||||
|
||||
|
||||
BOARD_ITEM* BOARD_ITEM::Duplicate() const
|
||||
{
|
||||
BOARD_ITEM* dupe = static_cast<BOARD_ITEM*>( Clone() );
|
||||
|
|
|
@ -45,8 +45,6 @@ void PCB_EDIT_FRAME::Edit_Zone_Params( ZONE* aZone )
|
|||
|
||||
// Save initial zones configuration, for undo/redo, before adding new zone
|
||||
// note the net name and the layer can be changed, so we must save all zones
|
||||
deletedList.ClearListAndDeleteItems();
|
||||
pickedList.ClearListAndDeleteItems();
|
||||
SaveCopyOfZones( pickedList, GetBoard() );
|
||||
|
||||
if( aZone->GetIsRuleArea() )
|
||||
|
@ -69,8 +67,8 @@ void PCB_EDIT_FRAME::Edit_Zone_Params( ZONE* aZone )
|
|||
|
||||
if( dialogResult == wxID_CANCEL )
|
||||
{
|
||||
deletedList.ClearListAndDeleteItems();
|
||||
pickedList.ClearListAndDeleteItems();
|
||||
ClearListAndDeleteItems( &deletedList );
|
||||
ClearListAndDeleteItems( &pickedList );
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -196,6 +196,13 @@ FOOTPRINT::FOOTPRINT( FOOTPRINT&& aFootprint ) :
|
|||
|
||||
FOOTPRINT::~FOOTPRINT()
|
||||
{
|
||||
// Untangle group parents before doing any deleting
|
||||
for( PCB_GROUP* group : m_fp_groups )
|
||||
{
|
||||
for( BOARD_ITEM* item : group->GetItems() )
|
||||
item->SetParentGroup( nullptr );
|
||||
}
|
||||
|
||||
// Clean up the owned elements
|
||||
delete m_reference;
|
||||
delete m_value;
|
||||
|
@ -2573,7 +2580,7 @@ void FOOTPRINT::CheckNetTiePadGroups( const std::function<void( const wxString&
|
|||
}
|
||||
|
||||
|
||||
void FOOTPRINT::SwapData( BOARD_ITEM* aImage )
|
||||
void FOOTPRINT::swapData( BOARD_ITEM* aImage )
|
||||
{
|
||||
wxASSERT( aImage->Type() == PCB_FOOTPRINT_T );
|
||||
|
||||
|
|
|
@ -757,7 +757,9 @@ public:
|
|||
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
|
||||
FLASHING aFlash = FLASHING::DEFAULT ) const override;
|
||||
|
||||
virtual void SwapData( BOARD_ITEM* aImage ) override;
|
||||
#if defined(DEBUG)
|
||||
virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
|
||||
#endif
|
||||
|
||||
struct cmp_drawings
|
||||
{
|
||||
|
@ -774,10 +776,8 @@ public:
|
|||
bool operator()( const FP_ZONE* aFirst, const FP_ZONE* aSecond ) const;
|
||||
};
|
||||
|
||||
|
||||
#if defined(DEBUG)
|
||||
virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
|
||||
#endif
|
||||
protected:
|
||||
virtual void swapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
private:
|
||||
DRAWINGS m_drawings; // BOARD_ITEMs for drawings on the board, owned by pointer.
|
||||
|
|
|
@ -1541,7 +1541,7 @@ void PAD::ImportSettingsFrom( const PAD& aMasterPad )
|
|||
}
|
||||
|
||||
|
||||
void PAD::SwapData( BOARD_ITEM* aImage )
|
||||
void PAD::swapData( BOARD_ITEM* aImage )
|
||||
{
|
||||
assert( aImage->Type() == PCB_PAD_T );
|
||||
|
||||
|
|
|
@ -716,8 +716,6 @@ public:
|
|||
|
||||
virtual const BOX2I ViewBBox() const override;
|
||||
|
||||
virtual void SwapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
void ClearZoneConnectionCache()
|
||||
{
|
||||
for( size_t ii = 0; ii < arrayDim( m_zoneLayerConnections ); ++ii )
|
||||
|
@ -733,6 +731,8 @@ public:
|
|||
virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
virtual void swapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
private:
|
||||
void addPadPrimitivesToPolygon( SHAPE_POLY_SET* aMergedPolygon, int aError,
|
||||
|
|
|
@ -205,6 +205,8 @@ public:
|
|||
*/
|
||||
void ClearUndoORRedoList( UNDO_REDO_LIST whichList, int aItemCount = -1 ) override;
|
||||
|
||||
void ClearListAndDeleteItems( PICKED_ITEMS_LIST* aList );
|
||||
|
||||
/**
|
||||
* Return the absolute path to the design rules file for the currently-loaded board.
|
||||
*
|
||||
|
|
|
@ -94,7 +94,7 @@ EDA_ITEM* PCB_BITMAP::Clone() const
|
|||
}
|
||||
|
||||
|
||||
void PCB_BITMAP::SwapData( BOARD_ITEM* aItem )
|
||||
void PCB_BITMAP::swapData( BOARD_ITEM* aItem )
|
||||
{
|
||||
wxCHECK_RET( aItem->Type() == PCB_BITMAP_T,
|
||||
wxString::Format( wxT( "PCB_BITMAP object cannot swap data with %s object." ),
|
||||
|
|
|
@ -85,8 +85,6 @@ public:
|
|||
std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
|
||||
FLASHING aFlash = FLASHING::DEFAULT ) const override;
|
||||
|
||||
void SwapData( BOARD_ITEM* aItem ) override;
|
||||
|
||||
//void Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset ) override;
|
||||
|
||||
/// @copydoc VIEW_ITEM::ViewGetLayers()
|
||||
|
@ -128,6 +126,9 @@ public:
|
|||
void Show( int nestLevel, std::ostream& os ) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void swapData( BOARD_ITEM* aItem ) override;
|
||||
|
||||
private:
|
||||
VECTOR2I m_pos; // XY coordinates of center of the bitmap
|
||||
BITMAP_BASE* m_image; // the BITMAP_BASE item
|
||||
|
|
|
@ -560,7 +560,7 @@ EDA_ITEM* PCB_DIM_ALIGNED::Clone() const
|
|||
}
|
||||
|
||||
|
||||
void PCB_DIM_ALIGNED::SwapData( BOARD_ITEM* aImage )
|
||||
void PCB_DIM_ALIGNED::swapData( BOARD_ITEM* aImage )
|
||||
{
|
||||
wxASSERT( aImage->Type() == Type() );
|
||||
|
||||
|
@ -752,7 +752,7 @@ EDA_ITEM* PCB_DIM_ORTHOGONAL::Clone() const
|
|||
}
|
||||
|
||||
|
||||
void PCB_DIM_ORTHOGONAL::SwapData( BOARD_ITEM* aImage )
|
||||
void PCB_DIM_ORTHOGONAL::swapData( BOARD_ITEM* aImage )
|
||||
{
|
||||
wxASSERT( aImage->Type() == Type() );
|
||||
|
||||
|
@ -969,7 +969,7 @@ EDA_ITEM* PCB_DIM_LEADER::Clone() const
|
|||
}
|
||||
|
||||
|
||||
void PCB_DIM_LEADER::SwapData( BOARD_ITEM* aImage )
|
||||
void PCB_DIM_LEADER::swapData( BOARD_ITEM* aImage )
|
||||
{
|
||||
wxASSERT( aImage->Type() == Type() );
|
||||
|
||||
|
@ -1112,7 +1112,7 @@ EDA_ITEM* PCB_DIM_RADIAL::Clone() const
|
|||
}
|
||||
|
||||
|
||||
void PCB_DIM_RADIAL::SwapData( BOARD_ITEM* aImage )
|
||||
void PCB_DIM_RADIAL::swapData( BOARD_ITEM* aImage )
|
||||
{
|
||||
wxASSERT( aImage->Type() == Type() );
|
||||
|
||||
|
@ -1240,7 +1240,7 @@ EDA_ITEM* PCB_DIM_CENTER::Clone() const
|
|||
}
|
||||
|
||||
|
||||
void PCB_DIM_CENTER::SwapData( BOARD_ITEM* aImage )
|
||||
void PCB_DIM_CENTER::swapData( BOARD_ITEM* aImage )
|
||||
{
|
||||
wxASSERT( aImage->Type() == Type() );
|
||||
|
||||
|
|
|
@ -358,8 +358,6 @@ public:
|
|||
|
||||
EDA_ITEM* Clone() const override;
|
||||
|
||||
virtual void SwapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
void Mirror( const VECTOR2I& axis_pos, bool aMirrorLeftRight = false ) override;
|
||||
|
||||
BITMAPS GetMenuImage() const override;
|
||||
|
@ -406,6 +404,8 @@ public:
|
|||
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
|
||||
|
||||
protected:
|
||||
virtual void swapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
void updateGeometry() override;
|
||||
|
||||
void updateText() override;
|
||||
|
@ -445,8 +445,6 @@ public:
|
|||
|
||||
EDA_ITEM* Clone() const override;
|
||||
|
||||
void SwapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
BITMAPS GetMenuImage() const override;
|
||||
|
||||
/**
|
||||
|
@ -464,6 +462,8 @@ public:
|
|||
void Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle ) override;
|
||||
|
||||
protected:
|
||||
void swapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
void updateGeometry() override;
|
||||
|
||||
void updateText() override;
|
||||
|
@ -508,8 +508,6 @@ public:
|
|||
|
||||
EDA_ITEM* Clone() const override;
|
||||
|
||||
virtual void SwapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
void SetLeaderLength( int aLength ) { m_leaderLength = aLength; }
|
||||
int GetLeaderLength() const { return m_leaderLength; }
|
||||
|
||||
|
@ -524,6 +522,8 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
virtual void swapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
void updateText() override;
|
||||
void updateGeometry() override;
|
||||
|
||||
|
@ -559,8 +559,6 @@ public:
|
|||
|
||||
EDA_ITEM* Clone() const override;
|
||||
|
||||
virtual void SwapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
BITMAPS GetMenuImage() const override;
|
||||
|
||||
wxString GetClass() const override
|
||||
|
@ -574,6 +572,8 @@ public:
|
|||
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
|
||||
|
||||
protected:
|
||||
virtual void swapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
void updateGeometry() override;
|
||||
|
||||
private:
|
||||
|
@ -600,8 +600,6 @@ public:
|
|||
|
||||
EDA_ITEM* Clone() const override;
|
||||
|
||||
virtual void SwapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
BITMAPS GetMenuImage() const override;
|
||||
|
||||
wxString GetClass() const override
|
||||
|
@ -614,6 +612,8 @@ public:
|
|||
const BOX2I ViewBBox() const override;
|
||||
|
||||
protected:
|
||||
virtual void swapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
void updateGeometry() override;
|
||||
};
|
||||
|
||||
|
|
|
@ -208,7 +208,7 @@ PCB_GROUP* PCB_GROUP::DeepDuplicate() const
|
|||
}
|
||||
|
||||
|
||||
void PCB_GROUP::SwapData( BOARD_ITEM* aImage )
|
||||
void PCB_GROUP::swapData( BOARD_ITEM* aImage )
|
||||
{
|
||||
assert( aImage->Type() == PCB_GROUP_T );
|
||||
|
||||
|
@ -234,16 +234,41 @@ const BOX2I PCB_GROUP::GetBoundingBox() const
|
|||
{
|
||||
BOX2I bbox;
|
||||
|
||||
for( BOARD_ITEM* item : m_items )
|
||||
auto calcBBox =
|
||||
[this]()
|
||||
{
|
||||
BOX2I box;
|
||||
|
||||
for( BOARD_ITEM* item : m_items )
|
||||
{
|
||||
if( item->Type() == PCB_FOOTPRINT_T )
|
||||
box.Merge( static_cast<FOOTPRINT*>( item )->GetBoundingBox( true, false ) );
|
||||
else
|
||||
box.Merge( item->GetBoundingBox() );
|
||||
}
|
||||
|
||||
box.Inflate( pcbIUScale.mmToIU( 0.25 ) ); // Give a min size to the bbox
|
||||
|
||||
return box;
|
||||
};
|
||||
|
||||
if( const BOARD* board = GetBoard() )
|
||||
{
|
||||
if( item->Type() == PCB_FOOTPRINT_T )
|
||||
bbox.Merge( static_cast<FOOTPRINT*>( item )->GetBoundingBox( true, false ) );
|
||||
else
|
||||
bbox.Merge( item->GetBoundingBox() );
|
||||
std::unordered_map<const PCB_GROUP*, BOX2I>& cache = board->m_GroupBBoxCache;
|
||||
auto cacheIter = cache.find( this );
|
||||
|
||||
if( cacheIter != cache.end() )
|
||||
return cacheIter->second;
|
||||
|
||||
bbox = calcBBox();
|
||||
|
||||
std::unique_lock<std::mutex> cacheLock( const_cast<BOARD*>( board )->m_CachesMutex );
|
||||
cache[ this ] = bbox;
|
||||
|
||||
return bbox;
|
||||
}
|
||||
|
||||
bbox.Inflate( pcbIUScale.mmToIU( 0.25 ) ); // Give a min size to the bbox
|
||||
|
||||
return bbox;
|
||||
}
|
||||
|
||||
|
|
|
@ -347,7 +347,7 @@ std::shared_ptr<SHAPE> PCB_SHAPE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHI
|
|||
}
|
||||
|
||||
|
||||
void PCB_SHAPE::SwapData( BOARD_ITEM* aImage )
|
||||
void PCB_SHAPE::swapData( BOARD_ITEM* aImage )
|
||||
{
|
||||
PCB_SHAPE* image = dynamic_cast<PCB_SHAPE*>( aImage );
|
||||
assert( image );
|
||||
|
|
|
@ -145,18 +145,18 @@ public:
|
|||
///< @copydoc VIEW_ITEM::ViewGetLOD
|
||||
double ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const override;
|
||||
|
||||
virtual void SwapData( BOARD_ITEM* aImage ) override;
|
||||
#if defined(DEBUG)
|
||||
void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
virtual void swapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
struct cmp_drawings
|
||||
{
|
||||
bool operator()( const BOARD_ITEM* aFirst, const BOARD_ITEM* aSecond ) const;
|
||||
};
|
||||
|
||||
#if defined(DEBUG)
|
||||
void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
EDA_ANGLE getParentOrientation() const override;
|
||||
VECTOR2I getParentPosition() const override;
|
||||
};
|
||||
|
|
|
@ -138,7 +138,7 @@ EDA_ITEM* PCB_TARGET::Clone() const
|
|||
}
|
||||
|
||||
|
||||
void PCB_TARGET::SwapData( BOARD_ITEM* aImage )
|
||||
void PCB_TARGET::swapData( BOARD_ITEM* aImage )
|
||||
{
|
||||
assert( aImage->Type() == PCB_TARGET_T );
|
||||
|
||||
|
|
|
@ -92,8 +92,6 @@ public:
|
|||
|
||||
EDA_ITEM* Clone() const override;
|
||||
|
||||
virtual void SwapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
|
||||
|
||||
/**
|
||||
|
@ -116,6 +114,9 @@ public:
|
|||
void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
virtual void swapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
private:
|
||||
int m_shape; // bit 0 : 0 = draw +, 1 = draw X
|
||||
int m_size;
|
||||
|
|
|
@ -272,7 +272,7 @@ EDA_ITEM* PCB_TEXT::Clone() const
|
|||
}
|
||||
|
||||
|
||||
void PCB_TEXT::SwapData( BOARD_ITEM* aImage )
|
||||
void PCB_TEXT::swapData( BOARD_ITEM* aImage )
|
||||
{
|
||||
assert( aImage->Type() == PCB_TEXT_T );
|
||||
|
||||
|
|
|
@ -147,13 +147,13 @@ public:
|
|||
|
||||
EDA_ITEM* Clone() const override;
|
||||
|
||||
virtual void SwapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
#if defined(DEBUG)
|
||||
virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
virtual void swapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
int getKnockoutMargin() const;
|
||||
};
|
||||
|
||||
|
|
|
@ -430,7 +430,7 @@ EDA_ITEM* PCB_TEXTBOX::Clone() const
|
|||
}
|
||||
|
||||
|
||||
void PCB_TEXTBOX::SwapData( BOARD_ITEM* aImage )
|
||||
void PCB_TEXTBOX::swapData( BOARD_ITEM* aImage )
|
||||
{
|
||||
assert( aImage->Type() == PCB_TEXTBOX_T );
|
||||
|
||||
|
|
|
@ -135,7 +135,8 @@ public:
|
|||
|
||||
EDA_ITEM* Clone() const override;
|
||||
|
||||
virtual void SwapData( BOARD_ITEM* aImage ) override;
|
||||
protected:
|
||||
virtual void swapData( BOARD_ITEM* aImage ) override;
|
||||
};
|
||||
|
||||
#endif // #define PCB_TEXTBOX_H
|
||||
|
|
|
@ -1074,21 +1074,21 @@ BITMAPS PCB_TRACK::GetMenuImage() const
|
|||
return BITMAPS::add_tracks;
|
||||
}
|
||||
|
||||
void PCB_TRACK::SwapData( BOARD_ITEM* aImage )
|
||||
void PCB_TRACK::swapData( BOARD_ITEM* aImage )
|
||||
{
|
||||
assert( aImage->Type() == PCB_TRACE_T );
|
||||
|
||||
std::swap( *((PCB_TRACK*) this), *((PCB_TRACK*) aImage) );
|
||||
}
|
||||
|
||||
void PCB_ARC::SwapData( BOARD_ITEM* aImage )
|
||||
void PCB_ARC::swapData( BOARD_ITEM* aImage )
|
||||
{
|
||||
assert( aImage->Type() == PCB_ARC_T );
|
||||
|
||||
std::swap( *this, *static_cast<PCB_ARC*>( aImage ) );
|
||||
}
|
||||
|
||||
void PCB_VIA::SwapData( BOARD_ITEM* aImage )
|
||||
void PCB_VIA::swapData( BOARD_ITEM* aImage )
|
||||
{
|
||||
assert( aImage->Type() == PCB_VIA_T );
|
||||
|
||||
|
|
|
@ -210,8 +210,6 @@ public:
|
|||
|
||||
const BOX2I ViewBBox() const override;
|
||||
|
||||
virtual void SwapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
/**
|
||||
* @return true because a track or a via is always on a copper layer.
|
||||
*/
|
||||
|
@ -266,6 +264,8 @@ public:
|
|||
#endif
|
||||
|
||||
protected:
|
||||
virtual void swapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
void GetMsgPanelInfoBase_Common( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) const;
|
||||
|
||||
protected:
|
||||
|
@ -349,7 +349,8 @@ public:
|
|||
|
||||
EDA_ITEM* Clone() const override;
|
||||
|
||||
virtual void SwapData( BOARD_ITEM* aImage ) override;
|
||||
protected:
|
||||
virtual void swapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
private:
|
||||
VECTOR2I m_Mid; ///< Arc mid point, halfway between start and end
|
||||
|
@ -534,8 +535,6 @@ public:
|
|||
*/
|
||||
bool IsDrillDefault() const { return m_drill <= 0; }
|
||||
|
||||
void SwapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
// @copydoc BOARD_ITEM::GetEffectiveShape
|
||||
std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
|
||||
FLASHING aFlash = FLASHING::DEFAULT ) const override;
|
||||
|
@ -552,6 +551,8 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
void swapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
wxString layerMaskDescribe() const override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -1001,7 +1001,7 @@ int BOARD_EDITOR_CONTROL::PlaceFootprint( const TOOL_EVENT& aEvent )
|
|||
if( undo )
|
||||
{
|
||||
m_frame->PutDataInPreviousState( undo );
|
||||
undo->ClearListAndDeleteItems();
|
||||
m_frame->ClearListAndDeleteItems( undo );
|
||||
delete undo;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -681,26 +681,36 @@ int EDIT_TOOL::DragArcTrack( const TOOL_EVENT& aEvent )
|
|||
|
||||
if( aTrack->GetLength() <= aMaxLengthIU )
|
||||
{
|
||||
aTrack->SetParentGroup( nullptr );
|
||||
delete aTrack;
|
||||
delete aTrackCopy;
|
||||
aTrack = nullptr;
|
||||
|
||||
aTrackCopy->SetParentGroup( nullptr );
|
||||
delete aTrackCopy;
|
||||
aTrackCopy = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_commit->Add( aTrack );
|
||||
|
||||
aTrackCopy->SetParentGroup( nullptr );
|
||||
delete aTrackCopy;
|
||||
aTrackCopy = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if( aTrack->GetLength() <= aMaxLengthIU )
|
||||
{
|
||||
aTrack->SwapData( aTrackCopy ); //restore the original before notifying COMMIT
|
||||
aTrack->SwapItemData( aTrackCopy ); //restore the original before notifying COMMIT
|
||||
m_commit->Remove( aTrack );
|
||||
|
||||
aTrackCopy->SetParentGroup( nullptr );
|
||||
delete aTrackCopy;
|
||||
aTrackCopy = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -452,6 +452,8 @@ int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference )
|
|||
grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
|
||||
grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
|
||||
|
||||
board->m_GroupBBoxCache.clear();
|
||||
|
||||
if( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) )
|
||||
eatFirstMouseUp = false;
|
||||
|
||||
|
|
|
@ -848,6 +848,14 @@ int PCB_CONTROL::Paste( const TOOL_EVENT& aEvent )
|
|||
FOOTPRINT* editorFootprint = board()->GetFirstFootprint();
|
||||
std::vector<BOARD_ITEM*> pastedItems;
|
||||
|
||||
for( PCB_GROUP* group : clipBoard->Groups() )
|
||||
{
|
||||
group->SetParent( nullptr );
|
||||
pastedItems.push_back( group );
|
||||
}
|
||||
|
||||
clipBoard->Groups().clear();
|
||||
|
||||
for( FOOTPRINT* clipFootprint : clipBoard->Footprints() )
|
||||
pasteFootprintItemsToFootprintEditor( clipFootprint, board(), pastedItems );
|
||||
|
||||
|
@ -856,44 +864,61 @@ int PCB_CONTROL::Paste( const TOOL_EVENT& aEvent )
|
|||
if( clipDrawItem->Type() == PCB_SHAPE_T )
|
||||
{
|
||||
PCB_SHAPE* clipShape = static_cast<PCB_SHAPE*>( clipDrawItem );
|
||||
PCB_GROUP* parentGroup = clipDrawItem->GetParentGroup();
|
||||
|
||||
if( parentGroup )
|
||||
parentGroup->RemoveItem( clipDrawItem );
|
||||
|
||||
// Convert to PCB_FP_SHAPE_T
|
||||
FP_SHAPE* pastedShape = new FP_SHAPE( editorFootprint );
|
||||
static_cast<PCB_SHAPE*>( pastedShape )->SwapData( clipShape );
|
||||
static_cast<PCB_SHAPE*>( pastedShape )->SwapItemData( clipShape );
|
||||
pastedShape->SetLocalCoord();
|
||||
|
||||
// Replace parent nuked by above call to SwapData()
|
||||
pastedShape->SetParent( editorFootprint );
|
||||
if( parentGroup )
|
||||
parentGroup->AddItem( pastedShape );
|
||||
|
||||
pastedItems.push_back( pastedShape );
|
||||
}
|
||||
else if( clipDrawItem->Type() == PCB_TEXT_T )
|
||||
{
|
||||
PCB_TEXT* clipTextItem = static_cast<PCB_TEXT*>( clipDrawItem );
|
||||
PCB_TEXT* clipTextItem = static_cast<PCB_TEXT*>( clipDrawItem );
|
||||
PCB_GROUP* parentGroup = clipDrawItem->GetParentGroup();
|
||||
|
||||
if( parentGroup )
|
||||
parentGroup->RemoveItem( clipDrawItem );
|
||||
|
||||
// Convert to PCB_FP_TEXT_T
|
||||
FP_TEXT* pastedTextItem = new FP_TEXT( editorFootprint );
|
||||
static_cast<EDA_TEXT*>( pastedTextItem )->SwapText( *clipTextItem );
|
||||
static_cast<EDA_TEXT*>( pastedTextItem )->SwapAttributes( *clipTextItem );
|
||||
|
||||
pastedTextItem->SetParent( editorFootprint );
|
||||
if( parentGroup )
|
||||
parentGroup->AddItem( pastedTextItem );
|
||||
|
||||
pastedItems.push_back( pastedTextItem );
|
||||
}
|
||||
else if( clipDrawItem->Type() == PCB_TEXTBOX_T )
|
||||
{
|
||||
PCB_TEXTBOX* clipTextBox = static_cast<PCB_TEXTBOX*>( clipDrawItem );
|
||||
PCB_GROUP* parentGroup = clipDrawItem->GetParentGroup();
|
||||
|
||||
if( parentGroup )
|
||||
parentGroup->RemoveItem( clipDrawItem );
|
||||
|
||||
// Convert to PCB_FP_TEXTBOX_T
|
||||
FP_TEXTBOX* pastedTextBox = new FP_TEXTBOX( editorFootprint );
|
||||
|
||||
// Handle shape data
|
||||
static_cast<PCB_SHAPE*>( pastedTextBox )->SwapData( clipTextBox );
|
||||
static_cast<PCB_SHAPE*>( pastedTextBox )->SwapItemData( clipTextBox );
|
||||
pastedTextBox->SetLocalCoord();
|
||||
|
||||
// Handle text data
|
||||
static_cast<EDA_TEXT*>( pastedTextBox )->SwapText( *clipTextBox );
|
||||
static_cast<EDA_TEXT*>( pastedTextBox )->SwapAttributes( *clipTextBox );
|
||||
|
||||
pastedTextBox->SetParent( editorFootprint );
|
||||
if( parentGroup )
|
||||
parentGroup->AddItem( pastedTextBox );
|
||||
|
||||
pastedItems.push_back( pastedTextBox );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
|
||||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2016 CERN
|
||||
* Copyright (C) 2012-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2012-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -154,28 +154,6 @@ static bool TestForExistingItem( BOARD* aPcb, BOARD_ITEM* aItem )
|
|||
}
|
||||
|
||||
|
||||
static void SwapItemData( BOARD_ITEM* aItem, BOARD_ITEM* aImage )
|
||||
{
|
||||
if( aImage == nullptr )
|
||||
return;
|
||||
|
||||
wxASSERT( aItem->Type() == aImage->Type() );
|
||||
|
||||
// Remark: to create images of edited items to undo, we are using Clone method
|
||||
// which does not do a deep copy.
|
||||
// So we have to use the current values of these parameters.
|
||||
|
||||
wxASSERT( aItem->m_Uuid == aImage->m_Uuid );
|
||||
|
||||
EDA_ITEM* parent = aItem->GetParent();
|
||||
|
||||
aItem->SwapData( aImage );
|
||||
|
||||
// Restore pointers to be sure they are not broken
|
||||
aItem->SetParent( parent );
|
||||
}
|
||||
|
||||
|
||||
void PCB_BASE_EDIT_FRAME::saveCopyInUndoList( PICKED_ITEMS_LIST* commandToUndo,
|
||||
const PICKED_ITEMS_LIST& aItemsList,
|
||||
UNDO_REDO aCommandType )
|
||||
|
@ -469,11 +447,11 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
|
|||
BOARD_ITEM* image = (BOARD_ITEM*) aList->GetPickedItemLink( ii );
|
||||
|
||||
// Remove all pads/drawings/texts, as they become invalid
|
||||
// for the VIEW after SwapData() called for footprints
|
||||
// for the VIEW after SwapItemData() called for footprints
|
||||
view->Remove( item );
|
||||
connectivity->Remove( item );
|
||||
|
||||
SwapItemData( item, image );
|
||||
item->SwapItemData( image );
|
||||
|
||||
if( item->Type() == PCB_GROUP_T )
|
||||
{
|
||||
|
@ -594,19 +572,32 @@ void PCB_BASE_EDIT_FRAME::ClearUndoORRedoList( UNDO_REDO_LIST whichList, int aIt
|
|||
|
||||
PICKED_ITEMS_LIST* curr_cmd = list.m_CommandsList[0];
|
||||
list.m_CommandsList.erase( list.m_CommandsList.begin() );
|
||||
|
||||
curr_cmd->ClearListAndDeleteItems();
|
||||
ClearListAndDeleteItems( curr_cmd );
|
||||
delete curr_cmd; // Delete command
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PCB_BASE_EDIT_FRAME::ClearListAndDeleteItems( PICKED_ITEMS_LIST* aList )
|
||||
{
|
||||
for( size_t ii = 0; ii < aList->GetCount(); ++ii )
|
||||
{
|
||||
if( BOARD_ITEM* item = static_cast<BOARD_ITEM*>( aList->GetPickedItem( ii ) ) )
|
||||
item->SetParentGroup( nullptr );
|
||||
|
||||
if( BOARD_ITEM* link = static_cast<BOARD_ITEM*>( aList->GetPickedItemLink( ii ) ) )
|
||||
link->SetParentGroup( nullptr );
|
||||
}
|
||||
|
||||
aList->ClearListAndDeleteItems();
|
||||
}
|
||||
|
||||
|
||||
void PCB_BASE_EDIT_FRAME::RollbackFromUndo()
|
||||
{
|
||||
PICKED_ITEMS_LIST* undo = PopCommandFromUndoList();
|
||||
PutDataInPreviousState( undo );
|
||||
|
||||
undo->ClearListAndDeleteItems();
|
||||
ClearListAndDeleteItems( undo );
|
||||
delete undo;
|
||||
|
||||
GetCanvas()->Refresh();
|
||||
|
|
|
@ -972,7 +972,7 @@ BITMAPS ZONE::GetMenuImage() const
|
|||
}
|
||||
|
||||
|
||||
void ZONE::SwapData( BOARD_ITEM* aImage )
|
||||
void ZONE::swapData( BOARD_ITEM* aImage )
|
||||
{
|
||||
assert( aImage->Type() == PCB_ZONE_T || aImage->Type() == PCB_FP_ZONE_T );
|
||||
|
||||
|
|
|
@ -781,7 +781,8 @@ public:
|
|||
|
||||
#endif
|
||||
|
||||
virtual void SwapData( BOARD_ITEM* aImage ) override;
|
||||
protected:
|
||||
virtual void swapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
protected:
|
||||
SHAPE_POLY_SET* m_Poly; ///< Outline of the zone.
|
||||
|
|
Loading…
Reference in New Issue