mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-13 17:53:11 +02:00
Rewrite GROUP undo based on uuids.
This also removes the GROUP/UNGROUP-specific undo actions. This also fixes a bunch of undo bugs when duplicating group members, creating pins, etc. This also fixes some undo bugs when dividing wires etc. This also fixes some bugs with new sch items not being created within an entered group.
This commit is contained in:
parent
2b5b3ffb8d
commit
f58fc0b952
@ -380,9 +380,6 @@ void BOARD_ADAPTER::createPadWithMargin( const PAD* aPad, CONTAINER_2D_BASE* aCo
|
||||
dummy.SetSize( aLayer, VECTOR2I( dummySize.x, dummySize.y ) );
|
||||
dummy.TransformShapeToPolygon( poly, aLayer, 0, maxError, ERROR_INSIDE );
|
||||
clearance = { 0, 0 };
|
||||
|
||||
// Remove group membership from dummy item before deleting
|
||||
dummy.SetParentGroup( nullptr );
|
||||
}
|
||||
else if( aPad->GetShape( aLayer ) == PAD_SHAPE::CUSTOM )
|
||||
{
|
||||
|
@ -1179,10 +1179,10 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||
|
||||
// ADD PLATED COPPER
|
||||
ConvertPolygonToTriangles( *m_frontPlatedCopperPolys, *m_platedPadsFront, m_biuTo3Dunits,
|
||||
*m_board->GetItem( niluuid ) );
|
||||
*DELETED_BOARD_ITEM::GetInstance() );
|
||||
|
||||
ConvertPolygonToTriangles( *m_backPlatedCopperPolys, *m_platedPadsBack, m_biuTo3Dunits,
|
||||
*m_board->GetItem( niluuid ) );
|
||||
*DELETED_BOARD_ITEM::GetInstance() );
|
||||
|
||||
m_platedPadsFront->BuildBVH();
|
||||
m_platedPadsBack->BuildBVH();
|
||||
|
@ -39,28 +39,12 @@ COMMIT::COMMIT()
|
||||
COMMIT::~COMMIT()
|
||||
{
|
||||
for( COMMIT_LINE& ent : m_changes )
|
||||
{
|
||||
if( ent.m_copy )
|
||||
{
|
||||
// If we're deleting changes, we have a commit that is being abandoned,
|
||||
// and the copies of items with group memberships can have their group membership
|
||||
// cleared as long as we make sure that group doesn't hold a reference to the copy.
|
||||
if( ent.m_copy->GetParentGroup() )
|
||||
{
|
||||
// This is a copy, so it should not be in the group.
|
||||
// (RemoveItem() returns false when it doesn't find the item),
|
||||
// but if it is we need to remove it to prevent a crash.
|
||||
wxASSERT( ent.m_copy->GetParentGroup()->RemoveItem( ent.m_copy ) == false );
|
||||
ent.m_copy->SetParentGroup( nullptr );
|
||||
}
|
||||
|
||||
delete ent.m_copy;
|
||||
}
|
||||
}
|
||||
delete ent.m_copy;
|
||||
}
|
||||
|
||||
|
||||
COMMIT& COMMIT::Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType, BASE_SCREEN* aScreen )
|
||||
COMMIT& COMMIT::Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType, BASE_SCREEN* aScreen,
|
||||
RECURSE_MODE aRecurse )
|
||||
{
|
||||
// CHT_MODIFY and CHT_DONE are not compatible
|
||||
wxASSERT( ( aChangeType & ( CHT_MODIFY | CHT_DONE ) ) != ( CHT_MODIFY | CHT_DONE ) );
|
||||
@ -71,32 +55,25 @@ COMMIT& COMMIT::Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType, BASE_SCREEN* aS
|
||||
{
|
||||
case CHT_ADD:
|
||||
makeEntry( aItem, CHT_ADD | flag, nullptr, aScreen );
|
||||
return *this;
|
||||
break;
|
||||
|
||||
case CHT_REMOVE:
|
||||
wxASSERT( m_deletedItems.find( aItem ) == m_deletedItems.end() );
|
||||
m_deletedItems.insert( aItem );
|
||||
makeEntry( aItem, CHT_REMOVE | flag, nullptr, aScreen );
|
||||
return *this;
|
||||
makeEntry( aItem, CHT_REMOVE | flag, makeImage( aItem ), aScreen );
|
||||
|
||||
if( EDA_GROUP* parentGroup = aItem->GetParentGroup() )
|
||||
Modify( parentGroup->AsEdaItem(), aScreen );
|
||||
|
||||
break;
|
||||
|
||||
case CHT_MODIFY:
|
||||
{
|
||||
EDA_ITEM* parent = parentObject( aItem );
|
||||
EDA_ITEM* clone = makeImage( parent );
|
||||
|
||||
wxASSERT( clone );
|
||||
|
||||
if( clone )
|
||||
return createModified( parent, clone, flag, aScreen );
|
||||
|
||||
createModified( parent, makeImage( parent ), flag, aScreen );
|
||||
break;
|
||||
}
|
||||
|
||||
case CHT_GROUP:
|
||||
case CHT_UNGROUP:
|
||||
makeEntry( aItem, aChangeType, nullptr, aScreen );
|
||||
return *this;
|
||||
|
||||
default:
|
||||
wxFAIL;
|
||||
}
|
||||
@ -106,7 +83,7 @@ COMMIT& COMMIT::Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType, BASE_SCREEN* aS
|
||||
|
||||
|
||||
COMMIT& COMMIT::Stage( std::vector<EDA_ITEM*> &container, CHANGE_TYPE aChangeType,
|
||||
BASE_SCREEN *aScreen )
|
||||
BASE_SCREEN *aScreen )
|
||||
{
|
||||
for( EDA_ITEM* item : container )
|
||||
Stage( item, aChangeType, aScreen);
|
||||
@ -157,7 +134,6 @@ COMMIT& COMMIT::createModified( EDA_ITEM* aItem, EDA_ITEM* aCopy, int aExtraFlag
|
||||
|
||||
if( m_changedItems.find( parent ) != m_changedItems.end() )
|
||||
{
|
||||
aCopy->SetParentGroup( nullptr );
|
||||
delete aCopy;
|
||||
return *this; // item has been already modified once
|
||||
}
|
||||
@ -170,9 +146,6 @@ COMMIT& COMMIT::createModified( EDA_ITEM* aItem, EDA_ITEM* aCopy, int aExtraFlag
|
||||
|
||||
void COMMIT::makeEntry( EDA_ITEM* aItem, CHANGE_TYPE aType, EDA_ITEM* aCopy, BASE_SCREEN *aScreen )
|
||||
{
|
||||
// Expect an item copy if it is going to be modified
|
||||
wxASSERT( !!aCopy == ( ( aType & CHT_TYPE ) == CHT_MODIFY ) );
|
||||
|
||||
COMMIT_LINE ent;
|
||||
|
||||
ent.m_item = aItem;
|
||||
@ -206,8 +179,6 @@ CHANGE_TYPE COMMIT::convert( UNDO_REDO aType ) const
|
||||
{
|
||||
case UNDO_REDO::NEWITEM: return CHT_ADD;
|
||||
case UNDO_REDO::DELETED: return CHT_REMOVE;
|
||||
case UNDO_REDO::REGROUP: return CHT_GROUP;
|
||||
case UNDO_REDO::UNGROUP: return CHT_UNGROUP;
|
||||
case UNDO_REDO::CHANGED: return CHT_MODIFY;
|
||||
default: wxASSERT( false ); return CHT_MODIFY;
|
||||
}
|
||||
@ -220,8 +191,6 @@ UNDO_REDO COMMIT::convert( CHANGE_TYPE aType ) const
|
||||
{
|
||||
case CHT_ADD: return UNDO_REDO::NEWITEM;
|
||||
case CHT_REMOVE: return UNDO_REDO::DELETED;
|
||||
case CHT_GROUP: return UNDO_REDO::REGROUP;
|
||||
case CHT_UNGROUP: return UNDO_REDO::UNGROUP;
|
||||
case CHT_MODIFY: return UNDO_REDO::CHANGED;
|
||||
default: wxASSERT( false ); return UNDO_REDO::CHANGED;
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ bool DIALOG_GROUP_PROPERTIES::TransferDataToWindow()
|
||||
|
||||
bool DIALOG_GROUP_PROPERTIES::TransferDataFromWindow()
|
||||
{
|
||||
m_commit->Modify( m_group->AsEdaItem(), m_frame->GetScreen() );
|
||||
m_commit->Modify( m_group->AsEdaItem(), m_frame->GetScreen(), RECURSE_MODE::RECURSE );
|
||||
|
||||
for( size_t ii = 0; ii < m_membersList->GetCount(); ++ii )
|
||||
{
|
||||
@ -117,7 +117,9 @@ bool DIALOG_GROUP_PROPERTIES::TransferDataFromWindow()
|
||||
m_group->SetDesignBlockLibId( libId );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_group->SetDesignBlockLibId( LIB_ID() );
|
||||
}
|
||||
|
||||
m_toolMgr->RunAction( ACTIONS::selectionClear );
|
||||
m_group->RemoveAll();
|
||||
|
@ -1,6 +1,68 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <eda_group.h>
|
||||
|
||||
EDA_GROUP::~EDA_GROUP()
|
||||
|
||||
void EDA_GROUP::AddItem( EDA_ITEM* aItem )
|
||||
{
|
||||
wxCHECK_RET( aItem, wxT( "Nullptr added to group." ) );
|
||||
|
||||
// Items can only be in one group at a time
|
||||
if( EDA_GROUP* parentGroup = aItem->GetParentGroup() )
|
||||
parentGroup->RemoveItem( aItem );
|
||||
|
||||
m_items.insert( aItem );
|
||||
aItem->SetParentGroup( this );
|
||||
}
|
||||
|
||||
|
||||
void EDA_GROUP::RemoveItem( EDA_ITEM* aItem )
|
||||
{
|
||||
wxCHECK_RET( aItem, wxT( "Nullptr removed from group." ) );
|
||||
|
||||
if( m_items.erase( aItem ) == 1 )
|
||||
aItem->SetParentGroup( nullptr );
|
||||
}
|
||||
|
||||
|
||||
void EDA_GROUP::RemoveAll()
|
||||
{
|
||||
for( EDA_ITEM* item : m_items )
|
||||
item->SetParentGroup( nullptr );
|
||||
|
||||
m_items.clear();
|
||||
}
|
||||
|
||||
|
||||
KIID_VECT_LIST EDA_GROUP::GetGroupMemberIds() const
|
||||
{
|
||||
KIID_VECT_LIST members;
|
||||
|
||||
for( EDA_ITEM* item : m_items )
|
||||
members.push_back( item->m_Uuid );
|
||||
|
||||
return members;
|
||||
}
|
||||
|
||||
|
||||
|
@ -46,53 +46,36 @@ class EDA_GROUP
|
||||
{
|
||||
public:
|
||||
virtual EDA_ITEM* AsEdaItem() = 0;
|
||||
virtual ~EDA_GROUP();
|
||||
virtual ~EDA_GROUP() = default;
|
||||
|
||||
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;
|
||||
void AddItem( EDA_ITEM* aItem );
|
||||
|
||||
/**
|
||||
* 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;
|
||||
void RemoveItem( EDA_ITEM* aItem );
|
||||
void RemoveAll();
|
||||
|
||||
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;
|
||||
KIID_VECT_LIST GetGroupMemberIds() const;
|
||||
|
||||
bool HasDesignBlockLink() const { return m_designBlockLibId.IsValid(); }
|
||||
|
||||
void SetDesignBlockLibId( const LIB_ID& aLibId ) { m_designBlockLibId = aLibId; }
|
||||
|
||||
const LIB_ID& GetDesignBlockLibId() const { return m_designBlockLibId; }
|
||||
|
||||
protected:
|
||||
std::unordered_set<EDA_ITEM*> m_items; // Members of the group
|
||||
wxString m_name; // Optional group name
|
||||
|
||||
// Optional link to a design block
|
||||
LIB_ID m_designBlockLibId;
|
||||
std::unordered_set<EDA_ITEM*> m_items; // Members of the group
|
||||
wxString m_name; // Optional group name
|
||||
LIB_ID m_designBlockLibId; // Optional link to a design block
|
||||
};
|
||||
|
||||
#endif // CLASS_PCB_GROUP_H_
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include <bitmaps.h>
|
||||
#include <eda_item.h>
|
||||
#include <eda_group.h>
|
||||
#include <trace_helpers.h>
|
||||
#include <trigo.h>
|
||||
#include <i18n_utility.h>
|
||||
@ -71,6 +72,31 @@ EDA_ITEM::EDA_ITEM( const EDA_ITEM& base ) :
|
||||
}
|
||||
|
||||
|
||||
EDA_ITEM* EDA_ITEM::findParent( KICAD_T aType ) const
|
||||
{
|
||||
EDA_ITEM* parent = GetParent();
|
||||
|
||||
while( parent )
|
||||
{
|
||||
if( parent->Type() == aType )
|
||||
return parent;
|
||||
else
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
KIID EDA_ITEM::GetParentGroupId() const
|
||||
{
|
||||
if( EDA_GROUP* group = GetParentGroup() )
|
||||
return group->AsEdaItem()->m_Uuid;
|
||||
else
|
||||
return niluuid;
|
||||
}
|
||||
|
||||
|
||||
void EDA_ITEM::SetModified()
|
||||
{
|
||||
SetFlags( IS_CHANGED );
|
||||
|
@ -402,9 +402,8 @@ unsigned int RC_TREE_MODEL::GetChildren( wxDataViewItem const& aItem,
|
||||
}
|
||||
|
||||
|
||||
void RC_TREE_MODEL::GetValue( wxVariant& aVariant,
|
||||
wxDataViewItem const& aItem,
|
||||
unsigned int aCol ) const
|
||||
void RC_TREE_MODEL::GetValue( wxVariant& aVariant, wxDataViewItem const& aItem,
|
||||
unsigned int aCol ) const
|
||||
{
|
||||
const RC_TREE_NODE* node = ToNode( aItem );
|
||||
const std::shared_ptr<RC_ITEM> rcItem = node->m_RcItem;
|
||||
@ -443,20 +442,20 @@ void RC_TREE_MODEL::GetValue( wxVariant& aVariant,
|
||||
if( marker && marker->GetMarkerType() == MARKER_BASE::MARKER_DRAWING_SHEET )
|
||||
msg = _( "Drawing Sheet" );
|
||||
else
|
||||
item = m_editFrame->GetItem( rcItem->GetMainItemID() );
|
||||
item = m_editFrame->ResolveItem( rcItem->GetMainItemID() );
|
||||
|
||||
break;
|
||||
|
||||
case RC_TREE_NODE::AUX_ITEM:
|
||||
item = m_editFrame->GetItem( rcItem->GetAuxItemID() );
|
||||
item = m_editFrame->ResolveItem( rcItem->GetAuxItemID() );
|
||||
break;
|
||||
|
||||
case RC_TREE_NODE::AUX_ITEM2:
|
||||
item = m_editFrame->GetItem( rcItem->GetAuxItem2ID() );
|
||||
item = m_editFrame->ResolveItem( rcItem->GetAuxItem2ID() );
|
||||
break;
|
||||
|
||||
case RC_TREE_NODE::AUX_ITEM3:
|
||||
item = m_editFrame->GetItem( rcItem->GetAuxItem3ID() );
|
||||
item = m_editFrame->ResolveItem( rcItem->GetAuxItem3ID() );
|
||||
break;
|
||||
|
||||
case RC_TREE_NODE::COMMENT:
|
||||
|
@ -164,18 +164,18 @@ int GROUP_TOOL::Ungroup( const TOOL_EVENT& aEvent )
|
||||
|
||||
for( EDA_ITEM* item : selCopy )
|
||||
{
|
||||
EDA_GROUP* group = dynamic_cast<EDA_GROUP*>( item );
|
||||
|
||||
if( group )
|
||||
if( EDA_GROUP* group = dynamic_cast<EDA_GROUP*>( item ) )
|
||||
{
|
||||
group->AsEdaItem()->SetSelected();
|
||||
m_commit->Remove( group->AsEdaItem(), m_frame->GetScreen() );
|
||||
|
||||
for( EDA_ITEM* member : group->GetItems() )
|
||||
{
|
||||
m_commit->Stage( member, CHT_UNGROUP, m_frame->GetScreen() );
|
||||
m_commit->Modify( member, m_frame->GetScreen() );
|
||||
toSelect.push_back( member );
|
||||
}
|
||||
|
||||
group->AsEdaItem()->SetSelected();
|
||||
m_commit->Remove( group->AsEdaItem(), m_frame->GetScreen() );
|
||||
group->RemoveAll();
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,7 +208,9 @@ int GROUP_TOOL::AddToGroup( const TOOL_EVENT& aEvent )
|
||||
group = item;
|
||||
}
|
||||
else if( !item->GetParentGroup() )
|
||||
{
|
||||
toAdd.push_back( item );
|
||||
}
|
||||
}
|
||||
|
||||
if( !group || toAdd.empty() )
|
||||
@ -219,7 +221,18 @@ int GROUP_TOOL::AddToGroup( const TOOL_EVENT& aEvent )
|
||||
m_commit->Modify( group, m_frame->GetScreen() );
|
||||
|
||||
for( EDA_ITEM* item : toAdd )
|
||||
m_commit->Stage( item, CHT_GROUP, m_frame->GetScreen() );
|
||||
{
|
||||
EDA_GROUP* existingGroup = item->GetParentGroup();
|
||||
KIID existingGroupId = existingGroup ? existingGroup->AsEdaItem()->m_Uuid : niluuid;
|
||||
|
||||
if( existingGroupId != group->m_Uuid )
|
||||
{
|
||||
m_commit->Modify( item, m_frame->GetScreen() );
|
||||
|
||||
if( existingGroup )
|
||||
m_commit->Modify( existingGroup->AsEdaItem(), m_frame->GetScreen() );
|
||||
}
|
||||
}
|
||||
|
||||
m_commit->Push( _( "Add Items to Group" ) );
|
||||
|
||||
@ -240,8 +253,12 @@ int GROUP_TOOL::RemoveFromGroup( const TOOL_EVENT& aEvent )
|
||||
|
||||
for( EDA_ITEM* item : selection )
|
||||
{
|
||||
if( item->GetParentGroup() )
|
||||
m_commit->Stage( item, CHT_UNGROUP, m_frame->GetScreen() );
|
||||
if( EDA_GROUP* group = item->GetParentGroup() )
|
||||
{
|
||||
m_commit->Modify( group->AsEdaItem(), m_frame->GetScreen() );
|
||||
m_commit->Modify( item, m_frame->GetScreen() );
|
||||
group->RemoveItem( item );
|
||||
}
|
||||
}
|
||||
|
||||
m_commit->Push( _( "Remove Group Items" ) );
|
||||
|
@ -24,6 +24,7 @@
|
||||
*/
|
||||
|
||||
#include <eda_item.h>
|
||||
#include <eda_group.h>
|
||||
#include <undo_redo_container.h>
|
||||
|
||||
|
||||
@ -47,13 +48,6 @@ ITEM_PICKER::ITEM_PICKER( BASE_SCREEN* aScreen, EDA_ITEM* aItem, UNDO_REDO aUndo
|
||||
}
|
||||
|
||||
|
||||
void ITEM_PICKER::SetItem( EDA_ITEM* aItem )
|
||||
{
|
||||
m_pickedItem = aItem;
|
||||
m_pickedItemType = aItem ? aItem->Type() : TYPE_NOT_INIT;
|
||||
}
|
||||
|
||||
|
||||
PICKED_ITEMS_LIST::PICKED_ITEMS_LIST()
|
||||
{
|
||||
}
|
||||
@ -64,6 +58,29 @@ PICKED_ITEMS_LIST::~PICKED_ITEMS_LIST()
|
||||
}
|
||||
|
||||
|
||||
void ITEM_PICKER::SetItem( EDA_ITEM* aItem )
|
||||
{
|
||||
m_pickedItem = aItem;
|
||||
m_pickedItemType = aItem ? aItem->Type() : TYPE_NOT_INIT;
|
||||
|
||||
if( EDA_GROUP* group = dynamic_cast<EDA_GROUP*>( aItem ) )
|
||||
m_groupMembers = group->GetGroupMemberIds();
|
||||
|
||||
m_groupId = aItem->GetParentGroupId();
|
||||
}
|
||||
|
||||
|
||||
void ITEM_PICKER::SetLink( EDA_ITEM* aItem )
|
||||
{
|
||||
m_link = aItem;
|
||||
|
||||
if( EDA_GROUP* group = dynamic_cast<EDA_GROUP*>( aItem ) )
|
||||
m_groupMembers = group->GetGroupMemberIds();
|
||||
|
||||
m_groupId = aItem->GetParentGroupId();
|
||||
}
|
||||
|
||||
|
||||
void PICKED_ITEMS_LIST::PushItem( const ITEM_PICKER& aItem )
|
||||
{
|
||||
m_ItemsList.push_back( aItem );
|
||||
@ -96,22 +113,6 @@ bool PICKED_ITEMS_LIST::ContainsItem( const EDA_ITEM* aItem ) const
|
||||
}
|
||||
|
||||
|
||||
bool PICKED_ITEMS_LIST::ContainsItemType( KICAD_T aItemType ) const
|
||||
{
|
||||
for( const ITEM_PICKER& picker : m_ItemsList )
|
||||
{
|
||||
const EDA_ITEM* item = picker.GetItem();
|
||||
|
||||
wxCHECK2( item, continue );
|
||||
|
||||
if( item->Type() == aItemType )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int PICKED_ITEMS_LIST::FindItem( const EDA_ITEM* aItem ) const
|
||||
{
|
||||
for( size_t i = 0; i < m_ItemsList.size(); i++ )
|
||||
@ -157,14 +158,15 @@ void PICKED_ITEMS_LIST::ClearListAndDeleteItems( std::function<void(EDA_ITEM*)>
|
||||
}
|
||||
|
||||
|
||||
ITEM_PICKER PICKED_ITEMS_LIST::GetItemWrapper( unsigned int aIdx ) const
|
||||
const ITEM_PICKER& PICKED_ITEMS_LIST::GetItemWrapper( unsigned int aIdx ) const
|
||||
{
|
||||
ITEM_PICKER picker;
|
||||
return m_ItemsList.at( aIdx );
|
||||
}
|
||||
|
||||
if( aIdx < m_ItemsList.size() )
|
||||
picker = m_ItemsList[aIdx];
|
||||
|
||||
return picker;
|
||||
ITEM_PICKER& PICKED_ITEMS_LIST::GetItemWrapper( unsigned int aIdx )
|
||||
{
|
||||
return m_ItemsList.at( aIdx );
|
||||
}
|
||||
|
||||
|
||||
@ -213,27 +215,6 @@ EDA_ITEM_FLAGS PICKED_ITEMS_LIST::GetPickerFlags( unsigned aIdx ) const
|
||||
}
|
||||
|
||||
|
||||
KIID PICKED_ITEMS_LIST::GetPickedItemGroupId( unsigned aIdx ) const
|
||||
{
|
||||
if( aIdx < m_ItemsList.size() )
|
||||
return m_ItemsList[aIdx].GetGroupId();
|
||||
|
||||
return KIID();
|
||||
}
|
||||
|
||||
|
||||
bool PICKED_ITEMS_LIST::SetPickedItemGroupId( KIID aGroupId, unsigned aIdx )
|
||||
{
|
||||
if( aIdx < m_ItemsList.size() )
|
||||
{
|
||||
m_ItemsList[aIdx].SetGroupId( aGroupId );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool PICKED_ITEMS_LIST::SetPickedItem( EDA_ITEM* aItem, unsigned aIdx )
|
||||
{
|
||||
if( aIdx < m_ItemsList.size() )
|
||||
@ -258,19 +239,6 @@ bool PICKED_ITEMS_LIST::SetPickedItemLink( EDA_ITEM* aLink, unsigned aIdx )
|
||||
}
|
||||
|
||||
|
||||
bool PICKED_ITEMS_LIST::SetPickedItem( EDA_ITEM* aItem, UNDO_REDO aStatus, unsigned aIdx )
|
||||
{
|
||||
if( aIdx < m_ItemsList.size() )
|
||||
{
|
||||
m_ItemsList[aIdx].SetItem( aItem );
|
||||
m_ItemsList[aIdx].SetStatus( aStatus );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool PICKED_ITEMS_LIST::SetPickedItemStatus( UNDO_REDO aStatus, unsigned aIdx )
|
||||
{
|
||||
if( aIdx < m_ItemsList.size() )
|
||||
|
@ -308,10 +308,8 @@ FOOTPRINT* DISPLAY_FOOTPRINTS_FRAME::GetFootprint( const wxString& aFootprintNam
|
||||
|
||||
try
|
||||
{
|
||||
const FOOTPRINT* fp = fpTable->GetEnumeratedFootprint( libNickname, fpName );
|
||||
|
||||
if( fp )
|
||||
footprint = static_cast<FOOTPRINT*>( fp->Duplicate() );
|
||||
if( const FOOTPRINT* fp = fpTable->GetEnumeratedFootprint( libNickname, fpName ) )
|
||||
footprint = static_cast<FOOTPRINT*>( fp->Duplicate( IGNORE_PARENT_GROUP ) );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
|
@ -302,7 +302,7 @@ void SCH_EDIT_FRAME::BreakSegment( SCH_COMMIT* aCommit, SCH_LINE* aSegment, cons
|
||||
// Save the copy of aSegment before breaking it
|
||||
aCommit->Modify( aSegment, aScreen );
|
||||
|
||||
SCH_LINE* newSegment = aSegment->BreakAt( aPoint );
|
||||
SCH_LINE* newSegment = aSegment->BreakAt( aCommit, aPoint );
|
||||
|
||||
aSegment->SetFlags( IS_CHANGED | IS_BROKEN );
|
||||
newSegment->SetFlags( IS_NEW | IS_BROKEN );
|
||||
|
@ -964,7 +964,7 @@ void SCH_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
|
||||
KIID uuid( payload );
|
||||
SCH_SHEET_PATH path;
|
||||
|
||||
if( SCH_ITEM* item = m_schematic->GetItem( uuid, &path ) )
|
||||
if( SCH_ITEM* item = m_schematic->ResolveItem( uuid, &path, true ) )
|
||||
{
|
||||
if( item->Type() == SCH_SHEET_T )
|
||||
payload = static_cast<SCH_SHEET*>( item )->GetShownName( false );
|
||||
|
@ -530,7 +530,7 @@ void DIALOG_ERC::OnERCItemSelected( wxDataViewEvent& aEvent )
|
||||
{
|
||||
const KIID& itemID = RC_TREE_MODEL::ToUUID( aEvent.GetItem() );
|
||||
SCH_SHEET_PATH sheet;
|
||||
SCH_ITEM* item = m_parent->Schematic().GetItem( itemID, &sheet );
|
||||
SCH_ITEM* item = m_parent->Schematic().ResolveItem( itemID, &sheet, true );
|
||||
|
||||
if( m_centerMarkerOnIdle )
|
||||
{
|
||||
@ -544,8 +544,8 @@ void DIALOG_ERC::OnERCItemSelected( wxDataViewEvent& aEvent )
|
||||
if( node )
|
||||
{
|
||||
// Determine the owning sheet for sheet-specific items
|
||||
std::shared_ptr<ERC_ITEM> ercItem =
|
||||
std::static_pointer_cast<ERC_ITEM>( node->m_RcItem );
|
||||
std::shared_ptr<ERC_ITEM> ercItem = std::static_pointer_cast<ERC_ITEM>( node->m_RcItem );
|
||||
|
||||
switch( node->m_Type )
|
||||
{
|
||||
case RC_TREE_NODE::MARKER:
|
||||
@ -569,8 +569,7 @@ void DIALOG_ERC::OnERCItemSelected( wxDataViewEvent& aEvent )
|
||||
|
||||
if( !sheet.empty() && sheet != m_parent->GetCurrentSheet() )
|
||||
{
|
||||
m_parent->GetToolManager()->RunAction<SCH_SHEET_PATH*>( SCH_ACTIONS::changeSheet,
|
||||
&sheet );
|
||||
m_parent->GetToolManager()->RunAction<SCH_SHEET_PATH*>( SCH_ACTIONS::changeSheet, &sheet );
|
||||
m_parent->RedrawScreen( m_parent->GetScreen()->m_ScrollCenter, false );
|
||||
}
|
||||
|
||||
|
@ -425,7 +425,7 @@ void ERC_TREE_MODEL::GetValue( wxVariant& aVariant, wxDataViewItem const& aItem,
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = getItemDesc( schEditFrame->GetItem( ercItem->GetMainItemID() ),
|
||||
msg = getItemDesc( schEditFrame->ResolveItem( ercItem->GetMainItemID() ),
|
||||
ercItem->MainItemHasSheetPath() ? ercItem->GetMainItemSheetPath()
|
||||
: schEditFrame->GetCurrentSheet() );
|
||||
}
|
||||
@ -433,18 +433,18 @@ void ERC_TREE_MODEL::GetValue( wxVariant& aVariant, wxDataViewItem const& aItem,
|
||||
break;
|
||||
|
||||
case RC_TREE_NODE::AUX_ITEM:
|
||||
msg = getItemDesc( schEditFrame->GetItem( ercItem->GetAuxItemID() ),
|
||||
msg = getItemDesc( schEditFrame->ResolveItem( ercItem->GetAuxItemID() ),
|
||||
ercItem->AuxItemHasSheetPath() ? ercItem->GetAuxItemSheetPath()
|
||||
: schEditFrame->GetCurrentSheet() );
|
||||
break;
|
||||
|
||||
case RC_TREE_NODE::AUX_ITEM2:
|
||||
msg = getItemDesc( schEditFrame->GetItem( ercItem->GetAuxItem2ID() ),
|
||||
msg = getItemDesc( schEditFrame->ResolveItem( ercItem->GetAuxItem2ID() ),
|
||||
schEditFrame->GetCurrentSheet() );
|
||||
break;
|
||||
|
||||
case RC_TREE_NODE::AUX_ITEM3:
|
||||
msg = getItemDesc( schEditFrame->GetItem( ercItem->GetAuxItem3ID() ),
|
||||
msg = getItemDesc( schEditFrame->ResolveItem( ercItem->GetAuxItem3ID() ),
|
||||
schEditFrame->GetCurrentSheet() );
|
||||
break;
|
||||
|
||||
|
@ -1357,7 +1357,7 @@ void LIB_SYMBOL::SetUnitCount( int aCount, bool aDuplicateDrawItems )
|
||||
|
||||
for( int j = prevCount + 1; j <= aCount; j++ )
|
||||
{
|
||||
SCH_ITEM* newItem = item.Duplicate();
|
||||
SCH_ITEM* newItem = item.Duplicate( IGNORE_PARENT_GROUP );
|
||||
newItem->m_unit = j;
|
||||
tmp.push_back( newItem );
|
||||
}
|
||||
@ -1397,7 +1397,7 @@ void LIB_SYMBOL::SetHasAlternateBodyStyle( bool aHasAlternate, bool aDuplicatePi
|
||||
{
|
||||
if( item.m_bodyStyle == 1 )
|
||||
{
|
||||
SCH_ITEM* newItem = item.Duplicate();
|
||||
SCH_ITEM* newItem = item.Duplicate( IGNORE_PARENT_GROUP );
|
||||
newItem->m_bodyStyle = 2;
|
||||
tmp.push_back( newItem );
|
||||
}
|
||||
|
@ -85,8 +85,6 @@ EDA_ITEM* SCH_BITMAP::Clone() const
|
||||
|
||||
void SCH_BITMAP::swapData( SCH_ITEM* aItem )
|
||||
{
|
||||
SCH_ITEM::SwapFlags( aItem );
|
||||
|
||||
wxCHECK_RET( aItem->Type() == SCH_BITMAP_T,
|
||||
wxString::Format( wxT( "SCH_BITMAP object cannot swap data with %s object." ),
|
||||
aItem->GetClass() ) );
|
||||
|
@ -136,8 +136,6 @@ VECTOR2I SCH_BUS_ENTRY_BASE::GetEnd() const
|
||||
|
||||
void SCH_BUS_ENTRY_BASE::swapData( SCH_ITEM* aItem )
|
||||
{
|
||||
SCH_ITEM::SwapFlags( aItem );
|
||||
|
||||
SCH_BUS_ENTRY_BASE* item = dynamic_cast<SCH_BUS_ENTRY_BASE*>( aItem );
|
||||
wxCHECK_RET( item, wxT( "Cannot swap bus entry data with invalid item." ) );
|
||||
|
||||
|
@ -67,7 +67,8 @@ SCH_COMMIT::~SCH_COMMIT()
|
||||
}
|
||||
|
||||
|
||||
COMMIT& SCH_COMMIT::Stage( EDA_ITEM *aItem, CHANGE_TYPE aChangeType, BASE_SCREEN *aScreen )
|
||||
COMMIT& SCH_COMMIT::Stage( EDA_ITEM *aItem, CHANGE_TYPE aChangeType, BASE_SCREEN *aScreen,
|
||||
RECURSE_MODE aRecurse )
|
||||
{
|
||||
wxCHECK( aItem, *this );
|
||||
|
||||
@ -82,18 +83,12 @@ COMMIT& SCH_COMMIT::Stage( EDA_ITEM *aItem, CHANGE_TYPE aChangeType, BASE_SCREEN
|
||||
aChangeType = CHT_MODIFY;
|
||||
}
|
||||
|
||||
// Many operations (move, rotate, etc.) are applied directly to a group's children, so they
|
||||
// must be staged as well.
|
||||
if( aChangeType == CHT_MODIFY )
|
||||
if( aRecurse == RECURSE_MODE::RECURSE )
|
||||
{
|
||||
if( SCH_GROUP* group = dynamic_cast<SCH_GROUP*>( aItem ) )
|
||||
{
|
||||
group->RunOnChildren(
|
||||
[&]( EDA_ITEM* child )
|
||||
{
|
||||
Stage( child, aChangeType, aScreen );
|
||||
},
|
||||
RECURSE_MODE::NO_RECURSE );
|
||||
for( EDA_ITEM* member : group->GetItems() )
|
||||
Stage( member, aChangeType, aScreen, aRecurse );
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,12 +193,12 @@ void SCH_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
|
||||
|
||||
SCH_EDIT_FRAME* frame = static_cast<SCH_EDIT_FRAME*>( m_toolMgr->GetToolHolder() );
|
||||
SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
|
||||
SCH_GROUP* enteredGroup = selTool ? selTool->GetEnteredGroup() : nullptr;
|
||||
bool itemsDeselected = false;
|
||||
bool selectedModified = false;
|
||||
bool dirtyConnectivity = false;
|
||||
bool refreshHierarchy = false;
|
||||
SCH_CLEANUP_FLAGS connectivityCleanUp = NO_CLEANUP;
|
||||
SCH_GROUP* addedGroup = nullptr;
|
||||
|
||||
if( Empty() )
|
||||
return;
|
||||
@ -215,6 +210,37 @@ void SCH_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
|
||||
std::vector<SCH_ITEM*> bulkRemovedItems;
|
||||
std::vector<SCH_ITEM*> itemsChanged;
|
||||
|
||||
auto updateConnectivityFlag =
|
||||
[&]( SCH_ITEM* schItem )
|
||||
{
|
||||
if( schItem->IsConnectable() || ( schItem->Type() == SCH_RULE_AREA_T ) )
|
||||
{
|
||||
dirtyConnectivity = true;
|
||||
|
||||
// Do a local clean up if there are any connectable objects in the commit.
|
||||
if( connectivityCleanUp == NO_CLEANUP )
|
||||
connectivityCleanUp = LOCAL_CLEANUP;
|
||||
|
||||
// Do a full rebuild of the connectivity if there is a sheet in the commit.
|
||||
if( schItem->Type() == SCH_SHEET_T )
|
||||
connectivityCleanUp = GLOBAL_CLEANUP;
|
||||
}
|
||||
};
|
||||
|
||||
// We don't know that anything will be added to the entered group, but it does no harm to
|
||||
// add it to the commit anyway.
|
||||
if( enteredGroup )
|
||||
Modify( enteredGroup );
|
||||
|
||||
for( COMMIT_LINE& ent : m_changes )
|
||||
{
|
||||
SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( ent.m_item );
|
||||
int changeType = ent.m_type & CHT_TYPE;
|
||||
|
||||
if( changeType == CHT_REMOVE && schItem->GetParentGroup() )
|
||||
Modify( schItem->GetParentGroup()->AsEdaItem() );
|
||||
}
|
||||
|
||||
for( COMMIT_LINE& ent : m_changes )
|
||||
{
|
||||
int changeType = ent.m_type & CHT_TYPE;
|
||||
@ -242,33 +268,14 @@ void SCH_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
|
||||
RECURSE_MODE::NO_RECURSE );
|
||||
}
|
||||
|
||||
auto updateConnectivityFlag = [&]()
|
||||
{
|
||||
if( schItem->IsConnectable() || ( schItem->Type() == SCH_RULE_AREA_T ) )
|
||||
{
|
||||
dirtyConnectivity = true;
|
||||
|
||||
// Do a local clean up if there are any connectable objects in the commit.
|
||||
if( connectivityCleanUp == NO_CLEANUP )
|
||||
connectivityCleanUp = LOCAL_CLEANUP;
|
||||
|
||||
// Do a full rebuild of the connectivity if there is a sheet in the commit.
|
||||
if( schItem->Type() == SCH_SHEET_T )
|
||||
connectivityCleanUp = GLOBAL_CLEANUP;
|
||||
}
|
||||
};
|
||||
|
||||
switch( changeType )
|
||||
{
|
||||
case CHT_ADD:
|
||||
{
|
||||
if( selTool && selTool->GetEnteredGroup() && !schItem->GetParentGroup()
|
||||
&& SCH_GROUP::IsGroupableType( schItem->Type() ) )
|
||||
{
|
||||
if( enteredGroup && schItem->IsGroupableType() && !schItem->GetParentGroup() )
|
||||
selTool->GetEnteredGroup()->AddItem( schItem );
|
||||
}
|
||||
|
||||
updateConnectivityFlag();
|
||||
updateConnectivityFlag( schItem );
|
||||
|
||||
if( !( aCommitFlags & SKIP_UNDO ) )
|
||||
undoList.PushItem( ITEM_PICKER( screen, schItem, UNDO_REDO::NEWITEM ) );
|
||||
@ -282,12 +289,6 @@ void SCH_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
|
||||
view->Add( schItem );
|
||||
}
|
||||
|
||||
if( schItem->Type() == SCH_GROUP_T )
|
||||
{
|
||||
wxASSERT_MSG( !addedGroup, "Multiple groups in a single commit. This is not supported." );
|
||||
addedGroup = static_cast<SCH_GROUP*>( schItem );
|
||||
}
|
||||
|
||||
if( frame )
|
||||
frame->UpdateItem( schItem, true, true );
|
||||
|
||||
@ -301,10 +302,15 @@ void SCH_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
|
||||
|
||||
case CHT_REMOVE:
|
||||
{
|
||||
updateConnectivityFlag();
|
||||
updateConnectivityFlag( schItem );
|
||||
|
||||
if( !( aCommitFlags & SKIP_UNDO ) )
|
||||
undoList.PushItem( ITEM_PICKER( screen, schItem, UNDO_REDO::DELETED ) );
|
||||
{
|
||||
ITEM_PICKER itemWrapper( screen, schItem, UNDO_REDO::DELETED );
|
||||
itemWrapper.SetLink( ent.m_copy );
|
||||
ent.m_copy = nullptr; // We've transferred ownership to the undo list
|
||||
undoList.PushItem( itemWrapper );
|
||||
}
|
||||
|
||||
if( schItem->IsSelected() )
|
||||
{
|
||||
@ -320,6 +326,9 @@ void SCH_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
|
||||
break;
|
||||
}
|
||||
|
||||
if( EDA_GROUP* group = schItem->GetParentGroup() )
|
||||
group->RemoveItem( schItem );
|
||||
|
||||
if( !( changeFlags & CHT_DONE ) )
|
||||
{
|
||||
screen->Remove( schItem );
|
||||
@ -331,104 +340,61 @@ void SCH_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
|
||||
if( frame )
|
||||
frame->UpdateItem( schItem, true, true );
|
||||
|
||||
bulkRemovedItems.push_back( schItem );
|
||||
|
||||
if( schItem->Type() == SCH_SHEET_T )
|
||||
refreshHierarchy = true;
|
||||
|
||||
bulkRemovedItems.push_back( schItem );
|
||||
break;
|
||||
}
|
||||
|
||||
case CHT_MODIFY:
|
||||
{
|
||||
const SCH_ITEM* itemCopy = static_cast<const SCH_ITEM*>( ent.m_copy );
|
||||
SCH_SHEET_PATH currentSheet;
|
||||
|
||||
if( frame )
|
||||
currentSheet = frame->GetCurrentSheet();
|
||||
|
||||
if( itemCopy->HasConnectivityChanges( schItem, ¤tSheet )
|
||||
|| ( itemCopy->Type() == SCH_RULE_AREA_T ) )
|
||||
{
|
||||
updateConnectivityFlag( schItem );
|
||||
}
|
||||
|
||||
if( !( aCommitFlags & SKIP_UNDO ) )
|
||||
{
|
||||
ITEM_PICKER itemWrapper( screen, schItem, UNDO_REDO::CHANGED );
|
||||
wxASSERT( ent.m_copy );
|
||||
itemWrapper.SetLink( ent.m_copy );
|
||||
|
||||
const SCH_ITEM* itemCopy = static_cast<const SCH_ITEM*>( ent.m_copy );
|
||||
|
||||
wxCHECK2( itemCopy, continue );
|
||||
|
||||
SCH_SHEET_PATH currentSheet;
|
||||
|
||||
if( frame )
|
||||
currentSheet = frame->GetCurrentSheet();
|
||||
|
||||
if( itemCopy->HasConnectivityChanges( schItem, ¤tSheet )
|
||||
|| ( itemCopy->Type() == SCH_RULE_AREA_T ) )
|
||||
{
|
||||
updateConnectivityFlag();
|
||||
}
|
||||
|
||||
|
||||
if( schItem->Type() == SCH_SHEET_T )
|
||||
{
|
||||
const SCH_SHEET* modifiedSheet = static_cast<const SCH_SHEET*>( schItem );
|
||||
const SCH_SHEET* originalSheet = static_cast<const SCH_SHEET*>( itemCopy );
|
||||
wxCHECK2( modifiedSheet && originalSheet, continue );
|
||||
|
||||
if( originalSheet->HasPageNumberChanges( *modifiedSheet ) )
|
||||
refreshHierarchy = true;
|
||||
}
|
||||
|
||||
undoList.PushItem( itemWrapper );
|
||||
ent.m_copy = nullptr; // We've transferred ownership to the undo list
|
||||
undoList.PushItem( itemWrapper );
|
||||
}
|
||||
|
||||
if( schItem->Type() == SCH_GROUP_T )
|
||||
if( schItem->Type() == SCH_SHEET_T )
|
||||
{
|
||||
wxASSERT_MSG( !addedGroup, "Multiple groups in a single commit. This is not supported." );
|
||||
addedGroup = static_cast<SCH_GROUP*>( schItem );
|
||||
const SCH_SHEET* modifiedSheet = static_cast<const SCH_SHEET*>( schItem );
|
||||
const SCH_SHEET* originalSheet = static_cast<const SCH_SHEET*>( itemCopy );
|
||||
wxCHECK2( modifiedSheet && originalSheet, continue );
|
||||
|
||||
if( originalSheet->HasPageNumberChanges( *modifiedSheet ) )
|
||||
refreshHierarchy = true;
|
||||
}
|
||||
|
||||
if( frame )
|
||||
frame->UpdateItem( schItem, false, true );
|
||||
|
||||
itemsChanged.push_back( schItem );
|
||||
|
||||
if( ent.m_copy )
|
||||
{
|
||||
// if no undo entry is needed, the copy would create a memory leak
|
||||
delete ent.m_copy;
|
||||
ent.m_copy = nullptr;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CHT_UNGROUP:
|
||||
if( EDA_GROUP* group = schItem->GetParentGroup() )
|
||||
{
|
||||
if( !( aCommitFlags & SKIP_UNDO ) )
|
||||
{
|
||||
ITEM_PICKER itemWrapper( nullptr, schItem, UNDO_REDO::UNGROUP );
|
||||
itemWrapper.SetGroupId( group->AsEdaItem()->m_Uuid );
|
||||
undoList.PushItem( itemWrapper );
|
||||
}
|
||||
|
||||
group->RemoveItem( schItem );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CHT_GROUP:
|
||||
if( addedGroup )
|
||||
{
|
||||
addedGroup->AddItem( schItem );
|
||||
|
||||
if( !( aCommitFlags & SKIP_UNDO ) )
|
||||
undoList.PushItem( ITEM_PICKER( nullptr, schItem, UNDO_REDO::REGROUP ) );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
wxASSERT( false );
|
||||
break;
|
||||
}
|
||||
|
||||
// Delete any copies we still have ownership of
|
||||
delete ent.m_copy;
|
||||
ent.m_copy = nullptr;
|
||||
|
||||
// Clear all flags but SELECTED and others used to move and rotate commands,
|
||||
// after edition (selected items must keep their selection flag).
|
||||
const int selected_mask = ( SELECTED | STARTPOINT | ENDPOINT );
|
||||
|
@ -55,8 +55,8 @@ public:
|
||||
int aCommitFlags = 0 ) override;
|
||||
|
||||
virtual void Revert() override;
|
||||
COMMIT& Stage( EDA_ITEM *aItem, CHANGE_TYPE aChangeType,
|
||||
BASE_SCREEN *aScreen = nullptr ) override;
|
||||
COMMIT& Stage( EDA_ITEM *aItem, CHANGE_TYPE aChangeType, BASE_SCREEN *aScreen = nullptr,
|
||||
RECURSE_MODE aRecurse = RECURSE_MODE::NO_RECURSE ) override;
|
||||
COMMIT& Stage( std::vector<EDA_ITEM*> &container, CHANGE_TYPE aChangeType,
|
||||
BASE_SCREEN *aScreen = nullptr ) override;
|
||||
COMMIT& Stage( const PICKED_ITEMS_LIST &aItems, UNDO_REDO aModFlag = UNDO_REDO::UNSPECIFIED,
|
||||
|
@ -392,10 +392,14 @@ bool SCH_EDIT_FRAME::SaveSelectionToDesignBlock( const LIB_ID& aLibId )
|
||||
{
|
||||
group = static_cast<SCH_GROUP*>( item );
|
||||
|
||||
selection.Remove( item );
|
||||
selection.Remove( group );
|
||||
|
||||
// Don't recurse; if we have a group of groups the user probably intends the inner groups to be saved
|
||||
group->RunOnChildren( [&]( EDA_ITEM* aItem ) { selection.Add( aItem ); }, RECURSE_MODE::NO_RECURSE );
|
||||
group->RunOnChildren( [&]( EDA_ITEM* aItem )
|
||||
{
|
||||
selection.Add( aItem );
|
||||
},
|
||||
RECURSE_MODE::NO_RECURSE );
|
||||
}
|
||||
}
|
||||
|
||||
@ -420,15 +424,15 @@ bool SCH_EDIT_FRAME::SaveSelectionToDesignBlock( const LIB_ID& aLibId )
|
||||
SCH_SCREEN* tempScreen = new SCH_SCREEN( m_schematic );
|
||||
|
||||
auto cloneAndAdd =
|
||||
[&] ( EDA_ITEM* aItem )
|
||||
{
|
||||
if( !aItem->IsSCH_ITEM() )
|
||||
return static_cast<SCH_ITEM*>( nullptr );
|
||||
[&] ( EDA_ITEM* aItem ) -> SCH_ITEM*
|
||||
{
|
||||
if( !aItem->IsSCH_ITEM() )
|
||||
return nullptr;
|
||||
|
||||
SCH_ITEM* copy = static_cast<SCH_ITEM*>( aItem->Clone() );
|
||||
tempScreen->Append( static_cast<SCH_ITEM*>( copy ) );
|
||||
return copy;
|
||||
};
|
||||
SCH_ITEM* copy = static_cast<SCH_ITEM*>( aItem->Clone() );
|
||||
tempScreen->Append( static_cast<SCH_ITEM*>( copy ) );
|
||||
return copy;
|
||||
};
|
||||
|
||||
// Copy the selected items to the temporary board
|
||||
for( EDA_ITEM* item : selection )
|
||||
|
@ -856,7 +856,7 @@ void SCH_EDIT_FRAME::AddCopyForRepeatItem( const SCH_ITEM* aItem )
|
||||
|
||||
if( aItem )
|
||||
{
|
||||
std::unique_ptr<SCH_ITEM> repeatItem( static_cast<SCH_ITEM*>( aItem->Duplicate() ) );
|
||||
std::unique_ptr<SCH_ITEM> repeatItem( static_cast<SCH_ITEM*>( aItem->Duplicate( IGNORE_PARENT_GROUP ) ) );
|
||||
|
||||
// Clone() preserves the flags & parent, we want 'em cleared.
|
||||
repeatItem->ClearFlags();
|
||||
@ -867,9 +867,9 @@ void SCH_EDIT_FRAME::AddCopyForRepeatItem( const SCH_ITEM* aItem )
|
||||
}
|
||||
|
||||
|
||||
EDA_ITEM* SCH_EDIT_FRAME::GetItem( const KIID& aId ) const
|
||||
EDA_ITEM* SCH_EDIT_FRAME::ResolveItem( const KIID& aId, bool aAllowNullptrReturn ) const
|
||||
{
|
||||
return Schematic().GetItem( aId );
|
||||
return Schematic().ResolveItem( aId, nullptr, aAllowNullptrReturn );
|
||||
}
|
||||
|
||||
|
||||
@ -2319,8 +2319,7 @@ void SCH_EDIT_FRAME::FocusOnItem( EDA_ITEM* aItem )
|
||||
|
||||
static KIID lastBrightenedItemID( niluuid );
|
||||
|
||||
SCH_SHEET_PATH dummy;
|
||||
SCH_ITEM* lastItem = Schematic().GetItem( lastBrightenedItemID, &dummy );
|
||||
SCH_ITEM* lastItem = Schematic().ResolveItem( lastBrightenedItemID, nullptr, true );
|
||||
|
||||
if( lastItem && lastItem != aItem )
|
||||
{
|
||||
@ -2377,7 +2376,7 @@ void SCH_EDIT_FRAME::SaveSymbolToSchematic( const LIB_SYMBOL& aSymbol,
|
||||
{
|
||||
SCH_SHEET_PATH principalPath;
|
||||
SCH_SHEET_LIST sheets = Schematic().Hierarchy();
|
||||
SCH_ITEM* item = sheets.GetItem( aSchematicSymbolUUID, &principalPath );
|
||||
SCH_ITEM* item = sheets.ResolveItem( aSchematicSymbolUUID, &principalPath, true );
|
||||
SCH_SYMBOL* principalSymbol = dynamic_cast<SCH_SYMBOL*>( item );
|
||||
SCH_COMMIT commit( m_toolManager );
|
||||
|
||||
|
@ -743,7 +743,7 @@ public:
|
||||
m_items_to_repeat.clear();
|
||||
}
|
||||
|
||||
EDA_ITEM* GetItem( const KIID& aId ) const override;
|
||||
EDA_ITEM* ResolveItem( const KIID& aId, bool aAllowNullptrReturn = false ) const override;
|
||||
|
||||
/**
|
||||
* Perform an undo of the last edit **without** logging a corresponding redo.
|
||||
|
@ -407,8 +407,6 @@ void SCH_FIELD::swapData( SCH_ITEM* aItem )
|
||||
{
|
||||
wxCHECK_RET( aItem && aItem->Type() == SCH_FIELD_T, wxT( "Cannot swap with invalid item." ) );
|
||||
|
||||
SCH_ITEM::SwapFlags( aItem );
|
||||
|
||||
SCH_FIELD* item = static_cast<SCH_FIELD*>( aItem );
|
||||
|
||||
std::swap( m_layer, item->m_layer );
|
||||
|
@ -47,91 +47,14 @@ SCH_GROUP::SCH_GROUP( SCH_SCREEN* aParent ) : SCH_ITEM( aParent, SCH_GROUP_T )
|
||||
{
|
||||
}
|
||||
|
||||
bool SCH_GROUP::IsGroupableType( KICAD_T aType )
|
||||
{
|
||||
switch( aType )
|
||||
{
|
||||
case SCH_SYMBOL_T:
|
||||
case SCH_PIN_T:
|
||||
case SCH_SHAPE_T:
|
||||
case SCH_BITMAP_T:
|
||||
case SCH_FIELD_T:
|
||||
case SCH_TEXT_T:
|
||||
case SCH_TEXTBOX_T:
|
||||
case SCH_TABLE_T:
|
||||
case SCH_GROUP_T:
|
||||
case SCH_LINE_T:
|
||||
case SCH_JUNCTION_T:
|
||||
case SCH_NO_CONNECT_T:
|
||||
case SCH_BUS_WIRE_ENTRY_T:
|
||||
case SCH_BUS_BUS_ENTRY_T:
|
||||
case SCH_LABEL_T:
|
||||
case SCH_GLOBAL_LABEL_T:
|
||||
case SCH_HIER_LABEL_T:
|
||||
case SCH_RULE_AREA_T:
|
||||
case SCH_DIRECTIVE_LABEL_T:
|
||||
case SCH_SHEET_PIN_T:
|
||||
case SCH_SHEET_T:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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() );
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
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 )
|
||||
{
|
||||
aItem->SetParentGroup( nullptr );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void SCH_GROUP::RemoveAll()
|
||||
{
|
||||
for( EDA_ITEM* item : m_items )
|
||||
item->SetParentGroup( nullptr );
|
||||
|
||||
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 );
|
||||
}
|
||||
if( item->IsSCH_ITEM() )
|
||||
items.insert( static_cast<SCH_ITEM*>( item ) );
|
||||
}
|
||||
|
||||
return items;
|
||||
@ -230,17 +153,17 @@ SCH_GROUP* SCH_GROUP::DeepClone() const
|
||||
}
|
||||
|
||||
|
||||
SCH_GROUP* SCH_GROUP::DeepDuplicate() const
|
||||
SCH_GROUP* SCH_GROUP::DeepDuplicate( bool addToParentGroup, SCH_COMMIT* aCommit ) const
|
||||
{
|
||||
SCH_GROUP* newGroup = static_cast<SCH_GROUP*>( Duplicate() );
|
||||
SCH_GROUP* newGroup = static_cast<SCH_GROUP*>( Duplicate( addToParentGroup, aCommit ) );
|
||||
newGroup->m_items.clear();
|
||||
|
||||
for( EDA_ITEM* member : m_items )
|
||||
{
|
||||
if( member->Type() == SCH_GROUP_T )
|
||||
newGroup->AddItem( static_cast<SCH_GROUP*>( member )->DeepDuplicate() );
|
||||
newGroup->AddItem( static_cast<SCH_GROUP*>( member )->DeepDuplicate( IGNORE_PARENT_GROUP ) );
|
||||
else
|
||||
newGroup->AddItem( static_cast<SCH_ITEM*>( member )->Duplicate() );
|
||||
newGroup->AddItem( static_cast<SCH_ITEM*>( member )->Duplicate( IGNORE_PARENT_GROUP ) );
|
||||
}
|
||||
|
||||
return newGroup;
|
||||
@ -252,26 +175,9 @@ void SCH_GROUP::swapData( SCH_ITEM* aImage )
|
||||
assert( aImage->Type() == SCH_GROUP_T );
|
||||
SCH_GROUP* image = static_cast<SCH_GROUP*>( aImage );
|
||||
|
||||
std::swap( *this, *image );
|
||||
|
||||
// A group doesn't own its children (they're owned by the schematic), so undo doesn't do a
|
||||
// deep clone when making an image. However, it's still safest to update the parentGroup
|
||||
// pointers of the group's children -- we just have to be careful to do it in the right
|
||||
// order in case any of the children are shared (ie: image first, "this" second so that
|
||||
// any shared children end up with "this").
|
||||
image->RunOnChildren(
|
||||
[&]( SCH_ITEM* child )
|
||||
{
|
||||
child->SetParentGroup( image );
|
||||
},
|
||||
RECURSE_MODE::NO_RECURSE );
|
||||
|
||||
RunOnChildren(
|
||||
[&]( SCH_ITEM* child )
|
||||
{
|
||||
child->SetParentGroup( this );
|
||||
},
|
||||
RECURSE_MODE::NO_RECURSE );
|
||||
std::swap( m_items, image->m_items );
|
||||
std::swap( m_name, image->m_name );
|
||||
std::swap( m_designBlockLibId, image->m_designBlockLibId );
|
||||
}
|
||||
|
||||
|
||||
|
@ -63,22 +63,6 @@ public:
|
||||
|
||||
wxString GetClass() const override { return wxT( "SCH_GROUP" ); }
|
||||
|
||||
/**
|
||||
* Add item to group. Does not take ownership of item.
|
||||
*
|
||||
* @return true if item was added (false if item belongs to a different group).
|
||||
*/
|
||||
bool AddItem( EDA_ITEM* aItem ) override;
|
||||
|
||||
/**
|
||||
* Remove item from group.
|
||||
*
|
||||
* @return true if item was removed (false if item was not in the group).
|
||||
*/
|
||||
bool RemoveItem( EDA_ITEM* aItem ) override;
|
||||
|
||||
void RemoveAll() override;
|
||||
|
||||
std::unordered_set<SCH_ITEM*> GetSchItems() const;
|
||||
|
||||
/*
|
||||
@ -111,14 +95,17 @@ public:
|
||||
EDA_ITEM* Clone() const override;
|
||||
|
||||
/*
|
||||
* Clone() this and all descendants
|
||||
* Clone this and all descendants
|
||||
*/
|
||||
SCH_GROUP* DeepClone() const override;
|
||||
SCH_GROUP* DeepClone() const;
|
||||
|
||||
/*
|
||||
* Duplicate() this and all descendants
|
||||
* Duplicate this and all descendants
|
||||
*
|
||||
* @param addToParentGroup if the original is part of a group then the new member will also
|
||||
* be added to said group
|
||||
*/
|
||||
SCH_GROUP* DeepDuplicate() const override;
|
||||
SCH_GROUP* DeepDuplicate( bool addToParentGroup, SCH_COMMIT* aCommit = nullptr ) const;
|
||||
|
||||
/// @copydoc EDA_ITEM::HitTest
|
||||
bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override;
|
||||
@ -166,13 +153,6 @@ public:
|
||||
///< @copydoc SCH_ITEM::RunOnChildren
|
||||
void RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction, RECURSE_MODE aMode ) override;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
static bool IsGroupableType( KICAD_T aType );
|
||||
|
||||
/// @copydoc SCH_ITEM::swapData
|
||||
void swapData( SCH_ITEM* aImage ) override;
|
||||
};
|
||||
|
@ -1728,7 +1728,7 @@ const LIB_SYMBOL* CADSTAR_SCH_ARCHIVE_LOADER::loadSymdef( const SYMDEF_ID& aSymd
|
||||
|
||||
RotatePoint( linePos, libtext->GetTextPos(), -libtext->GetTextAngle() );
|
||||
|
||||
SCH_TEXT* textLine = static_cast<SCH_TEXT*>( libtext->Duplicate() );
|
||||
SCH_TEXT* textLine = static_cast<SCH_TEXT*>( libtext->Duplicate( IGNORE_PARENT_GROUP ) );
|
||||
textLine->SetText( strings[ii] );
|
||||
textLine->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
|
||||
textLine->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
|
||||
@ -2655,8 +2655,8 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadItemOntoKiCadSheet( const LAYER_ID& aCadsta
|
||||
for( std::pair<LAYER_ID, SHEET_NAME> sheetPair : Sheets.SheetNames )
|
||||
{
|
||||
LAYER_ID sheetID = sheetPair.first;
|
||||
duplicateItem = aItem->Duplicate();
|
||||
m_sheetMap.at( sheetID )->GetScreen()->Append( aItem->Duplicate() );
|
||||
duplicateItem = aItem->Duplicate( IGNORE_PARENT_GROUP );
|
||||
m_sheetMap.at( sheetID )->GetScreen()->Append( aItem->Duplicate( IGNORE_PARENT_GROUP ) );
|
||||
}
|
||||
|
||||
//Get rid of the extra copy:
|
||||
|
@ -785,7 +785,7 @@ void SCH_IO_EAGLE::loadSchematic( const ESCHEMATIC& aSchematic )
|
||||
// Instantiate the missing symbol unit
|
||||
int unit = unitEntry.first;
|
||||
const wxString reference = origSymbol->GetField( FIELD_T::REFERENCE )->GetText();
|
||||
std::unique_ptr<SCH_SYMBOL> symbol( (SCH_SYMBOL*) origSymbol->Duplicate() );
|
||||
std::unique_ptr<SCH_SYMBOL> symbol( (SCH_SYMBOL*) origSymbol->Duplicate( IGNORE_PARENT_GROUP ) );
|
||||
|
||||
symbol->SetUnitSelection( &sheetpath, unit );
|
||||
symbol->SetUnit( unit );
|
||||
|
@ -397,16 +397,14 @@ LIB_SYMBOL* SCH_IO_HTTP_LIB::loadSymbolFromPart( const wxString& aSymbo
|
||||
}
|
||||
else if( !symbolId.IsValid() )
|
||||
{
|
||||
wxLogTrace( traceHTTPLib,
|
||||
wxT( "loadSymbolFromPart: source symbol id '%s' is invalid, "
|
||||
"will create empty symbol" ),
|
||||
wxLogTrace( traceHTTPLib, wxT( "loadSymbolFromPart: source symbol id '%s' is invalid, "
|
||||
"will create empty symbol" ),
|
||||
symbolIdStr );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( traceHTTPLib,
|
||||
wxT( "loadSymbolFromPart: source symbol '%s' not found, "
|
||||
"will create empty symbol" ),
|
||||
wxLogTrace( traceHTTPLib, wxT( "loadSymbolFromPart: source symbol '%s' not found, "
|
||||
"will create empty symbol" ),
|
||||
symbolIdStr );
|
||||
}
|
||||
}
|
||||
|
@ -3088,9 +3088,9 @@ SCH_SYMBOL* SCH_IO_KICAD_SEXPR_PARSER::parseSchematicSymbol()
|
||||
{
|
||||
if( static_cast<int>( name.size() ) > bad_pos )
|
||||
{
|
||||
wxString msg = wxString::Format(
|
||||
_( "Symbol %s contains invalid character '%c'" ), name,
|
||||
name[bad_pos] );
|
||||
wxString msg = wxString::Format( _( "Symbol %s contains invalid character '%c'" ),
|
||||
name,
|
||||
name[bad_pos] );
|
||||
|
||||
THROW_PARSE_ERROR( msg, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
|
||||
}
|
||||
@ -4865,6 +4865,7 @@ void SCH_IO_KICAD_SEXPR_PARSER::parseGroup()
|
||||
if( !IsSymbol( token ) && token != T_NUMBER )
|
||||
Expecting( "symbol|number" );
|
||||
|
||||
LIB_ID libId;
|
||||
wxString name = FromUTF8();
|
||||
// Some symbol LIB_IDs have the '/' character escaped which can break
|
||||
// symbol links. The '/' character is no longer an illegal LIB_ID character so
|
||||
@ -4952,15 +4953,8 @@ void SCH_IO_KICAD_SEXPR_PARSER::resolveGroups( SCH_SCREEN* aParent )
|
||||
{
|
||||
for( const KIID& aUuid : groupInfo.memberUuids )
|
||||
{
|
||||
SCH_ITEM* gItem = getItem( aUuid );
|
||||
|
||||
if( !gItem || gItem->Type() == NOT_USED )
|
||||
{
|
||||
// This is the deleted item singleton, which means we didn't find the uuid.
|
||||
continue;
|
||||
}
|
||||
|
||||
group->AddItem( gItem );
|
||||
if( SCH_ITEM* gItem = getItem( aUuid ) )
|
||||
group->AddItem( gItem );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -129,16 +129,45 @@ SCH_ITEM::~SCH_ITEM()
|
||||
}
|
||||
|
||||
|
||||
SCH_ITEM* SCH_ITEM::Duplicate( bool doClone ) const
|
||||
bool SCH_ITEM::IsGroupableType() const
|
||||
{
|
||||
switch( Type() )
|
||||
{
|
||||
case SCH_SYMBOL_T:
|
||||
case SCH_PIN_T:
|
||||
case SCH_SHAPE_T:
|
||||
case SCH_BITMAP_T:
|
||||
case SCH_FIELD_T:
|
||||
case SCH_TEXT_T:
|
||||
case SCH_TEXTBOX_T:
|
||||
case SCH_TABLE_T:
|
||||
case SCH_GROUP_T:
|
||||
case SCH_LINE_T:
|
||||
case SCH_JUNCTION_T:
|
||||
case SCH_NO_CONNECT_T:
|
||||
case SCH_BUS_WIRE_ENTRY_T:
|
||||
case SCH_BUS_BUS_ENTRY_T:
|
||||
case SCH_LABEL_T:
|
||||
case SCH_GLOBAL_LABEL_T:
|
||||
case SCH_HIER_LABEL_T:
|
||||
case SCH_RULE_AREA_T:
|
||||
case SCH_DIRECTIVE_LABEL_T:
|
||||
case SCH_SHEET_PIN_T:
|
||||
case SCH_SHEET_T:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SCH_ITEM* SCH_ITEM::Duplicate( bool addToParentGroup, SCH_COMMIT* aCommit, bool doClone ) const
|
||||
{
|
||||
SCH_ITEM* newItem = (SCH_ITEM*) Clone();
|
||||
|
||||
if( !doClone )
|
||||
const_cast<KIID&>( newItem->m_Uuid ) = KIID();
|
||||
|
||||
if( newItem->GetParentGroup() )
|
||||
newItem->GetParentGroup()->AddItem( newItem );
|
||||
|
||||
newItem->ClearFlags( SELECTED | BRIGHTENED );
|
||||
|
||||
newItem->RunOnChildren(
|
||||
@ -148,6 +177,17 @@ SCH_ITEM* SCH_ITEM::Duplicate( bool doClone ) const
|
||||
},
|
||||
RECURSE_MODE::NO_RECURSE );
|
||||
|
||||
if( addToParentGroup )
|
||||
{
|
||||
wxCHECK_MSG( aCommit, newItem, "Must supply a commit to update parent group" );
|
||||
|
||||
if( newItem->GetParentGroup() )
|
||||
{
|
||||
aCommit->Modify( newItem->GetParentGroup()->AsEdaItem() );
|
||||
newItem->GetParentGroup()->AddItem( newItem );
|
||||
}
|
||||
}
|
||||
|
||||
return newItem;
|
||||
}
|
||||
|
||||
@ -176,33 +216,17 @@ void SCH_ITEM::SetBodyStyleProp( int aBodyStyle )
|
||||
|
||||
SCHEMATIC* SCH_ITEM::Schematic() const
|
||||
{
|
||||
EDA_ITEM* parent = GetParent();
|
||||
|
||||
while( parent )
|
||||
{
|
||||
if( parent->Type() == SCHEMATIC_T )
|
||||
return static_cast<SCHEMATIC*>( parent );
|
||||
else
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return static_cast<SCHEMATIC*>( findParent( SCHEMATIC_T ) );
|
||||
}
|
||||
|
||||
|
||||
const SYMBOL* SCH_ITEM::GetParentSymbol() const
|
||||
{
|
||||
const EDA_ITEM* parent = GetParent();
|
||||
if( SYMBOL* sch_symbol = static_cast<SCH_SYMBOL*>( findParent( SCH_SYMBOL_T ) ) )
|
||||
return sch_symbol;
|
||||
|
||||
while( parent )
|
||||
{
|
||||
if( parent->Type() == SCH_SYMBOL_T )
|
||||
return static_cast<const SCH_SYMBOL*>( parent );
|
||||
else if( parent->Type() == LIB_SYMBOL_T )
|
||||
return static_cast<const LIB_SYMBOL*>( parent );
|
||||
else
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
if( SYMBOL* lib_symbol = static_cast<LIB_SYMBOL*>( findParent( LIB_SYMBOL_T ) ) )
|
||||
return lib_symbol;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@ -210,17 +234,11 @@ const SYMBOL* SCH_ITEM::GetParentSymbol() const
|
||||
|
||||
SYMBOL* SCH_ITEM::GetParentSymbol()
|
||||
{
|
||||
EDA_ITEM* parent = GetParent();
|
||||
if( SYMBOL* sch_symbol = static_cast<SCH_SYMBOL*>( findParent( SCH_SYMBOL_T ) ) )
|
||||
return sch_symbol;
|
||||
|
||||
while( parent )
|
||||
{
|
||||
if( parent->Type() == SCH_SYMBOL_T )
|
||||
return static_cast<SCH_SYMBOL*>( parent );
|
||||
else if( parent->Type() == LIB_SYMBOL_T )
|
||||
return static_cast<LIB_SYMBOL*>( parent );
|
||||
else
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
if( SYMBOL* lib_symbol = static_cast<LIB_SYMBOL*>( findParent( LIB_SYMBOL_T ) ) )
|
||||
return lib_symbol;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@ -381,16 +399,13 @@ void SCH_ITEM::SwapItemData( SCH_ITEM* aImage )
|
||||
if( aImage == nullptr )
|
||||
return;
|
||||
|
||||
EDA_ITEM* parent = GetParent();
|
||||
EDA_GROUP* group = GetParentGroup();
|
||||
EDA_ITEM* parent = GetParent();
|
||||
|
||||
SetParentGroup( nullptr );
|
||||
aImage->SetParentGroup( nullptr );
|
||||
SwapFlags( aImage );
|
||||
std::swap( m_group, aImage->m_group );
|
||||
swapData( aImage );
|
||||
|
||||
// Restore pointers to be sure they are not broken
|
||||
SetParent( parent );
|
||||
SetParentGroup( group );
|
||||
}
|
||||
|
||||
|
||||
|
@ -42,6 +42,7 @@ class CONNECTION_GRAPH;
|
||||
class SCH_CONNECTION;
|
||||
class SCH_SHEET_PATH;
|
||||
class SCHEMATIC;
|
||||
class SCH_COMMIT;
|
||||
class SYMBOL;
|
||||
class LINE_READER;
|
||||
class SCH_EDIT_FRAME;
|
||||
@ -202,6 +203,8 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsGroupableType() const;
|
||||
|
||||
/**
|
||||
* Swap data between \a aItem and \a aImage.
|
||||
*
|
||||
@ -224,10 +227,13 @@ public:
|
||||
*
|
||||
* The new object is not put in draw list (not linked).
|
||||
*
|
||||
* @param doClone (default = false) indicates unique values (such as timestamp and
|
||||
* sheet name) should be duplicated. Use only for undo/redo operations.
|
||||
* @param addToParentGroup Indicates whether or not the new item is added to the group
|
||||
* (if any) containing the old item. If true, aCommit must be
|
||||
* provided.
|
||||
* @param aDoClone (default = false) indicates unique values (such as timestamp and
|
||||
* sheet name) should be duplicated. Use only for undo/redo operations.
|
||||
*/
|
||||
SCH_ITEM* Duplicate( bool doClone = false ) const;
|
||||
SCH_ITEM* Duplicate( bool addToParentGroup, SCH_COMMIT* aCommit = nullptr, bool doClone = false ) const;
|
||||
|
||||
static wxString GetUnitDescription( int aUnit );
|
||||
static wxString GetBodyStyleDescription( int aBodyStyle );
|
||||
|
@ -60,8 +60,6 @@ EDA_ITEM* SCH_JUNCTION::Clone() const
|
||||
|
||||
void SCH_JUNCTION::swapData( SCH_ITEM* aItem )
|
||||
{
|
||||
SCH_ITEM::SwapFlags( aItem );
|
||||
|
||||
wxCHECK_RET( ( aItem != nullptr ) && ( aItem->Type() == SCH_JUNCTION_T ),
|
||||
wxT( "Cannot swap junction data with invalid item." ) );
|
||||
|
||||
|
@ -543,9 +543,9 @@ SCH_LINE* SCH_LINE::MergeOverlap( SCH_SCREEN* aScreen, SCH_LINE* aLine, bool aCh
|
||||
}
|
||||
|
||||
|
||||
SCH_LINE* SCH_LINE::BreakAt( const VECTOR2I& aPoint )
|
||||
SCH_LINE* SCH_LINE::BreakAt( SCH_COMMIT* aCommit, const VECTOR2I& aPoint )
|
||||
{
|
||||
SCH_LINE* newSegment = static_cast<SCH_LINE*>( Duplicate() );
|
||||
SCH_LINE* newSegment = static_cast<SCH_LINE*>( Duplicate( aCommit ) );
|
||||
|
||||
newSegment->SetStartPoint( aPoint );
|
||||
newSegment->SetConnectivityDirty( true );
|
||||
@ -804,8 +804,6 @@ bool SCH_LINE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) con
|
||||
|
||||
void SCH_LINE::swapData( SCH_ITEM* aItem )
|
||||
{
|
||||
SCH_ITEM::SwapFlags( aItem );
|
||||
|
||||
SCH_LINE* item = (SCH_LINE*) aItem;
|
||||
|
||||
std::swap( m_layer, item->m_layer );
|
||||
|
@ -256,7 +256,7 @@ public:
|
||||
* @param aPoint Point at which to break the segment
|
||||
* @return The newly created segment.
|
||||
*/
|
||||
SCH_LINE* BreakAt( const VECTOR2I& aPoint );
|
||||
SCH_LINE* BreakAt( SCH_COMMIT* aCommit, const VECTOR2I& aPoint );
|
||||
|
||||
bool IsParallel( const SCH_LINE* aLine ) const;
|
||||
|
||||
|
@ -70,8 +70,6 @@ EDA_ITEM* SCH_MARKER::Clone() const
|
||||
|
||||
void SCH_MARKER::swapData( SCH_ITEM* aItem )
|
||||
{
|
||||
SCH_ITEM::SwapFlags( aItem );
|
||||
|
||||
SCH_MARKER* item = static_cast<SCH_MARKER*>( aItem );
|
||||
|
||||
std::swap( m_isLegacyMarker, item->m_isLegacyMarker );
|
||||
@ -84,6 +82,7 @@ void SCH_MARKER::swapData( SCH_ITEM* aItem )
|
||||
std::swap( m_scalingFactor, item->m_scalingFactor );
|
||||
std::swap( m_shapeBoundingBox, item->m_shapeBoundingBox );
|
||||
|
||||
// TODO: isn't this going to swap all the stuff above a second time?
|
||||
std::swap( *((SCH_MARKER*) this), *((SCH_MARKER*) aItem ) );
|
||||
}
|
||||
|
||||
@ -106,7 +105,7 @@ wxString SCH_MARKER::SerializeToString() const
|
||||
|| m_rcItem->GetErrorCode() == ERCE_GENERIC_ERROR
|
||||
|| m_rcItem->GetErrorCode() == ERCE_UNRESOLVED_VARIABLE )
|
||||
{
|
||||
SCH_ITEM* sch_item = Schematic()->GetItem( erc->GetMainItemID() );
|
||||
SCH_ITEM* sch_item = Schematic()->ResolveItem( erc->GetMainItemID() );
|
||||
SCH_ITEM* parent = static_cast<SCH_ITEM*>( sch_item->GetParent() );
|
||||
EDA_TEXT* text_item = dynamic_cast<EDA_TEXT*>( sch_item );
|
||||
|
||||
@ -163,7 +162,7 @@ SCH_MARKER* SCH_MARKER::DeserializeFromString( const SCH_SHEET_LIST& aSheetList,
|
||||
if( !props[4].IsEmpty() )
|
||||
{
|
||||
KIID uuid = niluuid;
|
||||
SCH_ITEM* parent = aSheetList.GetItem( KIID( props[3] ) );
|
||||
SCH_ITEM* parent = aSheetList.ResolveItem( KIID( props[3] ) );
|
||||
|
||||
// Check fields and pins for a match
|
||||
parent->RunOnChildren(
|
||||
@ -386,10 +385,10 @@ void SCH_MARKER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_
|
||||
EDA_ITEM* auxItem = nullptr;
|
||||
|
||||
if( m_rcItem->GetMainItemID() != niluuid )
|
||||
mainItem = aFrame->GetItem( m_rcItem->GetMainItemID() );
|
||||
mainItem = aFrame->ResolveItem( m_rcItem->GetMainItemID() );
|
||||
|
||||
if( m_rcItem->GetAuxItemID() != niluuid )
|
||||
auxItem = aFrame->GetItem( m_rcItem->GetAuxItemID() );
|
||||
auxItem = aFrame->ResolveItem( m_rcItem->GetAuxItemID() );
|
||||
|
||||
if( mainItem )
|
||||
mainText = mainItem->GetItemDescription( aFrame, true );
|
||||
|
@ -57,8 +57,6 @@ EDA_ITEM* SCH_NO_CONNECT::Clone() const
|
||||
|
||||
void SCH_NO_CONNECT::swapData( SCH_ITEM* aItem )
|
||||
{
|
||||
SCH_ITEM::SwapFlags( aItem );
|
||||
|
||||
wxCHECK_RET( ( aItem != nullptr ) && ( aItem->Type() == SCH_NO_CONNECT_T ),
|
||||
wxT( "Cannot swap no connect data with invalid item." ) );
|
||||
|
||||
|
@ -306,13 +306,6 @@ void SCH_SCREEN::FreeDrawList()
|
||||
std::copy_if( m_rtree.begin(), m_rtree.end(), std::back_inserter( delete_list ),
|
||||
[]( SCH_ITEM* aItem )
|
||||
{
|
||||
// Untangle group parents before doing any deleting
|
||||
if( aItem->Type() == SCH_GROUP_T )
|
||||
{
|
||||
for( EDA_ITEM* item : static_cast<SCH_GROUP*>(aItem)->GetItems() )
|
||||
item->SetParentGroup( nullptr );
|
||||
}
|
||||
|
||||
return ( aItem->Type() != SCH_SHEET_PIN_T && aItem->Type() != SCH_FIELD_T );
|
||||
} );
|
||||
|
||||
|
@ -59,8 +59,6 @@ int SCH_SHAPE::GetArcToSegMaxErrorIU( bool aHighDefinition ) const
|
||||
|
||||
void SCH_SHAPE::swapData( SCH_ITEM* aItem )
|
||||
{
|
||||
SCH_ITEM::SwapFlags( aItem );
|
||||
|
||||
SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
|
||||
|
||||
EDA_SHAPE::SwapShape( shape );
|
||||
|
@ -327,8 +327,6 @@ bool SCH_SHEET::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, in
|
||||
|
||||
void SCH_SHEET::swapData( SCH_ITEM* aItem )
|
||||
{
|
||||
SCH_ITEM::SwapFlags( aItem );
|
||||
|
||||
wxCHECK_RET( aItem->Type() == SCH_SHEET_T,
|
||||
wxString::Format( wxT( "SCH_SHEET object cannot swap data with %s object." ),
|
||||
aItem->GetClass() ) );
|
||||
|
@ -978,11 +978,11 @@ void SCH_SHEET_LIST::ClearModifyStatus()
|
||||
}
|
||||
|
||||
|
||||
SCH_ITEM* SCH_SHEET_LIST::GetItem( const KIID& aID, SCH_SHEET_PATH* aPathOut ) const
|
||||
SCH_ITEM* SCH_SHEET_LIST::ResolveItem( const KIID& aID, SCH_SHEET_PATH* aPathOut, bool aAllowNullptrReturn ) const
|
||||
{
|
||||
for( const SCH_SHEET_PATH& sheet : *this )
|
||||
{
|
||||
SCH_ITEM* item = sheet.GetItem( aID );
|
||||
SCH_ITEM* item = sheet.ResolveItem( aID );
|
||||
|
||||
if( item )
|
||||
{
|
||||
@ -994,11 +994,14 @@ SCH_ITEM* SCH_SHEET_LIST::GetItem( const KIID& aID, SCH_SHEET_PATH* aPathOut ) c
|
||||
}
|
||||
|
||||
// Not found; weak reference has been deleted.
|
||||
return DELETED_SHEET_ITEM::GetInstance();
|
||||
if( aAllowNullptrReturn )
|
||||
return nullptr;
|
||||
else
|
||||
return DELETED_SHEET_ITEM::GetInstance();
|
||||
}
|
||||
|
||||
|
||||
SCH_ITEM* SCH_SHEET_PATH::GetItem( const KIID& aID ) const
|
||||
SCH_ITEM* SCH_SHEET_PATH::ResolveItem( const KIID& aID ) const
|
||||
{
|
||||
for( SCH_ITEM* aItem : LastScreen()->Items() )
|
||||
{
|
||||
|
@ -270,7 +270,7 @@ public:
|
||||
/**
|
||||
* Fetch a SCH_ITEM by ID.
|
||||
*/
|
||||
SCH_ITEM* GetItem( const KIID& aID ) const;
|
||||
SCH_ITEM* ResolveItem( const KIID& aID ) const;
|
||||
|
||||
/**
|
||||
* Return the path of time stamps which do not changes even when editing sheet parameters.
|
||||
@ -487,7 +487,8 @@ public:
|
||||
*
|
||||
* Also returns the sheet the item was found on in \a aPathOut.
|
||||
*/
|
||||
SCH_ITEM* GetItem( const KIID& aID, SCH_SHEET_PATH* aPathOut = nullptr ) const;
|
||||
SCH_ITEM* ResolveItem( const KIID& aID, SCH_SHEET_PATH* aPathOut = nullptr,
|
||||
bool aAllowNullptrReturn = false ) const;
|
||||
|
||||
/**
|
||||
* Fill an item cache for temporary use when many items need to be fetched.
|
||||
|
@ -1202,8 +1202,6 @@ std::vector<SCH_PIN*> SCH_SYMBOL::GetPins() const
|
||||
|
||||
void SCH_SYMBOL::swapData( SCH_ITEM* aItem )
|
||||
{
|
||||
SCH_ITEM::SwapFlags( aItem );
|
||||
|
||||
wxCHECK_RET( aItem != nullptr && aItem->Type() == SCH_SYMBOL_T,
|
||||
wxT( "Cannot swap data with invalid symbol." ) );
|
||||
|
||||
|
@ -78,8 +78,6 @@ SCH_TABLE::~SCH_TABLE()
|
||||
|
||||
void SCH_TABLE::swapData( SCH_ITEM* aItem )
|
||||
{
|
||||
SCH_ITEM::SwapFlags( aItem );
|
||||
|
||||
wxCHECK_RET( aItem != nullptr && aItem->Type() == SCH_TABLE_T,
|
||||
wxT( "Cannot swap data with invalid table." ) );
|
||||
|
||||
|
@ -230,8 +230,6 @@ void SCH_TEXT::MirrorSpinStyle( bool aLeftRight )
|
||||
|
||||
void SCH_TEXT::swapData( SCH_ITEM* aItem )
|
||||
{
|
||||
SCH_ITEM::SwapFlags( aItem );
|
||||
|
||||
SCH_TEXT* item = static_cast<SCH_TEXT*>( aItem );
|
||||
|
||||
std::swap( m_layer, item->m_layer );
|
||||
|
@ -440,7 +440,7 @@ bool SCHEMATIC::ResolveCrossReference( wxString* token, int aDepth ) const
|
||||
KIID_PATH path( ref );
|
||||
KIID uuid = path.back();
|
||||
SCH_SHEET_PATH sheetPath;
|
||||
SCH_ITEM* refItem = GetItem( KIID( uuid ), &sheetPath );
|
||||
SCH_ITEM* refItem = ResolveItem( KIID( uuid ), &sheetPath, true );
|
||||
|
||||
if( path.size() > 1 )
|
||||
{
|
||||
@ -602,7 +602,7 @@ wxString SCHEMATIC::ConvertKIIDsToRefs( const wxString& aSource ) const
|
||||
KIID_PATH path( ref );
|
||||
KIID uuid = path.back();
|
||||
SCH_SHEET_PATH sheetPath;
|
||||
SCH_ITEM* refItem = GetItem( uuid, &sheetPath );
|
||||
SCH_ITEM* refItem = ResolveItem( uuid, &sheetPath, true );
|
||||
|
||||
if( path.size() > 1 )
|
||||
{
|
||||
@ -768,7 +768,7 @@ void SCHEMATIC::FixupJunctions()
|
||||
// Breakup wires
|
||||
for( SCH_LINE* wire : screen->GetBusesAndWires( point, true ) )
|
||||
{
|
||||
SCH_LINE* newSegment = wire->BreakAt( point );
|
||||
SCH_LINE* newSegment = wire->BreakAt( nullptr, point );
|
||||
screen->Append( newSegment );
|
||||
}
|
||||
}
|
||||
@ -858,7 +858,7 @@ void SCHEMATIC::ResolveERCExclusionsPostUpdate()
|
||||
for( SCH_MARKER* marker : ResolveERCExclusions() )
|
||||
{
|
||||
SCH_SHEET_PATH errorPath;
|
||||
ignore_unused( sheetList.GetItem( marker->GetRCItem()->GetMainItemID(), &errorPath ) );
|
||||
ignore_unused( sheetList.ResolveItem( marker->GetRCItem()->GetMainItemID(), &errorPath ) );
|
||||
|
||||
if( errorPath.LastScreen() )
|
||||
errorPath.LastScreen()->Append( marker );
|
||||
|
@ -109,9 +109,10 @@ public:
|
||||
|
||||
void RefreshHierarchy();
|
||||
|
||||
SCH_ITEM* GetItem( const KIID& aID, SCH_SHEET_PATH* aPathOut = nullptr ) const
|
||||
SCH_ITEM* ResolveItem( const KIID& aID, SCH_SHEET_PATH* aPathOut = nullptr,
|
||||
bool aAllowNullptrReturn = false ) const
|
||||
{
|
||||
return BuildUnorderedSheetList().GetItem( aID, aPathOut );
|
||||
return BuildUnorderedSheetList().ResolveItem( aID, aPathOut, aAllowNullptrReturn );
|
||||
}
|
||||
|
||||
SCH_SHEET& Root() const
|
||||
|
@ -143,7 +143,7 @@ void SCH_EDIT_FRAME::SaveCopyInUndoList( SCH_SCREEN* aScreen, SCH_ITEM* aItem,
|
||||
switch( aCommandType )
|
||||
{
|
||||
case UNDO_REDO::CHANGED: /* Create a copy of item */
|
||||
itemWrapper.SetLink( aItem->Duplicate( true ) );
|
||||
itemWrapper.SetLink( aItem->Duplicate( IGNORE_PARENT_GROUP, nullptr, true ) );
|
||||
commandToUndo->PushItem( itemWrapper );
|
||||
break;
|
||||
|
||||
@ -246,7 +246,7 @@ void SCH_EDIT_FRAME::SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList,
|
||||
* If this link is not null, the copy is already done
|
||||
*/
|
||||
if( commandToUndo->GetPickedItemLink( ii ) == nullptr )
|
||||
commandToUndo->SetPickedItemLink( sch_item->Duplicate( true ), ii );
|
||||
commandToUndo->SetPickedItemLink( sch_item->Duplicate( IGNORE_PARENT_GROUP, nullptr, true ), ii );
|
||||
|
||||
wxASSERT( commandToUndo->GetPickedItemLink( ii ) );
|
||||
break;
|
||||
@ -255,8 +255,6 @@ void SCH_EDIT_FRAME::SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList,
|
||||
case UNDO_REDO::DELETED:
|
||||
case UNDO_REDO::PAGESETTINGS:
|
||||
case UNDO_REDO::REPEAT_ITEM:
|
||||
case UNDO_REDO::REGROUP:
|
||||
case UNDO_REDO::UNGROUP:
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -390,26 +388,6 @@ void SCH_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
|
||||
|
||||
bulkAddedItems.emplace_back( schItem );
|
||||
}
|
||||
else if( status == UNDO_REDO::REGROUP ) /* grouped items are ungrouped */
|
||||
{
|
||||
aList->SetPickedItemStatus( UNDO_REDO::UNGROUP, ii );
|
||||
|
||||
if( EDA_GROUP* group = eda_item->GetParentGroup() )
|
||||
{
|
||||
aList->SetPickedItemGroupId( group->AsEdaItem()->m_Uuid, ii );
|
||||
|
||||
group->RemoveItem( eda_item );
|
||||
}
|
||||
}
|
||||
else if( status == UNDO_REDO::UNGROUP ) /* ungrouped items are re-added to their previuos groups */
|
||||
{
|
||||
aList->SetPickedItemStatus( UNDO_REDO::REGROUP, ii );
|
||||
|
||||
EDA_GROUP* group = dynamic_cast<EDA_GROUP*>( Schematic().GetItem( aList->GetPickedItemGroupId( ii ) ) );
|
||||
|
||||
if( group )
|
||||
group->AddItem( eda_item );
|
||||
}
|
||||
else if( status == UNDO_REDO::PAGESETTINGS )
|
||||
{
|
||||
if( GetCurrentSheet() != undoSheet )
|
||||
@ -450,8 +428,6 @@ void SCH_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
|
||||
|
||||
wxCHECK2( itemCopy, continue );
|
||||
|
||||
EDA_GROUP* parentGroup = schItem->GetParentGroup();
|
||||
|
||||
if( schItem->HasConnectivityChanges( itemCopy, &GetCurrentSheet() ) )
|
||||
propagateConnectivityDamage( schItem );
|
||||
|
||||
@ -485,24 +461,8 @@ void SCH_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
|
||||
}
|
||||
}
|
||||
|
||||
if( parentGroup )
|
||||
parentGroup->RemoveItem( schItem );
|
||||
|
||||
schItem->SwapItemData( itemCopy );
|
||||
|
||||
if( SCH_GROUP* group = dynamic_cast<SCH_GROUP*>( schItem ) )
|
||||
{
|
||||
group->RunOnChildren( [&]( SCH_ITEM* child )
|
||||
{
|
||||
child->SetParentGroup( group );
|
||||
},
|
||||
RECURSE_MODE::NO_RECURSE );
|
||||
}
|
||||
|
||||
if( parentGroup )
|
||||
parentGroup->AddItem( schItem );
|
||||
|
||||
|
||||
bulkChangedItems.emplace_back( schItem );
|
||||
|
||||
// Special cases for items which have instance data
|
||||
@ -544,6 +504,32 @@ void SCH_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
|
||||
}
|
||||
}
|
||||
|
||||
// We have now swapped all the group parent and group member pointers. But it is a
|
||||
// risky proposition to bet on the pointers being invariant, so validate them all.
|
||||
for( int ii = 0; ii < (int) aList->GetCount(); ++ii )
|
||||
{
|
||||
ITEM_PICKER& wrapper = aList->GetItemWrapper( ii );
|
||||
|
||||
SCH_ITEM* parentGroup = Schematic().ResolveItem( wrapper.GetGroupId(), nullptr, true );
|
||||
wrapper.GetItem()->SetParentGroup( dynamic_cast<SCH_GROUP*>( parentGroup ) );
|
||||
|
||||
if( EDA_GROUP* group = dynamic_cast<SCH_GROUP*>( wrapper.GetItem() ) )
|
||||
{
|
||||
// Items list may contain dodgy pointers, so don't use RemoveAll()
|
||||
group->GetItems().clear();
|
||||
|
||||
for( const KIID& member : wrapper.GetGroupMembers() )
|
||||
{
|
||||
if( SCH_ITEM* memberItem = Schematic().ResolveItem( member, nullptr, true ) )
|
||||
group->AddItem( memberItem );
|
||||
}
|
||||
}
|
||||
|
||||
// And prepare for a redo by updating group info based on current image
|
||||
if( EDA_ITEM* item = wrapper.GetLink() )
|
||||
wrapper.SetLink( item );
|
||||
}
|
||||
|
||||
GetCanvas()->GetView()->ClearHiddenFlags();
|
||||
|
||||
// Notify our listeners
|
||||
|
@ -1653,7 +1653,7 @@ void SIMULATOR_FRAME_UI::AddTuner( const SCH_SHEET_PATH& aSheetPath, SCH_SYMBOL*
|
||||
void SIMULATOR_FRAME_UI::UpdateTunerValue( const SCH_SHEET_PATH& aSheetPath, const KIID& aSymbol,
|
||||
const wxString& aRef, const wxString& aValue )
|
||||
{
|
||||
SCH_ITEM* item = aSheetPath.GetItem( aSymbol );
|
||||
SCH_ITEM* item = aSheetPath.ResolveItem( aSymbol );
|
||||
SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item );
|
||||
|
||||
if( !symbol )
|
||||
@ -2156,7 +2156,7 @@ void SIMULATOR_FRAME_UI::applyTuners()
|
||||
SCH_SHEET_PATH sheetPath;
|
||||
wxString ref = tuner->GetSymbolRef();
|
||||
KIID symbolId = tuner->GetSymbol( &sheetPath );
|
||||
SCH_ITEM* schItem = sheetPath.GetItem( symbolId );
|
||||
SCH_ITEM* schItem = sheetPath.ResolveItem( symbolId );
|
||||
SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( schItem );
|
||||
|
||||
if( !symbol )
|
||||
|
@ -52,14 +52,3 @@ std::vector<int> SYMBOL::ViewGetLayers() const
|
||||
LAYER_FIELDS, LAYER_DEVICE_BACKGROUND, LAYER_SHAPES_BACKGROUND,
|
||||
LAYER_NOTES_BACKGROUND, LAYER_SELECTION_SHADOWS };
|
||||
}
|
||||
|
||||
|
||||
SYMBOL::~SYMBOL()
|
||||
{
|
||||
// Untangle group parents before doing any deleting
|
||||
RunOnChildren( []( EDA_ITEM* item )
|
||||
{
|
||||
if( item->Type() == SCH_GROUP_T)
|
||||
item->SetParentGroup( nullptr );
|
||||
}, RECURSE_MODE::RECURSE );
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ public:
|
||||
return *this;
|
||||
};
|
||||
|
||||
~SYMBOL() override;
|
||||
~SYMBOL() override = default;
|
||||
|
||||
virtual const LIB_ID& GetLibId() const = 0;
|
||||
virtual wxString GetDescription() const = 0;
|
||||
|
@ -37,8 +37,6 @@ void SYMBOL_EDIT_FRAME::PushSymbolToUndoList( const wxString& aDescription, LIB_
|
||||
if( !aSymbolCopy )
|
||||
return;
|
||||
|
||||
auto* drawingTool = GetToolManager()->GetTool<SYMBOL_EDITOR_DRAWING_TOOLS>();
|
||||
|
||||
PICKED_ITEMS_LIST* lastcmd = new PICKED_ITEMS_LIST();
|
||||
|
||||
// Clear current flags (which can be temporary set by a current edit command).
|
||||
@ -47,7 +45,6 @@ void SYMBOL_EDIT_FRAME::PushSymbolToUndoList( const wxString& aDescription, LIB_
|
||||
aSymbolCopy->SetFlags( UR_TRANSIENT );
|
||||
|
||||
ITEM_PICKER wrapper( GetScreen(), aSymbolCopy, aUndoType );
|
||||
wrapper.SetGroupId( drawingTool->GetLastPin() );
|
||||
lastcmd->PushItem( wrapper );
|
||||
lastcmd->SetDescription( aDescription );
|
||||
PushCommandToUndoList( lastcmd );
|
||||
@ -91,7 +88,6 @@ void SYMBOL_EDIT_FRAME::GetSymbolFromRedoList()
|
||||
|
||||
oldSymbol->SetFlags( UR_TRANSIENT );
|
||||
ITEM_PICKER undoWrapper( GetScreen(), oldSymbol, undoRedoType );
|
||||
undoWrapper.SetGroupId( drawingTool->GetLastPin() );
|
||||
undoCommand->SetDescription( description );
|
||||
undoCommand->PushItem( undoWrapper );
|
||||
PushCommandToUndoList( undoCommand );
|
||||
@ -147,7 +143,6 @@ void SYMBOL_EDIT_FRAME::GetSymbolFromUndoList()
|
||||
|
||||
oldSymbol->SetFlags( UR_TRANSIENT );
|
||||
ITEM_PICKER redoWrapper( GetScreen(), oldSymbol, undoRedoType );
|
||||
redoWrapper.SetGroupId( drawingTool->GetLastPin() );
|
||||
redoCommand->PushItem( redoWrapper );
|
||||
redoCommand->SetDescription( description );
|
||||
PushCommandToRedoList( redoCommand );
|
||||
|
@ -487,7 +487,7 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
|
||||
// We are either stepping to the next unit or next symbol
|
||||
if( m_frame->eeconfig()->m_SymChooserPanel.keep_symbol || new_unit > 1 )
|
||||
{
|
||||
nextSymbol = static_cast<SCH_SYMBOL*>( symbol->Duplicate() );
|
||||
nextSymbol = static_cast<SCH_SYMBOL*>( symbol->Duplicate( IGNORE_PARENT_GROUP ) );
|
||||
nextSymbol->SetUnit( new_unit );
|
||||
nextSymbol->SetUnitSelection( new_unit );
|
||||
|
||||
@ -757,7 +757,9 @@ int SCH_DRAWING_TOOLS::ImportSheet( const TOOL_EVENT& aEvent )
|
||||
newItems.emplace_back( item );
|
||||
}
|
||||
else
|
||||
{
|
||||
item->ClearFlags( SKIP_STRUCT );
|
||||
}
|
||||
}
|
||||
|
||||
if( placeAsGroup )
|
||||
@ -766,7 +768,9 @@ int SCH_DRAWING_TOOLS::ImportSheet( const TOOL_EVENT& aEvent )
|
||||
selectionTool->AddItemToSel( group );
|
||||
}
|
||||
else
|
||||
{
|
||||
selectionTool->AddItemsToSel( &newItems, true );
|
||||
}
|
||||
|
||||
cursorPos = grid.Align( controls->GetMousePosition(),
|
||||
grid.GetSelectionGrid( selectionTool->GetSelection() ) );
|
||||
|
@ -824,7 +824,7 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
|
||||
rotPoint = m_frame->GetNearestHalfGridPosition( head->GetBoundingBox().GetCenter() );
|
||||
|
||||
if( !moving )
|
||||
commit->Modify( head, m_frame->GetScreen() );
|
||||
commit->Modify( head, m_frame->GetScreen(), RECURSE_MODE::RECURSE );
|
||||
|
||||
switch( head->Type() )
|
||||
{
|
||||
@ -989,7 +989,7 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
|
||||
continue;
|
||||
|
||||
if( !moving )
|
||||
commit->Modify( item, m_frame->GetScreen() );
|
||||
commit->Modify( item, m_frame->GetScreen(), RECURSE_MODE::RECURSE );
|
||||
|
||||
if( item->Type() == SCH_LINE_T )
|
||||
{
|
||||
@ -1092,7 +1092,7 @@ int SCH_EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
|
||||
if( selection.GetSize() == 1 )
|
||||
{
|
||||
if( !moving )
|
||||
commit->Modify( item, m_frame->GetScreen() );
|
||||
commit->Modify( item, m_frame->GetScreen(), RECURSE_MODE::RECURSE );
|
||||
|
||||
switch( item->Type() )
|
||||
{
|
||||
@ -1193,7 +1193,7 @@ int SCH_EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
|
||||
item = static_cast<SCH_ITEM*>( edaItem );
|
||||
|
||||
if( !moving )
|
||||
commit->Modify( item, m_frame->GetScreen() );
|
||||
commit->Modify( item, m_frame->GetScreen(), RECURSE_MODE::RECURSE );
|
||||
|
||||
if( item->Type() == SCH_SHEET_PIN_T )
|
||||
{
|
||||
@ -1511,12 +1511,13 @@ int SCH_EDIT_TOOL::RepeatDrawItem( const TOOL_EVENT& aEvent )
|
||||
|
||||
m_toolMgr->RunAction( ACTIONS::selectionClear );
|
||||
|
||||
SCH_COMMIT commit( m_toolMgr );
|
||||
SCH_SELECTION newItems;
|
||||
SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
|
||||
SCH_COMMIT commit( m_toolMgr );
|
||||
SCH_SELECTION newItems;
|
||||
|
||||
for( const std::unique_ptr<SCH_ITEM>& item : sourceItems )
|
||||
{
|
||||
SCH_ITEM* newItem = item->Duplicate();
|
||||
SCH_ITEM* newItem = item->Duplicate( IGNORE_PARENT_GROUP );
|
||||
SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
|
||||
EESCHEMA_SETTINGS* cfg = mgr.GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" );
|
||||
bool restore_state = false;
|
||||
@ -1525,6 +1526,15 @@ int SCH_EDIT_TOOL::RepeatDrawItem( const TOOL_EVENT& aEvent )
|
||||
// a list of items to repeat must be attached to this current screen
|
||||
newItem->SetParent( m_frame->GetScreen() );
|
||||
|
||||
if( SCH_GROUP* enteredGroup = selectionTool->GetEnteredGroup() )
|
||||
{
|
||||
if( newItem->IsGroupableType() )
|
||||
{
|
||||
commit.Modify( enteredGroup );
|
||||
enteredGroup->AddItem( newItem );
|
||||
}
|
||||
}
|
||||
|
||||
if( SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( newItem ) )
|
||||
{
|
||||
// If incrementing tries to go below zero, tell user why the value is repeated
|
||||
@ -1716,14 +1726,7 @@ int SCH_EDIT_TOOL::DoDelete( const TOOL_EVENT& aEvent )
|
||||
}
|
||||
else if( sch_item->Type() == SCH_GROUP_T )
|
||||
{
|
||||
// Groups need to have all children ungrouped, then deleted
|
||||
sch_item->RunOnChildren(
|
||||
[&]( SCH_ITEM* aChild )
|
||||
{
|
||||
commit.Stage( aChild, CHT_UNGROUP, m_frame->GetScreen() );
|
||||
},
|
||||
RECURSE_MODE::RECURSE );
|
||||
|
||||
// Groups need to delete their children
|
||||
sch_item->RunOnChildren(
|
||||
[&]( SCH_ITEM* aChild )
|
||||
{
|
||||
|
@ -2338,14 +2338,15 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
|
||||
SCH_ITEM* item = nullptr;
|
||||
|
||||
group->RunOnChildren(
|
||||
[&]( SCH_ITEM* schItem )
|
||||
{
|
||||
if( !found && schItem->Type() != SCH_GROUP_T )
|
||||
[&]( SCH_ITEM* schItem )
|
||||
{
|
||||
item = schItem;
|
||||
found = true;
|
||||
}
|
||||
}, RECURSE_MODE::RECURSE );
|
||||
if( !found && schItem->Type() != SCH_GROUP_T )
|
||||
{
|
||||
item = schItem;
|
||||
found = true;
|
||||
}
|
||||
},
|
||||
RECURSE_MODE::RECURSE );
|
||||
|
||||
if( found )
|
||||
selection.SetReferencePoint( item->GetPosition() );
|
||||
@ -2900,12 +2901,15 @@ int SCH_EDITOR_CONTROL::RepairSchematic( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
processItem( item );
|
||||
|
||||
item->RunOnChildren(
|
||||
[&]( SCH_ITEM* aChild )
|
||||
{
|
||||
processItem( item );
|
||||
},
|
||||
RECURSE_MODE::NO_RECURSE );
|
||||
if( item->Type() != SCH_GROUP_T )
|
||||
{
|
||||
item->RunOnChildren(
|
||||
[&]( SCH_ITEM* aChild )
|
||||
{
|
||||
processItem( item );
|
||||
},
|
||||
RECURSE_MODE::NO_RECURSE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,16 +69,7 @@ int SCH_FIND_REPLACE_TOOL::UpdateFind( const TOOL_EVENT& aEvent )
|
||||
[&]()
|
||||
{
|
||||
for( SCH_ITEM* item : m_frame->GetScreen()->Items() )
|
||||
{
|
||||
visit( item, &m_frame->GetCurrentSheet() );
|
||||
|
||||
item->RunOnChildren(
|
||||
[&]( SCH_ITEM* aChild )
|
||||
{
|
||||
visit( aChild, &m_frame->GetCurrentSheet() );
|
||||
},
|
||||
RECURSE_MODE::NO_RECURSE );
|
||||
}
|
||||
};
|
||||
|
||||
if( aEvent.IsAction( &ACTIONS::find ) || aEvent.IsAction( &ACTIONS::findAndReplace )
|
||||
|
@ -133,10 +133,12 @@ int SCH_GROUP_TOOL::Group( const TOOL_EVENT& aEvent )
|
||||
|
||||
for( EDA_ITEM* item : selection.GetItems() )
|
||||
{
|
||||
if( !SCH_GROUP::IsGroupableType( item->Type() ) )
|
||||
SCH_ITEM* schItem = static_cast<SCH_ITEM*>( item );
|
||||
|
||||
if( !schItem->IsGroupableType() )
|
||||
selection.Remove( item );
|
||||
|
||||
if( isSymbolEditor && static_cast<SCH_ITEM*>( item )->GetParentSymbol() )
|
||||
if( isSymbolEditor && schItem->GetParentSymbol() )
|
||||
selection.Remove( item );
|
||||
}
|
||||
|
||||
@ -151,11 +153,13 @@ int SCH_GROUP_TOOL::Group( const TOOL_EVENT& aEvent )
|
||||
else
|
||||
group->SetParent( screen );
|
||||
|
||||
m_commit->Add( group, screen );
|
||||
|
||||
for( EDA_ITEM* eda_item : selection )
|
||||
m_commit->Stage( eda_item, CHT_GROUP, screen );
|
||||
{
|
||||
m_commit->Modify( eda_item, screen );
|
||||
group->AddItem( eda_item );
|
||||
}
|
||||
|
||||
m_commit->Add( group, screen );
|
||||
m_commit->Push( _( "Group Items" ) );
|
||||
|
||||
m_toolMgr->RunAction( ACTIONS::selectionClear );
|
||||
|
@ -250,7 +250,7 @@ void SCH_INSPECTION_TOOL::InspectERCError( const std::shared_ptr<RC_ITEM>& aERCI
|
||||
|
||||
wxCHECK( frame, /* void */ );
|
||||
|
||||
EDA_ITEM* a = frame->GetItem( aERCItem->GetMainItemID() );
|
||||
EDA_ITEM* a = frame->ResolveItem( aERCItem->GetMainItemID() );
|
||||
|
||||
if( aERCItem->GetErrorCode() == ERCE_BUS_TO_NET_CONFLICT )
|
||||
{
|
||||
|
@ -291,6 +291,7 @@ int SCH_LINE_WIRE_BUS_TOOL::DrawSegments( const TOOL_EVENT& aEvent )
|
||||
REENTRANCY_GUARD guard( &m_inDrawingTool );
|
||||
|
||||
const DRAW_SEGMENT_EVENT_PARAMS* params = aEvent.Parameter<const DRAW_SEGMENT_EVENT_PARAMS*>();
|
||||
SCH_COMMIT commit( m_toolMgr );
|
||||
|
||||
m_frame->PushTool( aEvent );
|
||||
m_toolMgr->RunAction( ACTIONS::selectionClear );
|
||||
@ -304,10 +305,10 @@ int SCH_LINE_WIRE_BUS_TOOL::DrawSegments( const TOOL_EVENT& aEvent )
|
||||
grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !aEvent.DisableGridSnapping() );
|
||||
|
||||
VECTOR2D cursorPos = grid.BestSnapAnchor( aEvent.Position(), gridType, nullptr );
|
||||
startSegments( params->layer, cursorPos, params->sourceSegment );
|
||||
startSegments( commit, params->layer, cursorPos, params->sourceSegment );
|
||||
}
|
||||
|
||||
return doDrawSegments( aEvent, params->layer, params->quitOnDraw );
|
||||
return doDrawSegments( aEvent, commit, params->layer, params->quitOnDraw );
|
||||
}
|
||||
|
||||
|
||||
@ -318,9 +319,10 @@ int SCH_LINE_WIRE_BUS_TOOL::UnfoldBus( const TOOL_EVENT& aEvent )
|
||||
|
||||
REENTRANCY_GUARD guard( &m_inDrawingTool );
|
||||
|
||||
wxString* netPtr = aEvent.Parameter<wxString*>();
|
||||
wxString net;
|
||||
SCH_LINE* segment = nullptr;
|
||||
SCH_COMMIT commit( m_toolMgr );
|
||||
wxString* netPtr = aEvent.Parameter<wxString*>();
|
||||
wxString net;
|
||||
SCH_LINE* segment = nullptr;
|
||||
|
||||
m_frame->PushTool( aEvent );
|
||||
Activate();
|
||||
@ -366,12 +368,12 @@ int SCH_LINE_WIRE_BUS_TOOL::UnfoldBus( const TOOL_EVENT& aEvent )
|
||||
|
||||
// Break a wire for the given net out of the bus
|
||||
if( !net.IsEmpty() )
|
||||
segment = doUnfoldBus( net );
|
||||
segment = doUnfoldBus( commit, net );
|
||||
|
||||
// If we have an unfolded wire to draw, then draw it
|
||||
if( segment )
|
||||
{
|
||||
return doDrawSegments( aEvent, LAYER_WIRE, false );
|
||||
return doDrawSegments( aEvent, commit, LAYER_WIRE, false );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -388,7 +390,7 @@ SCH_LINE* SCH_LINE_WIRE_BUS_TOOL::getBusForUnfolding()
|
||||
}
|
||||
|
||||
|
||||
SCH_LINE* SCH_LINE_WIRE_BUS_TOOL::doUnfoldBus( const wxString& aNet,
|
||||
SCH_LINE* SCH_LINE_WIRE_BUS_TOOL::doUnfoldBus( SCH_COMMIT& aCommit, const wxString& aNet,
|
||||
const std::optional<VECTOR2I>& aPos )
|
||||
{
|
||||
SCHEMATIC_SETTINGS& cfg = getModel<SCHEMATIC>()->Settings();
|
||||
@ -398,9 +400,8 @@ SCH_LINE* SCH_LINE_WIRE_BUS_TOOL::doUnfoldBus( const wxString& aN
|
||||
|
||||
if ( bus == nullptr )
|
||||
{
|
||||
wxASSERT_MSG( false,
|
||||
wxString::Format( "Couldn't find the originating bus line (but had a net: %s )",
|
||||
aNet ) );
|
||||
wxASSERT_MSG( false, wxString::Format( "Couldn't find the originating bus line (but had a net: %s )",
|
||||
aNet ) );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -441,7 +442,7 @@ SCH_LINE* SCH_LINE_WIRE_BUS_TOOL::doUnfoldBus( const wxString& aN
|
||||
m_busUnfold.entry->SetEndDangling( false );
|
||||
m_busUnfold.label->SetIsDangling( false );
|
||||
|
||||
return startSegments( LAYER_WIRE, m_busUnfold.entry->GetEnd() );
|
||||
return startSegments( aCommit, LAYER_WIRE, m_busUnfold.entry->GetEnd() );
|
||||
}
|
||||
|
||||
|
||||
@ -601,7 +602,8 @@ void SCH_LINE_WIRE_BUS_TOOL::computeBreakPoint( const std::pair<SCH_LINE*, SCH_L
|
||||
}
|
||||
|
||||
|
||||
int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const TOOL_EVENT& aTool, int aType, bool aQuitOnDraw )
|
||||
int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const TOOL_EVENT& aTool, SCH_COMMIT& aCommit,
|
||||
int aType, bool aQuitOnDraw )
|
||||
{
|
||||
SCH_SCREEN* screen = m_frame->GetScreen();
|
||||
SCH_LINE* segment = nullptr;
|
||||
@ -717,7 +719,7 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const TOOL_EVENT& aTool, int aType,
|
||||
segment->SetEndPoint( cursorPos );
|
||||
|
||||
// Create a new segment, and chain it after the current segment.
|
||||
segment = static_cast<SCH_LINE*>( segment->Duplicate() );
|
||||
segment = static_cast<SCH_LINE*>( segment->Duplicate( true, &aCommit ) );
|
||||
segment->SetFlags( IS_NEW | IS_MOVING );
|
||||
segment->SetStartPoint( cursorPos );
|
||||
m_wires.push_back( segment );
|
||||
@ -778,9 +780,11 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const TOOL_EVENT& aTool, int aType,
|
||||
{
|
||||
if( segment || m_busUnfold.in_progress )
|
||||
{
|
||||
finishSegments();
|
||||
finishSegments( aCommit );
|
||||
segment = nullptr;
|
||||
|
||||
aCommit.Push( _( "Draw Wires" ) );
|
||||
|
||||
if( aQuitOnDraw )
|
||||
{
|
||||
m_frame->PopTool( aTool );
|
||||
@ -807,7 +811,7 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const TOOL_EVENT& aTool, int aType,
|
||||
|
||||
if( !segment )
|
||||
{
|
||||
segment = startSegments( aType, VECTOR2D( cursorPos ) );
|
||||
segment = startSegments( aCommit, aType, VECTOR2D( cursorPos ) );
|
||||
}
|
||||
// Create a new segment if we're out of previously-created ones
|
||||
else if( !segment->IsNull()
|
||||
@ -817,9 +821,11 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const TOOL_EVENT& aTool, int aType,
|
||||
// wire or bus.
|
||||
if( screen->IsTerminalPoint( cursorPos, segment->GetLayer() ) )
|
||||
{
|
||||
finishSegments();
|
||||
finishSegments( aCommit );
|
||||
segment = nullptr;
|
||||
|
||||
aCommit.Push( _( "Draw Wires" ) );
|
||||
|
||||
if( aQuitOnDraw )
|
||||
{
|
||||
m_frame->PopTool( aTool );
|
||||
@ -841,7 +847,7 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const TOOL_EVENT& aTool, int aType,
|
||||
for( int i = 0; i < placedSegments; i++ )
|
||||
{
|
||||
// Create a new segment, and chain it after the current segment.
|
||||
segment = static_cast<SCH_LINE*>( segment->Duplicate() );
|
||||
segment = static_cast<SCH_LINE*>( segment->Duplicate( true, &aCommit ) );
|
||||
segment->SetFlags( IS_NEW | IS_MOVING );
|
||||
segment->SetStartPoint( cursorPos );
|
||||
m_wires.push_back( segment );
|
||||
@ -859,9 +865,11 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const TOOL_EVENT& aTool, int aType,
|
||||
currentMode, posture );
|
||||
}
|
||||
|
||||
finishSegments();
|
||||
finishSegments( aCommit );
|
||||
segment = nullptr;
|
||||
|
||||
aCommit.Push( _( "Draw Wires" ) );
|
||||
|
||||
if( aQuitOnDraw )
|
||||
{
|
||||
m_frame->PopTool( aTool );
|
||||
@ -1031,7 +1039,7 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const TOOL_EVENT& aTool, int aType,
|
||||
|
||||
aType = LAYER_WIRE;
|
||||
wxString net = *evt->Parameter<wxString*>();
|
||||
segment = doUnfoldBus( net, contextMenuPos );
|
||||
segment = doUnfoldBus( aCommit, net, contextMenuPos );
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------
|
||||
@ -1073,7 +1081,7 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const TOOL_EVENT& aTool, int aType,
|
||||
}
|
||||
|
||||
|
||||
SCH_LINE* SCH_LINE_WIRE_BUS_TOOL::startSegments( int aType, const VECTOR2D& aPos,
|
||||
SCH_LINE* SCH_LINE_WIRE_BUS_TOOL::startSegments( SCH_COMMIT& aCommit, int aType, const VECTOR2D& aPos,
|
||||
SCH_LINE* aSegment )
|
||||
{
|
||||
if( !aSegment )
|
||||
@ -1093,7 +1101,7 @@ SCH_LINE* SCH_LINE_WIRE_BUS_TOOL::startSegments( int aType, const VECTOR2D& aPos
|
||||
}
|
||||
else
|
||||
{
|
||||
aSegment = static_cast<SCH_LINE*>( aSegment->Duplicate() );
|
||||
aSegment = static_cast<SCH_LINE*>( aSegment->Duplicate( true, &aCommit ) );
|
||||
aSegment->SetStartPoint( aPos );
|
||||
}
|
||||
|
||||
@ -1107,7 +1115,7 @@ SCH_LINE* SCH_LINE_WIRE_BUS_TOOL::startSegments( int aType, const VECTOR2D& aPos
|
||||
// horizontal and vertical lines only switch is on.
|
||||
if( m_frame->eeconfig()->m_Drawing.line_mode )
|
||||
{
|
||||
aSegment = static_cast<SCH_LINE*>( aSegment->Duplicate() );
|
||||
aSegment = static_cast<SCH_LINE*>( aSegment->Duplicate( true, &aCommit ) );
|
||||
aSegment->SetFlags( IS_NEW | IS_MOVING );
|
||||
m_wires.push_back( aSegment );
|
||||
|
||||
@ -1165,7 +1173,7 @@ void SCH_LINE_WIRE_BUS_TOOL::simplifyWireList()
|
||||
}
|
||||
|
||||
|
||||
void SCH_LINE_WIRE_BUS_TOOL::finishSegments()
|
||||
void SCH_LINE_WIRE_BUS_TOOL::finishSegments( SCH_COMMIT& aCommit )
|
||||
{
|
||||
// Clear selection when done so that a new wire can be started.
|
||||
// NOTE: this must be done before simplifyWireList is called or we might end up with
|
||||
@ -1173,7 +1181,6 @@ void SCH_LINE_WIRE_BUS_TOOL::finishSegments()
|
||||
m_toolMgr->RunAction( ACTIONS::selectionClear );
|
||||
|
||||
SCH_SCREEN* screen = m_frame->GetScreen();
|
||||
SCH_COMMIT commit( m_toolMgr );
|
||||
|
||||
// Remove segments backtracking over others
|
||||
simplifyWireList();
|
||||
@ -1198,17 +1205,17 @@ void SCH_LINE_WIRE_BUS_TOOL::finishSegments()
|
||||
new_ends.push_back( pt );
|
||||
}
|
||||
|
||||
commit.Added( wire, screen );
|
||||
aCommit.Added( wire, screen );
|
||||
}
|
||||
|
||||
if( m_busUnfold.in_progress && m_busUnfold.label_placed )
|
||||
{
|
||||
wxASSERT( m_busUnfold.entry && m_busUnfold.label );
|
||||
|
||||
commit.Added( m_busUnfold.entry, screen );
|
||||
aCommit.Added( m_busUnfold.entry, screen );
|
||||
m_frame->SaveCopyForRepeatItem( m_busUnfold.entry );
|
||||
|
||||
commit.Added( m_busUnfold.label, screen );
|
||||
aCommit.Added( m_busUnfold.label, screen );
|
||||
m_frame->AddCopyForRepeatItem( m_busUnfold.label );
|
||||
m_busUnfold.label->ClearEditFlags();
|
||||
}
|
||||
@ -1239,7 +1246,7 @@ void SCH_LINE_WIRE_BUS_TOOL::finishSegments()
|
||||
getViewControls()->SetAutoPan( false );
|
||||
|
||||
// Correct and remove segments that need to be merged.
|
||||
m_frame->SchematicCleanUp( &commit );
|
||||
m_frame->SchematicCleanUp( &aCommit );
|
||||
|
||||
std::vector<SCH_ITEM*> symbols;
|
||||
|
||||
@ -1256,14 +1263,14 @@ void SCH_LINE_WIRE_BUS_TOOL::finishSegments()
|
||||
for( auto pt = pts.begin(); pt != pts.end(); pt++ )
|
||||
{
|
||||
for( auto secondPt = pt + 1; secondPt != pts.end(); secondPt++ )
|
||||
m_frame->TrimWire( &commit, *pt, *secondPt );
|
||||
m_frame->TrimWire( &aCommit, *pt, *secondPt );
|
||||
}
|
||||
}
|
||||
|
||||
for( const VECTOR2I& pt : new_ends )
|
||||
{
|
||||
if( m_frame->GetScreen()->IsExplicitJunctionNeeded( pt ) )
|
||||
m_frame->AddJunction( &commit, m_frame->GetScreen(), pt );
|
||||
m_frame->AddJunction( &aCommit, m_frame->GetScreen(), pt );
|
||||
}
|
||||
|
||||
if( m_busUnfold.in_progress )
|
||||
@ -1271,8 +1278,6 @@ void SCH_LINE_WIRE_BUS_TOOL::finishSegments()
|
||||
|
||||
for( SCH_ITEM* item : m_frame->GetScreen()->Items() )
|
||||
item->ClearEditFlags();
|
||||
|
||||
commit.Push( _( "Draw Wires" ) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -96,9 +96,11 @@ public:
|
||||
int TrimOverLappingWires( SCH_COMMIT* aCommit, SCH_SELECTION* aSelection );
|
||||
|
||||
private:
|
||||
int doDrawSegments( const TOOL_EVENT& aTool, int aType, bool aQuitOnDraw );
|
||||
int doDrawSegments( const TOOL_EVENT& aTool, SCH_COMMIT& aCommit, int aType,
|
||||
bool aQuitOnDraw );
|
||||
|
||||
SCH_LINE* startSegments( int aType, const VECTOR2D& aPos, SCH_LINE* aSegment = nullptr );
|
||||
SCH_LINE* startSegments( SCH_COMMIT& aCommit, int aType, const VECTOR2D& aPos,
|
||||
SCH_LINE* aSegment = nullptr );
|
||||
|
||||
/**
|
||||
* Choose a bus to unfold based on the current tool selection.
|
||||
@ -112,10 +114,10 @@ private:
|
||||
* @param aPos The position to unfold the bus from, which will be the cursor if
|
||||
* not provided, and will then be snapped to the selected bus segment.
|
||||
*/
|
||||
SCH_LINE* doUnfoldBus( const wxString& aNet,
|
||||
SCH_LINE* doUnfoldBus( SCH_COMMIT& aCommit, const wxString& aNet,
|
||||
const std::optional<VECTOR2I>& aPos = std::nullopt );
|
||||
|
||||
void finishSegments();
|
||||
void finishSegments( SCH_COMMIT& aCommit );
|
||||
|
||||
/**
|
||||
* Iterate over the wire list and removes the null segments and
|
||||
|
@ -625,36 +625,48 @@ bool SCH_MOVE_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, SCH_COMMIT* aComm
|
||||
|
||||
for( EDA_ITEM* item : selection )
|
||||
{
|
||||
if( item->IsNew() )
|
||||
SCH_ITEM* schItem = static_cast<SCH_ITEM*>( item );
|
||||
|
||||
if( schItem->IsNew() )
|
||||
{
|
||||
// Item was added to commit in a previous command
|
||||
|
||||
// While SCH_COMMIT::Push() will add any new items to the entered group,
|
||||
// we need to do it earlier so that the previews while moving are correct.
|
||||
if( SCH_GROUP* enteredGroup = m_selectionTool->GetEnteredGroup() )
|
||||
{
|
||||
if( schItem->IsGroupableType() && !schItem->GetParentGroup() )
|
||||
{
|
||||
aCommit->Modify( enteredGroup );
|
||||
enteredGroup->AddItem( schItem );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( item->GetParent() && item->GetParent()->IsSelected() )
|
||||
else if( schItem->GetParent() && schItem->GetParent()->IsSelected() )
|
||||
{
|
||||
// Item will be (or has been) added to commit by parent
|
||||
}
|
||||
else
|
||||
{
|
||||
aCommit->Modify( item, m_frame->GetScreen() );
|
||||
aCommit->Modify( schItem, m_frame->GetScreen() );
|
||||
}
|
||||
|
||||
item->SetFlags( IS_MOVING );
|
||||
schItem->SetFlags( IS_MOVING );
|
||||
|
||||
if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( item ) )
|
||||
if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( schItem ) )
|
||||
{
|
||||
shape->SetHatchingDirty();
|
||||
shape->UpdateHatching();
|
||||
}
|
||||
|
||||
static_cast<SCH_ITEM*>( item )->RunOnChildren(
|
||||
schItem->RunOnChildren(
|
||||
[&]( SCH_ITEM* schItem )
|
||||
{
|
||||
item->SetFlags( IS_MOVING );
|
||||
},
|
||||
RECURSE_MODE::RECURSE );
|
||||
|
||||
if( SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( item ) )
|
||||
schItem->SetStoredPos( schItem->GetPosition() );
|
||||
schItem->SetStoredPos( schItem->GetPosition() );
|
||||
}
|
||||
|
||||
// Set up the starting position and move/drag offset
|
||||
@ -1670,7 +1682,7 @@ int SCH_MOVE_TOOL::AlignToGrid( const TOOL_EVENT& aEvent )
|
||||
auto doMoveItem =
|
||||
[&]( EDA_ITEM* item, const VECTOR2I& delta )
|
||||
{
|
||||
commit.Modify( item, m_frame->GetScreen() );
|
||||
commit.Modify( item, m_frame->GetScreen(), RECURSE_MODE::RECURSE );
|
||||
|
||||
// Ensure only one end is moved when calling moveItem
|
||||
// i.e. we are in drag mode
|
||||
|
@ -1076,7 +1076,7 @@ int SCH_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
|
||||
if( lastRolloverItem != niluuid && lastRolloverItem != rolloverItem )
|
||||
{
|
||||
EDA_ITEM* item = m_frame->GetItem( lastRolloverItem );
|
||||
EDA_ITEM* item = m_frame->ResolveItem( lastRolloverItem );
|
||||
|
||||
if( item->IsRollover() )
|
||||
{
|
||||
@ -1091,7 +1091,7 @@ int SCH_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
|
||||
if( rolloverItem != niluuid )
|
||||
{
|
||||
EDA_ITEM* item = m_frame->GetItem( rolloverItem );
|
||||
EDA_ITEM* item = m_frame->ResolveItem( rolloverItem );
|
||||
|
||||
if( !item->IsRollover() )
|
||||
{
|
||||
@ -1164,6 +1164,7 @@ void SCH_SELECTION_TOOL::EnterGroup()
|
||||
{
|
||||
if( aChild->Type() == SCH_LINE_T )
|
||||
aChild->SetFlags( STARTPOINT | ENDPOINT );
|
||||
|
||||
select( aChild );
|
||||
},
|
||||
RECURSE_MODE::NO_RECURSE );
|
||||
@ -1897,13 +1898,12 @@ SCH_SELECTION& SCH_SELECTION_TOOL::RequestSelection( const std::vector<KICAD_T>&
|
||||
|
||||
if( item->Type() == SCH_GROUP_T )
|
||||
{
|
||||
static_cast<SCH_ITEM*>(item)
|
||||
->RunOnChildren( [&]( SCH_ITEM* aChild )
|
||||
{
|
||||
if( aChild->IsType( aScanTypes ) )
|
||||
selectedChildren.insert( aChild );
|
||||
},
|
||||
RECURSE_MODE::RECURSE );
|
||||
static_cast<SCH_ITEM*>(item)->RunOnChildren( [&]( SCH_ITEM* aChild )
|
||||
{
|
||||
if( aChild->IsType( aScanTypes ) )
|
||||
selectedChildren.insert( aChild );
|
||||
},
|
||||
RECURSE_MODE::RECURSE );
|
||||
unselect( item );
|
||||
anyUnselected = true;
|
||||
}
|
||||
|
@ -290,7 +290,7 @@ int SYMBOL_EDITOR_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
|
||||
switch( item->Type() )
|
||||
{
|
||||
case SCH_PIN_T:
|
||||
pinTool->PlacePin( static_cast<SCH_PIN*>( item ) );
|
||||
pinTool->PlacePin( &commit, static_cast<SCH_PIN*>( item ) );
|
||||
item->ClearEditFlags();
|
||||
commit.Push( _( "Place Pin" ) );
|
||||
break;
|
||||
|
@ -183,7 +183,7 @@ int SYMBOL_EDITOR_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
|
||||
commit = &localCommit;
|
||||
|
||||
if( !item->IsMoving() )
|
||||
commit->Modify( m_frame->GetCurSymbol(), m_frame->GetScreen() );
|
||||
commit->Modify( m_frame->GetCurSymbol(), m_frame->GetScreen(), RECURSE_MODE::RECURSE );
|
||||
|
||||
if( selection.GetSize() == 1 )
|
||||
rotPoint = item->GetPosition();
|
||||
@ -1015,7 +1015,7 @@ int SYMBOL_EDITOR_EDIT_TOOL::Paste( const TOOL_EVENT& aEvent )
|
||||
if( item.Type() == SCH_FIELD_T )
|
||||
continue;
|
||||
|
||||
SCH_ITEM* newItem = item.Duplicate();
|
||||
SCH_ITEM* newItem = item.Duplicate( true, &commit );
|
||||
newItem->SetParent( symbol );
|
||||
newItem->SetFlags( IS_NEW | IS_PASTED | SELECTED );
|
||||
|
||||
@ -1093,7 +1093,7 @@ int SYMBOL_EDITOR_EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
|
||||
for( EDA_ITEM* item : oldItems )
|
||||
{
|
||||
SCH_ITEM* oldItem = static_cast<SCH_ITEM*>( item );
|
||||
SCH_ITEM* newItem = oldItem->Duplicate();
|
||||
SCH_ITEM* newItem = oldItem->Duplicate( true, &commit );
|
||||
|
||||
if( newItem->Type() == SCH_PIN_T )
|
||||
{
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <eda_item.h>
|
||||
#include <gal/graphics_abstraction_layer.h>
|
||||
#include <sch_shape.h>
|
||||
#include <sch_group.h>
|
||||
#include <sch_commit.h>
|
||||
#include <wx/debug.h>
|
||||
#include <view/view_controls.h>
|
||||
@ -232,8 +233,21 @@ bool SYMBOL_EDITOR_MOVE_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, SCH_COM
|
||||
// Drag items to the current cursor position
|
||||
for( EDA_ITEM* item : selection )
|
||||
{
|
||||
moveItem( item, delta );
|
||||
updateItem( item, false );
|
||||
SCH_ITEM* schItem = static_cast<SCH_ITEM*>( item );
|
||||
|
||||
moveItem( schItem, delta );
|
||||
updateItem( schItem, false );
|
||||
|
||||
// While SCH_COMMIT::Push() will add any new items to the entered group,
|
||||
// we need to do it earlier so that the previews while moving are correct.
|
||||
if( SCH_GROUP* enteredGroup = m_selectionTool->GetEnteredGroup() )
|
||||
{
|
||||
if( schItem->IsGroupableType() && !item->GetParentGroup() )
|
||||
{
|
||||
aCommit->Modify( enteredGroup );
|
||||
enteredGroup->AddItem( schItem );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_anchorPos = m_cursor;
|
||||
@ -329,7 +343,7 @@ bool SYMBOL_EDITOR_MOVE_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, SCH_COM
|
||||
{
|
||||
SCH_PIN* curr_pin = static_cast<SCH_PIN*>( selection.Front() );
|
||||
|
||||
if( pinTool->PlacePin( curr_pin ) )
|
||||
if( pinTool->PlacePin( aCommit, curr_pin ) )
|
||||
{
|
||||
// PlacePin() clears the current selection, which we don't want. Not only
|
||||
// is it a poor user experience, but it also prevents us from doing the
|
||||
@ -383,21 +397,17 @@ int SYMBOL_EDITOR_MOVE_TOOL::AlignElements( const TOOL_EVENT& aEvent )
|
||||
SCH_SELECTION& selection = m_selectionTool->RequestSelection();
|
||||
SCH_COMMIT commit( m_toolMgr );
|
||||
|
||||
auto doMoveItem =
|
||||
[&]( EDA_ITEM* item, const VECTOR2I& delta )
|
||||
{
|
||||
commit.Modify( item, m_frame->GetScreen() );
|
||||
static_cast<SCH_ITEM*>( item )->Move( delta );
|
||||
updateItem( item, true );
|
||||
};
|
||||
|
||||
for( EDA_ITEM* item : selection )
|
||||
{
|
||||
VECTOR2I newPos = grid.AlignGrid( item->GetPosition(), grid.GetItemGrid( item ) );
|
||||
VECTOR2I delta = newPos - item->GetPosition();
|
||||
|
||||
if( delta != VECTOR2I( 0, 0 ) )
|
||||
doMoveItem( item, delta );
|
||||
{
|
||||
commit.Modify( item, m_frame->GetScreen(), RECURSE_MODE::RECURSE );
|
||||
static_cast<SCH_ITEM*>( item )->Move( delta );
|
||||
updateItem( item, true );
|
||||
};
|
||||
|
||||
if( SCH_PIN* pin = dynamic_cast<SCH_PIN*>( item ) )
|
||||
{
|
||||
|
@ -24,8 +24,6 @@
|
||||
|
||||
#include "symbol_editor_pin_tool.h"
|
||||
|
||||
#include <tools/sch_selection_tool.h>
|
||||
#include <symbol_edit_frame.h>
|
||||
#include <sch_commit.h>
|
||||
#include <kidialog.h>
|
||||
#include <sch_actions.h>
|
||||
@ -217,7 +215,7 @@ bool SYMBOL_EDITOR_PIN_TOOL::EditPinProperties( SCH_PIN* aPin, bool aFocusPinNum
|
||||
}
|
||||
|
||||
|
||||
bool SYMBOL_EDITOR_PIN_TOOL::PlacePin( SCH_PIN* aPin )
|
||||
bool SYMBOL_EDITOR_PIN_TOOL::PlacePin( SCH_COMMIT* aCommit, SCH_PIN* aPin )
|
||||
{
|
||||
LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
|
||||
bool ask_for_pin = true; // Test for another pin in same position in other units
|
||||
@ -266,7 +264,7 @@ bool SYMBOL_EDITOR_PIN_TOOL::PlacePin( SCH_PIN* aPin )
|
||||
g_LastPinShape = aPin->GetShape();
|
||||
|
||||
if( m_frame->SynchronizePins() )
|
||||
CreateImagePins( aPin );
|
||||
CreateImagePins( aCommit, aPin );
|
||||
|
||||
symbol->AddDrawItem( aPin );
|
||||
aPin->ClearFlags( IS_NEW );
|
||||
@ -325,7 +323,7 @@ SCH_PIN* SYMBOL_EDITOR_PIN_TOOL::CreatePin( const VECTOR2I& aPosition, LIB_SYMBO
|
||||
}
|
||||
|
||||
|
||||
void SYMBOL_EDITOR_PIN_TOOL::CreateImagePins( SCH_PIN* aPin )
|
||||
void SYMBOL_EDITOR_PIN_TOOL::CreateImagePins( SCH_COMMIT* aCommit, SCH_PIN* aPin )
|
||||
{
|
||||
int ii;
|
||||
SCH_PIN* newPin;
|
||||
@ -348,7 +346,9 @@ void SYMBOL_EDITOR_PIN_TOOL::CreateImagePins( SCH_PIN* aPin )
|
||||
if( ii == aPin->GetUnit() )
|
||||
continue;
|
||||
|
||||
newPin = static_cast<SCH_PIN*>( aPin->Duplicate() );
|
||||
// Already called Modify() on parent symbol; no need for Modify() calls on individual items
|
||||
SCH_COMMIT dummy( m_toolMgr );
|
||||
newPin = static_cast<SCH_PIN*>( aPin->Duplicate( true, &dummy ) );
|
||||
|
||||
// To avoid mistakes, gives this pin a new pin number because
|
||||
// it does no have the save pin number as the master pin
|
||||
@ -366,8 +366,7 @@ void SYMBOL_EDITOR_PIN_TOOL::CreateImagePins( SCH_PIN* aPin )
|
||||
}
|
||||
catch( const boost::bad_pointer& e )
|
||||
{
|
||||
wxFAIL_MSG( wxString::Format( wxT( "Boost pointer exception occurred: %s" ),
|
||||
e.what() ));
|
||||
wxFAIL_MSG( wxString::Format( wxT( "Boost pointer exception occurred: %s" ), e.what() ));
|
||||
delete newPin;
|
||||
return;
|
||||
}
|
||||
@ -423,7 +422,7 @@ SCH_PIN* SYMBOL_EDITOR_PIN_TOOL::RepeatPin( const SCH_PIN* aSourcePin )
|
||||
|
||||
commit.Modify( symbol );
|
||||
|
||||
SCH_PIN* pin = static_cast<SCH_PIN*>( aSourcePin->Duplicate() );
|
||||
SCH_PIN* pin = static_cast<SCH_PIN*>( aSourcePin->Duplicate( true, &commit ) );
|
||||
VECTOR2I step;
|
||||
|
||||
pin->ClearFlags();
|
||||
@ -454,7 +453,7 @@ SCH_PIN* SYMBOL_EDITOR_PIN_TOOL::RepeatPin( const SCH_PIN* aSourcePin )
|
||||
if( m_frame->SynchronizePins() )
|
||||
pin->SetFlags( IS_LINKED );
|
||||
|
||||
if( PlacePin( pin ) )
|
||||
if( PlacePin( &commit, pin ) )
|
||||
{
|
||||
commit.Push( _( "Repeat Pin" ) );
|
||||
return pin;
|
||||
|
@ -44,8 +44,8 @@ public:
|
||||
SCH_PIN* CreatePin( const VECTOR2I& aPosition, LIB_SYMBOL* aSymbol );
|
||||
SCH_PIN* RepeatPin( const SCH_PIN* aSourcePin );
|
||||
|
||||
bool PlacePin( SCH_PIN* aPin );
|
||||
void CreateImagePins( SCH_PIN* aPin );
|
||||
bool PlacePin( SCH_COMMIT* aCommit, SCH_PIN* aPin );
|
||||
void CreateImagePins( SCH_COMMIT* aCommit, SCH_PIN* aPin );
|
||||
|
||||
bool EditPinProperties( SCH_PIN* aPin, bool aFocusPinNumber );
|
||||
int PushPinProperties( const TOOL_EVENT& aEvent );
|
||||
|
@ -37,6 +37,7 @@
|
||||
class BOARD;
|
||||
class BOARD_DESIGN_SETTINGS;
|
||||
class BOARD_ITEM_CONTAINER;
|
||||
class BOARD_COMMIT;
|
||||
class SHAPE_POLY_SET;
|
||||
class SHAPE_SEGMENT;
|
||||
class PCB_BASE_FRAME;
|
||||
@ -87,6 +88,8 @@ public:
|
||||
|
||||
virtual void CopyFrom( const BOARD_ITEM* aOther );
|
||||
|
||||
bool IsGroupableType() const;
|
||||
|
||||
// Do not create a copy constructor & operator=.
|
||||
// The ones generated by the compiler are adequate.
|
||||
int GetX() const
|
||||
@ -284,8 +287,11 @@ public:
|
||||
|
||||
/**
|
||||
* Create a copy of this #BOARD_ITEM.
|
||||
*
|
||||
* @param addToParentGroup Indicates whether or not the new item is added to the group
|
||||
* containing the old item. If true, aCommit must be provided.
|
||||
*/
|
||||
virtual BOARD_ITEM* Duplicate() const;
|
||||
virtual BOARD_ITEM* Duplicate( bool addToParentGroup, BOARD_COMMIT* aCommit = nullptr ) const;
|
||||
|
||||
/**
|
||||
* Swap data between \a aItem and \a aImage.
|
||||
|
@ -33,8 +33,9 @@
|
||||
#include <wx/string.h>
|
||||
#include <undo_redo_container.h>
|
||||
#include <kiid.h>
|
||||
#include <eda_item.h>
|
||||
|
||||
class EDA_ITEM;
|
||||
class EDA_GROUP;
|
||||
class BASE_SCREEN;
|
||||
|
||||
///< Types of changes
|
||||
@ -42,9 +43,7 @@ enum CHANGE_TYPE {
|
||||
CHT_ADD = 1,
|
||||
CHT_REMOVE = 2,
|
||||
CHT_MODIFY = 4,
|
||||
CHT_GROUP = 8,
|
||||
CHT_UNGROUP = 16,
|
||||
CHT_TYPE = CHT_ADD | CHT_REMOVE | CHT_MODIFY | CHT_GROUP | CHT_UNGROUP,
|
||||
CHT_TYPE = CHT_ADD | CHT_REMOVE | CHT_MODIFY,
|
||||
|
||||
CHT_DONE = 32, ///< Flag to indicate the change is already applied
|
||||
CHT_FLAGS = CHT_DONE
|
||||
@ -105,9 +104,10 @@ public:
|
||||
*
|
||||
* @note Must be called before modification is performed.
|
||||
*/
|
||||
COMMIT& Modify( EDA_ITEM* aItem, BASE_SCREEN *aScreen = nullptr )
|
||||
COMMIT& Modify( EDA_ITEM* aItem, BASE_SCREEN *aScreen = nullptr,
|
||||
RECURSE_MODE aRecurse = RECURSE_MODE::NO_RECURSE )
|
||||
{
|
||||
return Stage( aItem, CHT_MODIFY, aScreen );
|
||||
return Stage( aItem, CHT_MODIFY, aScreen, aRecurse );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -131,8 +131,8 @@ public:
|
||||
}
|
||||
|
||||
/// Add a change of the item aItem of type aChangeType to the change list.
|
||||
virtual COMMIT& Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType,
|
||||
BASE_SCREEN *aScreen = nullptr );
|
||||
virtual COMMIT& Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType, BASE_SCREEN *aScreen = nullptr,
|
||||
RECURSE_MODE aRecurse = RECURSE_MODE::NO_RECURSE );
|
||||
|
||||
virtual COMMIT& Stage( std::vector<EDA_ITEM*>& container, CHANGE_TYPE aChangeType,
|
||||
BASE_SCREEN *aScreen = nullptr );
|
||||
|
@ -431,7 +431,10 @@ public:
|
||||
/**
|
||||
* Fetch an item by KIID. Frame-type-specific implementation.
|
||||
*/
|
||||
virtual EDA_ITEM* GetItem( const KIID& aId ) const { return nullptr; }
|
||||
virtual EDA_ITEM* ResolveItem( const KIID& aId, bool aAllowNullptrReturn = false ) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use to start up the GAL drawing canvas.
|
||||
|
@ -51,6 +51,7 @@ enum RECURSE_MODE
|
||||
NO_RECURSE,
|
||||
};
|
||||
|
||||
#define IGNORE_PARENT_GROUP false
|
||||
|
||||
/**
|
||||
* Additional flag values wxFindReplaceData::m_Flags
|
||||
@ -95,7 +96,7 @@ typedef const INSPECTOR_FUNC& INSPECTOR;
|
||||
class EDA_ITEM : public KIGFX::VIEW_ITEM, public SERIALIZABLE
|
||||
{
|
||||
public:
|
||||
virtual ~EDA_ITEM() { wxASSERT( m_group == nullptr ); };
|
||||
virtual ~EDA_ITEM() = default;
|
||||
|
||||
/**
|
||||
* Returns the type of object.
|
||||
@ -113,6 +114,8 @@ public:
|
||||
virtual void SetParentGroup( EDA_GROUP* aGroup ) { m_group = aGroup; }
|
||||
virtual EDA_GROUP* GetParentGroup() const { return m_group; }
|
||||
|
||||
KIID GetParentGroupId() const;
|
||||
|
||||
virtual bool IsLocked() const { return false; }
|
||||
virtual void SetLocked( bool aLocked ) {}
|
||||
|
||||
@ -498,6 +501,8 @@ protected:
|
||||
*/
|
||||
bool Matches( const wxString& aText, const EDA_SEARCH_DATA& aSearchData ) const;
|
||||
|
||||
EDA_ITEM* findParent( KICAD_T aType ) const;
|
||||
|
||||
public:
|
||||
const KIID m_Uuid;
|
||||
|
||||
@ -511,8 +516,8 @@ 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
|
||||
EDA_ITEM* m_parent; ///< Owner.
|
||||
EDA_GROUP* m_group; ///< The group this item belongs to, if any. No ownership implied.
|
||||
bool m_forceVisible;
|
||||
bool m_isRollover;
|
||||
};
|
||||
|
@ -213,7 +213,7 @@ public:
|
||||
*/
|
||||
virtual BOARD_ITEM_CONTAINER* GetModel() const = 0;
|
||||
|
||||
EDA_ITEM* GetItem( const KIID& aId ) const override;
|
||||
EDA_ITEM* ResolveItem( const KIID& aId, bool aAllowNullptrReturn = false ) const override;
|
||||
|
||||
void FocusOnItem( EDA_ITEM* aItem ) override;
|
||||
void FocusOnItem( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer = UNDEFINED_LAYER );
|
||||
|
@ -68,9 +68,6 @@ enum class UNDO_REDO {
|
||||
DRILLORIGIN, // origin changed (like CHANGED, contains the origin and a copy)
|
||||
GRIDORIGIN, // origin changed (like CHANGED, contains the origin and a copy)
|
||||
PAGESETTINGS, // page settings or title block changes
|
||||
REGROUP, // new group of items created (NB: can't use GROUP because of collision
|
||||
// with a header on msys2)
|
||||
UNGROUP, // existing group destroyed (items not destroyed)
|
||||
REPEAT_ITEM // storage entry for the editor's global repeatItems list
|
||||
};
|
||||
|
||||
@ -78,32 +75,24 @@ enum class UNDO_REDO {
|
||||
class ITEM_PICKER
|
||||
{
|
||||
public:
|
||||
// ITEM_PICKER( EDA_ITEM* aItem = NULL, UNDO_REDO aStatus = UNSPECIFIED );
|
||||
ITEM_PICKER();
|
||||
ITEM_PICKER( BASE_SCREEN* aScreen, EDA_ITEM* aItem,
|
||||
UNDO_REDO aStatus = UNDO_REDO::UNSPECIFIED );
|
||||
|
||||
EDA_ITEM* GetItem() const { return m_pickedItem; }
|
||||
|
||||
void SetItem( EDA_ITEM* aItem );
|
||||
|
||||
KICAD_T GetItemType() const { return m_pickedItemType; }
|
||||
|
||||
void SetStatus( UNDO_REDO aStatus ) { m_undoRedoStatus = aStatus; }
|
||||
|
||||
UNDO_REDO GetStatus() const { return m_undoRedoStatus; }
|
||||
|
||||
void SetFlags( EDA_ITEM_FLAGS aFlags ) { m_pickerFlags = aFlags; }
|
||||
|
||||
EDA_ITEM_FLAGS GetFlags() const { return m_pickerFlags; }
|
||||
|
||||
void SetLink( EDA_ITEM* aItem ) { m_link = aItem; }
|
||||
|
||||
void SetLink( EDA_ITEM* aItem );
|
||||
EDA_ITEM* GetLink() const { return m_link; }
|
||||
|
||||
KIID GetGroupId() const { return m_groupId; }
|
||||
|
||||
void SetGroupId( KIID aId ) { m_groupId = aId; }
|
||||
KIID_VECT_LIST GetGroupMembers() const { return m_groupMembers; }
|
||||
|
||||
BASE_SCREEN* GetScreen() const { return m_screen; }
|
||||
|
||||
@ -122,8 +111,8 @@ private:
|
||||
* duplicate) m_Item points the duplicate (i.e the old
|
||||
* copy of an active item) and m_Link points the active
|
||||
* item in schematic */
|
||||
KIID m_groupId; /* Id of the group of items in case this is a
|
||||
* group/ungroup command */
|
||||
KIID m_groupId; /* Id of the parent group */
|
||||
KIID_VECT_LIST m_groupMembers; /* Ids of the members of a group */
|
||||
|
||||
BASE_SCREEN* m_screen; /* For new and deleted items the screen the item should
|
||||
* be added to/removed from. */
|
||||
@ -159,14 +148,6 @@ public:
|
||||
*/
|
||||
bool ContainsItem( const EDA_ITEM* aItem ) const;
|
||||
|
||||
/**
|
||||
* Check the undo/redo list for any #EDA_ITEM of type \a aItemType.
|
||||
*
|
||||
* @param aItemType is an #EDA_ITEM type from the list of #KICAD_T types.
|
||||
* @return true if an item of \a aItemType is found in the pick list.
|
||||
*/
|
||||
bool ContainsItemType( KICAD_T aItemType ) const;
|
||||
|
||||
/**
|
||||
* @return Index of the searched item. If the item is not stored in the list, negative value
|
||||
* is returned.
|
||||
@ -206,7 +187,8 @@ public:
|
||||
* @param aIdx Index of the picker in the picked list if this picker does not exist,
|
||||
* a picker is returned, with its members set to 0 or NULL.
|
||||
*/
|
||||
ITEM_PICKER GetItemWrapper( unsigned int aIdx ) const;
|
||||
const ITEM_PICKER& GetItemWrapper( unsigned int aIdx ) const;
|
||||
ITEM_PICKER& GetItemWrapper( unsigned int aIdx );
|
||||
|
||||
/**
|
||||
* @return A pointer to the picked item.
|
||||
@ -233,12 +215,6 @@ public:
|
||||
*/
|
||||
UNDO_REDO GetPickedItemStatus( unsigned int aIdx ) const;
|
||||
|
||||
/**
|
||||
* @return The group id of the picked item, or null KIID if does not exist.
|
||||
* @param aIdx Index of the picked item in the picked list.
|
||||
*/
|
||||
KIID GetPickedItemGroupId( unsigned int aIdx ) const;
|
||||
|
||||
/**
|
||||
* Return the value of the picker flag.
|
||||
*
|
||||
@ -254,14 +230,6 @@ public:
|
||||
*/
|
||||
bool SetPickedItem( EDA_ITEM* aItem, unsigned aIdx );
|
||||
|
||||
/**
|
||||
* @param aItem A pointer to the item to pick.
|
||||
* @param aStatus The type of undo/redo operation associated to the item to pick.
|
||||
* @param aIdx Index of the picker in the picked list.
|
||||
* @return True if the picker exists or false if does not exist.
|
||||
*/
|
||||
bool SetPickedItem( EDA_ITEM* aItem, UNDO_REDO aStatus, unsigned aIdx );
|
||||
|
||||
/**
|
||||
* Set the link associated to a given picked item.
|
||||
*
|
||||
@ -271,15 +239,6 @@ public:
|
||||
*/
|
||||
bool SetPickedItemLink( EDA_ITEM* aLink, unsigned aIdx );
|
||||
|
||||
/**
|
||||
* Set the group id associated to a given picked item.
|
||||
*
|
||||
* @param aId is the group id to associate to the picked item.
|
||||
* @param aIdx is index of the picker in the picked list.
|
||||
* @return true if the picker exists, or false if does not exist.
|
||||
*/
|
||||
bool SetPickedItemGroupId( KIID aId, unsigned aIdx );
|
||||
|
||||
/**
|
||||
* Set the type of undo/redo operation for a given picked item.
|
||||
*
|
||||
|
@ -270,9 +270,9 @@ std::unique_ptr<COMMIT> API_HANDLER_PCB::createCommit()
|
||||
|
||||
std::optional<BOARD_ITEM*> API_HANDLER_PCB::getItemById( const KIID& aId ) const
|
||||
{
|
||||
BOARD_ITEM* item = frame()->GetBoard()->GetItem( aId );
|
||||
BOARD_ITEM* item = frame()->GetBoard()->ResolveItem( aId, true );
|
||||
|
||||
if( item == DELETED_BOARD_ITEM::GetInstance() )
|
||||
if( !item )
|
||||
return std::nullopt;
|
||||
|
||||
return item;
|
||||
@ -649,7 +649,7 @@ void API_HANDLER_PCB::deleteItemsInternal( std::map<KIID, ItemDeletionStatus>& a
|
||||
|
||||
for( std::pair<const KIID, ItemDeletionStatus> pair : aItemsToDelete )
|
||||
{
|
||||
if( BOARD_ITEM* item = board->GetItem( pair.first ) )
|
||||
if( BOARD_ITEM* item = board->ResolveItem( pair.first, true ) )
|
||||
{
|
||||
validatedItems.push_back( item );
|
||||
aItemsToDelete[pair.first] = ItemDeletionStatus::IDS_OK;
|
||||
|
@ -147,19 +147,6 @@ BOARD::BOARD() :
|
||||
|
||||
BOARD::~BOARD()
|
||||
{
|
||||
// Untangle group parents before doing any deleting
|
||||
for( PCB_GROUP* group : m_groups )
|
||||
{
|
||||
for( EDA_ITEM* item : group->GetItems() )
|
||||
item->SetParentGroup( nullptr );
|
||||
}
|
||||
|
||||
for( PCB_GENERATOR* generator : m_generators )
|
||||
{
|
||||
for( EDA_ITEM* item : generator->GetItems() )
|
||||
item->SetParentGroup( nullptr );
|
||||
}
|
||||
|
||||
m_itemByIdCache.clear();
|
||||
|
||||
// Clean up the owned elements
|
||||
@ -390,7 +377,7 @@ std::vector<PCB_MARKER*> BOARD::ResolveDRCExclusions( bool aCreateMarkers )
|
||||
// Check to see if items still exist
|
||||
for( const KIID& guid : marker->GetRCItem()->GetIDs() )
|
||||
{
|
||||
if( GetItem( guid ) == DELETED_BOARD_ITEM::GetInstance() )
|
||||
if( !ResolveItem( guid, true ) )
|
||||
{
|
||||
delete marker;
|
||||
marker = nullptr;
|
||||
@ -444,9 +431,9 @@ bool BOARD::ResolveTextVar( wxString* token, int aDepth ) const
|
||||
{
|
||||
if( token->Contains( ':' ) )
|
||||
{
|
||||
wxString remainder;
|
||||
wxString ref = token->BeforeFirst( ':', &remainder );
|
||||
BOARD_ITEM* refItem = GetItem( KIID( ref ) );
|
||||
wxString remainder;
|
||||
wxString ref = token->BeforeFirst( ':', &remainder );
|
||||
BOARD_ITEM* refItem = ResolveItem( KIID( ref ), true );
|
||||
|
||||
if( refItem && refItem->Type() == PCB_FOOTPRINT_T )
|
||||
{
|
||||
@ -1322,11 +1309,6 @@ void BOARD::Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aRemoveMode )
|
||||
|
||||
aBoardItem->SetFlags( STRUCT_DELETED );
|
||||
|
||||
EDA_GROUP* parentGroup = aBoardItem->GetParentGroup();
|
||||
|
||||
if( parentGroup && !( parentGroup->AsEdaItem()->GetFlags() & STRUCT_DELETED ) )
|
||||
parentGroup->RemoveItem( aBoardItem );
|
||||
|
||||
m_connectivity->Remove( aBoardItem );
|
||||
|
||||
if( aRemoveMode != REMOVE_MODE::BULK )
|
||||
@ -1509,7 +1491,7 @@ void BOARD::DetachAllFootprints()
|
||||
}
|
||||
|
||||
|
||||
BOARD_ITEM* BOARD::GetItem( const KIID& aID ) const
|
||||
BOARD_ITEM* BOARD::ResolveItem( const KIID& aID, bool aAllowNullptrReturn ) const
|
||||
{
|
||||
if( aID == niluuid )
|
||||
return nullptr;
|
||||
@ -1517,6 +1499,22 @@ BOARD_ITEM* BOARD::GetItem( const KIID& aID ) const
|
||||
if( m_itemByIdCache.count( aID ) )
|
||||
return m_itemByIdCache.at( aID );
|
||||
|
||||
// Main clients include highlighting, group undo/redo and DRC items. Since
|
||||
// everything but group undo/redo will be spread over all object types, we
|
||||
// might as well prioritize group undo/redo and search them first.
|
||||
|
||||
for( PCB_GROUP* group : m_groups )
|
||||
{
|
||||
if( group->m_Uuid == aID )
|
||||
return group;
|
||||
}
|
||||
|
||||
for( PCB_GENERATOR* generator : m_generators )
|
||||
{
|
||||
if( generator->m_Uuid == aID )
|
||||
return generator;
|
||||
}
|
||||
|
||||
for( PCB_TRACK* track : Tracks() )
|
||||
{
|
||||
if( track->m_Uuid == aID )
|
||||
@ -1586,19 +1584,6 @@ BOARD_ITEM* BOARD::GetItem( const KIID& aID ) const
|
||||
return marker;
|
||||
}
|
||||
|
||||
for( PCB_GROUP* group : m_groups )
|
||||
{
|
||||
if( group->m_Uuid == aID )
|
||||
return group;
|
||||
}
|
||||
|
||||
for( PCB_GENERATOR* generator : m_generators )
|
||||
{
|
||||
if( generator->m_Uuid == aID )
|
||||
return generator;
|
||||
}
|
||||
|
||||
|
||||
for( NETINFO_ITEM* netInfo : m_NetInfo )
|
||||
{
|
||||
if( netInfo->m_Uuid == aID )
|
||||
@ -1609,7 +1594,10 @@ BOARD_ITEM* BOARD::GetItem( const KIID& aID ) const
|
||||
return const_cast<BOARD*>( this );
|
||||
|
||||
// Not found; weak reference has been deleted.
|
||||
return DELETED_BOARD_ITEM::GetInstance();
|
||||
if( aAllowNullptrReturn )
|
||||
return nullptr;
|
||||
else
|
||||
return DELETED_BOARD_ITEM::GetInstance();
|
||||
}
|
||||
|
||||
|
||||
@ -1733,7 +1721,7 @@ wxString BOARD::ConvertKIIDsToCrossReferences( const wxString& aSource ) const
|
||||
{
|
||||
wxString remainder;
|
||||
wxString ref = token.BeforeFirst( ':', &remainder );
|
||||
BOARD_ITEM* refItem = GetItem( KIID( ref ) );
|
||||
BOARD_ITEM* refItem = ResolveItem( KIID( ref ), true );
|
||||
|
||||
if( refItem && refItem->Type() == PCB_FOOTPRINT_T )
|
||||
{
|
||||
|
@ -476,9 +476,10 @@ public:
|
||||
void DetachAllFootprints();
|
||||
|
||||
/**
|
||||
* @return null if aID is null. Returns an object of Type() == NOT_USED if the aID is not found.
|
||||
* @return null if aID is null. If \a aID cannot be resolved, returns either an object of
|
||||
* Type() == NOT_USED or null, depending on \a aAllowNullptrReturn.
|
||||
*/
|
||||
BOARD_ITEM* GetItem( const KIID& aID ) const;
|
||||
BOARD_ITEM* ResolveItem( const KIID& aID, bool aAllowNullptrReturn = false ) const;
|
||||
|
||||
void FillItemMap( std::map<KIID, EDA_ITEM*>& aMap );
|
||||
|
||||
|
@ -94,20 +94,15 @@ BOARD* BOARD_COMMIT::GetBoard() const
|
||||
}
|
||||
|
||||
|
||||
COMMIT& BOARD_COMMIT::Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType, BASE_SCREEN* aScreen )
|
||||
COMMIT& BOARD_COMMIT::Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType, BASE_SCREEN* aScreen,
|
||||
RECURSE_MODE aRecurse )
|
||||
{
|
||||
// Many operations (move, rotate, etc.) are applied directly to a group's children, so they
|
||||
// must be staged as well.
|
||||
if( aChangeType == CHT_MODIFY )
|
||||
if( aRecurse == RECURSE_MODE::RECURSE )
|
||||
{
|
||||
if( PCB_GROUP* group = dynamic_cast<PCB_GROUP*>( aItem ) )
|
||||
{
|
||||
group->RunOnChildren(
|
||||
[&]( BOARD_ITEM* child )
|
||||
{
|
||||
Stage( child, aChangeType );
|
||||
},
|
||||
RECURSE_MODE::NO_RECURSE );
|
||||
for( EDA_ITEM* member : group->GetItems() )
|
||||
Stage( member, aChangeType, aScreen, aRecurse );
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,6 +170,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
||||
BOARD* board = static_cast<BOARD*>( m_toolMgr->GetModel() );
|
||||
PCB_BASE_FRAME* frame = dynamic_cast<PCB_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
|
||||
PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
|
||||
PCB_GROUP* enteredGroup = selTool ? selTool->GetEnteredGroup() : nullptr;
|
||||
|
||||
// Notification info
|
||||
PICKED_ITEMS_LIST undoList;
|
||||
@ -186,7 +182,6 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
||||
bool autofillZones = false;
|
||||
std::vector<BOARD_ITEM*> staleTeardropPadsAndVias;
|
||||
std::set<PCB_TRACK*> staleTeardropTracks;
|
||||
PCB_GROUP* addedGroup = nullptr;
|
||||
std::vector<ZONE*> staleZonesStorage;
|
||||
std::vector<ZONE*>* staleZones = nullptr;
|
||||
|
||||
@ -269,14 +264,21 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
||||
if( !staleTeardropPadsAndVias.empty() || !staleTeardropTracks.empty() )
|
||||
teardropMgr.RemoveTeardrops( *this, &staleTeardropPadsAndVias, &staleTeardropTracks );
|
||||
|
||||
auto updateComponentClasses = [this]( BOARD_ITEM* boardItem )
|
||||
{
|
||||
if( boardItem->Type() != PCB_FOOTPRINT_T )
|
||||
return;
|
||||
auto updateComponentClasses =
|
||||
[this]( BOARD_ITEM* boardItem )
|
||||
{
|
||||
if( boardItem->Type() != PCB_FOOTPRINT_T )
|
||||
return;
|
||||
|
||||
FOOTPRINT* footprint = static_cast<FOOTPRINT*>( boardItem );
|
||||
GetBoard()->GetComponentClassManager().RebuildRequiredCaches( footprint );
|
||||
};
|
||||
|
||||
// We don't know that anything will be added to the entered group, but it does no harm to
|
||||
// add it to the commit anyway.
|
||||
if( enteredGroup )
|
||||
Modify( enteredGroup );
|
||||
|
||||
FOOTPRINT* footprint = static_cast<FOOTPRINT*>( boardItem );
|
||||
GetBoard()->GetComponentClassManager().RebuildRequiredCaches( footprint );
|
||||
};
|
||||
|
||||
for( COMMIT_LINE& ent : m_changes )
|
||||
{
|
||||
@ -290,11 +292,8 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
||||
switch( changeType )
|
||||
{
|
||||
case CHT_ADD:
|
||||
if( selTool && selTool->GetEnteredGroup() && !boardItem->GetParentGroup()
|
||||
&& PCB_GROUP::IsGroupableType( boardItem->Type() ) )
|
||||
{
|
||||
selTool->GetEnteredGroup()->AddItem( boardItem );
|
||||
}
|
||||
if( enteredGroup && boardItem->IsGroupableType() && !boardItem->GetParentGroup() )
|
||||
enteredGroup->AddItem( boardItem );
|
||||
|
||||
if( !( aCommitFlags & SKIP_UNDO ) )
|
||||
undoList.PushItem( ITEM_PICKER( nullptr, boardItem, UNDO_REDO::NEWITEM ) );
|
||||
@ -319,12 +318,6 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
||||
}
|
||||
}
|
||||
|
||||
if( boardItem->Type() == PCB_GROUP_T || boardItem->Type() == PCB_GENERATOR_T )
|
||||
{
|
||||
wxASSERT_MSG( !addedGroup, "Multiple groups in a single commit. This is not supported." );
|
||||
addedGroup = static_cast<PCB_GROUP*>( boardItem );
|
||||
}
|
||||
|
||||
if( boardItem->Type() != PCB_MARKER_T )
|
||||
propagateDamage( boardItem, staleZones );
|
||||
|
||||
@ -341,7 +334,12 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
||||
EDA_GROUP* parentGroup = boardItem->GetParentGroup();
|
||||
|
||||
if( !( aCommitFlags & SKIP_UNDO ) )
|
||||
undoList.PushItem( ITEM_PICKER( nullptr, boardItem, UNDO_REDO::DELETED ) );
|
||||
{
|
||||
ITEM_PICKER itemWrapper( nullptr, boardItem, UNDO_REDO::DELETED );
|
||||
itemWrapper.SetLink( ent.m_copy );
|
||||
ent.m_copy = nullptr; // We've transferred ownership to the undo list
|
||||
undoList.PushItem( itemWrapper );
|
||||
}
|
||||
|
||||
if( boardItem->IsSelected() )
|
||||
{
|
||||
@ -417,65 +415,27 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
||||
|
||||
// The item has been removed from the board; it is now owned by undo/redo.
|
||||
boardItem->SetFlags( UR_TRANSIENT );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CHT_UNGROUP:
|
||||
if( EDA_GROUP* group = boardItem->GetParentGroup() )
|
||||
{
|
||||
if( !( aCommitFlags & SKIP_UNDO ) )
|
||||
{
|
||||
ITEM_PICKER itemWrapper( nullptr, boardItem, UNDO_REDO::UNGROUP );
|
||||
itemWrapper.SetGroupId( group->AsEdaItem()->m_Uuid );
|
||||
undoList.PushItem( itemWrapper );
|
||||
}
|
||||
|
||||
group->RemoveItem( boardItem );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CHT_GROUP:
|
||||
if( addedGroup )
|
||||
{
|
||||
addedGroup->AddItem( boardItem );
|
||||
|
||||
if( !( aCommitFlags & SKIP_UNDO ) )
|
||||
undoList.PushItem( ITEM_PICKER( nullptr, boardItem, UNDO_REDO::REGROUP ) );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CHT_MODIFY:
|
||||
{
|
||||
BOARD_ITEM* boardItemCopy = nullptr;
|
||||
|
||||
if( ent.m_copy && ent.m_copy->IsBOARD_ITEM() )
|
||||
boardItemCopy = static_cast<BOARD_ITEM*>( ent.m_copy );
|
||||
BOARD_ITEM* boardItemCopy = dynamic_cast<BOARD_ITEM*>( ent.m_copy );
|
||||
|
||||
if( !( aCommitFlags & SKIP_UNDO ) )
|
||||
{
|
||||
ITEM_PICKER itemWrapper( nullptr, boardItem, UNDO_REDO::CHANGED );
|
||||
wxASSERT( boardItemCopy );
|
||||
itemWrapper.SetLink( boardItemCopy );
|
||||
itemWrapper.SetLink( ent.m_copy );
|
||||
ent.m_copy = nullptr; // We've transferred ownership to the undo list
|
||||
undoList.PushItem( itemWrapper );
|
||||
}
|
||||
|
||||
if( !( aCommitFlags & SKIP_CONNECTIVITY ) )
|
||||
{
|
||||
if( boardItemCopy )
|
||||
connectivity->MarkItemNetAsDirty( boardItemCopy );
|
||||
|
||||
connectivity->MarkItemNetAsDirty( boardItemCopy );
|
||||
connectivity->Update( boardItem );
|
||||
}
|
||||
|
||||
if( boardItem->Type() == PCB_GROUP_T || boardItem->Type() == PCB_GENERATOR_T )
|
||||
{
|
||||
wxASSERT_MSG( !addedGroup, "Multiple groups in a single commit. This is not supported." );
|
||||
addedGroup = static_cast<PCB_GROUP*>( boardItem );
|
||||
}
|
||||
|
||||
if( boardItem->Type() != PCB_MARKER_T )
|
||||
{
|
||||
propagateDamage( boardItemCopy, staleZones ); // before
|
||||
@ -488,11 +448,6 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
||||
view->Update( boardItem );
|
||||
|
||||
itemsChanged.push_back( boardItem );
|
||||
|
||||
// if no undo entry is needed, the copy would create a memory leak
|
||||
if( aCommitFlags & SKIP_UNDO )
|
||||
delete ent.m_copy;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -501,6 +456,10 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
||||
break;
|
||||
}
|
||||
|
||||
// Delete any copies we still have ownership of
|
||||
delete ent.m_copy;
|
||||
ent.m_copy = nullptr;
|
||||
|
||||
boardItem->ClearEditFlags();
|
||||
boardItem->RunOnChildren(
|
||||
[&]( BOARD_ITEM* item )
|
||||
@ -656,10 +615,6 @@ EDA_ITEM* BOARD_COMMIT::makeImage( EDA_ITEM* aItem ) const
|
||||
EDA_ITEM* BOARD_COMMIT::MakeImage( EDA_ITEM* aItem )
|
||||
{
|
||||
EDA_ITEM* clone = aItem->Clone();
|
||||
|
||||
if( clone->IsBOARD_ITEM() )
|
||||
static_cast<BOARD_ITEM*>( clone )->SetParentGroup( nullptr );
|
||||
|
||||
clone->SetFlags( UR_TRANSIENT );
|
||||
|
||||
return clone;
|
||||
@ -700,14 +655,6 @@ void BOARD_COMMIT::Revert()
|
||||
switch( changeType )
|
||||
{
|
||||
case CHT_ADD:
|
||||
// Items are auto-added to the parent group by BOARD_ITEM::Duplicate(), not when
|
||||
// the commit is pushed.
|
||||
if( EDA_GROUP* parentGroup = boardItem->GetParentGroup() )
|
||||
{
|
||||
if( GetStatus( parentGroup->AsEdaItem() ) == 0 )
|
||||
parentGroup->RemoveItem( boardItem );
|
||||
}
|
||||
|
||||
if( !( changeFlags & CHT_DONE ) )
|
||||
break;
|
||||
|
||||
@ -732,18 +679,17 @@ void BOARD_COMMIT::Revert()
|
||||
|
||||
view->Add( boardItem );
|
||||
|
||||
// Note: parent can be nullptr, because entry.m_parent is only set for children
|
||||
// of footprints.
|
||||
BOARD_ITEM* parent = board->GetItem( entry.m_parent );
|
||||
|
||||
if( parent && parent->Type() == PCB_FOOTPRINT_T )
|
||||
if( BOARD_ITEM* parent = board->ResolveItem( entry.m_parent, true ) )
|
||||
{
|
||||
static_cast<FOOTPRINT*>( parent )->Add( boardItem, ADD_MODE::INSERT );
|
||||
}
|
||||
else
|
||||
{
|
||||
board->Add( boardItem, ADD_MODE::INSERT );
|
||||
bulkAddedItems.push_back( boardItem );
|
||||
if( parent->Type() == PCB_FOOTPRINT_T )
|
||||
{
|
||||
static_cast<FOOTPRINT*>( parent )->Add( boardItem, ADD_MODE::INSERT );
|
||||
}
|
||||
else
|
||||
{
|
||||
board->Add( boardItem, ADD_MODE::INSERT );
|
||||
bulkAddedItems.push_back( boardItem );
|
||||
}
|
||||
}
|
||||
|
||||
updateComponentClasses( boardItem );
|
||||
|
@ -61,7 +61,8 @@ public:
|
||||
|
||||
virtual void Revert() override;
|
||||
COMMIT& Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType,
|
||||
BASE_SCREEN* aScreen = nullptr ) override;
|
||||
BASE_SCREEN* aScreen = nullptr,
|
||||
RECURSE_MODE aRecurse = RECURSE_MODE::NO_RECURSE ) override;
|
||||
COMMIT& Stage( std::vector<EDA_ITEM*>& container, CHANGE_TYPE aChangeType,
|
||||
BASE_SCREEN* aScreen = nullptr ) override;
|
||||
COMMIT& Stage( const PICKED_ITEMS_LIST& aItems,
|
||||
|
@ -38,6 +38,37 @@
|
||||
#include <font/font.h>
|
||||
|
||||
|
||||
bool BOARD_ITEM::IsGroupableType() const
|
||||
{
|
||||
switch ( Type() )
|
||||
{
|
||||
case PCB_FOOTPRINT_T:
|
||||
case PCB_PAD_T:
|
||||
case PCB_SHAPE_T:
|
||||
case PCB_REFERENCE_IMAGE_T:
|
||||
case PCB_FIELD_T:
|
||||
case PCB_TEXT_T:
|
||||
case PCB_TEXTBOX_T:
|
||||
case PCB_TABLE_T:
|
||||
case PCB_GROUP_T:
|
||||
case PCB_GENERATOR_T:
|
||||
case PCB_TRACE_T:
|
||||
case PCB_VIA_T:
|
||||
case PCB_ARC_T:
|
||||
case PCB_DIMENSION_T:
|
||||
case PCB_DIM_ALIGNED_T:
|
||||
case PCB_DIM_LEADER_T:
|
||||
case PCB_DIM_CENTER_T:
|
||||
case PCB_DIM_RADIAL_T:
|
||||
case PCB_DIM_ORTHOGONAL_T:
|
||||
case PCB_ZONE_T:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BOARD_ITEM::CopyFrom( const BOARD_ITEM* aOther )
|
||||
{
|
||||
wxCHECK( aOther, /* void */ );
|
||||
@ -50,12 +81,7 @@ const BOARD* BOARD_ITEM::GetBoard() const
|
||||
if( Type() == PCB_T )
|
||||
return static_cast<const BOARD*>( this );
|
||||
|
||||
BOARD_ITEM* parent = GetParent();
|
||||
|
||||
if( parent )
|
||||
return parent->GetBoard();
|
||||
|
||||
return nullptr;
|
||||
return static_cast<const BOARD*>( findParent( PCB_T ) );
|
||||
}
|
||||
|
||||
|
||||
@ -64,23 +90,28 @@ BOARD* BOARD_ITEM::GetBoard()
|
||||
if( Type() == PCB_T )
|
||||
return static_cast<BOARD*>( this );
|
||||
|
||||
BOARD_ITEM* parent = GetParent();
|
||||
return static_cast<BOARD*>( findParent( PCB_T ) );
|
||||
}
|
||||
|
||||
if( parent )
|
||||
return parent->GetBoard();
|
||||
|
||||
return nullptr;
|
||||
FOOTPRINT* BOARD_ITEM::GetParentFootprint() const
|
||||
{
|
||||
return static_cast<FOOTPRINT*>( findParent( PCB_FOOTPRINT_T ) );
|
||||
}
|
||||
|
||||
|
||||
bool BOARD_ITEM::IsLocked() const
|
||||
{
|
||||
if( GetParentGroup() && static_cast<PCB_GROUP*>( GetParentGroup() )->IsLocked() )
|
||||
return true;
|
||||
if( EDA_GROUP* group = GetParentGroup() )
|
||||
{
|
||||
if( group->AsEdaItem()->IsLocked() )
|
||||
return true;
|
||||
}
|
||||
|
||||
const BOARD* board = GetBoard();
|
||||
if( !GetBoard() || GetBoard()->GetBoardUse() == BOARD_USE::FPHOLDER )
|
||||
return false;
|
||||
|
||||
return board && board->GetBoardUse() != BOARD_USE::FPHOLDER && m_isLocked;
|
||||
return m_isLocked;
|
||||
}
|
||||
|
||||
|
||||
@ -220,6 +251,7 @@ void BOARD_ITEM::DeleteStructure()
|
||||
|
||||
void BOARD_ITEM::swapData( BOARD_ITEM* aImage )
|
||||
{
|
||||
UNIMPLEMENTED_FOR( GetClass() );
|
||||
}
|
||||
|
||||
|
||||
@ -228,26 +260,29 @@ void BOARD_ITEM::SwapItemData( BOARD_ITEM* aImage )
|
||||
if( aImage == nullptr )
|
||||
return;
|
||||
|
||||
EDA_ITEM* parent = GetParent();
|
||||
EDA_GROUP* group = GetParentGroup();
|
||||
EDA_ITEM* parent = GetParent();
|
||||
|
||||
SetParentGroup( nullptr );
|
||||
aImage->SetParentGroup( nullptr );
|
||||
swapData( aImage );
|
||||
|
||||
// Restore pointers to be sure they are not broken
|
||||
SetParent( parent );
|
||||
SetParentGroup( group );
|
||||
}
|
||||
|
||||
|
||||
BOARD_ITEM* BOARD_ITEM::Duplicate() const
|
||||
BOARD_ITEM* BOARD_ITEM::Duplicate( bool addToParentGroup, BOARD_COMMIT* aCommit ) const
|
||||
{
|
||||
BOARD_ITEM* dupe = static_cast<BOARD_ITEM*>( Clone() );
|
||||
const_cast<KIID&>( dupe->m_Uuid ) = KIID();
|
||||
|
||||
if( dupe->GetParentGroup() )
|
||||
dupe->GetParentGroup()->AddItem( dupe );
|
||||
if( addToParentGroup )
|
||||
{
|
||||
wxCHECK_MSG( aCommit, dupe, "Must supply a commit to update parent group" );
|
||||
|
||||
if( dupe->GetParentGroup() )
|
||||
{
|
||||
aCommit->Modify( dupe->GetParentGroup()->AsEdaItem() );
|
||||
dupe->GetParentGroup()->AddItem( dupe );
|
||||
}
|
||||
}
|
||||
|
||||
return dupe;
|
||||
}
|
||||
@ -296,35 +331,6 @@ std::shared_ptr<SHAPE_SEGMENT> BOARD_ITEM::GetEffectiveHoleShape() const
|
||||
}
|
||||
|
||||
|
||||
FOOTPRINT* BOARD_ITEM::GetParentFootprint() const
|
||||
{
|
||||
// EDA_ITEM::IsType is too slow here.
|
||||
auto isContainer = []( BOARD_ITEM_CONTAINER* aTest )
|
||||
{
|
||||
switch( aTest->Type() )
|
||||
{
|
||||
case PCB_GROUP_T:
|
||||
case PCB_GENERATOR_T:
|
||||
case PCB_TABLE_T:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
BOARD_ITEM_CONTAINER* ancestor = GetParent();
|
||||
|
||||
while( ancestor && isContainer( ancestor ) )
|
||||
ancestor = ancestor->GetParent();
|
||||
|
||||
if( ancestor && ancestor->Type() == PCB_FOOTPRINT_T )
|
||||
return static_cast<FOOTPRINT*>( ancestor );
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I BOARD_ITEM::GetFPRelativePosition() const
|
||||
{
|
||||
VECTOR2I pos = GetPosition();
|
||||
|
@ -321,7 +321,6 @@ void collectItemsForSyncParts( ItemContainer& aItems, std::set<wxString>& parts
|
||||
PCB_GROUP* group = static_cast<PCB_GROUP*>( item );
|
||||
|
||||
collectItemsForSyncParts( group->GetItems(), parts );
|
||||
|
||||
break;
|
||||
}
|
||||
case PCB_FOOTPRINT_T:
|
||||
@ -330,7 +329,6 @@ void collectItemsForSyncParts( ItemContainer& aItems, std::set<wxString>& parts
|
||||
wxString ref = footprint->GetReference();
|
||||
|
||||
parts.emplace( wxT( "F" ) + EscapeString( ref, CTX_IPC ) );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -341,7 +339,6 @@ void collectItemsForSyncParts( ItemContainer& aItems, std::set<wxString>& parts
|
||||
|
||||
parts.emplace( wxT( "P" ) + EscapeString( ref, CTX_IPC ) + wxT( "/" )
|
||||
+ EscapeString( pad->GetNumber(), CTX_IPC ) );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -139,15 +139,18 @@ void DIALOG_CLEANUP_GRAPHICS::doCleanup( bool aDryRun )
|
||||
|
||||
void DIALOG_CLEANUP_GRAPHICS::OnSelectItem( wxDataViewEvent& aEvent )
|
||||
{
|
||||
const KIID& itemID = RC_TREE_MODEL::ToUUID( aEvent.GetItem() );
|
||||
BOARD_ITEM* item = m_parentFrame->GetBoard()->GetItem( itemID );
|
||||
WINDOW_THAWER thawer( m_parentFrame );
|
||||
const KIID& itemID = RC_TREE_MODEL::ToUUID( aEvent.GetItem() );
|
||||
|
||||
if( item && !item->GetLayerSet().test( m_parentFrame->GetActiveLayer() ) )
|
||||
m_parentFrame->SetActiveLayer( item->GetLayerSet().UIOrder().front() );
|
||||
if( BOARD_ITEM* item = m_parentFrame->GetBoard()->ResolveItem( itemID, true ) )
|
||||
{
|
||||
WINDOW_THAWER thawer( m_parentFrame );
|
||||
|
||||
m_parentFrame->FocusOnItem( item );
|
||||
m_parentFrame->GetCanvas()->Refresh();
|
||||
if( !item->GetLayerSet().test( m_parentFrame->GetActiveLayer() ) )
|
||||
m_parentFrame->SetActiveLayer( item->GetLayerSet().UIOrder().front() );
|
||||
|
||||
m_parentFrame->FocusOnItem( item );
|
||||
m_parentFrame->GetCanvas()->Refresh();
|
||||
}
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
@ -313,12 +313,15 @@ void DIALOG_CLEANUP_TRACKS_AND_VIAS::doCleanup( bool aDryRun )
|
||||
|
||||
void DIALOG_CLEANUP_TRACKS_AND_VIAS::OnSelectItem( wxDataViewEvent& aEvent )
|
||||
{
|
||||
const KIID& itemID = RC_TREE_MODEL::ToUUID( aEvent.GetItem() );
|
||||
BOARD_ITEM* item = m_brd->GetItem( itemID );
|
||||
WINDOW_THAWER thawer( m_parentFrame );
|
||||
const KIID& itemID = RC_TREE_MODEL::ToUUID( aEvent.GetItem() );
|
||||
|
||||
m_parentFrame->FocusOnItem( item );
|
||||
m_parentFrame->GetCanvas()->Refresh();
|
||||
if( BOARD_ITEM* item = m_brd->ResolveItem( itemID, true ) )
|
||||
{
|
||||
WINDOW_THAWER thawer( m_parentFrame );
|
||||
|
||||
m_parentFrame->FocusOnItem( item );
|
||||
m_parentFrame->GetCanvas()->Refresh();
|
||||
}
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
@ -462,22 +462,21 @@ void DIALOG_DRC::OnDRCItemSelected( wxDataViewEvent& aEvent )
|
||||
}
|
||||
|
||||
const KIID& itemID = RC_TREE_MODEL::ToUUID( aEvent.GetItem() );
|
||||
BOARD_ITEM* item = board->GetItem( itemID );
|
||||
BOARD_ITEM* item = board->ResolveItem( itemID, true );
|
||||
|
||||
if( !item || item == DELETED_BOARD_ITEM::GetInstance() )
|
||||
if( item )
|
||||
{
|
||||
// nothing to highlight / focus on
|
||||
|
||||
aEvent.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
PCB_LAYER_ID principalLayer;
|
||||
LSET violationLayers;
|
||||
BOARD_ITEM* a = board->GetItem( rc_item->GetMainItemID() );
|
||||
BOARD_ITEM* b = board->GetItem( rc_item->GetAuxItemID() );
|
||||
BOARD_ITEM* c = board->GetItem( rc_item->GetAuxItem2ID() );
|
||||
BOARD_ITEM* d = board->GetItem( rc_item->GetAuxItem3ID() );
|
||||
BOARD_ITEM* a = board->ResolveItem( rc_item->GetMainItemID(), true );
|
||||
BOARD_ITEM* b = board->ResolveItem( rc_item->GetAuxItemID(), true );
|
||||
BOARD_ITEM* c = board->ResolveItem( rc_item->GetAuxItem2ID(), true );
|
||||
BOARD_ITEM* d = board->ResolveItem( rc_item->GetAuxItem3ID(), true );
|
||||
|
||||
if( rc_item->GetErrorCode() == DRCE_MALFORMED_COURTYARD )
|
||||
{
|
||||
@ -491,7 +490,7 @@ void DIALOG_DRC::OnDRCItemSelected( wxDataViewEvent& aEvent )
|
||||
principalLayer = F_CrtYd;
|
||||
}
|
||||
}
|
||||
else if (rc_item->GetErrorCode() == DRCE_INVALID_OUTLINE )
|
||||
else if( rc_item->GetErrorCode() == DRCE_INVALID_OUTLINE )
|
||||
{
|
||||
principalLayer = Edge_Cuts;
|
||||
}
|
||||
@ -596,7 +595,7 @@ void DIALOG_DRC::OnDRCItemSelected( wxDataViewEvent& aEvent )
|
||||
|
||||
for( const KIID& id : rc_item->GetIDs() )
|
||||
{
|
||||
auto* candidate = dynamic_cast<BOARD_CONNECTED_ITEM*>( board->GetItem( id ) );
|
||||
auto* candidate = dynamic_cast<BOARD_CONNECTED_ITEM*>( board->ResolveItem( id, true ) );
|
||||
|
||||
if( candidate && candidate->GetNetCode() == net )
|
||||
items.push_back( candidate );
|
||||
|
@ -235,7 +235,7 @@ void DIALOG_FOOTPRINT_CHECKER::OnSelectItem( wxDataViewEvent& aEvent )
|
||||
BOARD* board = m_frame->GetBoard();
|
||||
RC_TREE_NODE* node = RC_TREE_MODEL::ToNode( aEvent.GetItem() );
|
||||
const KIID& itemID = node ? RC_TREE_MODEL::ToUUID( aEvent.GetItem() ) : niluuid;
|
||||
BOARD_ITEM* item = board->GetItem( itemID );
|
||||
BOARD_ITEM* item = board->ResolveItem( itemID, true );
|
||||
|
||||
if( m_centerMarkerOnIdle )
|
||||
{
|
||||
@ -257,7 +257,7 @@ void DIALOG_FOOTPRINT_CHECKER::OnSelectItem( wxDataViewEvent& aEvent )
|
||||
|
||||
if( rc_item->GetErrorCode() == DRCE_MALFORMED_COURTYARD )
|
||||
{
|
||||
BOARD_ITEM* a = board->GetItem( rc_item->GetMainItemID() );
|
||||
BOARD_ITEM* a = board->ResolveItem( rc_item->GetMainItemID(), true );
|
||||
|
||||
if( a && ( a->GetFlags() & MALFORMED_B_COURTYARD ) > 0
|
||||
&& ( a->GetFlags() & MALFORMED_F_COURTYARD ) == 0 )
|
||||
@ -275,10 +275,10 @@ void DIALOG_FOOTPRINT_CHECKER::OnSelectItem( wxDataViewEvent& aEvent )
|
||||
}
|
||||
else
|
||||
{
|
||||
BOARD_ITEM* a = board->GetItem( rc_item->GetMainItemID() );
|
||||
BOARD_ITEM* b = board->GetItem( rc_item->GetAuxItemID() );
|
||||
BOARD_ITEM* c = board->GetItem( rc_item->GetAuxItem2ID() );
|
||||
BOARD_ITEM* d = board->GetItem( rc_item->GetAuxItem3ID() );
|
||||
BOARD_ITEM* a = board->ResolveItem( rc_item->GetMainItemID(), true );
|
||||
BOARD_ITEM* b = board->ResolveItem( rc_item->GetAuxItemID(), true );
|
||||
BOARD_ITEM* c = board->ResolveItem( rc_item->GetAuxItem2ID(), true );
|
||||
BOARD_ITEM* d = board->ResolveItem( rc_item->GetAuxItem3ID(), true );
|
||||
|
||||
if( a || b || c || d )
|
||||
violationLayers = LSET::AllLayersMask();
|
||||
|
@ -410,7 +410,7 @@ void DIALOG_GENERATORS::OnItemSelected( wxDataViewEvent& aEvent )
|
||||
wxVariant var;
|
||||
model->GetValue( var, viewItem, uuidCol );
|
||||
|
||||
BOARD_ITEM* brdItem = m_currentBoard->GetItem( var.GetString() );
|
||||
BOARD_ITEM* brdItem = m_currentBoard->ResolveItem( var.GetString() );
|
||||
|
||||
if( !brdItem || brdItem->Type() != KICAD_T::PCB_GENERATOR_T )
|
||||
continue;
|
||||
@ -447,7 +447,7 @@ void DIALOG_GENERATORS::OnRebuildTypeClick( wxCommandEvent& event )
|
||||
wxVariant var;
|
||||
model->GetValueByRow( var, row, uuidCol );
|
||||
|
||||
BOARD_ITEM* item = m_currentBoard->GetItem( var.GetString() );
|
||||
BOARD_ITEM* item = m_currentBoard->ResolveItem( var.GetString() );
|
||||
|
||||
if( !item || item->Type() != KICAD_T::PCB_GENERATOR_T )
|
||||
continue;
|
||||
|
@ -134,12 +134,7 @@ void DIALOG_GLOBAL_DELETION::DoGlobalDeletions()
|
||||
[&]( BOARD_ITEM* item, const LSET& layers_mask )
|
||||
{
|
||||
if( ( item->GetLayerSet() & layers_mask ).any() )
|
||||
{
|
||||
if( item->GetParentGroup() )
|
||||
commit.Stage( item, CHT_UNGROUP );
|
||||
|
||||
commit.Remove( item );
|
||||
}
|
||||
};
|
||||
|
||||
auto processConnectedItem =
|
||||
@ -147,9 +142,6 @@ void DIALOG_GLOBAL_DELETION::DoGlobalDeletions()
|
||||
{
|
||||
if( ( item->GetLayerSet() & layers_mask ).any() )
|
||||
{
|
||||
if( item->GetParentGroup() )
|
||||
commit.Stage( item, CHT_UNGROUP );
|
||||
|
||||
commit.Remove( item );
|
||||
gen_rastnest = true;
|
||||
}
|
||||
|
@ -291,10 +291,6 @@ DIALOG_PAD_PROPERTIES::~DIALOG_PAD_PROPERTIES()
|
||||
|
||||
m_page = m_notebook->GetSelection();
|
||||
|
||||
// Remove the preview pad from the group of the actual pad before deletion
|
||||
if( m_previewPad )
|
||||
m_previewPad->SetParentGroup( nullptr );
|
||||
|
||||
delete m_previewPad;
|
||||
delete m_axisOrigin;
|
||||
}
|
||||
|
@ -845,9 +845,6 @@ DIALOG_SHAPE_PROPERTIES::DIALOG_SHAPE_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent,
|
||||
m_solderMaskMargin( aParent, m_solderMaskMarginLabel, m_solderMaskMarginCtrl, m_solderMaskMarginUnit ),
|
||||
m_workingCopy( *m_item )
|
||||
{
|
||||
m_workingCopy.SetParentGroup( nullptr );
|
||||
m_workingCopy.SetParent( nullptr );
|
||||
|
||||
SetTitle( wxString::Format( GetTitle(), m_item->GetFriendlyName() ) );
|
||||
m_hash_key = TO_UTF8( GetTitle() );
|
||||
|
||||
@ -1135,10 +1132,6 @@ bool DIALOG_SHAPE_PROPERTIES::TransferDataFromWindow()
|
||||
if( !pushCommit )
|
||||
m_item->SetFlags( IN_EDIT );
|
||||
|
||||
// Ensure parent and parent group item are restored. m_workingCopy had previously
|
||||
// these parents cleared and not restored for some PCB_SHAPE types (i.e. POLY)
|
||||
m_workingCopy.SetParentGroup( m_item->GetParentGroup() );
|
||||
m_workingCopy.SetParent( m_item->GetParent() );
|
||||
*m_item = m_workingCopy;
|
||||
|
||||
bool wasLocked = m_item->IsLocked();
|
||||
|
@ -194,22 +194,18 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
|
||||
edges.back()->SetShape( SHAPE_T::SEGMENT );
|
||||
edges.back()->SetEndX( shape->GetStartX() );
|
||||
edges.back()->SetStroke( stroke );
|
||||
edges.back()->SetParentGroup( nullptr );
|
||||
edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
|
||||
edges.back()->SetShape( SHAPE_T::SEGMENT );
|
||||
edges.back()->SetEndY( shape->GetStartY() );
|
||||
edges.back()->SetStroke( stroke );
|
||||
edges.back()->SetParentGroup( nullptr );
|
||||
edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
|
||||
edges.back()->SetShape( SHAPE_T::SEGMENT );
|
||||
edges.back()->SetStartX( shape->GetEndX() );
|
||||
edges.back()->SetStroke( stroke );
|
||||
edges.back()->SetParentGroup( nullptr );
|
||||
edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
|
||||
edges.back()->SetShape( SHAPE_T::SEGMENT );
|
||||
edges.back()->SetStartY( shape->GetEndY() );
|
||||
edges.back()->SetStroke( stroke );
|
||||
edges.back()->SetParentGroup( nullptr );
|
||||
}
|
||||
else if( shape->GetShape() == SHAPE_T::POLY && !shape->IsSolidFill() )
|
||||
{
|
||||
@ -225,14 +221,12 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
|
||||
edges.back()->SetStart( seg.A );
|
||||
edges.back()->SetEnd( seg.B );
|
||||
edges.back()->SetStroke( stroke );
|
||||
edges.back()->SetParentGroup( nullptr );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
|
||||
edges.back()->SetStroke( stroke );
|
||||
edges.back()->SetParentGroup( nullptr );
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -155,8 +155,7 @@ void PCB_EDIT_FRAME::OnEditItemRequest( BOARD_ITEM* aItem )
|
||||
break;
|
||||
|
||||
case PCB_GROUP_T:
|
||||
m_toolManager->RunAction( ACTIONS::groupProperties,
|
||||
static_cast<EDA_GROUP*>( static_cast<PCB_GROUP*>( aItem ) ) );
|
||||
m_toolManager->RunAction( ACTIONS::groupProperties, static_cast<PCB_GROUP*>( aItem ) );
|
||||
break;
|
||||
|
||||
case PCB_GENERATOR_T:
|
||||
|
@ -233,13 +233,6 @@ FOOTPRINT::FOOTPRINT( FOOTPRINT&& aFootprint ) :
|
||||
|
||||
FOOTPRINT::~FOOTPRINT()
|
||||
{
|
||||
// Untangle group parents before doing any deleting
|
||||
for( PCB_GROUP* group : m_groups )
|
||||
{
|
||||
for( EDA_ITEM* item : group->GetItems() )
|
||||
item->SetParentGroup( nullptr );
|
||||
}
|
||||
|
||||
// Clean up the owned elements
|
||||
delete m_initial_comments;
|
||||
|
||||
@ -1213,11 +1206,6 @@ void FOOTPRINT::Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aMode )
|
||||
}
|
||||
|
||||
aBoardItem->SetFlags( STRUCT_DELETED );
|
||||
|
||||
EDA_GROUP* parentGroup = aBoardItem->GetParentGroup();
|
||||
|
||||
if( parentGroup && !( parentGroup->AsEdaItem()->GetFlags() & STRUCT_DELETED ) )
|
||||
parentGroup->RemoveItem( aBoardItem );
|
||||
}
|
||||
|
||||
|
||||
@ -1313,10 +1301,6 @@ BOX2I FOOTPRINT::GetFpPadsLocalBbox() const
|
||||
for( PAD* pad : dummy.Pads() )
|
||||
bbox.Merge( pad->GetBoundingBox() );
|
||||
|
||||
// Remove the parent and the group from the dummy footprint before deletion
|
||||
dummy.SetParent( nullptr );
|
||||
dummy.SetParentGroup( nullptr );
|
||||
|
||||
return bbox;
|
||||
}
|
||||
|
||||
@ -2569,9 +2553,9 @@ void FOOTPRINT::SetOrientation( const EDA_ANGLE& aNewAngle )
|
||||
}
|
||||
|
||||
|
||||
BOARD_ITEM* FOOTPRINT::Duplicate() const
|
||||
BOARD_ITEM* FOOTPRINT::Duplicate( bool addToParentGroup, BOARD_COMMIT* aCommit ) const
|
||||
{
|
||||
FOOTPRINT* dupe = static_cast<FOOTPRINT*>( BOARD_ITEM::Duplicate() );
|
||||
FOOTPRINT* dupe = static_cast<FOOTPRINT*>( BOARD_ITEM::Duplicate( addToParentGroup, aCommit ) );
|
||||
|
||||
dupe->RunOnChildren( [&]( BOARD_ITEM* child )
|
||||
{
|
||||
@ -2583,7 +2567,8 @@ BOARD_ITEM* FOOTPRINT::Duplicate() const
|
||||
}
|
||||
|
||||
|
||||
BOARD_ITEM* FOOTPRINT::DuplicateItem( const BOARD_ITEM* aItem, bool aAddToFootprint )
|
||||
BOARD_ITEM* FOOTPRINT::DuplicateItem( bool addToParentGroup, BOARD_COMMIT* aCommit,
|
||||
const BOARD_ITEM* aItem, bool addToFootprint )
|
||||
{
|
||||
BOARD_ITEM* new_item = nullptr;
|
||||
|
||||
@ -2594,7 +2579,7 @@ BOARD_ITEM* FOOTPRINT::DuplicateItem( const BOARD_ITEM* aItem, bool aAddToFootpr
|
||||
PAD* new_pad = new PAD( *static_cast<const PAD*>( aItem ) );
|
||||
const_cast<KIID&>( new_pad->m_Uuid ) = KIID();
|
||||
|
||||
if( aAddToFootprint )
|
||||
if( addToFootprint )
|
||||
m_pads.push_back( new_pad );
|
||||
|
||||
new_item = new_pad;
|
||||
@ -2606,7 +2591,7 @@ BOARD_ITEM* FOOTPRINT::DuplicateItem( const BOARD_ITEM* aItem, bool aAddToFootpr
|
||||
ZONE* new_zone = new ZONE( *static_cast<const ZONE*>( aItem ) );
|
||||
const_cast<KIID&>( new_zone->m_Uuid ) = KIID();
|
||||
|
||||
if( aAddToFootprint )
|
||||
if( addToFootprint )
|
||||
m_zones.push_back( new_zone );
|
||||
|
||||
new_item = new_zone;
|
||||
@ -2626,11 +2611,11 @@ BOARD_ITEM* FOOTPRINT::DuplicateItem( const BOARD_ITEM* aItem, bool aAddToFootpr
|
||||
case FIELD_T::REFERENCE: new_text->SetText( wxT( "${REFERENCE}" ) ); break;
|
||||
case FIELD_T::VALUE: new_text->SetText( wxT( "${VALUE}" ) ); break;
|
||||
case FIELD_T::DATASHEET: new_text->SetText( wxT( "${DATASHEET}" ) ); break;
|
||||
default: break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
if( aAddToFootprint )
|
||||
if( addToFootprint )
|
||||
Add( new_text );
|
||||
|
||||
new_item = new_text;
|
||||
@ -2642,7 +2627,7 @@ BOARD_ITEM* FOOTPRINT::DuplicateItem( const BOARD_ITEM* aItem, bool aAddToFootpr
|
||||
PCB_SHAPE* new_shape = new PCB_SHAPE( *static_cast<const PCB_SHAPE*>( aItem ) );
|
||||
const_cast<KIID&>( new_shape->m_Uuid ) = KIID();
|
||||
|
||||
if( aAddToFootprint )
|
||||
if( addToFootprint )
|
||||
Add( new_shape );
|
||||
|
||||
new_item = new_shape;
|
||||
@ -2654,7 +2639,7 @@ BOARD_ITEM* FOOTPRINT::DuplicateItem( const BOARD_ITEM* aItem, bool aAddToFootpr
|
||||
PCB_TEXTBOX* new_textbox = new PCB_TEXTBOX( *static_cast<const PCB_TEXTBOX*>( aItem ) );
|
||||
const_cast<KIID&>( new_textbox->m_Uuid ) = KIID();
|
||||
|
||||
if( aAddToFootprint )
|
||||
if( addToFootprint )
|
||||
Add( new_textbox );
|
||||
|
||||
new_item = new_textbox;
|
||||
@ -2667,9 +2652,10 @@ BOARD_ITEM* FOOTPRINT::DuplicateItem( const BOARD_ITEM* aItem, bool aAddToFootpr
|
||||
case PCB_DIM_RADIAL_T:
|
||||
case PCB_DIM_ORTHOGONAL_T:
|
||||
{
|
||||
PCB_DIMENSION_BASE* dimension = static_cast<PCB_DIMENSION_BASE*>( aItem->Duplicate() );
|
||||
PCB_DIMENSION_BASE* dimension = static_cast<PCB_DIMENSION_BASE*>( aItem->Duplicate( addToParentGroup,
|
||||
aCommit ) );
|
||||
|
||||
if( aAddToFootprint )
|
||||
if( addToFootprint )
|
||||
Add( dimension );
|
||||
|
||||
new_item = dimension;
|
||||
@ -2678,9 +2664,9 @@ BOARD_ITEM* FOOTPRINT::DuplicateItem( const BOARD_ITEM* aItem, bool aAddToFootpr
|
||||
|
||||
case PCB_GROUP_T:
|
||||
{
|
||||
PCB_GROUP* group = static_cast<const PCB_GROUP*>( aItem )->DeepDuplicate();
|
||||
PCB_GROUP* group = static_cast<const PCB_GROUP*>( aItem )->DeepDuplicate( addToParentGroup, aCommit );
|
||||
|
||||
if( aAddToFootprint )
|
||||
if( addToFootprint )
|
||||
{
|
||||
group->RunOnChildren(
|
||||
[&]( BOARD_ITEM* aCurrItem )
|
||||
|
@ -846,14 +846,15 @@ public:
|
||||
KIID GetLink() const { return m_link; }
|
||||
void SetLink( const KIID& aLink ) { m_link = aLink; }
|
||||
|
||||
BOARD_ITEM* Duplicate() const override;
|
||||
BOARD_ITEM* Duplicate( bool addToParentGroup, BOARD_COMMIT* aCommit = nullptr ) const override;
|
||||
|
||||
/**
|
||||
* Duplicate a given item within the footprint, optionally adding it to the board.
|
||||
*
|
||||
* @return the new item, or NULL if the item could not be duplicated.
|
||||
*/
|
||||
BOARD_ITEM* DuplicateItem( const BOARD_ITEM* aItem, bool aAddToFootprint = false );
|
||||
BOARD_ITEM* DuplicateItem( bool addToParentGroup, BOARD_COMMIT* aCommit, const BOARD_ITEM* aItem,
|
||||
bool addToFootprint = false );
|
||||
|
||||
/**
|
||||
* Add \a a3DModel definition to the end of the 3D model list.
|
||||
|
@ -244,8 +244,7 @@ void FOOTPRINT_EDIT_FRAME::OnEditItemRequest( BOARD_ITEM* aItem )
|
||||
}
|
||||
|
||||
case PCB_GROUP_T:
|
||||
m_toolManager->RunAction( ACTIONS::groupProperties,
|
||||
static_cast<EDA_GROUP*>( static_cast<PCB_GROUP*>( aItem ) ) );
|
||||
m_toolManager->RunAction( ACTIONS::groupProperties, static_cast<PCB_GROUP*>( aItem ) );
|
||||
break;
|
||||
|
||||
case PCB_MARKER_T:
|
||||
|
@ -636,7 +636,7 @@ void PCB_EDIT_FRAME::ExportFootprintsToLibrary( bool aStoreInNewLib, const wxStr
|
||||
|
||||
if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
|
||||
{
|
||||
FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate() );
|
||||
FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate( IGNORE_PARENT_GROUP ) );
|
||||
|
||||
// Reset reference designator and group membership before saving
|
||||
resetReference( fpCopy );
|
||||
@ -694,7 +694,7 @@ void PCB_EDIT_FRAME::ExportFootprintsToLibrary( bool aStoreInNewLib, const wxStr
|
||||
{
|
||||
if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
|
||||
{
|
||||
FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate() );
|
||||
FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate( IGNORE_PARENT_GROUP ) );
|
||||
|
||||
// Reset reference designator and group membership before saving
|
||||
resetReference( fpCopy );
|
||||
@ -743,10 +743,8 @@ bool FOOTPRINT_EDIT_FRAME::SaveFootprint( FOOTPRINT* aFootprint )
|
||||
m_footprintNameWhenLoaded = footprintName;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else if( libraryName.IsEmpty() || footprintName.IsEmpty() )
|
||||
{
|
||||
@ -756,10 +754,8 @@ bool FOOTPRINT_EDIT_FRAME::SaveFootprint( FOOTPRINT* aFootprint )
|
||||
SyncLibraryTree( true );
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
FP_LIB_TABLE* tbl = PROJECT_PCB::PcbFootprintLibs( &Prj() );
|
||||
|
@ -182,7 +182,7 @@ bool FOOTPRINT_PREVIEW_PANEL::DisplayFootprint( const LIB_ID& aFPID )
|
||||
aFPID.GetLibItemName() );
|
||||
|
||||
if( fp )
|
||||
m_currentFootprint.reset( static_cast<FOOTPRINT*>( fp->Duplicate() ) );
|
||||
m_currentFootprint.reset( static_cast<FOOTPRINT*>( fp->Duplicate( IGNORE_PARENT_GROUP ) ) );
|
||||
else
|
||||
m_currentFootprint.reset();
|
||||
}
|
||||
|
@ -757,7 +757,7 @@ void FOOTPRINT_VIEWER_FRAME::AddFootprintToPCB()
|
||||
BOARD_COMMIT commit( pcbframe );
|
||||
|
||||
// Create the "new" footprint
|
||||
FOOTPRINT* newFootprint = (FOOTPRINT*) GetBoard()->GetFirstFootprint()->Duplicate();
|
||||
FOOTPRINT* newFootprint = (FOOTPRINT*) GetBoard()->GetFirstFootprint()->Duplicate( IGNORE_PARENT_GROUP );
|
||||
newFootprint->SetParent( pcbframe->GetBoard() );
|
||||
newFootprint->SetLink( niluuid );
|
||||
newFootprint->SetFlags(IS_NEW ); // whatever
|
||||
|
@ -1225,17 +1225,6 @@ void PCB_TUNING_PATTERN::Remove( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COM
|
||||
PNS::ROUTER* router = aTool->Router();
|
||||
PNS_KICAD_IFACE* iface = aTool->GetInterface();
|
||||
|
||||
// Ungroup first so that undo works
|
||||
if( !GetItems().empty() )
|
||||
{
|
||||
PCB_GENERATOR* group = this;
|
||||
|
||||
for( EDA_ITEM* member : group->GetItems() )
|
||||
aCommit->Stage( member, CHT_UNGROUP );
|
||||
|
||||
group->GetItems().clear();
|
||||
}
|
||||
|
||||
aCommit->Remove( this );
|
||||
|
||||
aTool->ClearRouterChanges();
|
||||
@ -1637,7 +1626,6 @@ void PCB_TUNING_PATTERN::EditPush( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_C
|
||||
&& bounds.PointInside( track->GetEnd(), epsilon ) )
|
||||
{
|
||||
AddItem( item );
|
||||
aCommit->Stage( item, CHT_GROUP );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -273,9 +273,10 @@ void CLIPBOARD_IO::SaveSelection( const PCB_SELECTION& aSelected, bool isFootpri
|
||||
// some PCB_TEXT (reference and value) cannot be added to the footprint
|
||||
std::vector<BOARD_ITEM*> skipped_items;
|
||||
|
||||
if( copy->Type() == PCB_GROUP_T || copy->Type() == PCB_GENERATOR_T )
|
||||
// Will catch at least PCB_GROUP_T and PCB_GENERATOR_T
|
||||
if( PCB_GROUP* group = dynamic_cast<PCB_GROUP*>( copy ) )
|
||||
{
|
||||
copy->RunOnChildren(
|
||||
group->RunOnChildren(
|
||||
[&]( BOARD_ITEM* descendant )
|
||||
{
|
||||
// One cannot add an additional mandatory field to a given footprint:
|
||||
|
@ -864,9 +864,8 @@ bool BOARD_NETLIST_UPDATER::updateFootprintGroup( FOOTPRINT* aPcbFootprint,
|
||||
EscapeHTML( existingGroup->GetName() ) );
|
||||
|
||||
changed = true;
|
||||
m_commit.Modify( aPcbFootprint->GetParentGroup()->AsEdaItem() );
|
||||
aPcbFootprint->GetParentGroup()->RemoveItem( aPcbFootprint );
|
||||
aPcbFootprint->SetParentGroup( nullptr );
|
||||
m_commit.Modify( existingGroup );
|
||||
existingGroup->RemoveItem( aPcbFootprint );
|
||||
}
|
||||
|
||||
m_reporter->Report( msg, RPT_SEVERITY_ACTION );
|
||||
@ -906,7 +905,6 @@ bool BOARD_NETLIST_UPDATER::updateFootprintGroup( FOOTPRINT* aPcbFootprint,
|
||||
}
|
||||
|
||||
newGroup->AddItem( aPcbFootprint );
|
||||
aPcbFootprint->SetParentGroup( newGroup );
|
||||
}
|
||||
|
||||
m_reporter->Report( msg, RPT_SEVERITY_ACTION );
|
||||
@ -1624,9 +1622,6 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
|
||||
}
|
||||
else
|
||||
{
|
||||
if( footprint->GetParentGroup() )
|
||||
m_commit.Stage( footprint, CHT_UNGROUP );
|
||||
|
||||
m_commit.Remove( footprint );
|
||||
msg.Printf( _( "Removed unused footprint %s." ),
|
||||
footprint->GetReference() );
|
||||
|
@ -2190,7 +2190,7 @@ std::vector<PCB_SHAPE*> PAD::Recombine( bool aIsDryRun, int maxError )
|
||||
if( EDA_GROUP* group = fpShape->GetParentGroup(); group )
|
||||
group->RemoveItem( fpShape );
|
||||
|
||||
PCB_SHAPE* primitive = static_cast<PCB_SHAPE*>( fpShape->Duplicate() );
|
||||
PCB_SHAPE* primitive = static_cast<PCB_SHAPE*>( fpShape->Duplicate( IGNORE_PARENT_GROUP ) );
|
||||
|
||||
primitive->SetParent( nullptr );
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user