diff --git a/include/board_item.h b/include/board_item.h index fa3aa99279..5f4ba31b41 100644 --- a/include/board_item.h +++ b/include/board_item.h @@ -198,7 +198,8 @@ public: * Invoke a function on all descendants. * @note This function should not add or remove items. */ - virtual void RunOnDescendants( const std::function& aFunction ) const { } + virtual void RunOnDescendants( const std::function& aFunction, + int aDepth = 0 ) const { } BOARD_ITEM_CONTAINER* GetParent() const { return (BOARD_ITEM_CONTAINER*) m_parent; } diff --git a/pcbnew/footprint.cpp b/pcbnew/footprint.cpp index 28be0ed11a..6fbe1f7f02 100644 --- a/pcbnew/footprint.cpp +++ b/pcbnew/footprint.cpp @@ -1724,8 +1724,13 @@ void FOOTPRINT::RunOnChildren( const std::function& aFunct } -void FOOTPRINT::RunOnDescendants( const std::function& aFunction ) const +void FOOTPRINT::RunOnDescendants( const std::function& aFunction, + int aDepth ) const { + // Avoid freezes with infinite recursion + if( aDepth > 20 ) + return; + try { for( PCB_FIELD* field : m_fields ) @@ -1740,13 +1745,13 @@ void FOOTPRINT::RunOnDescendants( const std::function& aFun for( PCB_GROUP* group : m_groups ) { aFunction( group ); - group->RunOnDescendants( aFunction ); + group->RunOnDescendants( aFunction, aDepth + 1 ); } for( BOARD_ITEM* drawing : m_drawings ) { aFunction( drawing ); - drawing->RunOnDescendants( aFunction ); + drawing->RunOnDescendants( aFunction, aDepth + 1 ); } } catch( std::bad_function_call& ) diff --git a/pcbnew/footprint.h b/pcbnew/footprint.h index 6f9a343bff..e114b8a103 100644 --- a/pcbnew/footprint.h +++ b/pcbnew/footprint.h @@ -831,7 +831,8 @@ public: void RunOnChildren( const std::function& aFunction ) const override; ///< @copydoc BOARD_ITEM::RunOnDescendants - void RunOnDescendants( const std::function& aFunction ) const override; + void RunOnDescendants( const std::function& aFunction, + int aDepth = 0 ) const override; virtual void ViewGetLayers( int aLayers[], int& aCount ) const override; diff --git a/pcbnew/pcb_group.cpp b/pcbnew/pcb_group.cpp index 9abbedded7..d25839b268 100644 --- a/pcbnew/pcb_group.cpp +++ b/pcbnew/pcb_group.cpp @@ -179,22 +179,6 @@ void PCB_GROUP::SetPosition( const VECTOR2I& aNewpos ) } -void PCB_GROUP::SetLayerRecursive( PCB_LAYER_ID aLayer, int aDepth ) -{ - for( BOARD_ITEM* item : m_items ) - { - if( ( item->Type() == PCB_GROUP_T ) && ( aDepth > 0 ) ) - { - static_cast( item )->SetLayerRecursive( aLayer, aDepth - 1 ); - } - else - { - item->SetLayer( aLayer ); - } - } -} - - void PCB_GROUP::SetLocked( bool aLockState ) { BOARD_ITEM::SetLocked( aLockState ); @@ -417,8 +401,13 @@ void PCB_GROUP::RunOnChildren( const std::function& aFuncti } -void PCB_GROUP::RunOnDescendants( const std::function& aFunction ) const +void PCB_GROUP::RunOnDescendants( const std::function& aFunction, + int aDepth ) const { + // Avoid freezes with infinite recursion + if( aDepth > 20 ) + return; + try { for( BOARD_ITEM* item : m_items ) @@ -426,7 +415,7 @@ void PCB_GROUP::RunOnDescendants( const std::function& aFun aFunction( item ); if( item->Type() == PCB_GROUP_T ) - item->RunOnDescendants( aFunction ); + item->RunOnDescendants( aFunction, aDepth + 1 ); } } catch( std::bad_function_call& ) diff --git a/pcbnew/pcb_group.h b/pcbnew/pcb_group.h index a8a1ec0e3c..53c101d931 100644 --- a/pcbnew/pcb_group.h +++ b/pcbnew/pcb_group.h @@ -125,7 +125,7 @@ public: /// @copydoc BOARD_ITEM::SetLayer void SetLayer( PCB_LAYER_ID aLayer ) override { - wxFAIL_MSG( wxT( "groups don't support layer SetLayer" ) ); + // NOP } bool IsOnCopperLayer() const override @@ -134,12 +134,6 @@ public: return false; } - /** Set layer for all items within the group. - * - * To avoid freezes with circular references, the maximum depth is 20 by default. - */ - void SetLayerRecursive( PCB_LAYER_ID aLayer, int aDepth ); - void SetLocked( bool aLocked ) override; /// @copydoc EDA_ITEM::Clone @@ -203,7 +197,8 @@ public: void RunOnChildren( const std::function& aFunction ) const override; ///< @copydoc BOARD_ITEM::RunOnDescendants - void RunOnDescendants( const std::function& aFunction ) const override; + void RunOnDescendants( const std::function& aFunction, + int aDepth = 0 ) const override; /** * Check if the proposed type can be added to a group diff --git a/pcbnew/tools/drawing_stackup_table_tool.cpp b/pcbnew/tools/drawing_stackup_table_tool.cpp index 0776193a49..d2ba9ee9b3 100644 --- a/pcbnew/tools/drawing_stackup_table_tool.cpp +++ b/pcbnew/tools/drawing_stackup_table_tool.cpp @@ -638,10 +638,13 @@ int DRAWING_TOOL::InteractivePlaceWithPreview( const TOOL_EVENT& aEvent, for( BOARD_ITEM* item : aItems ) { - if( item->Type() == PCB_GROUP_T ) - static_cast( item )->SetLayerRecursive( destLayer, 200 ); - else - item->SetLayer( destLayer ); + item->SetLayer( destLayer ); + + item->RunOnDescendants( + [&]( BOARD_ITEM* descendant ) + { + descendant->SetLayer( destLayer ); + } ); } } @@ -649,6 +652,12 @@ int DRAWING_TOOL::InteractivePlaceWithPreview( const TOOL_EVENT& aEvent, { item->Move( cursorPosition ); commit.Add( item ); + + item->RunOnDescendants( + [&]( BOARD_ITEM* descendant ) + { + commit.Add( descendant ); + } ); } commit.Push( wxT( "Placing items" ) );