sch groups: fix grid alignment on copy/paste

Fixes: https://gitlab.com/kicad/code/kicad/-/issues/20823
This commit is contained in:
Mike Williams 2025-05-05 10:00:56 -04:00
parent 9ede0ef25b
commit 3112a0b38b
2 changed files with 55 additions and 0 deletions

View File

@ -26,6 +26,7 @@
#include <functional>
#include <macros.h>
#include <gal/graphics_abstraction_layer.h>
#include <sch_group.h>
#include <sch_item.h>
#include <sch_line.h>
#include <sch_table.h>
@ -406,6 +407,28 @@ GRID_HELPER_GRIDS EE_GRID_HELPER::GetItemGrid( const EDA_ITEM* aItem ) const
case SCH_BUS_WIRE_ENTRY_T:
return GRID_WIRES;
// Groups need to get the grid of their children
case SCH_GROUP_T:
{
const SCH_GROUP* group = static_cast<const SCH_GROUP*>( aItem );
// Shouldn't happen
if( group->GetItems().empty() )
return GRID_CURRENT;
GRID_HELPER_GRIDS grid = GetItemGrid( *group->GetItems().begin() );
for( EDA_ITEM* item : static_cast<const SCH_GROUP*>( aItem )->GetItems() )
{
GRID_HELPER_GRIDS itemGrid = GetItemGrid( item );
if( GetGridSize( itemGrid ) > GetGridSize( grid ) )
grid = itemGrid;
}
return grid;
}
default:
return GRID_CURRENT;
}
@ -487,6 +510,14 @@ void EE_GRID_HELPER::computeAnchors( SCH_ITEM *aItem, const VECTOR2I &aRefPos, b
break;
}
case SCH_GROUP_T:
for( EDA_ITEM* item : static_cast<SCH_GROUP*>( aItem )->GetItems() )
{
computeAnchors( static_cast<SCH_ITEM*>( item ), aRefPos, aFrom, aIncludeText );
}
break;
default:
break;
}

View File

@ -50,6 +50,7 @@
#include <sch_edit_frame.h>
#include <sch_io/kicad_sexpr/sch_io_kicad_sexpr.h>
#include <sch_bitmap.h>
#include <sch_group.h>
#include <sch_line.h>
#include <sch_junction.h>
#include <sch_bus_entry.h>
@ -2326,6 +2327,29 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
selection.SetIsHover( m_duplicateIsHoverSelection );
}
// We want to the first non-group item in the selection to be the reference point.
else if( selection.GetTopLeftItem()->Type() == SCH_GROUP_T )
{
SCH_GROUP* group = static_cast<SCH_GROUP*>( selection.GetTopLeftItem() );
bool found = false;
SCH_ITEM* item = nullptr;
group->RunOnChildren(
[&]( SCH_ITEM* schItem )
{
if( !found && schItem->Type() != SCH_GROUP_T )
{
item = schItem;
found = true;
}
}, RECURSE_MODE::RECURSE );
if( found )
selection.SetReferencePoint( item->GetPosition() );
else
selection.SetReferencePoint( group->GetPosition() );
}
else
{
SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.GetTopLeftItem() );