From 05e9772d5411471edad8dbe5a6a01fb186dfbfcc Mon Sep 17 00:00:00 2001 From: Mike Williams Date: Tue, 1 Apr 2025 14:20:03 -0400 Subject: [PATCH] groups: extract common class methods into EDA_GROUP base class --- common/CMakeLists.txt | 3 + common/dialogs/dialog_group_properties.cpp | 67 +++++++----- common/dialogs/dialog_group_properties.h | 15 +-- common/eda_group.cpp | 6 ++ common/eda_group.h | 95 +++++++++++++++++ common/eda_item.cpp | 3 + eeschema/sch_group.cpp | 89 ++++++++++------ eeschema/sch_group.h | 30 +++--- eeschema/sch_item.cpp | 9 +- eeschema/sch_item.h | 5 - include/board_item.h | 10 +- include/eda_item.h | 7 +- pcbnew/CMakeLists.txt | 2 - pcbnew/board.cpp | 20 ++-- pcbnew/board_commit.cpp | 12 +-- pcbnew/board_item.cpp | 10 +- .../dialog_cleanup_tracks_and_vias.cpp | 6 +- .../dialogs/dialog_global_edit_teardrops.cpp | 6 +- .../dialog_global_edit_text_and_graphics.cpp | 6 +- .../dialog_global_edit_tracks_and_vias.cpp | 6 +- pcbnew/footprint.cpp | 16 +-- pcbnew/footprint_libraries_utils.cpp | 2 +- pcbnew/generators/pcb_tuning_pattern.cpp | 8 +- pcbnew/pad.cpp | 2 +- pcbnew/pcb_edit_frame.cpp | 2 +- pcbnew/pcb_generator.cpp | 14 +-- pcbnew/pcb_generator.h | 4 +- pcbnew/pcb_group.cpp | 100 +++++++++++------- pcbnew/pcb_group.h | 35 +++--- .../pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp | 4 +- pcbnew/pcbexpr_functions.cpp | 4 +- pcbnew/python/swig/pcb_group.i | 2 +- .../specctra_import.cpp | 2 +- pcbnew/tools/board_editor_control.cpp | 4 +- pcbnew/tools/board_inspection_tool.cpp | 4 +- pcbnew/tools/edit_tool.cpp | 12 +-- pcbnew/tools/edit_tool.h | 2 +- pcbnew/tools/group_tool.cpp | 4 +- pcbnew/tools/multichannel_tool.cpp | 7 +- pcbnew/tools/pcb_control.cpp | 10 +- pcbnew/tools/pcb_grid_helper.cpp | 2 +- pcbnew/tools/pcb_selection_tool.cpp | 39 ++++--- pcbnew/tracks_cleaner.cpp | 2 +- pcbnew/undo_redo.cpp | 6 +- qa/tests/pcbnew/group_saveload.cpp | 8 +- 45 files changed, 409 insertions(+), 293 deletions(-) create mode 100644 common/eda_group.cpp create mode 100644 common/eda_group.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index f00c21507f..7024f25026 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -363,6 +363,8 @@ set( COMMON_DLG_SRCS dialogs/dialog_global_design_block_lib_table_config.cpp dialogs/dialog_grid_settings.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_HTML_reporter_base.cpp dialogs/dialog_import_choose_project.cpp @@ -600,6 +602,7 @@ set( COMMON_SRCS eda_dde.cpp eda_doc.cpp eda_draw_frame.cpp + eda_group.cpp eda_item.cpp eda_shape.cpp eda_text.cpp diff --git a/common/dialogs/dialog_group_properties.cpp b/common/dialogs/dialog_group_properties.cpp index 939c360e30..9a20075fbf 100644 --- a/common/dialogs/dialog_group_properties.cpp +++ b/common/dialogs/dialog_group_properties.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -33,10 +34,10 @@ #include -DIALOG_GROUP_PROPERTIES::DIALOG_GROUP_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, - PCB_GROUP* aGroup ) : +DIALOG_GROUP_PROPERTIES::DIALOG_GROUP_PROPERTIES( EDA_DRAW_FRAME* aParent, + EDA_GROUP* aGroup ) : DIALOG_GROUP_PROPERTIES_BASE( aParent ), - m_brdEditor( aParent ), + m_frame( aParent ), m_toolMgr( aParent->GetToolManager() ), 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_locked->SetValue( m_group->IsLocked() ); - m_locked->Show( dynamic_cast( aParent ) != nullptr ); + if( aGroup->AsEdaItem()->Type() == PCB_GROUP_T ) + { + m_locked->SetValue( static_cast( aGroup )->IsLocked() ); + m_locked->Show( dynamic_cast( aParent ) != nullptr ); + } + else + { + m_locked->SetValue( false ); + m_locked->Hide(); + } - for( BOARD_ITEM* item : m_group->GetItems() ) - m_membersList->Append( item->GetItemDescription( m_brdEditor, true ), item ); + for( EDA_ITEM* item : m_group->GetItems() ) + m_membersList->Append( item->GetItemDescription( m_frame, true ), item ); SetupStandardButtons(); @@ -62,11 +71,11 @@ DIALOG_GROUP_PROPERTIES::DIALOG_GROUP_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, DIALOG_GROUP_PROPERTIES::~DIALOG_GROUP_PROPERTIES() { - if( m_brdEditor->IsBeingDeleted() ) + if( m_frame->IsBeingDeleted() ) return; - m_brdEditor->ClearFocus(); - m_brdEditor->GetCanvas()->Refresh(); + m_frame->ClearFocus(); + m_frame->GetCanvas()->Refresh(); } @@ -80,36 +89,40 @@ bool DIALOG_GROUP_PROPERTIES::TransferDataToWindow() bool DIALOG_GROUP_PROPERTIES::TransferDataFromWindow() { - BOARD_COMMIT commit( m_brdEditor ); - commit.Modify( m_group ); + BOARD_COMMIT commit( m_frame ); + commit.Modify( m_group->AsEdaItem() ); for( size_t ii = 0; ii < m_membersList->GetCount(); ++ii ) { - BOARD_ITEM* item = static_cast( m_membersList->GetClientData( ii ) ); - PCB_GROUP* existingGroup = item->GetParentGroup(); + EDA_ITEM* item = static_cast( m_membersList->GetClientData( ii ) ); + EDA_GROUP* existingGroup = item->GetParentGroup(); if( existingGroup != m_group ) { commit.Modify( item ); if( existingGroup ) - commit.Modify( existingGroup ); + commit.Modify( existingGroup->AsEdaItem() ); } } m_group->SetName( m_nameCtrl->GetValue() ); - m_group->SetLocked( m_locked->GetValue() ); + + if( m_group->AsEdaItem()->Type() == PCB_GROUP_T ) + { + static_cast( m_group )->SetLocked( m_locked->GetValue() ); + } m_toolMgr->RunAction( PCB_ACTIONS::selectionClear ); m_group->RemoveAll(); for( size_t ii = 0; ii < m_membersList->GetCount(); ++ii ) { - BOARD_ITEM* item = static_cast( m_membersList->GetClientData( ii ) ); + EDA_ITEM* item = static_cast( m_membersList->GetClientData( ii ) ); m_group->AddItem( item ); } - m_toolMgr->RunAction( PCB_ACTIONS::selectItem, m_group ); + m_toolMgr->RunAction( PCB_ACTIONS::selectItem, m_group->AsEdaItem() ); commit.Push( _( "Edit Group Properties" ) ); return true; @@ -122,11 +135,11 @@ void DIALOG_GROUP_PROPERTIES::OnMemberSelected( wxCommandEvent& aEvent ) if( selected >= 0 ) { - WINDOW_THAWER thawer( m_brdEditor ); - BOARD_ITEM* item = static_cast( m_membersList->GetClientData( selected ) ); + WINDOW_THAWER thawer( m_frame ); + EDA_ITEM* item = static_cast( m_membersList->GetClientData( selected ) ); - m_brdEditor->FocusOnItem( item ); - m_brdEditor->GetCanvas()->Refresh(); + m_frame->FocusOnItem( item ); + m_frame->GetCanvas()->Refresh(); } aEvent.Skip(); @@ -144,14 +157,14 @@ void DIALOG_GROUP_PROPERTIES::DoAddMember( EDA_ITEM* aItem ) for( size_t ii = 0; ii < m_membersList->GetCount(); ++ii ) { - if( aItem == static_cast( m_membersList->GetClientData( ii ) ) ) + if( aItem == static_cast( m_membersList->GetClientData( ii ) ) ) return; } - if( aItem == m_group ) + if( aItem == m_group->AsEdaItem() ) 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 ) m_membersList->Delete( selected ); - m_brdEditor->ClearFocus(); - m_brdEditor->GetCanvas()->Refresh(); + m_frame->ClearFocus(); + m_frame->GetCanvas()->Refresh(); } diff --git a/common/dialogs/dialog_group_properties.h b/common/dialogs/dialog_group_properties.h index b26a32ed34..aa584afb24 100644 --- a/common/dialogs/dialog_group_properties.h +++ b/common/dialogs/dialog_group_properties.h @@ -26,16 +26,17 @@ #include -class PCB_BASE_EDIT_FRAME; +class EDA_DRAW_FRAME; class TOOL_MANAGER; -class PCB_GROUP; +class EDA_GROUP; +class EDA_ITEM; class DIALOG_GROUP_PROPERTIES : public DIALOG_GROUP_PROPERTIES_BASE { public: - DIALOG_GROUP_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, PCB_GROUP* aTarget ); - ~DIALOG_GROUP_PROPERTIES(); + DIALOG_GROUP_PROPERTIES( EDA_DRAW_FRAME* aParent, EDA_GROUP* aTarget ); + ~DIALOG_GROUP_PROPERTIES() override; void OnMemberSelected( wxCommandEvent& event ) override; void OnAddMember( wxCommandEvent& event ) override; @@ -47,9 +48,9 @@ private: bool TransferDataToWindow() override; bool TransferDataFromWindow() override; - PCB_BASE_EDIT_FRAME* m_brdEditor; - TOOL_MANAGER* m_toolMgr; - PCB_GROUP* m_group; + EDA_DRAW_FRAME* m_frame; + TOOL_MANAGER* m_toolMgr; + EDA_GROUP* m_group; }; #endif // DIALOG_GROUP_PROPERTIES_H diff --git a/common/eda_group.cpp b/common/eda_group.cpp new file mode 100644 index 0000000000..de953d3b49 --- /dev/null +++ b/common/eda_group.cpp @@ -0,0 +1,6 @@ + +#include + +EDA_GROUP::~EDA_GROUP() +{ +} diff --git a/common/eda_group.h b/common/eda_group.h new file mode 100644 index 0000000000..a0ac190103 --- /dev/null +++ b/common/eda_group.h @@ -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 +#include +#include + +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& GetItems() { return m_items; } + + const std::unordered_set& 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 m_items; // Members of the group + wxString m_name; // Optional group name +}; + +#endif // CLASS_PCB_GROUP_H_ diff --git a/common/eda_item.cpp b/common/eda_item.cpp index 4f913dfd19..e7e85ebe57 100644 --- a/common/eda_item.cpp +++ b/common/eda_item.cpp @@ -40,6 +40,7 @@ EDA_ITEM::EDA_ITEM( EDA_ITEM* parent, KICAD_T idType, bool isSCH_ITEM, bool isBO m_structType( idType ), m_flags( 0 ), m_parent( parent ), + m_group( nullptr ), m_forceVisible( 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_flags( 0 ), m_parent( nullptr ), + m_group( nullptr ), m_forceVisible( false ), m_isRollover( false ) { } @@ -61,6 +63,7 @@ EDA_ITEM::EDA_ITEM( const EDA_ITEM& base ) : m_structType( base.m_structType ), m_flags( base.m_flags ), m_parent( base.m_parent ), + m_group( base.m_group ), m_forceVisible( base.m_forceVisible ), m_isRollover( false ) { diff --git a/eeschema/sch_group.cpp b/eeschema/sch_group.cpp index 4dff41955d..96b1c511c8 100644 --- a/eeschema/sch_group.cpp +++ b/eeschema/sch_group.cpp @@ -22,6 +22,7 @@ */ #include #include +#include #include #include #include @@ -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, 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 if( m_items.erase( aItem ) == 1 ) { @@ -104,18 +109,36 @@ bool SCH_GROUP::RemoveItem( SCH_ITEM* aItem ) void SCH_GROUP::RemoveAll() { - for( SCH_ITEM* item : m_items ) + for( EDA_ITEM* item : m_items ) item->SetParentGroup( nullptr ); m_items.clear(); } +std::unordered_set SCH_GROUP::GetSchItems() const +{ + std::unordered_set items; + + for( EDA_ITEM* item : m_items ) + { + SCH_ITEM* sch_item = dynamic_cast( 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 * 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 ) return static_cast( 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 -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 ) 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; - group = group->GetParentGroup(); + group = group->AsEdaItem()->GetParentGroup(); } 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 ); } @@ -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 ) { - SCH_GROUP* group = getClosestGroup( aItem, isSymbolEditor ); + EDA_GROUP* group = getClosestGroup( aItem, isSymbolEditor ); if( group && group == aScope ) 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 ); newGroup->m_items.clear(); - for( SCH_ITEM* member : m_items ) + for( EDA_ITEM* member : m_items ) { if( member->Type() == SCH_GROUP_T ) newGroup->AddItem( static_cast( member )->DeepClone() ); @@ -208,12 +231,12 @@ SCH_GROUP* SCH_GROUP::DeepDuplicate() const SCH_GROUP* newGroup = static_cast( Duplicate() ); newGroup->m_items.clear(); - for( SCH_ITEM* member : m_items ) + for( EDA_ITEM* member : m_items ) { if( member->Type() == SCH_GROUP_T ) newGroup->AddItem( static_cast( member )->DeepDuplicate() ); else - newGroup->AddItem( static_cast( member->Duplicate() ) ); + newGroup->AddItem( static_cast( member )->Duplicate() ); } return newGroup; @@ -246,7 +269,7 @@ const BOX2I SCH_GROUP::GetBoundingBox() const { 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 ) bbox.Merge( static_cast( item )->GetBoundingBox() ); @@ -293,29 +316,29 @@ double SCH_GROUP::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const void SCH_GROUP::Move( const VECTOR2I& aMoveVector ) { - for( SCH_ITEM* member : m_items ) - member->Move( aMoveVector ); + for( EDA_ITEM* member : m_items ) + static_cast( member )->Move( aMoveVector ); } void SCH_GROUP::Rotate( const VECTOR2I& aCenter, bool aRotateCCW ) { - for( SCH_ITEM* member : m_items ) - member->Rotate( aCenter, aRotateCCW ); + for( EDA_ITEM* member : m_items ) + static_cast( member )->Rotate( aCenter, aRotateCCW ); } void SCH_GROUP::MirrorHorizontally( int aCenter ) { - for( SCH_ITEM* item : m_items ) - item->MirrorHorizontally( aCenter ); + for( EDA_ITEM* item : m_items ) + static_cast( item )->MirrorHorizontally( aCenter ); } void SCH_GROUP::MirrorVertically( int aCenter ) { - for( SCH_ITEM* item : m_items ) - item->MirrorVertically( aCenter ); + for( EDA_ITEM* item : m_items ) + static_cast( item )->MirrorVertically( aCenter ); } @@ -345,12 +368,12 @@ void SCH_GROUP::RunOnChildren( const std::function& aFunction { try { - for( SCH_ITEM* item : m_items ) + for( EDA_ITEM* item : m_items ) { - aFunction( item ); + aFunction( static_cast( item ) ); if( item->Type() == SCH_GROUP_T ) - item->RunOnChildren( aFunction, RECURSE_MODE::RECURSE ); + static_cast( item )->RunOnChildren( aFunction, RECURSE_MODE::RECURSE ); } } catch( std::bad_function_call& ) @@ -402,11 +425,11 @@ double SCH_GROUP::Similarity( const SCH_ITEM& aOther ) const 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( item )->Similarity( *static_cast( otherItem ) ); } } @@ -421,7 +444,9 @@ static struct SCH_GROUP_DESC PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance(); REGISTER_TYPE( SCH_GROUP ); propMgr.AddTypeCast( new TYPE_CAST ); + propMgr.AddTypeCast( new TYPE_CAST ); 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 Y" ) ); @@ -429,7 +454,7 @@ static struct SCH_GROUP_DESC const wxString groupTab = _HKI( "Group Properties" ); propMgr.AddProperty( - new PROPERTY( _HKI( "Name" ), &SCH_GROUP::SetName, &SCH_GROUP::GetName ), + new PROPERTY( _HKI( "Name" ), &SCH_GROUP::SetName, &SCH_GROUP::GetName ), groupTab ); } } _SCH_GROUP_DESC; diff --git a/eeschema/sch_group.h b/eeschema/sch_group.h index 5d092d5a20..ec1715189d 100644 --- a/eeschema/sch_group.h +++ b/eeschema/sch_group.h @@ -29,6 +29,7 @@ #ifndef CLASS_SCH_GROUP_H_ #define CLASS_SCH_GROUP_H_ +#include #include #include #include @@ -47,39 +48,36 @@ class VIEW; * 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 SCH_GROUP : public SCH_ITEM +class SCH_GROUP : public SCH_ITEM, public EDA_GROUP { public: SCH_GROUP(); 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(); } 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& GetItems() { return m_items; } - - const std::unordered_set& 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( SCH_ITEM* aItem ); + bool AddItem( EDA_ITEM* aItem ) override; /** * Remove item from 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 GetSchItems() const; /* * 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 * @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 ); @@ -113,12 +111,12 @@ public: /* * Clone() this and all descendants */ - SCH_GROUP* DeepClone() const; + SCH_GROUP* DeepClone() const override; /* * Duplicate() this and all descendants */ - SCH_GROUP* DeepDuplicate() const; + SCH_GROUP* DeepDuplicate() const override; /// @copydoc EDA_ITEM::HitTest bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override; @@ -172,10 +170,6 @@ public: /// @copydoc SCH_ITEM::swapData void swapData( SCH_ITEM* aImage ) override; - -protected: - std::unordered_set m_items; // Members of the group - wxString m_name; // Optional group name }; #endif diff --git a/eeschema/sch_item.cpp b/eeschema/sch_item.cpp index 33c9b0d4db..167f7b9247 100644 --- a/eeschema/sch_item.cpp +++ b/eeschema/sch_item.cpp @@ -78,8 +78,7 @@ SCH_ITEM::SCH_ITEM( EDA_ITEM* aParent, KICAD_T aType, int aUnit, int aBodyStyle EDA_ITEM( aParent, aType, true, false ), m_unit( aUnit ), m_bodyStyle( aBodyStyle ), - m_private( false ), - m_group( nullptr ) + m_private( false ) { m_layer = LAYER_WIRE; // It's only a default, in fact m_fieldsAutoplaced = AUTOPLACE_NONE; @@ -95,7 +94,6 @@ SCH_ITEM::SCH_ITEM( const SCH_ITEM& aItem ) : m_bodyStyle = aItem.m_bodyStyle; m_private = aItem.m_private; m_fieldsAutoplaced = aItem.m_fieldsAutoplaced; - m_group = aItem.m_group; 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_private = aItem.m_private; m_fieldsAutoplaced = aItem.m_fieldsAutoplaced; - m_group = aItem.m_group; m_connectivity_dirty = aItem.m_connectivity_dirty; return *this; @@ -116,8 +113,6 @@ SCH_ITEM& SCH_ITEM::operator=( const SCH_ITEM& aItem ) SCH_ITEM::~SCH_ITEM() { - wxASSERT( m_group == nullptr ); - for( const auto& it : m_connection_map ) delete it.second; @@ -361,7 +356,7 @@ void SCH_ITEM::SwapItemData( SCH_ITEM* aImage ) return; EDA_ITEM* parent = GetParent(); - SCH_GROUP* group = GetParentGroup(); + EDA_GROUP* group = GetParentGroup(); SetParentGroup( nullptr ); aImage->SetParentGroup( nullptr ); diff --git a/eeschema/sch_item.h b/eeschema/sch_item.h index bd97b83512..18af45879f 100644 --- a/eeschema/sch_item.h +++ b/eeschema/sch_item.h @@ -40,7 +40,6 @@ class CONNECTION_GRAPH; class SCH_CONNECTION; -class SCH_GROUP; class SCH_SHEET_PATH; class SCHEMATIC; class SYMBOL; @@ -175,9 +174,6 @@ public: virtual ~SCH_ITEM(); - void SetParentGroup( SCH_GROUP* aGroup ) { m_group = aGroup; } - SCH_GROUP* GetParentGroup() const { return m_group; } - wxString GetClass() const override { return wxT( "SCH_ITEM" ); @@ -714,7 +710,6 @@ protected: AUTOPLACE_ALGO m_fieldsAutoplaced; // indicates status of field autoplacement VECTOR2I m_storedPos; // temp variable used in some move commands to store // 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. std::map m_connected_items; diff --git a/include/board_item.h b/include/board_item.h index 8228c0e72c..bfd0b53553 100644 --- a/include/board_item.h +++ b/include/board_item.h @@ -81,18 +81,12 @@ public: EDA_ITEM( aParent, idtype, false, true ), m_layer( aLayer ), m_isKnockout( false ), - m_isLocked( false ), - m_group( nullptr ) + m_isLocked( false ) { } - ~BOARD_ITEM(); - 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=. // The ones generated by the compiler are adequate. int GetX() const @@ -452,8 +446,6 @@ protected: bool m_isKnockout; bool m_isLocked; - - PCB_GROUP* m_group; }; #ifndef SWIG diff --git a/include/eda_item.h b/include/eda_item.h index dc8e259ba6..593798b1b9 100644 --- a/include/eda_item.h +++ b/include/eda_item.h @@ -57,6 +57,7 @@ enum RECURSE_MODE */ class UNITS_PROVIDER; class EDA_DRAW_FRAME; +class EDA_GROUP; class MSG_PANEL_ITEM; class EMBEDDED_FILES; @@ -94,7 +95,7 @@ typedef const INSPECTOR_FUNC& INSPECTOR; class EDA_ITEM : public KIGFX::VIEW_ITEM, public SERIALIZABLE { public: - virtual ~EDA_ITEM() { }; + virtual ~EDA_ITEM() { wxASSERT( m_group == nullptr ); }; /** * Returns the type of object. @@ -109,6 +110,9 @@ public: EDA_ITEM* GetParent() const { return m_parent; } 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 IsNew() const { return m_flags & IS_NEW; } inline bool IsMoving() const { return m_flags & IS_MOVING; } @@ -504,6 +508,7 @@ private: protected: EDA_ITEM_FLAGS m_flags; EDA_ITEM* m_parent; ///< Linked list: Link (parent struct). + EDA_GROUP* m_group; ///< The group this item belongs to bool m_forceVisible; bool m_isRollover; }; diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 81a97db139..0041b70bed 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -97,8 +97,6 @@ set( PCBNEW_DIALOGS dialogs/dialog_global_edit_text_and_graphics.cpp dialogs/dialog_global_edit_text_and_graphics_base.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_base.cpp dialogs/dialog_shape_properties.cpp diff --git a/pcbnew/board.cpp b/pcbnew/board.cpp index 4b8a59d525..ff51dabc59 100644 --- a/pcbnew/board.cpp +++ b/pcbnew/board.cpp @@ -141,13 +141,13 @@ BOARD::~BOARD() // Untangle group parents before doing any deleting for( PCB_GROUP* group : m_groups ) { - for( BOARD_ITEM* item : group->GetItems() ) + for( EDA_ITEM* item : group->GetItems() ) item->SetParentGroup( nullptr ); } for( PCB_GENERATOR* generator : m_generators ) { - for( BOARD_ITEM* item : generator->GetItems() ) + for( EDA_ITEM* item : generator->GetItems() ) item->SetParentGroup( nullptr ); } @@ -1311,9 +1311,9 @@ void BOARD::Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aRemoveMode ) 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 ); 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. // // Groups we know are cycle free - std::unordered_set knownCycleFreeGroups; + std::unordered_set knownCycleFreeGroups; // Groups in the current chain we're exploring. - std::unordered_set currentChainGroups; + std::unordered_set currentChainGroups; // Groups we haven't checked yet. - std::unordered_set toCheckGroups; + std::unordered_set toCheckGroups; // Initialize set of groups and generators to check that could participate in a cycle. for( PCB_GROUP* group : Groups() ) @@ -2834,14 +2834,14 @@ wxString BOARD::GroupsSanityCheckInternal( bool repair ) while( !toCheckGroups.empty() ) { currentChainGroups.clear(); - PCB_GROUP* group = *toCheckGroups.begin(); + EDA_GROUP* group = *toCheckGroups.begin(); while( true ) { if( currentChainGroups.find( group ) != currentChainGroups.end() ) { if( repair ) - Remove( group ); + Remove( static_cast( group->AsEdaItem() ) ); 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 toCheckGroups.erase( group ); - group = group->GetParentGroup(); + group = group->AsEdaItem()->GetParentGroup(); if( !group ) { diff --git a/pcbnew/board_commit.cpp b/pcbnew/board_commit.cpp index 42f6b037c9..f11a267b5c 100644 --- a/pcbnew/board_commit.cpp +++ b/pcbnew/board_commit.cpp @@ -387,7 +387,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags ) case CHT_REMOVE: { FOOTPRINT* parentFP = boardItem->GetParentFootprint(); - PCB_GROUP* parentGroup = boardItem->GetParentGroup(); + EDA_GROUP* parentGroup = boardItem->GetParentGroup(); if( !( aCommitFlags & SKIP_UNDO ) ) undoList.PushItem( ITEM_PICKER( nullptr, boardItem, UNDO_REDO::DELETED ) ); @@ -400,7 +400,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags ) itemsDeselected = true; } - if( parentGroup && !( parentGroup->GetFlags() & STRUCT_DELETED ) ) + if( parentGroup && !( parentGroup->AsEdaItem()->GetFlags() & STRUCT_DELETED ) ) parentGroup->RemoveItem( boardItem ); if( parentFP && !( parentFP->GetFlags() & STRUCT_DELETED ) ) @@ -471,12 +471,12 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags ) } case CHT_UNGROUP: - if( PCB_GROUP* group = boardItem->GetParentGroup() ) + if( EDA_GROUP* group = boardItem->GetParentGroup() ) { if( !( aCommitFlags & SKIP_UNDO ) ) { ITEM_PICKER itemWrapper( nullptr, boardItem, UNDO_REDO::UNGROUP ); - itemWrapper.SetGroupId( group->m_Uuid ); + itemWrapper.SetGroupId( group->AsEdaItem()->m_Uuid ); undoList.PushItem( itemWrapper ); } @@ -751,9 +751,9 @@ void BOARD_COMMIT::Revert() case CHT_ADD: // Items are auto-added to the parent group by BOARD_ITEM::Duplicate(), not when // 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 ); } diff --git a/pcbnew/board_item.cpp b/pcbnew/board_item.cpp index 3bc4910002..396025bf84 100644 --- a/pcbnew/board_item.cpp +++ b/pcbnew/board_item.cpp @@ -38,12 +38,6 @@ #include -BOARD_ITEM::~BOARD_ITEM() -{ - wxASSERT( m_group == nullptr ); -} - - void BOARD_ITEM::CopyFrom( const BOARD_ITEM* aOther ) { wxCHECK( aOther, /* void */ ); @@ -81,7 +75,7 @@ BOARD* BOARD_ITEM::GetBoard() bool BOARD_ITEM::IsLocked() const { - if( GetParentGroup() && GetParentGroup()->IsLocked() ) + if( GetParentGroup() && static_cast( GetParentGroup() )->IsLocked() ) return true; const BOARD* board = GetBoard(); @@ -235,7 +229,7 @@ void BOARD_ITEM::SwapItemData( BOARD_ITEM* aImage ) return; EDA_ITEM* parent = GetParent(); - PCB_GROUP* group = GetParentGroup(); + EDA_GROUP* group = GetParentGroup(); SetParentGroup( nullptr ); aImage->SetParentGroup( nullptr ); diff --git a/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.cpp b/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.cpp index ae1fc7db76..68ed797a13 100644 --- a/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.cpp +++ b/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.cpp @@ -214,10 +214,10 @@ void DIALOG_CLEANUP_TRACKS_AND_VIAS::doCleanup( bool aDryRun ) { if( !aItem->IsSelected() ) { - PCB_GROUP* group = aItem->GetParentGroup(); + EDA_GROUP* group = aItem->GetParentGroup(); - while( group && !group->IsSelected() ) - group = group->GetParentGroup(); + while( group && !group->AsEdaItem()->IsSelected() ) + group = group->AsEdaItem()->GetParentGroup(); if( !group ) return true; diff --git a/pcbnew/dialogs/dialog_global_edit_teardrops.cpp b/pcbnew/dialogs/dialog_global_edit_teardrops.cpp index 418321b5ea..9fe4478cbc 100644 --- a/pcbnew/dialogs/dialog_global_edit_teardrops.cpp +++ b/pcbnew/dialogs/dialog_global_edit_teardrops.cpp @@ -387,10 +387,10 @@ void DIALOG_GLOBAL_EDIT_TEARDROPS::visitItem( BOARD_COMMIT* aCommit, { if( !aItem->IsSelected() ) { - PCB_GROUP* group = aItem->GetParentGroup(); + EDA_GROUP* group = aItem->GetParentGroup(); - while( group && !group->IsSelected() ) - group = group->GetParentGroup(); + while( group && !group->AsEdaItem()->IsSelected() ) + group = group->AsEdaItem()->GetParentGroup(); if( !group ) return; diff --git a/pcbnew/dialogs/dialog_global_edit_text_and_graphics.cpp b/pcbnew/dialogs/dialog_global_edit_text_and_graphics.cpp index b19494a287..8dde7ea730 100644 --- a/pcbnew/dialogs/dialog_global_edit_text_and_graphics.cpp +++ b/pcbnew/dialogs/dialog_global_edit_text_and_graphics.cpp @@ -480,7 +480,7 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::visitItem( BOARD_COMMIT& aCommit, BOA { if( m_selectedItemsFilter->GetValue() ) { - BOARD_ITEM* candidate = aItem; + EDA_ITEM* candidate = aItem; if( !candidate->IsSelected() ) { @@ -490,10 +490,10 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::visitItem( BOARD_COMMIT& aCommit, BOA if( !candidate->IsSelected() ) { - candidate = candidate->GetParentGroup(); + candidate = ( candidate->GetParentGroup() ? candidate->GetParentGroup()->AsEdaItem() : nullptr ); while( candidate && !candidate->IsSelected() ) - candidate = candidate->GetParentGroup(); + candidate = candidate->GetParentGroup()->AsEdaItem(); if( !candidate ) return; diff --git a/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp b/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp index 7fb8420e4d..daf1001746 100644 --- a/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp +++ b/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp @@ -352,10 +352,10 @@ void DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::visitItem( PICKED_ITEMS_LIST* aUndoList { if( !aItem->IsSelected() ) { - PCB_GROUP* group = aItem->GetParentGroup(); + EDA_GROUP* group = aItem->GetParentGroup(); - while( group && !group->IsSelected() ) - group = group->GetParentGroup(); + while( group && !group->AsEdaItem()->IsSelected() ) + group = group->AsEdaItem()->GetParentGroup(); if( !group ) return; diff --git a/pcbnew/footprint.cpp b/pcbnew/footprint.cpp index 03a49b32fe..b8c94aa828 100644 --- a/pcbnew/footprint.cpp +++ b/pcbnew/footprint.cpp @@ -136,7 +136,7 @@ FOOTPRINT::FOOTPRINT( const FOOTPRINT& aFootprint ) : std::ranges::copy( aFootprint.m_jumperPadGroups, std::inserter( m_jumperPadGroups, m_jumperPadGroups.end() ) ); - std::map ptrMap; + std::map ptrMap; // Copy fields for( PCB_FIELD* field : aFootprint.m_fields ) @@ -201,7 +201,7 @@ FOOTPRINT::FOOTPRINT( const FOOTPRINT& aFootprint ) : newGroup->GetItems().clear(); - for( BOARD_ITEM* member : group->GetItems() ) + for( EDA_ITEM* member : group->GetItems() ) { if( ptrMap.count( member ) ) newGroup->AddItem( ptrMap[ member ] ); @@ -236,7 +236,7 @@ FOOTPRINT::~FOOTPRINT() // Untangle group parents before doing any deleting for( PCB_GROUP* group : m_groups ) { - for( BOARD_ITEM* item : group->GetItems() ) + for( EDA_ITEM* item : group->GetItems() ) item->SetParentGroup( nullptr ); } @@ -871,7 +871,7 @@ FOOTPRINT& FOOTPRINT::operator=( const FOOTPRINT& aOther ) m_zoneConnection = aOther.m_zoneConnection; m_netTiePadGroups = aOther.m_netTiePadGroups; - std::map ptrMap; + std::map ptrMap; // Copy fields m_fields.clear(); @@ -927,7 +927,7 @@ FOOTPRINT& FOOTPRINT::operator=( const FOOTPRINT& aOther ) PCB_GROUP* newGroup = static_cast( group->Clone() ); newGroup->GetItems().clear(); - for( BOARD_ITEM* member : group->GetItems() ) + for( EDA_ITEM* member : group->GetItems() ) newGroup->AddItem( ptrMap[ member ] ); Add( newGroup ); @@ -1211,9 +1211,9 @@ void FOOTPRINT::Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aMode ) 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 ); } @@ -2808,7 +2808,7 @@ double FOOTPRINT::GetCoverageArea( const BOARD_ITEM* aItem, const GENERAL_COLLEC { double combinedArea = 0.0; - for( BOARD_ITEM* member : static_cast( aItem )->GetItems() ) + for( BOARD_ITEM* member : static_cast( aItem )->GetBoardItems() ) combinedArea += GetCoverageArea( member, aCollector ); return combinedArea; diff --git a/pcbnew/footprint_libraries_utils.cpp b/pcbnew/footprint_libraries_utils.cpp index 105635614f..ffca28b8d2 100644 --- a/pcbnew/footprint_libraries_utils.cpp +++ b/pcbnew/footprint_libraries_utils.cpp @@ -602,7 +602,7 @@ void PCB_EDIT_FRAME::ExportFootprintsToLibrary( bool aStoreInNewLib, const wxStr auto resetGroup = []( FOOTPRINT* aFootprint ) { - if( PCB_GROUP* parentGroup = aFootprint->GetParentGroup() ) + if( EDA_GROUP* parentGroup = aFootprint->GetParentGroup() ) parentGroup->RemoveItem( aFootprint ); }; diff --git a/pcbnew/generators/pcb_tuning_pattern.cpp b/pcbnew/generators/pcb_tuning_pattern.cpp index 8ea54881b4..1ceb4216a5 100644 --- a/pcbnew/generators/pcb_tuning_pattern.cpp +++ b/pcbnew/generators/pcb_tuning_pattern.cpp @@ -1137,7 +1137,7 @@ void PCB_TUNING_PATTERN::Remove( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COM { PCB_GENERATOR* group = this; - for( BOARD_ITEM* member : group->GetItems() ) + for( EDA_ITEM* member : group->GetItems() ) aCommit->Stage( member, CHT_UNGROUP ); group->GetItems().clear(); @@ -2004,7 +2004,7 @@ void PCB_TUNING_PATTERN::ShowPropertiesDialog( PCB_BASE_EDIT_FRAME* aEditFrame ) if( !m_items.empty() ) { - BOARD_ITEM* startItem = *m_items.begin(); + BOARD_ITEM* startItem = static_cast( *m_items.begin() ); std::shared_ptr& drcEngine = GetBoard()->GetDesignSettings().m_DRCEngine; 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() ); - for( BOARD_ITEM* member : GetItems() ) + for( EDA_ITEM* member : GetItems() ) { if( PCB_TRACK* track = dynamic_cast( member ) ) { @@ -2539,7 +2539,7 @@ int DRAWING_TOOL::PlaceTuningPattern( const TOOL_EVENT& aEvent ) { 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, startItem->GetLayer() ); diff --git a/pcbnew/pad.cpp b/pcbnew/pad.cpp index 828e709760..0737e996e1 100644 --- a/pcbnew/pad.cpp +++ b/pcbnew/pad.cpp @@ -2170,7 +2170,7 @@ std::vector PAD::Recombine( bool aIsDryRun, int maxError ) // 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 // primitives to wind up in a group. - if( PCB_GROUP* group = fpShape->GetParentGroup(); group ) + if( EDA_GROUP* group = fpShape->GetParentGroup(); group ) group->RemoveItem( fpShape ); PCB_SHAPE* primitive = static_cast( fpShape->Duplicate() ); diff --git a/pcbnew/pcb_edit_frame.cpp b/pcbnew/pcb_edit_frame.cpp index c189b52c58..1b84253eaf 100644 --- a/pcbnew/pcb_edit_frame.cpp +++ b/pcbnew/pcb_edit_frame.cpp @@ -2419,7 +2419,7 @@ void PCB_EDIT_FRAME::ExchangeFootprint( FOOTPRINT* aExisting, FOOTPRINT* aNew, bool resetTextContent, bool resetFabricationAttrs, bool reset3DModels, bool* aUpdated ) { - PCB_GROUP* parentGroup = aExisting->GetParentGroup(); + EDA_GROUP* parentGroup = aExisting->GetParentGroup(); bool dummyBool = false; if( !aUpdated ) diff --git a/pcbnew/pcb_generator.cpp b/pcbnew/pcb_generator.cpp index 2b72e7e348..8f2f8afc9d 100644 --- a/pcbnew/pcb_generator.cpp +++ b/pcbnew/pcb_generator.cpp @@ -44,7 +44,7 @@ PCB_GENERATOR* PCB_GENERATOR::DeepClone() const PCB_GENERATOR* newGenerator = static_cast( Clone() ); newGenerator->m_items.clear(); - for( BOARD_ITEM* member : m_items ) + for( EDA_ITEM* member : m_items ) { if( member->Type() == PCB_GROUP_T ) newGenerator->AddItem( static_cast( member )->DeepClone() ); @@ -158,18 +158,6 @@ void PCB_GENERATOR::baseMirror( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDir 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 { return PCB_GROUP::GetLayerSet() | LSET( { GetLayer() } ); diff --git a/pcbnew/pcb_generator.h b/pcbnew/pcb_generator.h index 9cf5ea3797..c578ea0310 100644 --- a/pcbnew/pcb_generator.h +++ b/pcbnew/pcb_generator.h @@ -51,7 +51,7 @@ public: /* * 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 ); @@ -89,8 +89,6 @@ public: void Mirror( const VECTOR2I& aCentre, FLIP_DIRECTION aMirrorDirection ) override; - bool AddItem( BOARD_ITEM* aItem ) override; - LSET GetLayerSet() const override; virtual void SetLayer( PCB_LAYER_ID aLayer ) override; diff --git a/pcbnew/pcb_group.cpp b/pcbnew/pcb_group.cpp index 45c520d61d..2413c8e6a5 100644 --- a/pcbnew/pcb_group.cpp +++ b/pcbnew/pcb_group.cpp @@ -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, 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 if( m_items.erase( aItem ) == 1 ) { @@ -108,18 +112,36 @@ bool PCB_GROUP::RemoveItem( BOARD_ITEM* aItem ) void PCB_GROUP::RemoveAll() { - for( BOARD_ITEM* item : m_items ) + for( EDA_ITEM* item : m_items ) item->SetParentGroup( nullptr ); m_items.clear(); } +std::unordered_set PCB_GROUP::GetBoardItems() const +{ + std::unordered_set items; + + for( EDA_ITEM* item : m_items ) + { + BOARD_ITEM* board_item = dynamic_cast( 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 * 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 ) 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 -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 ) 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; - group = group->GetParentGroup(); + group = group->AsEdaItem()->GetParentGroup(); } 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 ); } @@ -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 ) { - PCB_GROUP* group = getClosestGroup( aItem, isFootprintEditor ); + EDA_GROUP* group = getClosestGroup( aItem, isFootprintEditor ); if( group && group == aScope ) 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 ); newGroup->m_items.clear(); - for( BOARD_ITEM* member : m_items ) + for( EDA_ITEM* member : m_items ) { if( member->Type() == PCB_GROUP_T ) newGroup->AddItem( static_cast( member )->DeepClone() ); @@ -227,12 +249,12 @@ PCB_GROUP* PCB_GROUP::DeepDuplicate() const PCB_GROUP* newGroup = static_cast( Duplicate() ); newGroup->m_items.clear(); - for( BOARD_ITEM* member : m_items ) + for( EDA_ITEM* member : m_items ) { if( member->Type() == PCB_GROUP_T ) newGroup->AddItem( static_cast( member )->DeepDuplicate() ); else - newGroup->AddItem( static_cast( member->Duplicate() ) ); + newGroup->AddItem( static_cast( static_cast( member )->Duplicate() ) ); } return newGroup; @@ -265,7 +287,7 @@ const BOX2I PCB_GROUP::GetBoundingBox() const { BOX2I bbox; - for( BOARD_ITEM* item : m_items ) + for( EDA_ITEM* item : m_items ) { if( item->Type() == PCB_FOOTPRINT_T ) bbox.Merge( static_cast( item )->GetBoundingBox( true ) ); @@ -283,8 +305,8 @@ std::shared_ptr PCB_GROUP::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHI { std::shared_ptr shape = std::make_shared(); - for( BOARD_ITEM* item : m_items ) - shape->AddShape( item->GetEffectiveShape( aLayer, aFlash )->Clone() ); + for( EDA_ITEM* item : m_items ) + shape->AddShape( static_cast( item )->GetEffectiveShape( aLayer, aFlash )->Clone() ); return shape; } @@ -310,8 +332,8 @@ LSET PCB_GROUP::GetLayerSet() const { LSET aSet; - for( BOARD_ITEM* item : m_items ) - aSet |= item->GetLayerSet(); + for( EDA_ITEM* item : m_items ) + aSet |= static_cast( item )->GetLayerSet(); return aSet; } @@ -320,9 +342,9 @@ LSET PCB_GROUP::GetLayerSet() const bool PCB_GROUP::IsOnLayer( PCB_LAYER_ID aLayer ) const { // 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( item )->IsOnLayer( aLayer ) ) return true; } @@ -347,29 +369,29 @@ double PCB_GROUP::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const void PCB_GROUP::Move( const VECTOR2I& aMoveVector ) { - for( BOARD_ITEM* member : m_items ) - member->Move( aMoveVector ); + for( EDA_ITEM* member : m_items ) + static_cast( member )->Move( aMoveVector ); } void PCB_GROUP::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle ) { - for( BOARD_ITEM* item : m_items ) - item->Rotate( aRotCentre, aAngle ); + for( EDA_ITEM* item : m_items ) + static_cast( item )->Rotate( aRotCentre, aAngle ); } void PCB_GROUP::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection ) { - for( BOARD_ITEM* item : m_items ) - item->Flip( aCentre, aFlipDirection ); + for( EDA_ITEM* item : m_items ) + static_cast( item )->Flip( aCentre, aFlipDirection ); } void PCB_GROUP::Mirror( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection ) { - for( BOARD_ITEM* item : m_items ) - item->Mirror( aCentre, aFlipDirection ); + for( EDA_ITEM* item : m_items ) + static_cast( item )->Mirror( aCentre, aFlipDirection ); } @@ -402,7 +424,7 @@ void PCB_GROUP::RunOnChildren( const std::function& aFuncti { try { - for( BOARD_ITEM* item : m_items ) + for( BOARD_ITEM* item : GetBoardItems() ) { aFunction( item ); @@ -461,11 +483,11 @@ double PCB_GROUP::Similarity( const BOARD_ITEM& aOther ) const 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( item )->Similarity( *static_cast( otherItem ) ); } } @@ -480,7 +502,9 @@ static struct PCB_GROUP_DESC PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance(); REGISTER_TYPE( PCB_GROUP ); propMgr.AddTypeCast( new TYPE_CAST ); + propMgr.AddTypeCast( new TYPE_CAST ); 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 Y" ) ); @@ -488,8 +512,8 @@ static struct PCB_GROUP_DESC const wxString groupTab = _HKI( "Group Properties" ); - propMgr.AddProperty( new PROPERTY( _HKI( "Name" ), - &PCB_GROUP::SetName, &PCB_GROUP::GetName ), - groupTab ); + propMgr.AddProperty( + new PROPERTY( _HKI( "Name" ), &PCB_GROUP::SetName, &PCB_GROUP::GetName ), + groupTab ); } } _PCB_GROUP_DESC; diff --git a/pcbnew/pcb_group.h b/pcbnew/pcb_group.h index e160d75acf..789da8e09f 100644 --- a/pcbnew/pcb_group.h +++ b/pcbnew/pcb_group.h @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -48,11 +49,13 @@ class VIEW; * 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 PCB_GROUP : public BOARD_ITEM +class PCB_GROUP : public BOARD_ITEM, public EDA_GROUP { public: PCB_GROUP( BOARD_ITEM* aParent ); + EDA_ITEM* AsEdaItem() override { return this; } + static inline bool ClassOf( const EDA_ITEM* aItem ) { return aItem && PCB_GROUP_T == aItem->Type(); @@ -63,34 +66,23 @@ public: return wxT( "PCB_GROUP" ); } - wxString GetName() const { return m_name; } - void SetName( const wxString& aName ) { m_name = aName; } - - std::unordered_set& GetItems() - { - return m_items; - } - - const std::unordered_set& 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( BOARD_ITEM* aItem ); + bool AddItem( EDA_ITEM* aItem ) override; /** * Remove item from 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 GetBoardItems() const; /* * 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 * @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 ); @@ -144,12 +136,12 @@ public: /* * Clone() this and all descendants */ - PCB_GROUP* DeepClone() const; + PCB_GROUP* DeepClone() const override; /* * Duplicate() this and all descendants */ - PCB_GROUP* DeepDuplicate() const; + PCB_GROUP* DeepDuplicate() const override; /// @copydoc BOARD_ITEM::IsOnLayer bool IsOnLayer( PCB_LAYER_ID aLayer ) const override; @@ -213,9 +205,6 @@ protected: /// @copydoc BOARD_ITEM::swapData void swapData( BOARD_ITEM* aImage ) override; - - std::unordered_set m_items; // Members of the group - wxString m_name; // Optional group name }; #endif // CLASS_PCB_GROUP_H_ diff --git a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp index 4db217b50d..074ba5ce7a 100644 --- a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp +++ b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp @@ -2206,7 +2206,7 @@ void PCB_IO_KICAD_SEXPR::format( const PCB_GROUP* aGroup ) const wxArrayString memberIds; - for( BOARD_ITEM* member : aGroup->GetItems() ) + for( EDA_ITEM* member : aGroup->GetItems() ) memberIds.Add( member->m_Uuid.AsString() ); memberIds.Sort(); @@ -2304,7 +2304,7 @@ void PCB_IO_KICAD_SEXPR::format( const PCB_GENERATOR* aGenerator ) const wxArrayString memberIds; - for( BOARD_ITEM* member : aGenerator->GetItems() ) + for( EDA_ITEM* member : aGenerator->GetItems() ) memberIds.Add( member->m_Uuid.AsString() ); memberIds.Sort(); diff --git a/pcbnew/pcbexpr_functions.cpp b/pcbnew/pcbexpr_functions.cpp index 1585c1c3dd..1751682b7b 100644 --- a/pcbnew/pcbexpr_functions.cpp +++ b/pcbnew/pcbexpr_functions.cpp @@ -919,7 +919,7 @@ static void memberOfGroupFunc( LIBEVAL::CONTEXT* aCtx, void* self ) result->SetDeferredEval( [item, arg]() -> double { - PCB_GROUP* group = item->GetParentGroup(); + EDA_GROUP* group = item->GetParentGroup(); if( !group && item->GetParent() && item->GetParent()->Type() == PCB_FOOTPRINT_T ) group = item->GetParent()->GetParentGroup(); @@ -929,7 +929,7 @@ static void memberOfGroupFunc( LIBEVAL::CONTEXT* aCtx, void* self ) if( group->GetName().Matches( arg->AsString() ) ) return 1.0; - group = group->GetParentGroup(); + group = group->AsEdaItem()->GetParentGroup(); } return 0.0; diff --git a/pcbnew/python/swig/pcb_group.i b/pcbnew/python/swig/pcb_group.i index 66e62a633d..bf5f710a42 100644 --- a/pcbnew/python/swig/pcb_group.i +++ b/pcbnew/python/swig/pcb_group.i @@ -11,7 +11,7 @@ { std::deque result; - const std::unordered_set items = $self->GetItems(); + const std::unordered_set items = $self->GetBoardItems(); for(BOARD_ITEM* item: items) result.push_back(item); diff --git a/pcbnew/specctra_import_export/specctra_import.cpp b/pcbnew/specctra_import_export/specctra_import.cpp index 91da2f4015..335751b4e5 100644 --- a/pcbnew/specctra_import_export/specctra_import.cpp +++ b/pcbnew/specctra_import_export/specctra_import.cpp @@ -387,7 +387,7 @@ void SPECCTRA_DB::FromSESSION( BOARD* aBoard ) } else { - if( PCB_GROUP* group = track->GetParentGroup() ) + if( EDA_GROUP* group = track->GetParentGroup() ) group->RemoveItem( track ); delete track; diff --git a/pcbnew/tools/board_editor_control.cpp b/pcbnew/tools/board_editor_control.cpp index 03047911fa..0bc2801966 100644 --- a/pcbnew/tools/board_editor_control.cpp +++ b/pcbnew/tools/board_editor_control.cpp @@ -1301,9 +1301,9 @@ int BOARD_EDITOR_CONTROL::modifyLockSelected( MODIFY_MODE aMode ) if( board_item->Type() == PCB_PAD_T ) 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( parent_group ); diff --git a/pcbnew/tools/board_inspection_tool.cpp b/pcbnew/tools/board_inspection_tool.cpp index 7b3f22fad2..46db3a0bb7 100644 --- a/pcbnew/tools/board_inspection_tool.cpp +++ b/pcbnew/tools/board_inspection_tool.cpp @@ -735,7 +735,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent ) return 0; } - a = *ag->GetItems().begin(); + a = static_cast( *ag->GetItems().begin() ); } if( b->Type() == PCB_GROUP_T ) @@ -748,7 +748,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent ) return 0; } - b = *bg->GetItems().begin(); + b = static_cast( *bg->GetItems().begin() ); } // a or b could be null after group tests above. diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index a265cc1c68..3cb085a27d 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -2424,13 +2424,13 @@ int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent ) void EDIT_TOOL::getChildItemsOfGroupsAndGenerators( EDA_ITEM* item, - std::unordered_set& children ) + std::unordered_set& children ) { wxASSERT( item->Type() == PCB_GROUP_T || item->Type() == PCB_GENERATOR_T ); - std::unordered_set& childItems = static_cast( item )->GetItems(); + std::unordered_set& childItems = static_cast( item )->GetItems(); - for( BOARD_ITEM* childItem : childItems ) + for( EDA_ITEM* childItem : childItems ) { children.insert( childItem ); @@ -2454,7 +2454,7 @@ void EDIT_TOOL::removeNonRootItems( std::unordered_set& items ) if( curItem->Type() == PCB_GROUP_T || curItem->Type() == PCB_GENERATOR_T ) { - std::unordered_set childItems; + std::unordered_set childItems; getChildItemsOfGroupsAndGenerators( curItem, childItems ); 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( board_item ); - for( BOARD_ITEM* member : generator->GetItems() ) + for( EDA_ITEM* member : generator->GetItems() ) commit.Stage( member, CHT_UNGROUP ); - for( BOARD_ITEM* member : generator->GetItems() ) + for( EDA_ITEM* member : generator->GetItems() ) commit.Remove( member ); commit.Remove( board_item ); diff --git a/pcbnew/tools/edit_tool.h b/pcbnew/tools/edit_tool.h index 3e51704fe5..846129ccb8 100644 --- a/pcbnew/tools/edit_tool.h +++ b/pcbnew/tools/edit_tool.h @@ -232,7 +232,7 @@ private: ///< Recursively adds any child items of the given item to the set void getChildItemsOfGroupsAndGenerators( EDA_ITEM* item, - std::unordered_set& children ); + std::unordered_set& children ); private: diff --git a/pcbnew/tools/group_tool.cpp b/pcbnew/tools/group_tool.cpp index 4014365377..7cfc3faaa2 100644 --- a/pcbnew/tools/group_tool.cpp +++ b/pcbnew/tools/group_tool.cpp @@ -305,7 +305,7 @@ int GROUP_TOOL::Ungroup( const TOOL_EVENT& aEvent ) if( group ) { - for( BOARD_ITEM* member : group->GetItems() ) + for( EDA_ITEM* member : group->GetItems() ) { commit.Stage( member, CHT_UNGROUP ); toSelect.push_back( member ); @@ -339,7 +339,7 @@ int GROUP_TOOL::RemoveFromGroup( const TOOL_EVENT& aEvent ) for( EDA_ITEM* item : selection ) { BOARD_ITEM* boardItem = static_cast( item ); - PCB_GROUP* group = boardItem->GetParentGroup(); + EDA_GROUP* group = boardItem->GetParentGroup(); if( group ) commit.Stage( boardItem, CHT_UNGROUP ); diff --git a/pcbnew/tools/multichannel_tool.cpp b/pcbnew/tools/multichannel_tool.cpp index 2d27079952..4d9e4ddc41 100644 --- a/pcbnew/tools/multichannel_tool.cpp +++ b/pcbnew/tools/multichannel_tool.cpp @@ -404,7 +404,7 @@ int MULTICHANNEL_TOOL::repeatLayout( const TOOL_EVENT& aEvent ) { PCB_GROUP *group = static_cast( item ); - for( BOARD_ITEM* grpItem : group->GetItems() ) + for( EDA_ITEM* grpItem : group->GetItems() ) { if( auto grpZone = isSelectedItemAnRA( grpItem ) ) { @@ -1012,12 +1012,11 @@ bool MULTICHANNEL_TOOL::pruneExistingGroups( COMMIT& aCommit, auto grp = pending.front(); pending.pop_front(); - std::unordered_set& grpItems = grp->GetItems(); + std::unordered_set& grpItems = grp->GetItems(); size_t n_erased = 0; - for( BOARD_ITEM* refItem : grpItems ) + for( EDA_ITEM* refItem : grpItems ) { - if( refItem->Type() == PCB_GROUP_T ) pending.push_back( static_cast(refItem) ); diff --git a/pcbnew/tools/pcb_control.cpp b/pcbnew/tools/pcb_control.cpp index 1e6b94f0a4..4d3e6901d6 100644 --- a/pcbnew/tools/pcb_control.cpp +++ b/pcbnew/tools/pcb_control.cpp @@ -918,7 +918,7 @@ static void pasteFootprintItemsToFootprintEditor( FOOTPRINT* aClipFootprint, BOA { if( field->IsMandatory() ) { - if( PCB_GROUP* parentGroup = field->GetParentGroup() ) + if( EDA_GROUP* parentGroup = field->GetParentGroup() ) parentGroup->RemoveItem( field ); } else @@ -1029,7 +1029,7 @@ void PCB_CONTROL::pruneItemLayers( std::vector& aItems ) } else { - if( PCB_GROUP* parentGroup = item->GetParentGroup() ) + if( EDA_GROUP* parentGroup = item->GetParentGroup() ) parentGroup->RemoveItem( item ); } } @@ -1186,7 +1186,7 @@ int PCB_CONTROL::Paste( const TOOL_EVENT& aEvent ) default: // Everything we *didn't* put into pastedItems is going to get nuked, so // 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 ); 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 // removed from the pasted groups. BOARD_ITEM* boardItem = static_cast( item ); - PCB_GROUP* parentGroup = boardItem->GetParentGroup(); + EDA_GROUP* parentGroup = boardItem->GetParentGroup(); if( parentGroup ) parentGroup->RemoveItem( boardItem ); @@ -1478,7 +1478,7 @@ bool PCB_CONTROL::placeBoardItems( BOARD_COMMIT* aCommit, std::vectorGetParentGroup() || !alg::contains( aItems, item->GetParentGroup() ) ) + if( !item->GetParentGroup() || !alg::contains( aItems, item->GetParentGroup()->AsEdaItem() ) ) itemsToSel.push_back( item ); } diff --git a/pcbnew/tools/pcb_grid_helper.cpp b/pcbnew/tools/pcb_grid_helper.cpp index 7218f9e75a..15be087d19 100644 --- a/pcbnew/tools/pcb_grid_helper.cpp +++ b/pcbnew/tools/pcb_grid_helper.cpp @@ -1606,7 +1606,7 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos break; case PCB_GROUP_T: - for( BOARD_ITEM* item : static_cast( aItem )->GetItems() ) + for( BOARD_ITEM* item : static_cast( aItem )->GetBoardItems() ) { if( checkVisibility( item ) ) computeAnchors( item, aRefPos, aFrom, nullptr ); diff --git a/pcbnew/tools/pcb_selection_tool.cpp b/pcbnew/tools/pcb_selection_tool.cpp index 621271f077..b97fddc366 100644 --- a/pcbnew/tools/pcb_selection_tool.cpp +++ b/pcbnew/tools/pcb_selection_tool.cpp @@ -1138,7 +1138,7 @@ bool PCB_SELECTION_TOOL::selectMultiple() GENERAL_COLLECTOR collector; GENERAL_COLLECTOR padsCollector; - std::set group_items; + std::set group_items; for( PCB_GROUP* group : board()->Groups() ) { @@ -1146,21 +1146,21 @@ bool PCB_SELECTION_TOOL::selectMultiple() if( m_enteredGroup == group ) continue; - std::unordered_set& newset = group->GetItems(); + std::unordered_set& newset = group->GetItems(); // 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 if( !greedySelection && selectionRect.Contains( group->GetBoundingBox() ) && newset.size() ) { - for( BOARD_ITEM* group_item : newset ) + for( EDA_ITEM* group_item : newset ) { - if( Selectable( group_item ) ) + if( Selectable( static_cast( group_item ) ) ) collector.Append( *newset.begin() ); } } - for( BOARD_ITEM* group_item : newset ) + for( EDA_ITEM* group_item : newset ) 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 ) { - for( BOARD_ITEM* generatedItem : static_cast( item )->GetItems() ) + for( BOARD_ITEM* generatedItem : static_cast( item )->GetBoardItems() ) { if( BOARD_CONNECTED_ITEM::ClassOf( generatedItem ) ) startItems.push_back( static_cast( generatedItem ) ); @@ -1767,14 +1767,14 @@ void PCB_SELECTION_TOOL::selectAllConnectedTracks( continue; BOARD_ITEM* boardItem = static_cast( 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 ); - if( !parent->IsSelected() ) - toSelect.insert( parent ); + if( !parent->AsEdaItem()->IsSelected() ) + 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. // (This recurses.) - for( BOARD_ITEM* item : group->GetItems() ) + for( BOARD_ITEM* item : group->GetBoardItems() ) { if( Selectable( item, true ) ) return true; @@ -2926,7 +2926,7 @@ bool PCB_SELECTION_TOOL::Selectable( const BOARD_ITEM* aItem, bool checkVisibili return false; } - if( aItem->GetParentGroup() && aItem->GetParentGroup()->Type() == PCB_GENERATOR_T ) + if( aItem->GetParentGroup() && aItem->GetParentGroup()->AsEdaItem()->Type() == PCB_GENERATOR_T ) return false; const ZONE* zone = nullptr; @@ -3343,7 +3343,7 @@ int PCB_SELECTION_TOOL::hitTestDistance( const VECTOR2I& aWhere, BOARD_ITEM* aIt { PCB_GROUP* group = static_cast( aItem ); - for( BOARD_ITEM* member : group->GetItems() ) + for( BOARD_ITEM* member : group->GetBoardItems() ) distance = std::min( distance, hitTestDistance( aWhere, member, aMaxDistance ) ); break; @@ -3729,7 +3729,7 @@ void PCB_SELECTION_TOOL::GuessSelectionCandidates( GENERAL_COLLECTOR& aCollector void PCB_SELECTION_TOOL::FilterCollectorForHierarchy( GENERAL_COLLECTOR& aCollector, bool aMultiselect ) const { - std::unordered_set toAdd; + std::unordered_set toAdd; // 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). @@ -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 // group. - if( PCB_GROUP* top = PCB_GROUP::TopLevelGroup( start, m_enteredGroup, - m_isFootprintEditor ) ) + if( EDA_GROUP* top = PCB_GROUP::TopLevelGroup( start, m_enteredGroup, m_isFootprintEditor ) ) { - if( top != item ) + if( top->AsEdaItem() != item ) { - toAdd.insert( top ); - top->SetFlags(CANDIDATE ); + toAdd.insert( top->AsEdaItem() ); + top->AsEdaItem()->SetFlags( CANDIDATE ); aCollector.Remove( item ); continue; @@ -3787,7 +3786,7 @@ void PCB_SELECTION_TOOL::FilterCollectorForHierarchy( GENERAL_COLLECTOR& aCollec ++j; } - for( BOARD_ITEM* item : toAdd ) + for( EDA_ITEM* item : toAdd ) { if( !aCollector.HasItem( item ) ) aCollector.Append( item ); diff --git a/pcbnew/tracks_cleaner.cpp b/pcbnew/tracks_cleaner.cpp index 0c7dfcc05b..0274fd72cd 100644 --- a/pcbnew/tracks_cleaner.cpp +++ b/pcbnew/tracks_cleaner.cpp @@ -787,7 +787,7 @@ bool TRACKS_CLEANER::mergeCollinearSegments( PCB_TRACK* aSeg1, PCB_TRACK* aSeg2 { m_commit.Modify( aSeg1 ); - PCB_GROUP* group = aSeg1->GetParentGroup(); + EDA_GROUP* group = aSeg1->GetParentGroup(); *aSeg1 = dummy_seg; aSeg1->SetParentGroup( group ); diff --git a/pcbnew/undo_redo.cpp b/pcbnew/undo_redo.cpp index eb77aef215..61456f7c79 100644 --- a/pcbnew/undo_redo.cpp +++ b/pcbnew/undo_redo.cpp @@ -433,7 +433,7 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList ) { BOARD_ITEM* item = (BOARD_ITEM*) eda_item; BOARD_ITEM_CONTAINER* parent = GetBoard(); - PCB_GROUP* parentGroup = item->GetParentGroup(); + EDA_GROUP* parentGroup = item->GetParentGroup(); if( item->GetParentFootprint() ) { @@ -509,9 +509,9 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList ) { BOARD_ITEM* boardItem = static_cast( 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 ); } diff --git a/qa/tests/pcbnew/group_saveload.cpp b/qa/tests/pcbnew/group_saveload.cpp index 909ac653f5..0871cac428 100644 --- a/qa/tests/pcbnew/group_saveload.cpp +++ b/qa/tests/pcbnew/group_saveload.cpp @@ -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.GetName(), group2.GetName() ); - const std::unordered_set& items1 = group1.GetItems(); - const std::unordered_set& items2 = group2.GetItems(); + const std::unordered_set& items1 = group1.GetItems(); + const std::unordered_set& items2 = group2.GetItems(); BOOST_CHECK_EQUAL( items1.size(), items2.size() ); // 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(); };