groups: extract common class methods into EDA_GROUP base class

This commit is contained in:
Mike Williams 2025-04-01 14:20:03 -04:00
parent 8b69ec4761
commit 05e9772d54
45 changed files with 409 additions and 293 deletions

View File

@ -363,6 +363,8 @@ set( COMMON_DLG_SRCS
dialogs/dialog_global_design_block_lib_table_config.cpp dialogs/dialog_global_design_block_lib_table_config.cpp
dialogs/dialog_grid_settings.cpp dialogs/dialog_grid_settings.cpp
dialogs/dialog_grid_settings_base.cpp dialogs/dialog_grid_settings_base.cpp
dialogs/dialog_group_properties.cpp
dialogs/dialog_group_properties_base.cpp
dialogs/dialog_hotkey_list.cpp dialogs/dialog_hotkey_list.cpp
dialogs/dialog_HTML_reporter_base.cpp dialogs/dialog_HTML_reporter_base.cpp
dialogs/dialog_import_choose_project.cpp dialogs/dialog_import_choose_project.cpp
@ -600,6 +602,7 @@ set( COMMON_SRCS
eda_dde.cpp eda_dde.cpp
eda_doc.cpp eda_doc.cpp
eda_draw_frame.cpp eda_draw_frame.cpp
eda_group.cpp
eda_item.cpp eda_item.cpp
eda_shape.cpp eda_shape.cpp
eda_text.cpp eda_text.cpp

View File

@ -26,6 +26,7 @@
#include <tools/pcb_picker_tool.h> #include <tools/pcb_picker_tool.h>
#include <pcb_base_edit_frame.h> #include <pcb_base_edit_frame.h>
#include <pcb_group.h> #include <pcb_group.h>
#include <eda_group.h>
#include <status_popup.h> #include <status_popup.h>
#include <board_commit.h> #include <board_commit.h>
#include <bitmaps.h> #include <bitmaps.h>
@ -33,10 +34,10 @@
#include <dialogs/dialog_group_properties.h> #include <dialogs/dialog_group_properties.h>
DIALOG_GROUP_PROPERTIES::DIALOG_GROUP_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, DIALOG_GROUP_PROPERTIES::DIALOG_GROUP_PROPERTIES( EDA_DRAW_FRAME* aParent,
PCB_GROUP* aGroup ) : EDA_GROUP* aGroup ) :
DIALOG_GROUP_PROPERTIES_BASE( aParent ), DIALOG_GROUP_PROPERTIES_BASE( aParent ),
m_brdEditor( aParent ), m_frame( aParent ),
m_toolMgr( aParent->GetToolManager() ), m_toolMgr( aParent->GetToolManager() ),
m_group( aGroup ) m_group( aGroup )
{ {
@ -45,11 +46,19 @@ DIALOG_GROUP_PROPERTIES::DIALOG_GROUP_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent,
m_nameCtrl->SetValue( m_group->GetName() ); m_nameCtrl->SetValue( m_group->GetName() );
m_locked->SetValue( m_group->IsLocked() ); if( aGroup->AsEdaItem()->Type() == PCB_GROUP_T )
{
m_locked->SetValue( static_cast<PCB_GROUP*>( aGroup )->IsLocked() );
m_locked->Show( dynamic_cast<PCB_EDIT_FRAME*>( aParent ) != nullptr ); m_locked->Show( dynamic_cast<PCB_EDIT_FRAME*>( aParent ) != nullptr );
}
else
{
m_locked->SetValue( false );
m_locked->Hide();
}
for( BOARD_ITEM* item : m_group->GetItems() ) for( EDA_ITEM* item : m_group->GetItems() )
m_membersList->Append( item->GetItemDescription( m_brdEditor, true ), item ); m_membersList->Append( item->GetItemDescription( m_frame, true ), item );
SetupStandardButtons(); SetupStandardButtons();
@ -62,11 +71,11 @@ DIALOG_GROUP_PROPERTIES::DIALOG_GROUP_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent,
DIALOG_GROUP_PROPERTIES::~DIALOG_GROUP_PROPERTIES() DIALOG_GROUP_PROPERTIES::~DIALOG_GROUP_PROPERTIES()
{ {
if( m_brdEditor->IsBeingDeleted() ) if( m_frame->IsBeingDeleted() )
return; return;
m_brdEditor->ClearFocus(); m_frame->ClearFocus();
m_brdEditor->GetCanvas()->Refresh(); m_frame->GetCanvas()->Refresh();
} }
@ -80,36 +89,40 @@ bool DIALOG_GROUP_PROPERTIES::TransferDataToWindow()
bool DIALOG_GROUP_PROPERTIES::TransferDataFromWindow() bool DIALOG_GROUP_PROPERTIES::TransferDataFromWindow()
{ {
BOARD_COMMIT commit( m_brdEditor ); BOARD_COMMIT commit( m_frame );
commit.Modify( m_group ); commit.Modify( m_group->AsEdaItem() );
for( size_t ii = 0; ii < m_membersList->GetCount(); ++ii ) for( size_t ii = 0; ii < m_membersList->GetCount(); ++ii )
{ {
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( m_membersList->GetClientData( ii ) ); EDA_ITEM* item = static_cast<EDA_ITEM*>( m_membersList->GetClientData( ii ) );
PCB_GROUP* existingGroup = item->GetParentGroup(); EDA_GROUP* existingGroup = item->GetParentGroup();
if( existingGroup != m_group ) if( existingGroup != m_group )
{ {
commit.Modify( item ); commit.Modify( item );
if( existingGroup ) if( existingGroup )
commit.Modify( existingGroup ); commit.Modify( existingGroup->AsEdaItem() );
} }
} }
m_group->SetName( m_nameCtrl->GetValue() ); m_group->SetName( m_nameCtrl->GetValue() );
m_group->SetLocked( m_locked->GetValue() );
if( m_group->AsEdaItem()->Type() == PCB_GROUP_T )
{
static_cast<PCB_GROUP*>( m_group )->SetLocked( m_locked->GetValue() );
}
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear ); m_toolMgr->RunAction( PCB_ACTIONS::selectionClear );
m_group->RemoveAll(); m_group->RemoveAll();
for( size_t ii = 0; ii < m_membersList->GetCount(); ++ii ) for( size_t ii = 0; ii < m_membersList->GetCount(); ++ii )
{ {
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( m_membersList->GetClientData( ii ) ); EDA_ITEM* item = static_cast<EDA_ITEM*>( m_membersList->GetClientData( ii ) );
m_group->AddItem( item ); m_group->AddItem( item );
} }
m_toolMgr->RunAction<EDA_ITEM*>( PCB_ACTIONS::selectItem, m_group ); m_toolMgr->RunAction<EDA_ITEM*>( PCB_ACTIONS::selectItem, m_group->AsEdaItem() );
commit.Push( _( "Edit Group Properties" ) ); commit.Push( _( "Edit Group Properties" ) );
return true; return true;
@ -122,11 +135,11 @@ void DIALOG_GROUP_PROPERTIES::OnMemberSelected( wxCommandEvent& aEvent )
if( selected >= 0 ) if( selected >= 0 )
{ {
WINDOW_THAWER thawer( m_brdEditor ); WINDOW_THAWER thawer( m_frame );
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( m_membersList->GetClientData( selected ) ); EDA_ITEM* item = static_cast<EDA_ITEM*>( m_membersList->GetClientData( selected ) );
m_brdEditor->FocusOnItem( item ); m_frame->FocusOnItem( item );
m_brdEditor->GetCanvas()->Refresh(); m_frame->GetCanvas()->Refresh();
} }
aEvent.Skip(); aEvent.Skip();
@ -144,14 +157,14 @@ void DIALOG_GROUP_PROPERTIES::DoAddMember( EDA_ITEM* aItem )
for( size_t ii = 0; ii < m_membersList->GetCount(); ++ii ) for( size_t ii = 0; ii < m_membersList->GetCount(); ++ii )
{ {
if( aItem == static_cast<BOARD_ITEM*>( m_membersList->GetClientData( ii ) ) ) if( aItem == static_cast<EDA_ITEM*>( m_membersList->GetClientData( ii ) ) )
return; return;
} }
if( aItem == m_group ) if( aItem == m_group->AsEdaItem() )
return; return;
m_membersList->Append( aItem->GetItemDescription( m_brdEditor, true ), aItem ); m_membersList->Append( aItem->GetItemDescription( m_frame, true ), aItem );
} }
@ -162,8 +175,8 @@ void DIALOG_GROUP_PROPERTIES::OnRemoveMember( wxCommandEvent& event )
if( selected >= 0 ) if( selected >= 0 )
m_membersList->Delete( selected ); m_membersList->Delete( selected );
m_brdEditor->ClearFocus(); m_frame->ClearFocus();
m_brdEditor->GetCanvas()->Refresh(); m_frame->GetCanvas()->Refresh();
} }

View File

@ -26,16 +26,17 @@
#include <dialogs/dialog_group_properties_base.h> #include <dialogs/dialog_group_properties_base.h>
class PCB_BASE_EDIT_FRAME; class EDA_DRAW_FRAME;
class TOOL_MANAGER; class TOOL_MANAGER;
class PCB_GROUP; class EDA_GROUP;
class EDA_ITEM;
class DIALOG_GROUP_PROPERTIES : public DIALOG_GROUP_PROPERTIES_BASE class DIALOG_GROUP_PROPERTIES : public DIALOG_GROUP_PROPERTIES_BASE
{ {
public: public:
DIALOG_GROUP_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, PCB_GROUP* aTarget ); DIALOG_GROUP_PROPERTIES( EDA_DRAW_FRAME* aParent, EDA_GROUP* aTarget );
~DIALOG_GROUP_PROPERTIES(); ~DIALOG_GROUP_PROPERTIES() override;
void OnMemberSelected( wxCommandEvent& event ) override; void OnMemberSelected( wxCommandEvent& event ) override;
void OnAddMember( wxCommandEvent& event ) override; void OnAddMember( wxCommandEvent& event ) override;
@ -47,9 +48,9 @@ private:
bool TransferDataToWindow() override; bool TransferDataToWindow() override;
bool TransferDataFromWindow() override; bool TransferDataFromWindow() override;
PCB_BASE_EDIT_FRAME* m_brdEditor; EDA_DRAW_FRAME* m_frame;
TOOL_MANAGER* m_toolMgr; TOOL_MANAGER* m_toolMgr;
PCB_GROUP* m_group; EDA_GROUP* m_group;
}; };
#endif // DIALOG_GROUP_PROPERTIES_H #endif // DIALOG_GROUP_PROPERTIES_H

6
common/eda_group.cpp Normal file
View File

@ -0,0 +1,6 @@
#include <eda_group.h>
EDA_GROUP::~EDA_GROUP()
{
}

95
common/eda_group.h Normal file
View File

@ -0,0 +1,95 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The 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 EDA_GROUP_H
#define EDA_GROUP_H
#include <eda_item.h>
#include <lset.h>
#include <unordered_set>
namespace KIGFX
{
class VIEW;
}
/**
* A set of EDA_ITEMs (i.e., without duplicates).
*
* The group parent is always board/sheet, not logical parent group. The group is transparent
* container - e.g., its position is derived from the position of its members. A selection
* containing a group implicitly contains its members. However other operations on sets of
* items, like committing, updating the view, etc the set is explicit.
*/
class EDA_GROUP
{
public:
virtual EDA_ITEM* AsEdaItem() = 0;
virtual ~EDA_GROUP();
wxString GetName() const { return m_name; }
void SetName( const wxString& aName ) { m_name = aName; }
std::unordered_set<EDA_ITEM*>& GetItems() { return m_items; }
const std::unordered_set<EDA_ITEM*>& GetItems() const { return m_items; }
/**
* Add item to group. Does not take ownership of item.
*
* @return true if item was added (false if item belongs to a different group).
*/
virtual bool AddItem( EDA_ITEM* aItem ) = 0;
/**
* Remove item from group.
*
* @return true if item was removed (false if item was not in the group).
*/
virtual bool RemoveItem( EDA_ITEM* aItem ) = 0;
virtual void RemoveAll() = 0;
/*
* Clone() this and all descendants
*/
virtual EDA_GROUP* DeepClone() const = 0;
/*
* Duplicate() this and all descendants
*/
virtual EDA_GROUP* DeepDuplicate() const = 0;
/**
* Check if the proposed type can be added to a group
* @param aType KICAD_T type to check
* @return true if the type can belong to a group, false otherwise
*/
//virtual static bool IsGroupableType( KICAD_T aType );
protected:
std::unordered_set<EDA_ITEM*> m_items; // Members of the group
wxString m_name; // Optional group name
};
#endif // CLASS_PCB_GROUP_H_

View File

@ -40,6 +40,7 @@ EDA_ITEM::EDA_ITEM( EDA_ITEM* parent, KICAD_T idType, bool isSCH_ITEM, bool isBO
m_structType( idType ), m_structType( idType ),
m_flags( 0 ), m_flags( 0 ),
m_parent( parent ), m_parent( parent ),
m_group( nullptr ),
m_forceVisible( false ), m_forceVisible( false ),
m_isRollover( false ) m_isRollover( false )
{ } { }
@ -50,6 +51,7 @@ EDA_ITEM::EDA_ITEM( KICAD_T idType, bool isSCH_ITEM, bool isBOARD_ITEM ) :
m_structType( idType ), m_structType( idType ),
m_flags( 0 ), m_flags( 0 ),
m_parent( nullptr ), m_parent( nullptr ),
m_group( nullptr ),
m_forceVisible( false ), m_forceVisible( false ),
m_isRollover( false ) m_isRollover( false )
{ } { }
@ -61,6 +63,7 @@ EDA_ITEM::EDA_ITEM( const EDA_ITEM& base ) :
m_structType( base.m_structType ), m_structType( base.m_structType ),
m_flags( base.m_flags ), m_flags( base.m_flags ),
m_parent( base.m_parent ), m_parent( base.m_parent ),
m_group( base.m_group ),
m_forceVisible( base.m_forceVisible ), m_forceVisible( base.m_forceVisible ),
m_isRollover( false ) m_isRollover( false )
{ {

View File

@ -22,6 +22,7 @@
*/ */
#include <bitmaps.h> #include <bitmaps.h>
#include <eda_draw_frame.h> #include <eda_draw_frame.h>
#include <eda_group.h>
#include <geometry/shape_compound.h> #include <geometry/shape_compound.h>
#include <sch_item.h> #include <sch_item.h>
#include <sch_group.h> #include <sch_group.h>
@ -74,8 +75,10 @@ bool SCH_GROUP::IsGroupableType( KICAD_T aType )
} }
bool SCH_GROUP::AddItem( SCH_ITEM* aItem ) bool SCH_GROUP::AddItem( EDA_ITEM* aItem )
{ {
wxCHECK_MSG( aItem, false, wxT( "Nullptr added to group." ) );
wxCHECK_MSG( IsGroupableType( aItem->Type() ), false, wxCHECK_MSG( IsGroupableType( aItem->Type() ), false,
wxT( "Invalid item type added to group: " ) + aItem->GetTypeDesc() ); wxT( "Invalid item type added to group: " ) + aItem->GetTypeDesc() );
@ -89,8 +92,10 @@ bool SCH_GROUP::AddItem( SCH_ITEM* aItem )
} }
bool SCH_GROUP::RemoveItem( SCH_ITEM* aItem ) bool SCH_GROUP::RemoveItem( EDA_ITEM* aItem )
{ {
wxCHECK_MSG( aItem, false, wxT( "Nullptr removed from group." ) );
// Only clear the item's group field if it was inside this group // Only clear the item's group field if it was inside this group
if( m_items.erase( aItem ) == 1 ) if( m_items.erase( aItem ) == 1 )
{ {
@ -104,18 +109,36 @@ bool SCH_GROUP::RemoveItem( SCH_ITEM* aItem )
void SCH_GROUP::RemoveAll() void SCH_GROUP::RemoveAll()
{ {
for( SCH_ITEM* item : m_items ) for( EDA_ITEM* item : m_items )
item->SetParentGroup( nullptr ); item->SetParentGroup( nullptr );
m_items.clear(); m_items.clear();
} }
std::unordered_set<SCH_ITEM*> SCH_GROUP::GetSchItems() const
{
std::unordered_set<SCH_ITEM*> items;
for( EDA_ITEM* item : m_items )
{
SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( item );
if( sch_item )
{
items.insert( sch_item );
}
}
return items;
}
/* /*
* @return if not in the symbol editor and aItem is in a symbol, returns the * @return if not in the symbol editor and aItem is in a symbol, returns the
* symbol's parent group. Otherwise, returns the aItem's parent group. * symbol's parent group. Otherwise, returns the aItem's parent group.
*/ */
SCH_GROUP* getClosestGroup( SCH_ITEM* aItem, bool isSymbolEditor ) EDA_GROUP* getClosestGroup( SCH_ITEM* aItem, bool isSymbolEditor )
{ {
if( !isSymbolEditor && aItem->GetParent() && aItem->GetParent()->Type() == SCH_SYMBOL_T ) if( !isSymbolEditor && aItem->GetParent() && aItem->GetParent()->Type() == SCH_SYMBOL_T )
return static_cast<SCH_SYMBOL*>( aItem->GetParent() )->GetParentGroup(); return static_cast<SCH_SYMBOL*>( aItem->GetParent() )->GetParentGroup();
@ -125,26 +148,26 @@ SCH_GROUP* getClosestGroup( SCH_ITEM* aItem, bool isSymbolEditor )
/// Returns the top level group inside the aScope group, or nullptr /// Returns the top level group inside the aScope group, or nullptr
SCH_GROUP* getNestedGroup( SCH_ITEM* aItem, SCH_GROUP* aScope, bool isSymbolEditor ) EDA_GROUP* getNestedGroup( SCH_ITEM* aItem, EDA_GROUP* aScope, bool isSymbolEditor )
{ {
SCH_GROUP* group = getClosestGroup( aItem, isSymbolEditor ); EDA_GROUP* group = getClosestGroup( aItem, isSymbolEditor );
if( group == aScope ) if( group == aScope )
return nullptr; return nullptr;
while( group && group->GetParentGroup() && group->GetParentGroup() != aScope ) while( group && group->AsEdaItem()->GetParentGroup() && group->AsEdaItem()->GetParentGroup() != aScope )
{ {
if( group->GetParent()->Type() == LIB_SYMBOL_T && isSymbolEditor ) if( group->AsEdaItem()->GetParent()->Type() == LIB_SYMBOL_T && isSymbolEditor )
break; break;
group = group->GetParentGroup(); group = group->AsEdaItem()->GetParentGroup();
} }
return group; return group;
} }
SCH_GROUP* SCH_GROUP::TopLevelGroup( SCH_ITEM* aItem, SCH_GROUP* aScope, bool isSymbolEditor ) EDA_GROUP* SCH_GROUP::TopLevelGroup( SCH_ITEM* aItem, EDA_GROUP* aScope, bool isSymbolEditor )
{ {
return getNestedGroup( aItem, aScope, isSymbolEditor ); return getNestedGroup( aItem, aScope, isSymbolEditor );
} }
@ -152,14 +175,14 @@ SCH_GROUP* SCH_GROUP::TopLevelGroup( SCH_ITEM* aItem, SCH_GROUP* aScope, bool is
bool SCH_GROUP::WithinScope( SCH_ITEM* aItem, SCH_GROUP* aScope, bool isSymbolEditor ) bool SCH_GROUP::WithinScope( SCH_ITEM* aItem, SCH_GROUP* aScope, bool isSymbolEditor )
{ {
SCH_GROUP* group = getClosestGroup( aItem, isSymbolEditor ); EDA_GROUP* group = getClosestGroup( aItem, isSymbolEditor );
if( group && group == aScope ) if( group && group == aScope )
return true; return true;
SCH_GROUP* nested = getNestedGroup( aItem, aScope, isSymbolEditor ); EDA_GROUP* nested = getNestedGroup( aItem, aScope, isSymbolEditor );
return nested && nested->GetParentGroup() && nested->GetParentGroup() == aScope; return nested && nested->AsEdaItem()->GetParentGroup() && nested->AsEdaItem()->GetParentGroup() == aScope;
} }
@ -191,7 +214,7 @@ SCH_GROUP* SCH_GROUP::DeepClone() const
SCH_GROUP* newGroup = new SCH_GROUP( *this ); SCH_GROUP* newGroup = new SCH_GROUP( *this );
newGroup->m_items.clear(); newGroup->m_items.clear();
for( SCH_ITEM* member : m_items ) for( EDA_ITEM* member : m_items )
{ {
if( member->Type() == SCH_GROUP_T ) if( member->Type() == SCH_GROUP_T )
newGroup->AddItem( static_cast<SCH_GROUP*>( member )->DeepClone() ); newGroup->AddItem( static_cast<SCH_GROUP*>( member )->DeepClone() );
@ -208,12 +231,12 @@ SCH_GROUP* SCH_GROUP::DeepDuplicate() const
SCH_GROUP* newGroup = static_cast<SCH_GROUP*>( Duplicate() ); SCH_GROUP* newGroup = static_cast<SCH_GROUP*>( Duplicate() );
newGroup->m_items.clear(); newGroup->m_items.clear();
for( SCH_ITEM* member : m_items ) for( EDA_ITEM* member : m_items )
{ {
if( member->Type() == SCH_GROUP_T ) if( member->Type() == SCH_GROUP_T )
newGroup->AddItem( static_cast<SCH_GROUP*>( member )->DeepDuplicate() ); newGroup->AddItem( static_cast<SCH_GROUP*>( member )->DeepDuplicate() );
else else
newGroup->AddItem( static_cast<SCH_ITEM*>( member->Duplicate() ) ); newGroup->AddItem( static_cast<SCH_ITEM*>( member )->Duplicate() );
} }
return newGroup; return newGroup;
@ -246,7 +269,7 @@ const BOX2I SCH_GROUP::GetBoundingBox() const
{ {
BOX2I bbox; BOX2I bbox;
for( SCH_ITEM* item : m_items ) for( EDA_ITEM* item : m_items )
{ {
if( item->Type() == SCH_SYMBOL_T || item->Type() == LIB_SYMBOL_T ) if( item->Type() == SCH_SYMBOL_T || item->Type() == LIB_SYMBOL_T )
bbox.Merge( static_cast<SYMBOL*>( item )->GetBoundingBox() ); bbox.Merge( static_cast<SYMBOL*>( item )->GetBoundingBox() );
@ -293,29 +316,29 @@ double SCH_GROUP::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
void SCH_GROUP::Move( const VECTOR2I& aMoveVector ) void SCH_GROUP::Move( const VECTOR2I& aMoveVector )
{ {
for( SCH_ITEM* member : m_items ) for( EDA_ITEM* member : m_items )
member->Move( aMoveVector ); static_cast<SCH_ITEM*>( member )->Move( aMoveVector );
} }
void SCH_GROUP::Rotate( const VECTOR2I& aCenter, bool aRotateCCW ) void SCH_GROUP::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
{ {
for( SCH_ITEM* member : m_items ) for( EDA_ITEM* member : m_items )
member->Rotate( aCenter, aRotateCCW ); static_cast<SCH_ITEM*>( member )->Rotate( aCenter, aRotateCCW );
} }
void SCH_GROUP::MirrorHorizontally( int aCenter ) void SCH_GROUP::MirrorHorizontally( int aCenter )
{ {
for( SCH_ITEM* item : m_items ) for( EDA_ITEM* item : m_items )
item->MirrorHorizontally( aCenter ); static_cast<SCH_ITEM*>( item )->MirrorHorizontally( aCenter );
} }
void SCH_GROUP::MirrorVertically( int aCenter ) void SCH_GROUP::MirrorVertically( int aCenter )
{ {
for( SCH_ITEM* item : m_items ) for( EDA_ITEM* item : m_items )
item->MirrorVertically( aCenter ); static_cast<SCH_ITEM*>( item )->MirrorVertically( aCenter );
} }
@ -345,12 +368,12 @@ void SCH_GROUP::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction
{ {
try try
{ {
for( SCH_ITEM* item : m_items ) for( EDA_ITEM* item : m_items )
{ {
aFunction( item ); aFunction( static_cast<SCH_ITEM*>( item ) );
if( item->Type() == SCH_GROUP_T ) if( item->Type() == SCH_GROUP_T )
item->RunOnChildren( aFunction, RECURSE_MODE::RECURSE ); static_cast<SCH_ITEM*>( item )->RunOnChildren( aFunction, RECURSE_MODE::RECURSE );
} }
} }
catch( std::bad_function_call& ) catch( std::bad_function_call& )
@ -402,11 +425,11 @@ double SCH_GROUP::Similarity( const SCH_ITEM& aOther ) const
double similarity = 0.0; double similarity = 0.0;
for( SCH_ITEM* item : m_items ) for( EDA_ITEM* item : m_items )
{ {
for( SCH_ITEM* otherItem : other.m_items ) for( EDA_ITEM* otherItem : other.m_items )
{ {
similarity += item->Similarity( *otherItem ); similarity += static_cast<SCH_ITEM*>( item )->Similarity( *static_cast<SCH_ITEM*>( otherItem ) );
} }
} }
@ -421,7 +444,9 @@ static struct SCH_GROUP_DESC
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance(); PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
REGISTER_TYPE( SCH_GROUP ); REGISTER_TYPE( SCH_GROUP );
propMgr.AddTypeCast( new TYPE_CAST<SCH_GROUP, SCH_ITEM> ); propMgr.AddTypeCast( new TYPE_CAST<SCH_GROUP, SCH_ITEM> );
propMgr.AddTypeCast( new TYPE_CAST<SCH_GROUP, EDA_GROUP> );
propMgr.InheritsAfter( TYPE_HASH( SCH_GROUP ), TYPE_HASH( SCH_ITEM ) ); propMgr.InheritsAfter( TYPE_HASH( SCH_GROUP ), TYPE_HASH( SCH_ITEM ) );
propMgr.InheritsAfter( TYPE_HASH( SCH_GROUP ), TYPE_HASH( EDA_GROUP ) );
propMgr.Mask( TYPE_HASH( SCH_GROUP ), TYPE_HASH( SCH_ITEM ), _HKI( "Position X" ) ); propMgr.Mask( TYPE_HASH( SCH_GROUP ), TYPE_HASH( SCH_ITEM ), _HKI( "Position X" ) );
propMgr.Mask( TYPE_HASH( SCH_GROUP ), TYPE_HASH( SCH_ITEM ), _HKI( "Position Y" ) ); propMgr.Mask( TYPE_HASH( SCH_GROUP ), TYPE_HASH( SCH_ITEM ), _HKI( "Position Y" ) );
@ -429,7 +454,7 @@ static struct SCH_GROUP_DESC
const wxString groupTab = _HKI( "Group Properties" ); const wxString groupTab = _HKI( "Group Properties" );
propMgr.AddProperty( propMgr.AddProperty(
new PROPERTY<SCH_GROUP, wxString>( _HKI( "Name" ), &SCH_GROUP::SetName, &SCH_GROUP::GetName ), new PROPERTY<EDA_GROUP, wxString>( _HKI( "Name" ), &SCH_GROUP::SetName, &SCH_GROUP::GetName ),
groupTab ); groupTab );
} }
} _SCH_GROUP_DESC; } _SCH_GROUP_DESC;

View File

@ -29,6 +29,7 @@
#ifndef CLASS_SCH_GROUP_H_ #ifndef CLASS_SCH_GROUP_H_
#define CLASS_SCH_GROUP_H_ #define CLASS_SCH_GROUP_H_
#include <eda_group.h>
#include <sch_commit.h> #include <sch_commit.h>
#include <sch_item.h> #include <sch_item.h>
#include <lset.h> #include <lset.h>
@ -47,39 +48,36 @@ class VIEW;
* containing a group implicitly contains its members. However other operations on sets of * containing a group implicitly contains its members. However other operations on sets of
* items, like committing, updating the view, etc the set is explicit. * items, like committing, updating the view, etc the set is explicit.
*/ */
class SCH_GROUP : public SCH_ITEM class SCH_GROUP : public SCH_ITEM, public EDA_GROUP
{ {
public: public:
SCH_GROUP(); SCH_GROUP();
SCH_GROUP( SCH_ITEM* aParent ); SCH_GROUP( SCH_ITEM* aParent );
EDA_ITEM* AsEdaItem() override { return this; }
static inline bool ClassOf( const EDA_ITEM* aItem ) { return aItem && SCH_GROUP_T == aItem->Type(); } static inline bool ClassOf( const EDA_ITEM* aItem ) { return aItem && SCH_GROUP_T == aItem->Type(); }
wxString GetClass() const override { return wxT( "SCH_GROUP" ); } wxString GetClass() const override { return wxT( "SCH_GROUP" ); }
wxString GetName() const { return m_name; }
void SetName( const wxString& aName ) { m_name = aName; }
std::unordered_set<SCH_ITEM*>& GetItems() { return m_items; }
const std::unordered_set<SCH_ITEM*>& GetItems() const { return m_items; }
/** /**
* Add item to group. Does not take ownership of item. * Add item to group. Does not take ownership of item.
* *
* @return true if item was added (false if item belongs to a different group). * @return true if item was added (false if item belongs to a different group).
*/ */
virtual bool AddItem( SCH_ITEM* aItem ); bool AddItem( EDA_ITEM* aItem ) override;
/** /**
* Remove item from group. * Remove item from group.
* *
* @return true if item was removed (false if item was not in the group). * @return true if item was removed (false if item was not in the group).
*/ */
virtual bool RemoveItem( SCH_ITEM* aItem ); bool RemoveItem( EDA_ITEM* aItem ) override;
void RemoveAll(); void RemoveAll() override;
std::unordered_set<SCH_ITEM*> GetSchItems() const;
/* /*
* Search for highest level group inside of aScope, containing item. * Search for highest level group inside of aScope, containing item.
@ -88,7 +86,7 @@ public:
* @param isSymbolEditor true if we should stop promoting at the symbol level * @param isSymbolEditor true if we should stop promoting at the symbol level
* @return group inside of aScope, containing item, if exists, otherwise, nullptr * @return group inside of aScope, containing item, if exists, otherwise, nullptr
*/ */
static SCH_GROUP* TopLevelGroup( SCH_ITEM* aItem, SCH_GROUP* aScope, bool isSymbolEditor ); static EDA_GROUP* TopLevelGroup( SCH_ITEM* aItem, EDA_GROUP* aScope, bool isSymbolEditor );
static bool WithinScope( SCH_ITEM* aItem, SCH_GROUP* aScope, bool isSymbolEditor ); static bool WithinScope( SCH_ITEM* aItem, SCH_GROUP* aScope, bool isSymbolEditor );
@ -113,12 +111,12 @@ public:
/* /*
* Clone() this and all descendants * Clone() this and all descendants
*/ */
SCH_GROUP* DeepClone() const; SCH_GROUP* DeepClone() const override;
/* /*
* Duplicate() this and all descendants * Duplicate() this and all descendants
*/ */
SCH_GROUP* DeepDuplicate() const; SCH_GROUP* DeepDuplicate() const override;
/// @copydoc EDA_ITEM::HitTest /// @copydoc EDA_ITEM::HitTest
bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override; bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override;
@ -172,10 +170,6 @@ public:
/// @copydoc SCH_ITEM::swapData /// @copydoc SCH_ITEM::swapData
void swapData( SCH_ITEM* aImage ) override; void swapData( SCH_ITEM* aImage ) override;
protected:
std::unordered_set<SCH_ITEM*> m_items; // Members of the group
wxString m_name; // Optional group name
}; };
#endif #endif

View File

@ -78,8 +78,7 @@ SCH_ITEM::SCH_ITEM( EDA_ITEM* aParent, KICAD_T aType, int aUnit, int aBodyStyle
EDA_ITEM( aParent, aType, true, false ), EDA_ITEM( aParent, aType, true, false ),
m_unit( aUnit ), m_unit( aUnit ),
m_bodyStyle( aBodyStyle ), m_bodyStyle( aBodyStyle ),
m_private( false ), m_private( false )
m_group( nullptr )
{ {
m_layer = LAYER_WIRE; // It's only a default, in fact m_layer = LAYER_WIRE; // It's only a default, in fact
m_fieldsAutoplaced = AUTOPLACE_NONE; m_fieldsAutoplaced = AUTOPLACE_NONE;
@ -95,7 +94,6 @@ SCH_ITEM::SCH_ITEM( const SCH_ITEM& aItem ) :
m_bodyStyle = aItem.m_bodyStyle; m_bodyStyle = aItem.m_bodyStyle;
m_private = aItem.m_private; m_private = aItem.m_private;
m_fieldsAutoplaced = aItem.m_fieldsAutoplaced; m_fieldsAutoplaced = aItem.m_fieldsAutoplaced;
m_group = aItem.m_group;
m_connectivity_dirty = aItem.m_connectivity_dirty; m_connectivity_dirty = aItem.m_connectivity_dirty;
} }
@ -107,7 +105,6 @@ SCH_ITEM& SCH_ITEM::operator=( const SCH_ITEM& aItem )
m_bodyStyle = aItem.m_bodyStyle; m_bodyStyle = aItem.m_bodyStyle;
m_private = aItem.m_private; m_private = aItem.m_private;
m_fieldsAutoplaced = aItem.m_fieldsAutoplaced; m_fieldsAutoplaced = aItem.m_fieldsAutoplaced;
m_group = aItem.m_group;
m_connectivity_dirty = aItem.m_connectivity_dirty; m_connectivity_dirty = aItem.m_connectivity_dirty;
return *this; return *this;
@ -116,8 +113,6 @@ SCH_ITEM& SCH_ITEM::operator=( const SCH_ITEM& aItem )
SCH_ITEM::~SCH_ITEM() SCH_ITEM::~SCH_ITEM()
{ {
wxASSERT( m_group == nullptr );
for( const auto& it : m_connection_map ) for( const auto& it : m_connection_map )
delete it.second; delete it.second;
@ -361,7 +356,7 @@ void SCH_ITEM::SwapItemData( SCH_ITEM* aImage )
return; return;
EDA_ITEM* parent = GetParent(); EDA_ITEM* parent = GetParent();
SCH_GROUP* group = GetParentGroup(); EDA_GROUP* group = GetParentGroup();
SetParentGroup( nullptr ); SetParentGroup( nullptr );
aImage->SetParentGroup( nullptr ); aImage->SetParentGroup( nullptr );

View File

@ -40,7 +40,6 @@
class CONNECTION_GRAPH; class CONNECTION_GRAPH;
class SCH_CONNECTION; class SCH_CONNECTION;
class SCH_GROUP;
class SCH_SHEET_PATH; class SCH_SHEET_PATH;
class SCHEMATIC; class SCHEMATIC;
class SYMBOL; class SYMBOL;
@ -175,9 +174,6 @@ public:
virtual ~SCH_ITEM(); virtual ~SCH_ITEM();
void SetParentGroup( SCH_GROUP* aGroup ) { m_group = aGroup; }
SCH_GROUP* GetParentGroup() const { return m_group; }
wxString GetClass() const override wxString GetClass() const override
{ {
return wxT( "SCH_ITEM" ); return wxT( "SCH_ITEM" );
@ -714,7 +710,6 @@ protected:
AUTOPLACE_ALGO m_fieldsAutoplaced; // indicates status of field autoplacement AUTOPLACE_ALGO m_fieldsAutoplaced; // indicates status of field autoplacement
VECTOR2I m_storedPos; // temp variable used in some move commands to store VECTOR2I m_storedPos; // temp variable used in some move commands to store
// an initial position of the item or mouse cursor // an initial position of the item or mouse cursor
SCH_GROUP* m_group; // The group this item belongs to
/// Store pointers to other items that are connected to this one, per sheet. /// Store pointers to other items that are connected to this one, per sheet.
std::map<SCH_SHEET_PATH, SCH_ITEM_VEC, SHEET_PATH_CMP> m_connected_items; std::map<SCH_SHEET_PATH, SCH_ITEM_VEC, SHEET_PATH_CMP> m_connected_items;

View File

@ -81,18 +81,12 @@ public:
EDA_ITEM( aParent, idtype, false, true ), EDA_ITEM( aParent, idtype, false, true ),
m_layer( aLayer ), m_layer( aLayer ),
m_isKnockout( false ), m_isKnockout( false ),
m_isLocked( false ), m_isLocked( false )
m_group( nullptr )
{ {
} }
~BOARD_ITEM();
virtual void CopyFrom( const BOARD_ITEM* aOther ); virtual void CopyFrom( const BOARD_ITEM* aOther );
void SetParentGroup( PCB_GROUP* aGroup ) { m_group = aGroup; }
PCB_GROUP* GetParentGroup() const { return m_group; }
// Do not create a copy constructor & operator=. // Do not create a copy constructor & operator=.
// The ones generated by the compiler are adequate. // The ones generated by the compiler are adequate.
int GetX() const int GetX() const
@ -452,8 +446,6 @@ protected:
bool m_isKnockout; bool m_isKnockout;
bool m_isLocked; bool m_isLocked;
PCB_GROUP* m_group;
}; };
#ifndef SWIG #ifndef SWIG

View File

@ -57,6 +57,7 @@ enum RECURSE_MODE
*/ */
class UNITS_PROVIDER; class UNITS_PROVIDER;
class EDA_DRAW_FRAME; class EDA_DRAW_FRAME;
class EDA_GROUP;
class MSG_PANEL_ITEM; class MSG_PANEL_ITEM;
class EMBEDDED_FILES; class EMBEDDED_FILES;
@ -94,7 +95,7 @@ typedef const INSPECTOR_FUNC& INSPECTOR;
class EDA_ITEM : public KIGFX::VIEW_ITEM, public SERIALIZABLE class EDA_ITEM : public KIGFX::VIEW_ITEM, public SERIALIZABLE
{ {
public: public:
virtual ~EDA_ITEM() { }; virtual ~EDA_ITEM() { wxASSERT( m_group == nullptr ); };
/** /**
* Returns the type of object. * Returns the type of object.
@ -109,6 +110,9 @@ public:
EDA_ITEM* GetParent() const { return m_parent; } EDA_ITEM* GetParent() const { return m_parent; }
virtual void SetParent( EDA_ITEM* aParent ) { m_parent = aParent; } virtual void SetParent( EDA_ITEM* aParent ) { m_parent = aParent; }
virtual void SetParentGroup( EDA_GROUP* aGroup ) { m_group = aGroup; }
EDA_GROUP* GetParentGroup() const { return m_group; }
inline bool IsModified() const { return m_flags & IS_CHANGED; } inline bool IsModified() const { return m_flags & IS_CHANGED; }
inline bool IsNew() const { return m_flags & IS_NEW; } inline bool IsNew() const { return m_flags & IS_NEW; }
inline bool IsMoving() const { return m_flags & IS_MOVING; } inline bool IsMoving() const { return m_flags & IS_MOVING; }
@ -504,6 +508,7 @@ private:
protected: protected:
EDA_ITEM_FLAGS m_flags; EDA_ITEM_FLAGS m_flags;
EDA_ITEM* m_parent; ///< Linked list: Link (parent struct). EDA_ITEM* m_parent; ///< Linked list: Link (parent struct).
EDA_GROUP* m_group; ///< The group this item belongs to
bool m_forceVisible; bool m_forceVisible;
bool m_isRollover; bool m_isRollover;
}; };

View File

@ -97,8 +97,6 @@ set( PCBNEW_DIALOGS
dialogs/dialog_global_edit_text_and_graphics.cpp dialogs/dialog_global_edit_text_and_graphics.cpp
dialogs/dialog_global_edit_text_and_graphics_base.cpp dialogs/dialog_global_edit_text_and_graphics_base.cpp
dialogs/dialog_global_fp_lib_table_config.cpp dialogs/dialog_global_fp_lib_table_config.cpp
dialogs/dialog_group_properties.cpp
dialogs/dialog_group_properties_base.cpp
dialogs/dialog_push_pad_properties.cpp dialogs/dialog_push_pad_properties.cpp
dialogs/dialog_push_pad_properties_base.cpp dialogs/dialog_push_pad_properties_base.cpp
dialogs/dialog_shape_properties.cpp dialogs/dialog_shape_properties.cpp

View File

@ -141,13 +141,13 @@ BOARD::~BOARD()
// Untangle group parents before doing any deleting // Untangle group parents before doing any deleting
for( PCB_GROUP* group : m_groups ) for( PCB_GROUP* group : m_groups )
{ {
for( BOARD_ITEM* item : group->GetItems() ) for( EDA_ITEM* item : group->GetItems() )
item->SetParentGroup( nullptr ); item->SetParentGroup( nullptr );
} }
for( PCB_GENERATOR* generator : m_generators ) for( PCB_GENERATOR* generator : m_generators )
{ {
for( BOARD_ITEM* item : generator->GetItems() ) for( EDA_ITEM* item : generator->GetItems() )
item->SetParentGroup( nullptr ); item->SetParentGroup( nullptr );
} }
@ -1311,9 +1311,9 @@ void BOARD::Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aRemoveMode )
aBoardItem->SetFlags( STRUCT_DELETED ); aBoardItem->SetFlags( STRUCT_DELETED );
PCB_GROUP* parentGroup = aBoardItem->GetParentGroup(); EDA_GROUP* parentGroup = aBoardItem->GetParentGroup();
if( parentGroup && !( parentGroup->GetFlags() & STRUCT_DELETED ) ) if( parentGroup && !( parentGroup->AsEdaItem()->GetFlags() & STRUCT_DELETED ) )
parentGroup->RemoveItem( aBoardItem ); parentGroup->RemoveItem( aBoardItem );
m_connectivity->Remove( aBoardItem ); m_connectivity->Remove( aBoardItem );
@ -2818,11 +2818,11 @@ wxString BOARD::GroupsSanityCheckInternal( bool repair )
// There may be extra time taken due to the container access calls and iterators. // There may be extra time taken due to the container access calls and iterators.
// //
// Groups we know are cycle free // Groups we know are cycle free
std::unordered_set<PCB_GROUP*> knownCycleFreeGroups; std::unordered_set<EDA_GROUP*> knownCycleFreeGroups;
// Groups in the current chain we're exploring. // Groups in the current chain we're exploring.
std::unordered_set<PCB_GROUP*> currentChainGroups; std::unordered_set<EDA_GROUP*> currentChainGroups;
// Groups we haven't checked yet. // Groups we haven't checked yet.
std::unordered_set<PCB_GROUP*> toCheckGroups; std::unordered_set<EDA_GROUP*> toCheckGroups;
// Initialize set of groups and generators to check that could participate in a cycle. // Initialize set of groups and generators to check that could participate in a cycle.
for( PCB_GROUP* group : Groups() ) for( PCB_GROUP* group : Groups() )
@ -2834,14 +2834,14 @@ wxString BOARD::GroupsSanityCheckInternal( bool repair )
while( !toCheckGroups.empty() ) while( !toCheckGroups.empty() )
{ {
currentChainGroups.clear(); currentChainGroups.clear();
PCB_GROUP* group = *toCheckGroups.begin(); EDA_GROUP* group = *toCheckGroups.begin();
while( true ) while( true )
{ {
if( currentChainGroups.find( group ) != currentChainGroups.end() ) if( currentChainGroups.find( group ) != currentChainGroups.end() )
{ {
if( repair ) if( repair )
Remove( group ); Remove( static_cast<BOARD_ITEM*>( group->AsEdaItem() ) );
return "Cycle detected in group membership"; return "Cycle detected in group membership";
} }
@ -2855,7 +2855,7 @@ wxString BOARD::GroupsSanityCheckInternal( bool repair )
// We haven't visited currIdx yet, so it must be in toCheckGroups // We haven't visited currIdx yet, so it must be in toCheckGroups
toCheckGroups.erase( group ); toCheckGroups.erase( group );
group = group->GetParentGroup(); group = group->AsEdaItem()->GetParentGroup();
if( !group ) if( !group )
{ {

View File

@ -387,7 +387,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
case CHT_REMOVE: case CHT_REMOVE:
{ {
FOOTPRINT* parentFP = boardItem->GetParentFootprint(); FOOTPRINT* parentFP = boardItem->GetParentFootprint();
PCB_GROUP* parentGroup = boardItem->GetParentGroup(); EDA_GROUP* parentGroup = boardItem->GetParentGroup();
if( !( aCommitFlags & SKIP_UNDO ) ) if( !( aCommitFlags & SKIP_UNDO ) )
undoList.PushItem( ITEM_PICKER( nullptr, boardItem, UNDO_REDO::DELETED ) ); undoList.PushItem( ITEM_PICKER( nullptr, boardItem, UNDO_REDO::DELETED ) );
@ -400,7 +400,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
itemsDeselected = true; itemsDeselected = true;
} }
if( parentGroup && !( parentGroup->GetFlags() & STRUCT_DELETED ) ) if( parentGroup && !( parentGroup->AsEdaItem()->GetFlags() & STRUCT_DELETED ) )
parentGroup->RemoveItem( boardItem ); parentGroup->RemoveItem( boardItem );
if( parentFP && !( parentFP->GetFlags() & STRUCT_DELETED ) ) if( parentFP && !( parentFP->GetFlags() & STRUCT_DELETED ) )
@ -471,12 +471,12 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
} }
case CHT_UNGROUP: case CHT_UNGROUP:
if( PCB_GROUP* group = boardItem->GetParentGroup() ) if( EDA_GROUP* group = boardItem->GetParentGroup() )
{ {
if( !( aCommitFlags & SKIP_UNDO ) ) if( !( aCommitFlags & SKIP_UNDO ) )
{ {
ITEM_PICKER itemWrapper( nullptr, boardItem, UNDO_REDO::UNGROUP ); ITEM_PICKER itemWrapper( nullptr, boardItem, UNDO_REDO::UNGROUP );
itemWrapper.SetGroupId( group->m_Uuid ); itemWrapper.SetGroupId( group->AsEdaItem()->m_Uuid );
undoList.PushItem( itemWrapper ); undoList.PushItem( itemWrapper );
} }
@ -751,9 +751,9 @@ void BOARD_COMMIT::Revert()
case CHT_ADD: case CHT_ADD:
// Items are auto-added to the parent group by BOARD_ITEM::Duplicate(), not when // Items are auto-added to the parent group by BOARD_ITEM::Duplicate(), not when
// the commit is pushed. // the commit is pushed.
if( PCB_GROUP* parentGroup = boardItem->GetParentGroup() ) if( EDA_GROUP* parentGroup = boardItem->GetParentGroup() )
{ {
if( GetStatus( parentGroup ) == 0 ) if( GetStatus( parentGroup->AsEdaItem() ) == 0 )
parentGroup->RemoveItem( boardItem ); parentGroup->RemoveItem( boardItem );
} }

View File

@ -38,12 +38,6 @@
#include <font/font.h> #include <font/font.h>
BOARD_ITEM::~BOARD_ITEM()
{
wxASSERT( m_group == nullptr );
}
void BOARD_ITEM::CopyFrom( const BOARD_ITEM* aOther ) void BOARD_ITEM::CopyFrom( const BOARD_ITEM* aOther )
{ {
wxCHECK( aOther, /* void */ ); wxCHECK( aOther, /* void */ );
@ -81,7 +75,7 @@ BOARD* BOARD_ITEM::GetBoard()
bool BOARD_ITEM::IsLocked() const bool BOARD_ITEM::IsLocked() const
{ {
if( GetParentGroup() && GetParentGroup()->IsLocked() ) if( GetParentGroup() && static_cast<PCB_GROUP*>( GetParentGroup() )->IsLocked() )
return true; return true;
const BOARD* board = GetBoard(); const BOARD* board = GetBoard();
@ -235,7 +229,7 @@ void BOARD_ITEM::SwapItemData( BOARD_ITEM* aImage )
return; return;
EDA_ITEM* parent = GetParent(); EDA_ITEM* parent = GetParent();
PCB_GROUP* group = GetParentGroup(); EDA_GROUP* group = GetParentGroup();
SetParentGroup( nullptr ); SetParentGroup( nullptr );
aImage->SetParentGroup( nullptr ); aImage->SetParentGroup( nullptr );

View File

@ -214,10 +214,10 @@ void DIALOG_CLEANUP_TRACKS_AND_VIAS::doCleanup( bool aDryRun )
{ {
if( !aItem->IsSelected() ) if( !aItem->IsSelected() )
{ {
PCB_GROUP* group = aItem->GetParentGroup(); EDA_GROUP* group = aItem->GetParentGroup();
while( group && !group->IsSelected() ) while( group && !group->AsEdaItem()->IsSelected() )
group = group->GetParentGroup(); group = group->AsEdaItem()->GetParentGroup();
if( !group ) if( !group )
return true; return true;

View File

@ -387,10 +387,10 @@ void DIALOG_GLOBAL_EDIT_TEARDROPS::visitItem( BOARD_COMMIT* aCommit,
{ {
if( !aItem->IsSelected() ) if( !aItem->IsSelected() )
{ {
PCB_GROUP* group = aItem->GetParentGroup(); EDA_GROUP* group = aItem->GetParentGroup();
while( group && !group->IsSelected() ) while( group && !group->AsEdaItem()->IsSelected() )
group = group->GetParentGroup(); group = group->AsEdaItem()->GetParentGroup();
if( !group ) if( !group )
return; return;

View File

@ -480,7 +480,7 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::visitItem( BOARD_COMMIT& aCommit, BOA
{ {
if( m_selectedItemsFilter->GetValue() ) if( m_selectedItemsFilter->GetValue() )
{ {
BOARD_ITEM* candidate = aItem; EDA_ITEM* candidate = aItem;
if( !candidate->IsSelected() ) if( !candidate->IsSelected() )
{ {
@ -490,10 +490,10 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::visitItem( BOARD_COMMIT& aCommit, BOA
if( !candidate->IsSelected() ) if( !candidate->IsSelected() )
{ {
candidate = candidate->GetParentGroup(); candidate = ( candidate->GetParentGroup() ? candidate->GetParentGroup()->AsEdaItem() : nullptr );
while( candidate && !candidate->IsSelected() ) while( candidate && !candidate->IsSelected() )
candidate = candidate->GetParentGroup(); candidate = candidate->GetParentGroup()->AsEdaItem();
if( !candidate ) if( !candidate )
return; return;

View File

@ -352,10 +352,10 @@ void DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::visitItem( PICKED_ITEMS_LIST* aUndoList
{ {
if( !aItem->IsSelected() ) if( !aItem->IsSelected() )
{ {
PCB_GROUP* group = aItem->GetParentGroup(); EDA_GROUP* group = aItem->GetParentGroup();
while( group && !group->IsSelected() ) while( group && !group->AsEdaItem()->IsSelected() )
group = group->GetParentGroup(); group = group->AsEdaItem()->GetParentGroup();
if( !group ) if( !group )
return; return;

View File

@ -136,7 +136,7 @@ FOOTPRINT::FOOTPRINT( const FOOTPRINT& aFootprint ) :
std::ranges::copy( aFootprint.m_jumperPadGroups, std::ranges::copy( aFootprint.m_jumperPadGroups,
std::inserter( m_jumperPadGroups, m_jumperPadGroups.end() ) ); std::inserter( m_jumperPadGroups, m_jumperPadGroups.end() ) );
std::map<BOARD_ITEM*, BOARD_ITEM*> ptrMap; std::map<EDA_ITEM*, EDA_ITEM*> ptrMap;
// Copy fields // Copy fields
for( PCB_FIELD* field : aFootprint.m_fields ) for( PCB_FIELD* field : aFootprint.m_fields )
@ -201,7 +201,7 @@ FOOTPRINT::FOOTPRINT( const FOOTPRINT& aFootprint ) :
newGroup->GetItems().clear(); newGroup->GetItems().clear();
for( BOARD_ITEM* member : group->GetItems() ) for( EDA_ITEM* member : group->GetItems() )
{ {
if( ptrMap.count( member ) ) if( ptrMap.count( member ) )
newGroup->AddItem( ptrMap[ member ] ); newGroup->AddItem( ptrMap[ member ] );
@ -236,7 +236,7 @@ FOOTPRINT::~FOOTPRINT()
// Untangle group parents before doing any deleting // Untangle group parents before doing any deleting
for( PCB_GROUP* group : m_groups ) for( PCB_GROUP* group : m_groups )
{ {
for( BOARD_ITEM* item : group->GetItems() ) for( EDA_ITEM* item : group->GetItems() )
item->SetParentGroup( nullptr ); item->SetParentGroup( nullptr );
} }
@ -871,7 +871,7 @@ FOOTPRINT& FOOTPRINT::operator=( const FOOTPRINT& aOther )
m_zoneConnection = aOther.m_zoneConnection; m_zoneConnection = aOther.m_zoneConnection;
m_netTiePadGroups = aOther.m_netTiePadGroups; m_netTiePadGroups = aOther.m_netTiePadGroups;
std::map<BOARD_ITEM*, BOARD_ITEM*> ptrMap; std::map<EDA_ITEM*, EDA_ITEM*> ptrMap;
// Copy fields // Copy fields
m_fields.clear(); m_fields.clear();
@ -927,7 +927,7 @@ FOOTPRINT& FOOTPRINT::operator=( const FOOTPRINT& aOther )
PCB_GROUP* newGroup = static_cast<PCB_GROUP*>( group->Clone() ); PCB_GROUP* newGroup = static_cast<PCB_GROUP*>( group->Clone() );
newGroup->GetItems().clear(); newGroup->GetItems().clear();
for( BOARD_ITEM* member : group->GetItems() ) for( EDA_ITEM* member : group->GetItems() )
newGroup->AddItem( ptrMap[ member ] ); newGroup->AddItem( ptrMap[ member ] );
Add( newGroup ); Add( newGroup );
@ -1211,9 +1211,9 @@ void FOOTPRINT::Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aMode )
aBoardItem->SetFlags( STRUCT_DELETED ); aBoardItem->SetFlags( STRUCT_DELETED );
PCB_GROUP* parentGroup = aBoardItem->GetParentGroup(); EDA_GROUP* parentGroup = aBoardItem->GetParentGroup();
if( parentGroup && !( parentGroup->GetFlags() & STRUCT_DELETED ) ) if( parentGroup && !( parentGroup->AsEdaItem()->GetFlags() & STRUCT_DELETED ) )
parentGroup->RemoveItem( aBoardItem ); parentGroup->RemoveItem( aBoardItem );
} }
@ -2808,7 +2808,7 @@ double FOOTPRINT::GetCoverageArea( const BOARD_ITEM* aItem, const GENERAL_COLLEC
{ {
double combinedArea = 0.0; double combinedArea = 0.0;
for( BOARD_ITEM* member : static_cast<const PCB_GROUP*>( aItem )->GetItems() ) for( BOARD_ITEM* member : static_cast<const PCB_GROUP*>( aItem )->GetBoardItems() )
combinedArea += GetCoverageArea( member, aCollector ); combinedArea += GetCoverageArea( member, aCollector );
return combinedArea; return combinedArea;

View File

@ -602,7 +602,7 @@ void PCB_EDIT_FRAME::ExportFootprintsToLibrary( bool aStoreInNewLib, const wxStr
auto resetGroup = auto resetGroup =
[]( FOOTPRINT* aFootprint ) []( FOOTPRINT* aFootprint )
{ {
if( PCB_GROUP* parentGroup = aFootprint->GetParentGroup() ) if( EDA_GROUP* parentGroup = aFootprint->GetParentGroup() )
parentGroup->RemoveItem( aFootprint ); parentGroup->RemoveItem( aFootprint );
}; };

View File

@ -1137,7 +1137,7 @@ void PCB_TUNING_PATTERN::Remove( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COM
{ {
PCB_GENERATOR* group = this; PCB_GENERATOR* group = this;
for( BOARD_ITEM* member : group->GetItems() ) for( EDA_ITEM* member : group->GetItems() )
aCommit->Stage( member, CHT_UNGROUP ); aCommit->Stage( member, CHT_UNGROUP );
group->GetItems().clear(); group->GetItems().clear();
@ -2004,7 +2004,7 @@ void PCB_TUNING_PATTERN::ShowPropertiesDialog( PCB_BASE_EDIT_FRAME* aEditFrame )
if( !m_items.empty() ) if( !m_items.empty() )
{ {
BOARD_ITEM* startItem = *m_items.begin(); BOARD_ITEM* startItem = static_cast<BOARD_ITEM*>( *m_items.begin() );
std::shared_ptr<DRC_ENGINE>& drcEngine = GetBoard()->GetDesignSettings().m_DRCEngine; std::shared_ptr<DRC_ENGINE>& drcEngine = GetBoard()->GetDesignSettings().m_DRCEngine;
constraint = drcEngine->EvalRules( LENGTH_CONSTRAINT, startItem, nullptr, GetLayer() ); constraint = drcEngine->EvalRules( LENGTH_CONSTRAINT, startItem, nullptr, GetLayer() );
@ -2094,7 +2094,7 @@ void PCB_TUNING_PATTERN::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame,
aList.emplace_back( _( "Type" ), GetFriendlyName() ); aList.emplace_back( _( "Type" ), GetFriendlyName() );
for( BOARD_ITEM* member : GetItems() ) for( EDA_ITEM* member : GetItems() )
{ {
if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( member ) ) if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( member ) )
{ {
@ -2539,7 +2539,7 @@ int DRAWING_TOOL::PlaceTuningPattern( const TOOL_EVENT& aEvent )
{ {
if( !m_tuningPattern->GetItems().empty() ) if( !m_tuningPattern->GetItems().empty() )
{ {
BOARD_ITEM* startItem = *m_tuningPattern->GetItems().begin(); BOARD_ITEM* startItem = *m_tuningPattern->GetBoardItems().begin();
constraint = drcEngine->EvalRules( LENGTH_CONSTRAINT, startItem, nullptr, constraint = drcEngine->EvalRules( LENGTH_CONSTRAINT, startItem, nullptr,
startItem->GetLayer() ); startItem->GetLayer() );

View File

@ -2170,7 +2170,7 @@ std::vector<PCB_SHAPE*> PAD::Recombine( bool aIsDryRun, int maxError )
// If the editor was inside a group when the pad was exploded, the added exploded shapes // If the editor was inside a group when the pad was exploded, the added exploded shapes
// will be part of the group. Remove them here before duplicating; we don't want the // will be part of the group. Remove them here before duplicating; we don't want the
// primitives to wind up in a group. // primitives to wind up in a group.
if( PCB_GROUP* group = fpShape->GetParentGroup(); group ) if( EDA_GROUP* group = fpShape->GetParentGroup(); group )
group->RemoveItem( fpShape ); group->RemoveItem( fpShape );
PCB_SHAPE* primitive = static_cast<PCB_SHAPE*>( fpShape->Duplicate() ); PCB_SHAPE* primitive = static_cast<PCB_SHAPE*>( fpShape->Duplicate() );

View File

@ -2419,7 +2419,7 @@ void PCB_EDIT_FRAME::ExchangeFootprint( FOOTPRINT* aExisting, FOOTPRINT* aNew,
bool resetTextContent, bool resetFabricationAttrs, bool resetTextContent, bool resetFabricationAttrs,
bool reset3DModels, bool* aUpdated ) bool reset3DModels, bool* aUpdated )
{ {
PCB_GROUP* parentGroup = aExisting->GetParentGroup(); EDA_GROUP* parentGroup = aExisting->GetParentGroup();
bool dummyBool = false; bool dummyBool = false;
if( !aUpdated ) if( !aUpdated )

View File

@ -44,7 +44,7 @@ PCB_GENERATOR* PCB_GENERATOR::DeepClone() const
PCB_GENERATOR* newGenerator = static_cast<PCB_GENERATOR*>( Clone() ); PCB_GENERATOR* newGenerator = static_cast<PCB_GENERATOR*>( Clone() );
newGenerator->m_items.clear(); newGenerator->m_items.clear();
for( BOARD_ITEM* member : m_items ) for( EDA_ITEM* member : m_items )
{ {
if( member->Type() == PCB_GROUP_T ) if( member->Type() == PCB_GROUP_T )
newGenerator->AddItem( static_cast<PCB_GROUP*>( member )->DeepClone() ); newGenerator->AddItem( static_cast<PCB_GROUP*>( member )->DeepClone() );
@ -158,18 +158,6 @@ void PCB_GENERATOR::baseMirror( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDir
MIRROR( m_origin.x, aCentre.x ); MIRROR( m_origin.x, aCentre.x );
} }
bool PCB_GENERATOR::AddItem( BOARD_ITEM* aItem )
{
// Items can only be in one group at a time
if( aItem->GetParentGroup() )
aItem->GetParentGroup()->RemoveItem( aItem );
m_items.insert( aItem );
aItem->SetParentGroup( this );
return true;
}
LSET PCB_GENERATOR::GetLayerSet() const LSET PCB_GENERATOR::GetLayerSet() const
{ {
return PCB_GROUP::GetLayerSet() | LSET( { GetLayer() } ); return PCB_GROUP::GetLayerSet() | LSET( { GetLayer() } );

View File

@ -51,7 +51,7 @@ public:
/* /*
* Clone() this and all descendants * Clone() this and all descendants
*/ */
PCB_GENERATOR* DeepClone() const; PCB_GENERATOR* DeepClone() const override;
virtual void EditStart( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COMMIT* aCommit ); virtual void EditStart( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COMMIT* aCommit );
@ -89,8 +89,6 @@ public:
void Mirror( const VECTOR2I& aCentre, FLIP_DIRECTION aMirrorDirection ) override; void Mirror( const VECTOR2I& aCentre, FLIP_DIRECTION aMirrorDirection ) override;
bool AddItem( BOARD_ITEM* aItem ) override;
LSET GetLayerSet() const override; LSET GetLayerSet() const override;
virtual void SetLayer( PCB_LAYER_ID aLayer ) override; virtual void SetLayer( PCB_LAYER_ID aLayer ) override;

View File

@ -78,8 +78,10 @@ bool PCB_GROUP::IsGroupableType( KICAD_T aType )
} }
bool PCB_GROUP::AddItem( BOARD_ITEM* aItem ) bool PCB_GROUP::AddItem( EDA_ITEM* aItem )
{ {
wxCHECK_MSG( aItem, false, wxT( "Nullptr added to group." ) );
wxCHECK_MSG( IsGroupableType( aItem->Type() ), false, wxCHECK_MSG( IsGroupableType( aItem->Type() ), false,
wxT( "Invalid item type added to group: " ) + aItem->GetTypeDesc() ); wxT( "Invalid item type added to group: " ) + aItem->GetTypeDesc() );
@ -93,8 +95,10 @@ bool PCB_GROUP::AddItem( BOARD_ITEM* aItem )
} }
bool PCB_GROUP::RemoveItem( BOARD_ITEM* aItem ) bool PCB_GROUP::RemoveItem( EDA_ITEM* aItem )
{ {
wxCHECK_MSG( aItem, false, wxT( "Nullptr removed from group." ) );
// Only clear the item's group field if it was inside this group // Only clear the item's group field if it was inside this group
if( m_items.erase( aItem ) == 1 ) if( m_items.erase( aItem ) == 1 )
{ {
@ -108,18 +112,36 @@ bool PCB_GROUP::RemoveItem( BOARD_ITEM* aItem )
void PCB_GROUP::RemoveAll() void PCB_GROUP::RemoveAll()
{ {
for( BOARD_ITEM* item : m_items ) for( EDA_ITEM* item : m_items )
item->SetParentGroup( nullptr ); item->SetParentGroup( nullptr );
m_items.clear(); m_items.clear();
} }
std::unordered_set<BOARD_ITEM*> PCB_GROUP::GetBoardItems() const
{
std::unordered_set<BOARD_ITEM*> items;
for( EDA_ITEM* item : m_items )
{
BOARD_ITEM* board_item = dynamic_cast<BOARD_ITEM*>( item );
if( board_item )
{
items.insert( board_item );
}
}
return items;
}
/* /*
* @return if not in the footprint editor and aItem is in a footprint, returns the * @return if not in the footprint editor and aItem is in a footprint, returns the
* footprint's parent group. Otherwise, returns the aItem's parent group. * footprint's parent group. Otherwise, returns the aItem's parent group.
*/ */
PCB_GROUP* getClosestGroup( BOARD_ITEM* aItem, bool isFootprintEditor ) EDA_GROUP* getClosestGroup( BOARD_ITEM* aItem, bool isFootprintEditor )
{ {
if( !isFootprintEditor && aItem->GetParent() && aItem->GetParent()->Type() == PCB_FOOTPRINT_T ) if( !isFootprintEditor && aItem->GetParent() && aItem->GetParent()->Type() == PCB_FOOTPRINT_T )
return aItem->GetParent()->GetParentGroup(); return aItem->GetParent()->GetParentGroup();
@ -129,26 +151,26 @@ PCB_GROUP* getClosestGroup( BOARD_ITEM* aItem, bool isFootprintEditor )
/// Returns the top level group inside the aScope group, or nullptr /// Returns the top level group inside the aScope group, or nullptr
PCB_GROUP* getNestedGroup( BOARD_ITEM* aItem, PCB_GROUP* aScope, bool isFootprintEditor ) EDA_GROUP* getNestedGroup( BOARD_ITEM* aItem, EDA_GROUP* aScope, bool isFootprintEditor )
{ {
PCB_GROUP* group = getClosestGroup( aItem, isFootprintEditor ); EDA_GROUP* group = getClosestGroup( aItem, isFootprintEditor );
if( group == aScope ) if( group == aScope )
return nullptr; return nullptr;
while( group && group->GetParentGroup() && group->GetParentGroup() != aScope ) while( group && group->AsEdaItem()->GetParentGroup() && group->AsEdaItem()->GetParentGroup() != aScope )
{ {
if( group->GetParent()->Type() == PCB_FOOTPRINT_T && isFootprintEditor ) if( group->AsEdaItem()->GetParent()->Type() == PCB_FOOTPRINT_T && isFootprintEditor )
break; break;
group = group->GetParentGroup(); group = group->AsEdaItem()->GetParentGroup();
} }
return group; return group;
} }
PCB_GROUP* PCB_GROUP::TopLevelGroup( BOARD_ITEM* aItem, PCB_GROUP* aScope, bool isFootprintEditor ) EDA_GROUP* PCB_GROUP::TopLevelGroup( BOARD_ITEM* aItem, EDA_GROUP* aScope, bool isFootprintEditor )
{ {
return getNestedGroup( aItem, aScope, isFootprintEditor ); return getNestedGroup( aItem, aScope, isFootprintEditor );
} }
@ -156,14 +178,14 @@ PCB_GROUP* PCB_GROUP::TopLevelGroup( BOARD_ITEM* aItem, PCB_GROUP* aScope, bool
bool PCB_GROUP::WithinScope( BOARD_ITEM* aItem, PCB_GROUP* aScope, bool isFootprintEditor ) bool PCB_GROUP::WithinScope( BOARD_ITEM* aItem, PCB_GROUP* aScope, bool isFootprintEditor )
{ {
PCB_GROUP* group = getClosestGroup( aItem, isFootprintEditor ); EDA_GROUP* group = getClosestGroup( aItem, isFootprintEditor );
if( group && group == aScope ) if( group && group == aScope )
return true; return true;
PCB_GROUP* nested = getNestedGroup( aItem, aScope, isFootprintEditor ); EDA_GROUP* nested = getNestedGroup( aItem, aScope, isFootprintEditor );
return nested && nested->GetParentGroup() && nested->GetParentGroup() == aScope; return nested && nested->AsEdaItem()->GetParentGroup() && ( nested->AsEdaItem()->GetParentGroup() == aScope );
} }
@ -208,7 +230,7 @@ PCB_GROUP* PCB_GROUP::DeepClone() const
PCB_GROUP* newGroup = new PCB_GROUP( *this ); PCB_GROUP* newGroup = new PCB_GROUP( *this );
newGroup->m_items.clear(); newGroup->m_items.clear();
for( BOARD_ITEM* member : m_items ) for( EDA_ITEM* member : m_items )
{ {
if( member->Type() == PCB_GROUP_T ) if( member->Type() == PCB_GROUP_T )
newGroup->AddItem( static_cast<PCB_GROUP*>( member )->DeepClone() ); newGroup->AddItem( static_cast<PCB_GROUP*>( member )->DeepClone() );
@ -227,12 +249,12 @@ PCB_GROUP* PCB_GROUP::DeepDuplicate() const
PCB_GROUP* newGroup = static_cast<PCB_GROUP*>( Duplicate() ); PCB_GROUP* newGroup = static_cast<PCB_GROUP*>( Duplicate() );
newGroup->m_items.clear(); newGroup->m_items.clear();
for( BOARD_ITEM* member : m_items ) for( EDA_ITEM* member : m_items )
{ {
if( member->Type() == PCB_GROUP_T ) if( member->Type() == PCB_GROUP_T )
newGroup->AddItem( static_cast<PCB_GROUP*>( member )->DeepDuplicate() ); newGroup->AddItem( static_cast<PCB_GROUP*>( member )->DeepDuplicate() );
else else
newGroup->AddItem( static_cast<BOARD_ITEM*>( member->Duplicate() ) ); newGroup->AddItem( static_cast<BOARD_ITEM*>( static_cast<BOARD_ITEM*>( member )->Duplicate() ) );
} }
return newGroup; return newGroup;
@ -265,7 +287,7 @@ const BOX2I PCB_GROUP::GetBoundingBox() const
{ {
BOX2I bbox; BOX2I bbox;
for( BOARD_ITEM* item : m_items ) for( EDA_ITEM* item : m_items )
{ {
if( item->Type() == PCB_FOOTPRINT_T ) if( item->Type() == PCB_FOOTPRINT_T )
bbox.Merge( static_cast<FOOTPRINT*>( item )->GetBoundingBox( true ) ); bbox.Merge( static_cast<FOOTPRINT*>( item )->GetBoundingBox( true ) );
@ -283,8 +305,8 @@ std::shared_ptr<SHAPE> PCB_GROUP::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHI
{ {
std::shared_ptr<SHAPE_COMPOUND> shape = std::make_shared<SHAPE_COMPOUND>(); std::shared_ptr<SHAPE_COMPOUND> shape = std::make_shared<SHAPE_COMPOUND>();
for( BOARD_ITEM* item : m_items ) for( EDA_ITEM* item : m_items )
shape->AddShape( item->GetEffectiveShape( aLayer, aFlash )->Clone() ); shape->AddShape( static_cast<BOARD_ITEM*>( item )->GetEffectiveShape( aLayer, aFlash )->Clone() );
return shape; return shape;
} }
@ -310,8 +332,8 @@ LSET PCB_GROUP::GetLayerSet() const
{ {
LSET aSet; LSET aSet;
for( BOARD_ITEM* item : m_items ) for( EDA_ITEM* item : m_items )
aSet |= item->GetLayerSet(); aSet |= static_cast<BOARD_ITEM*>( item )->GetLayerSet();
return aSet; return aSet;
} }
@ -320,9 +342,9 @@ LSET PCB_GROUP::GetLayerSet() const
bool PCB_GROUP::IsOnLayer( PCB_LAYER_ID aLayer ) const bool PCB_GROUP::IsOnLayer( PCB_LAYER_ID aLayer ) const
{ {
// A group is on a layer if any item is on the layer // A group is on a layer if any item is on the layer
for( BOARD_ITEM* item : m_items ) for( EDA_ITEM* item : m_items )
{ {
if( item->IsOnLayer( aLayer ) ) if( static_cast<BOARD_ITEM*>( item )->IsOnLayer( aLayer ) )
return true; return true;
} }
@ -347,29 +369,29 @@ double PCB_GROUP::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
void PCB_GROUP::Move( const VECTOR2I& aMoveVector ) void PCB_GROUP::Move( const VECTOR2I& aMoveVector )
{ {
for( BOARD_ITEM* member : m_items ) for( EDA_ITEM* member : m_items )
member->Move( aMoveVector ); static_cast<BOARD_ITEM*>( member )->Move( aMoveVector );
} }
void PCB_GROUP::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle ) void PCB_GROUP::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
{ {
for( BOARD_ITEM* item : m_items ) for( EDA_ITEM* item : m_items )
item->Rotate( aRotCentre, aAngle ); static_cast<BOARD_ITEM*>( item )->Rotate( aRotCentre, aAngle );
} }
void PCB_GROUP::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection ) void PCB_GROUP::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
{ {
for( BOARD_ITEM* item : m_items ) for( EDA_ITEM* item : m_items )
item->Flip( aCentre, aFlipDirection ); static_cast<BOARD_ITEM*>( item )->Flip( aCentre, aFlipDirection );
} }
void PCB_GROUP::Mirror( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection ) void PCB_GROUP::Mirror( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
{ {
for( BOARD_ITEM* item : m_items ) for( EDA_ITEM* item : m_items )
item->Mirror( aCentre, aFlipDirection ); static_cast<BOARD_ITEM*>( item )->Mirror( aCentre, aFlipDirection );
} }
@ -402,7 +424,7 @@ void PCB_GROUP::RunOnChildren( const std::function<void( BOARD_ITEM* )>& aFuncti
{ {
try try
{ {
for( BOARD_ITEM* item : m_items ) for( BOARD_ITEM* item : GetBoardItems() )
{ {
aFunction( item ); aFunction( item );
@ -461,11 +483,11 @@ double PCB_GROUP::Similarity( const BOARD_ITEM& aOther ) const
double similarity = 0.0; double similarity = 0.0;
for( BOARD_ITEM* item : m_items ) for( EDA_ITEM* item : m_items )
{ {
for( BOARD_ITEM* otherItem : other.m_items ) for( EDA_ITEM* otherItem : other.m_items )
{ {
similarity += item->Similarity( *otherItem ); similarity += static_cast<BOARD_ITEM*>( item )->Similarity( *static_cast<BOARD_ITEM*>( otherItem ) );
} }
} }
@ -480,7 +502,9 @@ static struct PCB_GROUP_DESC
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance(); PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
REGISTER_TYPE( PCB_GROUP ); REGISTER_TYPE( PCB_GROUP );
propMgr.AddTypeCast( new TYPE_CAST<PCB_GROUP, BOARD_ITEM> ); propMgr.AddTypeCast( new TYPE_CAST<PCB_GROUP, BOARD_ITEM> );
propMgr.AddTypeCast( new TYPE_CAST<PCB_GROUP, EDA_GROUP> );
propMgr.InheritsAfter( TYPE_HASH( PCB_GROUP ), TYPE_HASH( BOARD_ITEM ) ); propMgr.InheritsAfter( TYPE_HASH( PCB_GROUP ), TYPE_HASH( BOARD_ITEM ) );
propMgr.InheritsAfter( TYPE_HASH( PCB_GROUP ), TYPE_HASH( EDA_GROUP ) );
propMgr.Mask( TYPE_HASH( PCB_GROUP ), TYPE_HASH( BOARD_ITEM ), _HKI( "Position X" ) ); propMgr.Mask( TYPE_HASH( PCB_GROUP ), TYPE_HASH( BOARD_ITEM ), _HKI( "Position X" ) );
propMgr.Mask( TYPE_HASH( PCB_GROUP ), TYPE_HASH( BOARD_ITEM ), _HKI( "Position Y" ) ); propMgr.Mask( TYPE_HASH( PCB_GROUP ), TYPE_HASH( BOARD_ITEM ), _HKI( "Position Y" ) );
@ -488,8 +512,8 @@ static struct PCB_GROUP_DESC
const wxString groupTab = _HKI( "Group Properties" ); const wxString groupTab = _HKI( "Group Properties" );
propMgr.AddProperty( new PROPERTY<PCB_GROUP, wxString>( _HKI( "Name" ), propMgr.AddProperty(
&PCB_GROUP::SetName, &PCB_GROUP::GetName ), new PROPERTY<EDA_GROUP, wxString>( _HKI( "Name" ), &PCB_GROUP::SetName, &PCB_GROUP::GetName ),
groupTab ); groupTab );
} }
} _PCB_GROUP_DESC; } _PCB_GROUP_DESC;

View File

@ -32,6 +32,7 @@
#include <board_commit.h> #include <board_commit.h>
#include <board_item.h> #include <board_item.h>
#include <eda_group.h>
#include <lset.h> #include <lset.h>
#include <unordered_set> #include <unordered_set>
@ -48,11 +49,13 @@ class VIEW;
* containing a group implicitly contains its members. However other operations on sets of * containing a group implicitly contains its members. However other operations on sets of
* items, like committing, updating the view, etc the set is explicit. * items, like committing, updating the view, etc the set is explicit.
*/ */
class PCB_GROUP : public BOARD_ITEM class PCB_GROUP : public BOARD_ITEM, public EDA_GROUP
{ {
public: public:
PCB_GROUP( BOARD_ITEM* aParent ); PCB_GROUP( BOARD_ITEM* aParent );
EDA_ITEM* AsEdaItem() override { return this; }
static inline bool ClassOf( const EDA_ITEM* aItem ) static inline bool ClassOf( const EDA_ITEM* aItem )
{ {
return aItem && PCB_GROUP_T == aItem->Type(); return aItem && PCB_GROUP_T == aItem->Type();
@ -63,34 +66,23 @@ public:
return wxT( "PCB_GROUP" ); return wxT( "PCB_GROUP" );
} }
wxString GetName() const { return m_name; }
void SetName( const wxString& aName ) { m_name = aName; }
std::unordered_set<BOARD_ITEM*>& GetItems()
{
return m_items;
}
const std::unordered_set<BOARD_ITEM*>& GetItems() const
{
return m_items;
}
/** /**
* Add item to group. Does not take ownership of item. * Add item to group. Does not take ownership of item.
* *
* @return true if item was added (false if item belongs to a different group). * @return true if item was added (false if item belongs to a different group).
*/ */
virtual bool AddItem( BOARD_ITEM* aItem ); bool AddItem( EDA_ITEM* aItem ) override;
/** /**
* Remove item from group. * Remove item from group.
* *
* @return true if item was removed (false if item was not in the group). * @return true if item was removed (false if item was not in the group).
*/ */
virtual bool RemoveItem( BOARD_ITEM* aItem ); bool RemoveItem( EDA_ITEM* aItem ) override;
void RemoveAll(); void RemoveAll() override;
std::unordered_set<BOARD_ITEM*> GetBoardItems() const;
/* /*
* Search for highest level group inside of aScope, containing item. * Search for highest level group inside of aScope, containing item.
@ -99,7 +91,7 @@ public:
* @param isFootprintEditor true if we should stop promoting at the footprint level * @param isFootprintEditor true if we should stop promoting at the footprint level
* @return group inside of aScope, containing item, if exists, otherwise, nullptr * @return group inside of aScope, containing item, if exists, otherwise, nullptr
*/ */
static PCB_GROUP* TopLevelGroup( BOARD_ITEM* aItem, PCB_GROUP* aScope, bool isFootprintEditor ); static EDA_GROUP* TopLevelGroup( BOARD_ITEM* aItem, EDA_GROUP* aScope, bool isFootprintEditor );
static bool WithinScope( BOARD_ITEM* aItem, PCB_GROUP* aScope, bool isFootprintEditor ); static bool WithinScope( BOARD_ITEM* aItem, PCB_GROUP* aScope, bool isFootprintEditor );
@ -144,12 +136,12 @@ public:
/* /*
* Clone() this and all descendants * Clone() this and all descendants
*/ */
PCB_GROUP* DeepClone() const; PCB_GROUP* DeepClone() const override;
/* /*
* Duplicate() this and all descendants * Duplicate() this and all descendants
*/ */
PCB_GROUP* DeepDuplicate() const; PCB_GROUP* DeepDuplicate() const override;
/// @copydoc BOARD_ITEM::IsOnLayer /// @copydoc BOARD_ITEM::IsOnLayer
bool IsOnLayer( PCB_LAYER_ID aLayer ) const override; bool IsOnLayer( PCB_LAYER_ID aLayer ) const override;
@ -213,9 +205,6 @@ protected:
/// @copydoc BOARD_ITEM::swapData /// @copydoc BOARD_ITEM::swapData
void swapData( BOARD_ITEM* aImage ) override; void swapData( BOARD_ITEM* aImage ) override;
std::unordered_set<BOARD_ITEM*> m_items; // Members of the group
wxString m_name; // Optional group name
}; };
#endif // CLASS_PCB_GROUP_H_ #endif // CLASS_PCB_GROUP_H_

View File

@ -2206,7 +2206,7 @@ void PCB_IO_KICAD_SEXPR::format( const PCB_GROUP* aGroup ) const
wxArrayString memberIds; wxArrayString memberIds;
for( BOARD_ITEM* member : aGroup->GetItems() ) for( EDA_ITEM* member : aGroup->GetItems() )
memberIds.Add( member->m_Uuid.AsString() ); memberIds.Add( member->m_Uuid.AsString() );
memberIds.Sort(); memberIds.Sort();
@ -2304,7 +2304,7 @@ void PCB_IO_KICAD_SEXPR::format( const PCB_GENERATOR* aGenerator ) const
wxArrayString memberIds; wxArrayString memberIds;
for( BOARD_ITEM* member : aGenerator->GetItems() ) for( EDA_ITEM* member : aGenerator->GetItems() )
memberIds.Add( member->m_Uuid.AsString() ); memberIds.Add( member->m_Uuid.AsString() );
memberIds.Sort(); memberIds.Sort();

View File

@ -919,7 +919,7 @@ static void memberOfGroupFunc( LIBEVAL::CONTEXT* aCtx, void* self )
result->SetDeferredEval( result->SetDeferredEval(
[item, arg]() -> double [item, arg]() -> double
{ {
PCB_GROUP* group = item->GetParentGroup(); EDA_GROUP* group = item->GetParentGroup();
if( !group && item->GetParent() && item->GetParent()->Type() == PCB_FOOTPRINT_T ) if( !group && item->GetParent() && item->GetParent()->Type() == PCB_FOOTPRINT_T )
group = item->GetParent()->GetParentGroup(); group = item->GetParent()->GetParentGroup();
@ -929,7 +929,7 @@ static void memberOfGroupFunc( LIBEVAL::CONTEXT* aCtx, void* self )
if( group->GetName().Matches( arg->AsString() ) ) if( group->GetName().Matches( arg->AsString() ) )
return 1.0; return 1.0;
group = group->GetParentGroup(); group = group->AsEdaItem()->GetParentGroup();
} }
return 0.0; return 0.0;

View File

@ -11,7 +11,7 @@
{ {
std::deque<BOARD_ITEM*> result; std::deque<BOARD_ITEM*> result;
const std::unordered_set<BOARD_ITEM*> items = $self->GetItems(); const std::unordered_set<BOARD_ITEM*> items = $self->GetBoardItems();
for(BOARD_ITEM* item: items) for(BOARD_ITEM* item: items)
result.push_back(item); result.push_back(item);

View File

@ -387,7 +387,7 @@ void SPECCTRA_DB::FromSESSION( BOARD* aBoard )
} }
else else
{ {
if( PCB_GROUP* group = track->GetParentGroup() ) if( EDA_GROUP* group = track->GetParentGroup() )
group->RemoveItem( track ); group->RemoveItem( track );
delete track; delete track;

View File

@ -1301,9 +1301,9 @@ int BOARD_EDITOR_CONTROL::modifyLockSelected( MODIFY_MODE aMode )
if( board_item->Type() == PCB_PAD_T ) if( board_item->Type() == PCB_PAD_T )
continue; continue;
PCB_GROUP* parent_group = board_item->GetParentGroup(); EDA_GROUP* parent_group = board_item->GetParentGroup();
if( parent_group && parent_group->Type() == PCB_GENERATOR_T ) if( parent_group && parent_group->AsEdaItem()->Type() == PCB_GENERATOR_T )
{ {
PCB_GENERATOR* generator = static_cast<PCB_GENERATOR*>( parent_group ); PCB_GENERATOR* generator = static_cast<PCB_GENERATOR*>( parent_group );

View File

@ -735,7 +735,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
return 0; return 0;
} }
a = *ag->GetItems().begin(); a = static_cast<BOARD_ITEM*>( *ag->GetItems().begin() );
} }
if( b->Type() == PCB_GROUP_T ) if( b->Type() == PCB_GROUP_T )
@ -748,7 +748,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
return 0; return 0;
} }
b = *bg->GetItems().begin(); b = static_cast<BOARD_ITEM*>( *bg->GetItems().begin() );
} }
// a or b could be null after group tests above. // a or b could be null after group tests above.

View File

@ -2424,13 +2424,13 @@ int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent )
void EDIT_TOOL::getChildItemsOfGroupsAndGenerators( EDA_ITEM* item, void EDIT_TOOL::getChildItemsOfGroupsAndGenerators( EDA_ITEM* item,
std::unordered_set<BOARD_ITEM*>& children ) std::unordered_set<EDA_ITEM*>& children )
{ {
wxASSERT( item->Type() == PCB_GROUP_T || item->Type() == PCB_GENERATOR_T ); wxASSERT( item->Type() == PCB_GROUP_T || item->Type() == PCB_GENERATOR_T );
std::unordered_set<BOARD_ITEM*>& childItems = static_cast<PCB_GROUP*>( item )->GetItems(); std::unordered_set<EDA_ITEM*>& childItems = static_cast<PCB_GROUP*>( item )->GetItems();
for( BOARD_ITEM* childItem : childItems ) for( EDA_ITEM* childItem : childItems )
{ {
children.insert( childItem ); children.insert( childItem );
@ -2454,7 +2454,7 @@ void EDIT_TOOL::removeNonRootItems( std::unordered_set<EDA_ITEM*>& items )
if( curItem->Type() == PCB_GROUP_T || curItem->Type() == PCB_GENERATOR_T ) if( curItem->Type() == PCB_GROUP_T || curItem->Type() == PCB_GENERATOR_T )
{ {
std::unordered_set<BOARD_ITEM*> childItems; std::unordered_set<EDA_ITEM*> childItems;
getChildItemsOfGroupsAndGenerators( curItem, childItems ); getChildItemsOfGroupsAndGenerators( curItem, childItems );
std::for_each( childItems.begin(), childItems.end(), std::for_each( childItems.begin(), childItems.end(),
@ -2633,10 +2633,10 @@ void EDIT_TOOL::DeleteItems( const PCB_SELECTION& aItems, bool aIsCut )
{ {
PCB_GENERATOR* generator = static_cast<PCB_GENERATOR*>( board_item ); PCB_GENERATOR* generator = static_cast<PCB_GENERATOR*>( board_item );
for( BOARD_ITEM* member : generator->GetItems() ) for( EDA_ITEM* member : generator->GetItems() )
commit.Stage( member, CHT_UNGROUP ); commit.Stage( member, CHT_UNGROUP );
for( BOARD_ITEM* member : generator->GetItems() ) for( EDA_ITEM* member : generator->GetItems() )
commit.Remove( member ); commit.Remove( member );
commit.Remove( board_item ); commit.Remove( board_item );

View File

@ -232,7 +232,7 @@ private:
///< Recursively adds any child items of the given item to the set ///< Recursively adds any child items of the given item to the set
void getChildItemsOfGroupsAndGenerators( EDA_ITEM* item, void getChildItemsOfGroupsAndGenerators( EDA_ITEM* item,
std::unordered_set<BOARD_ITEM*>& children ); std::unordered_set<EDA_ITEM*>& children );
private: private:

View File

@ -305,7 +305,7 @@ int GROUP_TOOL::Ungroup( const TOOL_EVENT& aEvent )
if( group ) if( group )
{ {
for( BOARD_ITEM* member : group->GetItems() ) for( EDA_ITEM* member : group->GetItems() )
{ {
commit.Stage( member, CHT_UNGROUP ); commit.Stage( member, CHT_UNGROUP );
toSelect.push_back( member ); toSelect.push_back( member );
@ -339,7 +339,7 @@ int GROUP_TOOL::RemoveFromGroup( const TOOL_EVENT& aEvent )
for( EDA_ITEM* item : selection ) for( EDA_ITEM* item : selection )
{ {
BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item ); BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
PCB_GROUP* group = boardItem->GetParentGroup(); EDA_GROUP* group = boardItem->GetParentGroup();
if( group ) if( group )
commit.Stage( boardItem, CHT_UNGROUP ); commit.Stage( boardItem, CHT_UNGROUP );

View File

@ -404,7 +404,7 @@ int MULTICHANNEL_TOOL::repeatLayout( const TOOL_EVENT& aEvent )
{ {
PCB_GROUP *group = static_cast<PCB_GROUP*>( item ); PCB_GROUP *group = static_cast<PCB_GROUP*>( item );
for( BOARD_ITEM* grpItem : group->GetItems() ) for( EDA_ITEM* grpItem : group->GetItems() )
{ {
if( auto grpZone = isSelectedItemAnRA( grpItem ) ) if( auto grpZone = isSelectedItemAnRA( grpItem ) )
{ {
@ -1012,12 +1012,11 @@ bool MULTICHANNEL_TOOL::pruneExistingGroups( COMMIT& aCommit,
auto grp = pending.front(); auto grp = pending.front();
pending.pop_front(); pending.pop_front();
std::unordered_set<BOARD_ITEM*>& grpItems = grp->GetItems(); std::unordered_set<EDA_ITEM*>& grpItems = grp->GetItems();
size_t n_erased = 0; size_t n_erased = 0;
for( BOARD_ITEM* refItem : grpItems ) for( EDA_ITEM* refItem : grpItems )
{ {
if( refItem->Type() == PCB_GROUP_T ) if( refItem->Type() == PCB_GROUP_T )
pending.push_back( static_cast<PCB_GROUP*>(refItem) ); pending.push_back( static_cast<PCB_GROUP*>(refItem) );

View File

@ -918,7 +918,7 @@ static void pasteFootprintItemsToFootprintEditor( FOOTPRINT* aClipFootprint, BOA
{ {
if( field->IsMandatory() ) if( field->IsMandatory() )
{ {
if( PCB_GROUP* parentGroup = field->GetParentGroup() ) if( EDA_GROUP* parentGroup = field->GetParentGroup() )
parentGroup->RemoveItem( field ); parentGroup->RemoveItem( field );
} }
else else
@ -1029,7 +1029,7 @@ void PCB_CONTROL::pruneItemLayers( std::vector<BOARD_ITEM*>& aItems )
} }
else else
{ {
if( PCB_GROUP* parentGroup = item->GetParentGroup() ) if( EDA_GROUP* parentGroup = item->GetParentGroup() )
parentGroup->RemoveItem( item ); parentGroup->RemoveItem( item );
} }
} }
@ -1186,7 +1186,7 @@ int PCB_CONTROL::Paste( const TOOL_EVENT& aEvent )
default: default:
// Everything we *didn't* put into pastedItems is going to get nuked, so // Everything we *didn't* put into pastedItems is going to get nuked, so
// make sure it's not still included in its parent group. // make sure it's not still included in its parent group.
if( PCB_GROUP* parentGroup = clipDrawItem->GetParentGroup() ) if( EDA_GROUP* parentGroup = clipDrawItem->GetParentGroup() )
parentGroup->RemoveItem( clipDrawItem ); parentGroup->RemoveItem( clipDrawItem );
break; break;
@ -1203,7 +1203,7 @@ int PCB_CONTROL::Paste( const TOOL_EVENT& aEvent )
// Anything still on the clipboard didn't get copied and needs to be // Anything still on the clipboard didn't get copied and needs to be
// removed from the pasted groups. // removed from the pasted groups.
BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item ); BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
PCB_GROUP* parentGroup = boardItem->GetParentGroup(); EDA_GROUP* parentGroup = boardItem->GetParentGroup();
if( parentGroup ) if( parentGroup )
parentGroup->RemoveItem( boardItem ); parentGroup->RemoveItem( boardItem );
@ -1478,7 +1478,7 @@ bool PCB_CONTROL::placeBoardItems( BOARD_COMMIT* aCommit, std::vector<BOARD_ITEM
// We only need to add the items that aren't inside a group currently selected // We only need to add the items that aren't inside a group currently selected
// to the selection. If an item is inside a group and that group is selected, // to the selection. If an item is inside a group and that group is selected,
// then the selection tool will select it for us. // then the selection tool will select it for us.
if( !item->GetParentGroup() || !alg::contains( aItems, item->GetParentGroup() ) ) if( !item->GetParentGroup() || !alg::contains( aItems, item->GetParentGroup()->AsEdaItem() ) )
itemsToSel.push_back( item ); itemsToSel.push_back( item );
} }

View File

@ -1606,7 +1606,7 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos
break; break;
case PCB_GROUP_T: case PCB_GROUP_T:
for( BOARD_ITEM* item : static_cast<const PCB_GROUP*>( aItem )->GetItems() ) for( BOARD_ITEM* item : static_cast<PCB_GROUP*>( aItem )->GetBoardItems() )
{ {
if( checkVisibility( item ) ) if( checkVisibility( item ) )
computeAnchors( item, aRefPos, aFrom, nullptr ); computeAnchors( item, aRefPos, aFrom, nullptr );

View File

@ -1138,7 +1138,7 @@ bool PCB_SELECTION_TOOL::selectMultiple()
GENERAL_COLLECTOR collector; GENERAL_COLLECTOR collector;
GENERAL_COLLECTOR padsCollector; GENERAL_COLLECTOR padsCollector;
std::set<BOARD_ITEM*> group_items; std::set<EDA_ITEM*> group_items;
for( PCB_GROUP* group : board()->Groups() ) for( PCB_GROUP* group : board()->Groups() )
{ {
@ -1146,21 +1146,21 @@ bool PCB_SELECTION_TOOL::selectMultiple()
if( m_enteredGroup == group ) if( m_enteredGroup == group )
continue; continue;
std::unordered_set<BOARD_ITEM*>& newset = group->GetItems(); std::unordered_set<EDA_ITEM*>& newset = group->GetItems();
// If we are not greedy and have selected the whole group, add just one item // If we are not greedy and have selected the whole group, add just one item
// to allow it to be promoted to the group later // to allow it to be promoted to the group later
if( !greedySelection && selectionRect.Contains( group->GetBoundingBox() ) if( !greedySelection && selectionRect.Contains( group->GetBoundingBox() )
&& newset.size() ) && newset.size() )
{ {
for( BOARD_ITEM* group_item : newset ) for( EDA_ITEM* group_item : newset )
{ {
if( Selectable( group_item ) ) if( Selectable( static_cast<BOARD_ITEM*>( group_item ) ) )
collector.Append( *newset.begin() ); collector.Append( *newset.begin() );
} }
} }
for( BOARD_ITEM* group_item : newset ) for( EDA_ITEM* group_item : newset )
group_items.emplace( group_item ); group_items.emplace( group_item );
} }
@ -1466,7 +1466,7 @@ int PCB_SELECTION_TOOL::expandConnection( const TOOL_EVENT& aEvent )
} }
else if( item->Type() == PCB_GENERATOR_T ) else if( item->Type() == PCB_GENERATOR_T )
{ {
for( BOARD_ITEM* generatedItem : static_cast<PCB_GENERATOR*>( item )->GetItems() ) for( BOARD_ITEM* generatedItem : static_cast<PCB_GENERATOR*>( item )->GetBoardItems() )
{ {
if( BOARD_CONNECTED_ITEM::ClassOf( generatedItem ) ) if( BOARD_CONNECTED_ITEM::ClassOf( generatedItem ) )
startItems.push_back( static_cast<BOARD_CONNECTED_ITEM*>( generatedItem ) ); startItems.push_back( static_cast<BOARD_CONNECTED_ITEM*>( generatedItem ) );
@ -1767,14 +1767,14 @@ void PCB_SELECTION_TOOL::selectAllConnectedTracks(
continue; continue;
BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item ); BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
PCB_GROUP* parent = boardItem->GetParentGroup(); EDA_GROUP* parent = boardItem->GetParentGroup();
if( parent && parent->Type() == PCB_GENERATOR_T ) if( parent && parent->AsEdaItem()->Type() == PCB_GENERATOR_T )
{ {
toDeselect.insert( item ); toDeselect.insert( item );
if( !parent->IsSelected() ) if( !parent->AsEdaItem()->IsSelected() )
toSelect.insert( parent ); toSelect.insert( parent->AsEdaItem() );
} }
} }
@ -2917,7 +2917,7 @@ bool PCB_SELECTION_TOOL::Selectable( const BOARD_ITEM* aItem, bool checkVisibili
// Similar to logic for footprint, a group is selectable if any of its members are. // Similar to logic for footprint, a group is selectable if any of its members are.
// (This recurses.) // (This recurses.)
for( BOARD_ITEM* item : group->GetItems() ) for( BOARD_ITEM* item : group->GetBoardItems() )
{ {
if( Selectable( item, true ) ) if( Selectable( item, true ) )
return true; return true;
@ -2926,7 +2926,7 @@ bool PCB_SELECTION_TOOL::Selectable( const BOARD_ITEM* aItem, bool checkVisibili
return false; return false;
} }
if( aItem->GetParentGroup() && aItem->GetParentGroup()->Type() == PCB_GENERATOR_T ) if( aItem->GetParentGroup() && aItem->GetParentGroup()->AsEdaItem()->Type() == PCB_GENERATOR_T )
return false; return false;
const ZONE* zone = nullptr; const ZONE* zone = nullptr;
@ -3343,7 +3343,7 @@ int PCB_SELECTION_TOOL::hitTestDistance( const VECTOR2I& aWhere, BOARD_ITEM* aIt
{ {
PCB_GROUP* group = static_cast<PCB_GROUP*>( aItem ); PCB_GROUP* group = static_cast<PCB_GROUP*>( aItem );
for( BOARD_ITEM* member : group->GetItems() ) for( BOARD_ITEM* member : group->GetBoardItems() )
distance = std::min( distance, hitTestDistance( aWhere, member, aMaxDistance ) ); distance = std::min( distance, hitTestDistance( aWhere, member, aMaxDistance ) );
break; break;
@ -3729,7 +3729,7 @@ void PCB_SELECTION_TOOL::GuessSelectionCandidates( GENERAL_COLLECTOR& aCollector
void PCB_SELECTION_TOOL::FilterCollectorForHierarchy( GENERAL_COLLECTOR& aCollector, void PCB_SELECTION_TOOL::FilterCollectorForHierarchy( GENERAL_COLLECTOR& aCollector,
bool aMultiselect ) const bool aMultiselect ) const
{ {
std::unordered_set<BOARD_ITEM*> toAdd; std::unordered_set<EDA_ITEM*> toAdd;
// Set CANDIDATE on all parents which are included in the GENERAL_COLLECTOR. This // Set CANDIDATE on all parents which are included in the GENERAL_COLLECTOR. This
// algorithm is O(3n), whereas checking for the parent inclusion could potentially be O(n^2). // algorithm is O(3n), whereas checking for the parent inclusion could potentially be O(n^2).
@ -3763,13 +3763,12 @@ void PCB_SELECTION_TOOL::FilterCollectorForHierarchy( GENERAL_COLLECTOR& aCollec
// If any element is a member of a group, replace those elements with the top containing // If any element is a member of a group, replace those elements with the top containing
// group. // group.
if( PCB_GROUP* top = PCB_GROUP::TopLevelGroup( start, m_enteredGroup, if( EDA_GROUP* top = PCB_GROUP::TopLevelGroup( start, m_enteredGroup, m_isFootprintEditor ) )
m_isFootprintEditor ) )
{ {
if( top != item ) if( top->AsEdaItem() != item )
{ {
toAdd.insert( top ); toAdd.insert( top->AsEdaItem() );
top->SetFlags(CANDIDATE ); top->AsEdaItem()->SetFlags( CANDIDATE );
aCollector.Remove( item ); aCollector.Remove( item );
continue; continue;
@ -3787,7 +3786,7 @@ void PCB_SELECTION_TOOL::FilterCollectorForHierarchy( GENERAL_COLLECTOR& aCollec
++j; ++j;
} }
for( BOARD_ITEM* item : toAdd ) for( EDA_ITEM* item : toAdd )
{ {
if( !aCollector.HasItem( item ) ) if( !aCollector.HasItem( item ) )
aCollector.Append( item ); aCollector.Append( item );

View File

@ -787,7 +787,7 @@ bool TRACKS_CLEANER::mergeCollinearSegments( PCB_TRACK* aSeg1, PCB_TRACK* aSeg2
{ {
m_commit.Modify( aSeg1 ); m_commit.Modify( aSeg1 );
PCB_GROUP* group = aSeg1->GetParentGroup(); EDA_GROUP* group = aSeg1->GetParentGroup();
*aSeg1 = dummy_seg; *aSeg1 = dummy_seg;
aSeg1->SetParentGroup( group ); aSeg1->SetParentGroup( group );

View File

@ -433,7 +433,7 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
{ {
BOARD_ITEM* item = (BOARD_ITEM*) eda_item; BOARD_ITEM* item = (BOARD_ITEM*) eda_item;
BOARD_ITEM_CONTAINER* parent = GetBoard(); BOARD_ITEM_CONTAINER* parent = GetBoard();
PCB_GROUP* parentGroup = item->GetParentGroup(); EDA_GROUP* parentGroup = item->GetParentGroup();
if( item->GetParentFootprint() ) if( item->GetParentFootprint() )
{ {
@ -509,9 +509,9 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
{ {
BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( eda_item ); BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( eda_item );
if( PCB_GROUP* group = boardItem->GetParentGroup() ) if( EDA_GROUP* group = boardItem->GetParentGroup() )
{ {
aList->SetPickedItemGroupId( group->m_Uuid, ii ); aList->SetPickedItemGroupId( group->AsEdaItem()->m_Uuid, ii );
group->RemoveItem( boardItem ); group->RemoveItem( boardItem );
} }

View File

@ -164,15 +164,15 @@ void testGroupEqual( const PCB_GROUP& group1, const PCB_GROUP& group2 )
BOOST_CHECK_EQUAL( group1.m_Uuid.AsString(), group2.m_Uuid.AsString() ); BOOST_CHECK_EQUAL( group1.m_Uuid.AsString(), group2.m_Uuid.AsString() );
BOOST_CHECK_EQUAL( group1.GetName(), group2.GetName() ); BOOST_CHECK_EQUAL( group1.GetName(), group2.GetName() );
const std::unordered_set<BOARD_ITEM*>& items1 = group1.GetItems(); const std::unordered_set<EDA_ITEM*>& items1 = group1.GetItems();
const std::unordered_set<BOARD_ITEM*>& items2 = group2.GetItems(); const std::unordered_set<EDA_ITEM*>& items2 = group2.GetItems();
BOOST_CHECK_EQUAL( items1.size(), items2.size() ); BOOST_CHECK_EQUAL( items1.size(), items2.size() );
// Test that the sets items1 and items2 are identical, by checking m_Uuid // Test that the sets items1 and items2 are identical, by checking m_Uuid
for( BOARD_ITEM* item1 : items1 ) for( EDA_ITEM* item1 : items1 )
{ {
auto cmp = [&]( BOARD_ITEM* elem ) auto cmp = [&]( EDA_ITEM* elem )
{ {
return elem->m_Uuid.AsString() == item1->m_Uuid.AsString(); return elem->m_Uuid.AsString() == item1->m_Uuid.AsString();
}; };