Implement groups for modedit.
This uncovered a memory corruption bug in MODULE's move operator, several bugs in MODULE's move and copy constructors, and a bug in BOARD's GetItem() call. It also bumps the file format for saving/restoring groups inside footprints.
This commit is contained in:
parent
e76736b7bf
commit
ba26e056ec
|
@ -117,24 +117,6 @@ private:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Function getAllGroups()
|
|
||||||
* Returns all group ids for the item (collected from all layers the item occupies).
|
|
||||||
*
|
|
||||||
* @return vector of group ids.
|
|
||||||
*/
|
|
||||||
std::vector<int> getAllGroups() const
|
|
||||||
{
|
|
||||||
std::vector<int> groups( m_groupsSize );
|
|
||||||
|
|
||||||
for( int i = 0; i < m_groupsSize; ++i )
|
|
||||||
{
|
|
||||||
groups[i] = m_groups[i].second;
|
|
||||||
}
|
|
||||||
|
|
||||||
return groups;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function setGroup()
|
* Function setGroup()
|
||||||
* Sets a group id for the item and the layer combination.
|
* Sets a group id for the item and the layer combination.
|
||||||
|
|
|
@ -51,7 +51,7 @@ class VIEW;
|
||||||
class PCB_GROUP : public BOARD_ITEM
|
class PCB_GROUP : public BOARD_ITEM
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PCB_GROUP( BOARD* aParent );
|
PCB_GROUP( BOARD_ITEM* aParent );
|
||||||
|
|
||||||
static inline bool ClassOf( const EDA_ITEM* aItem )
|
static inline bool ClassOf( const EDA_ITEM* aItem )
|
||||||
{
|
{
|
||||||
|
|
|
@ -791,6 +791,18 @@ BOARD_ITEM* BOARD::GetItem( const KIID& aID ) const
|
||||||
if( drawing->m_Uuid == aID )
|
if( drawing->m_Uuid == aID )
|
||||||
return drawing;
|
return drawing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for( BOARD_ITEM* zone : module->Zones() )
|
||||||
|
{
|
||||||
|
if( zone->m_Uuid == aID )
|
||||||
|
return zone;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( PCB_GROUP* group : module->Groups() )
|
||||||
|
{
|
||||||
|
if( group->m_Uuid == aID )
|
||||||
|
return group;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for( ZONE_CONTAINER* zone : Zones() )
|
for( ZONE_CONTAINER* zone : Zones() )
|
||||||
|
|
|
@ -92,36 +92,48 @@ MODULE::MODULE( const MODULE& aModule ) :
|
||||||
m_Value = new TEXTE_MODULE( *aModule.m_Value );
|
m_Value = new TEXTE_MODULE( *aModule.m_Value );
|
||||||
m_Value->SetParent( this );
|
m_Value->SetParent( this );
|
||||||
|
|
||||||
// Copy auxiliary data: Pads
|
std::map<BOARD_ITEM*, BOARD_ITEM*> ptrMap;
|
||||||
for( D_PAD* pad : aModule.Pads() )
|
|
||||||
Add( static_cast<D_PAD*>( pad->Clone() ) );
|
|
||||||
|
|
||||||
// Copy auxiliary data: Zones
|
// Copy pads
|
||||||
for( MODULE_ZONE_CONTAINER* item : aModule.Zones() )
|
for( D_PAD* pad : aModule.Pads() )
|
||||||
{
|
{
|
||||||
Add( static_cast<MODULE_ZONE_CONTAINER*>( item->Clone() ) );
|
D_PAD* newPad = static_cast<D_PAD*>( pad->Clone() );
|
||||||
|
ptrMap[ pad ] = newPad;
|
||||||
|
Add( newPad );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy zones
|
||||||
|
for( MODULE_ZONE_CONTAINER* zone : aModule.Zones() )
|
||||||
|
{
|
||||||
|
MODULE_ZONE_CONTAINER* newZone = static_cast<MODULE_ZONE_CONTAINER*>( zone->Clone() );
|
||||||
|
ptrMap[ zone ] = newZone;
|
||||||
|
Add( newZone );
|
||||||
|
|
||||||
// Ensure the net info is OK and especially uses the net info list
|
// Ensure the net info is OK and especially uses the net info list
|
||||||
// living in the current board
|
// living in the current board
|
||||||
// Needed when copying a fp from fp editor that has its own board
|
// Needed when copying a fp from fp editor that has its own board
|
||||||
// Must be NETINFO_LIST::ORPHANED_ITEM for a keepout that has no net.
|
// Must be NETINFO_LIST::ORPHANED_ITEM for a keepout that has no net.
|
||||||
item->SetNetCode( -1 );
|
newZone->SetNetCode( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy auxiliary data: Drawings
|
// Copy drawings
|
||||||
for( BOARD_ITEM* item : aModule.GraphicalItems() )
|
for( BOARD_ITEM* item : aModule.GraphicalItems() )
|
||||||
{
|
{
|
||||||
switch( item->Type() )
|
BOARD_ITEM* newItem = static_cast<BOARD_ITEM*>( item->Clone() );
|
||||||
{
|
ptrMap[ item ] = newItem;
|
||||||
case PCB_MODULE_TEXT_T:
|
Add( newItem );
|
||||||
case PCB_MODULE_EDGE_T:
|
}
|
||||||
Add( static_cast<BOARD_ITEM*>( item->Clone() ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
// Copy groups
|
||||||
wxLogMessage( wxT( "Class MODULE copy constructor internal error: unknown type" ) );
|
for( PCB_GROUP* group : aModule.Groups() )
|
||||||
break;
|
{
|
||||||
}
|
PCB_GROUP* newGroup = static_cast<PCB_GROUP*>( group->Clone() );
|
||||||
|
const_cast<std::unordered_set<BOARD_ITEM*>*>( &newGroup->GetItems() )->clear();
|
||||||
|
|
||||||
|
for( BOARD_ITEM* member : group->GetItems() )
|
||||||
|
newGroup->AddItem( ptrMap[ member ] );
|
||||||
|
|
||||||
|
Add( newGroup );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy auxiliary data: 3D_Drawings info
|
// Copy auxiliary data: 3D_Drawings info
|
||||||
|
@ -160,11 +172,16 @@ MODULE::~MODULE()
|
||||||
|
|
||||||
m_pads.clear();
|
m_pads.clear();
|
||||||
|
|
||||||
for( MODULE_ZONE_CONTAINER* p : m_fp_zones )
|
for( MODULE_ZONE_CONTAINER* zone : m_fp_zones )
|
||||||
delete p;
|
delete zone;
|
||||||
|
|
||||||
m_fp_zones.clear();
|
m_fp_zones.clear();
|
||||||
|
|
||||||
|
for( PCB_GROUP* group : m_fp_groups )
|
||||||
|
delete group;
|
||||||
|
|
||||||
|
m_fp_groups.clear();
|
||||||
|
|
||||||
for( BOARD_ITEM* d : m_drawings )
|
for( BOARD_ITEM* d : m_drawings )
|
||||||
delete d;
|
delete d;
|
||||||
|
|
||||||
|
@ -209,12 +226,14 @@ MODULE& MODULE::operator=( MODULE&& aOther )
|
||||||
for( D_PAD* pad : aOther.Pads() )
|
for( D_PAD* pad : aOther.Pads() )
|
||||||
Add( pad );
|
Add( pad );
|
||||||
|
|
||||||
|
aOther.Pads().clear();
|
||||||
|
|
||||||
// Move the zones
|
// Move the zones
|
||||||
m_fp_zones.clear();
|
m_fp_zones.clear();
|
||||||
|
|
||||||
for( MODULE_ZONE_CONTAINER* item : aOther.Zones() )
|
for( MODULE_ZONE_CONTAINER* item : aOther.Zones() )
|
||||||
{
|
{
|
||||||
Add( static_cast<MODULE_ZONE_CONTAINER*>( item ) );
|
Add( item );
|
||||||
|
|
||||||
// Ensure the net info is OK and especially uses the net info list
|
// Ensure the net info is OK and especially uses the net info list
|
||||||
// living in the current board
|
// living in the current board
|
||||||
|
@ -223,23 +242,23 @@ MODULE& MODULE::operator=( MODULE&& aOther )
|
||||||
item->SetNetCode( -1 );
|
item->SetNetCode( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aOther.Zones().clear();
|
||||||
|
|
||||||
// Move the drawings
|
// Move the drawings
|
||||||
m_drawings.clear();
|
m_drawings.clear();
|
||||||
|
|
||||||
for( BOARD_ITEM* item : aOther.GraphicalItems() )
|
for( BOARD_ITEM* item : aOther.GraphicalItems() )
|
||||||
{
|
Add( item );
|
||||||
switch( item->Type() )
|
|
||||||
{
|
|
||||||
case PCB_MODULE_TEXT_T:
|
|
||||||
case PCB_MODULE_EDGE_T:
|
|
||||||
Add( static_cast<BOARD_ITEM*>( item ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
aOther.GraphicalItems().clear();
|
||||||
wxLogMessage( wxT( "MODULE::operator=() internal error: unknown type" ) );
|
|
||||||
break;
|
// Move the groups
|
||||||
}
|
m_fp_groups.clear();
|
||||||
}
|
|
||||||
|
for( PCB_GROUP* group : aOther.Groups() )
|
||||||
|
Add( group );
|
||||||
|
|
||||||
|
aOther.Groups().clear();
|
||||||
|
|
||||||
// Copy auxiliary data: 3D_Drawings info
|
// Copy auxiliary data: 3D_Drawings info
|
||||||
m_3D_Drawings.clear();
|
m_3D_Drawings.clear();
|
||||||
|
@ -295,42 +314,56 @@ MODULE& MODULE::operator=( const MODULE& aOther )
|
||||||
*m_Value = *aOther.m_Value;
|
*m_Value = *aOther.m_Value;
|
||||||
m_Value->SetParent( this );
|
m_Value->SetParent( this );
|
||||||
|
|
||||||
// Copy auxiliary data: Pads
|
std::map<BOARD_ITEM*, BOARD_ITEM*> ptrMap;
|
||||||
|
|
||||||
|
// Copy pads
|
||||||
m_pads.clear();
|
m_pads.clear();
|
||||||
|
|
||||||
for( D_PAD* pad : aOther.Pads() )
|
for( D_PAD* pad : aOther.Pads() )
|
||||||
Add( new D_PAD( *pad ) );
|
{
|
||||||
|
D_PAD* newPad = new D_PAD( *pad );
|
||||||
|
ptrMap[ pad ] = newPad;
|
||||||
|
Add( newPad );
|
||||||
|
}
|
||||||
|
|
||||||
// Copy auxiliary data: Zones
|
// Copy zones
|
||||||
m_fp_zones.clear();
|
m_fp_zones.clear();
|
||||||
|
|
||||||
for( MODULE_ZONE_CONTAINER* item : aOther.Zones() )
|
for( MODULE_ZONE_CONTAINER* zone : aOther.Zones() )
|
||||||
{
|
{
|
||||||
Add( static_cast<MODULE_ZONE_CONTAINER*>( item->Clone() ) );
|
MODULE_ZONE_CONTAINER* newZone = static_cast<MODULE_ZONE_CONTAINER*>( zone->Clone() );
|
||||||
|
ptrMap[ zone ] = newZone;
|
||||||
|
Add( newZone );
|
||||||
|
|
||||||
// Ensure the net info is OK and especially uses the net info list
|
// Ensure the net info is OK and especially uses the net info list
|
||||||
// living in the current board
|
// living in the current board
|
||||||
// Needed when copying a fp from fp editor that has its own board
|
// Needed when copying a fp from fp editor that has its own board
|
||||||
// Must be NETINFO_LIST::ORPHANED_ITEM for a keepout that has no net.
|
// Must be NETINFO_LIST::ORPHANED_ITEM for a keepout that has no net.
|
||||||
item->SetNetCode( -1 );
|
newZone->SetNetCode( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy auxiliary data: Drawings
|
// Copy drawings
|
||||||
m_drawings.clear();
|
m_drawings.clear();
|
||||||
|
|
||||||
for( BOARD_ITEM* item : aOther.GraphicalItems() )
|
for( BOARD_ITEM* item : aOther.GraphicalItems() )
|
||||||
{
|
{
|
||||||
switch( item->Type() )
|
BOARD_ITEM* newItem = static_cast<BOARD_ITEM*>( item->Clone() );
|
||||||
{
|
ptrMap[ item ] = newItem;
|
||||||
case PCB_MODULE_TEXT_T:
|
Add( newItem );
|
||||||
case PCB_MODULE_EDGE_T:
|
}
|
||||||
Add( static_cast<BOARD_ITEM*>( item->Clone() ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
// Copy groups
|
||||||
wxLogMessage( wxT( "MODULE::operator=() internal error: unknown type" ) );
|
m_fp_groups.clear();
|
||||||
break;
|
|
||||||
}
|
for( PCB_GROUP* group : aOther.Groups() )
|
||||||
|
{
|
||||||
|
PCB_GROUP* newGroup = static_cast<PCB_GROUP*>( group->Clone() );
|
||||||
|
const_cast<std::unordered_set<BOARD_ITEM*>*>( &newGroup->GetItems() )->clear();
|
||||||
|
|
||||||
|
for( BOARD_ITEM* member : group->GetItems() )
|
||||||
|
newGroup->AddItem( ptrMap[ member ] );
|
||||||
|
|
||||||
|
Add( newGroup );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy auxiliary data: 3D_Drawings info
|
// Copy auxiliary data: 3D_Drawings info
|
||||||
|
@ -424,6 +457,13 @@ void MODULE::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode )
|
||||||
m_fp_zones.insert( m_fp_zones.begin(), static_cast<MODULE_ZONE_CONTAINER*>( aBoardItem ) );
|
m_fp_zones.insert( m_fp_zones.begin(), static_cast<MODULE_ZONE_CONTAINER*>( aBoardItem ) );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PCB_GROUP_T:
|
||||||
|
if( aMode == ADD_MODE::APPEND )
|
||||||
|
m_fp_groups.push_back( static_cast<PCB_GROUP*>( aBoardItem ) );
|
||||||
|
else
|
||||||
|
m_fp_groups.insert( m_fp_groups.begin(), static_cast<PCB_GROUP*>( aBoardItem ) );
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
wxString msg;
|
wxString msg;
|
||||||
|
@ -487,6 +527,18 @@ void MODULE::Remove( BOARD_ITEM* aBoardItem )
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PCB_GROUP_T:
|
||||||
|
for( auto it = m_fp_groups.begin(); it != m_fp_groups.end(); ++it )
|
||||||
|
{
|
||||||
|
if( *it == static_cast<PCB_GROUP*>( aBoardItem ) )
|
||||||
|
{
|
||||||
|
m_fp_groups.erase( it );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
wxString msg;
|
wxString msg;
|
||||||
|
@ -532,6 +584,8 @@ EDA_RECT MODULE::GetFootprintRect() const
|
||||||
for( MODULE_ZONE_CONTAINER* zone : m_fp_zones )
|
for( MODULE_ZONE_CONTAINER* zone : m_fp_zones )
|
||||||
area.Merge( zone->GetBoundingBox() );
|
area.Merge( zone->GetBoundingBox() );
|
||||||
|
|
||||||
|
// Groups do not contribute to the rect, only their members
|
||||||
|
|
||||||
return area;
|
return area;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -770,6 +824,8 @@ bool MODULE::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) co
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Groups are not hit-tested; only their members
|
||||||
|
|
||||||
// No items were hit
|
// No items were hit
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -955,6 +1011,11 @@ SEARCH_RESULT MODULE::Visit( INSPECTOR inspector, void* testData, const KICAD_T
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PCB_GROUP_T:
|
||||||
|
result = IterateForward<PCB_GROUP*>( m_fp_groups, inspector, testData, p );
|
||||||
|
++p;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
done = true;
|
done = true;
|
||||||
break;
|
break;
|
||||||
|
@ -1001,6 +1062,9 @@ void MODULE::RunOnChildren( const std::function<void (BOARD_ITEM*)>& aFunction )
|
||||||
for( MODULE_ZONE_CONTAINER* zone : m_fp_zones )
|
for( MODULE_ZONE_CONTAINER* zone : m_fp_zones )
|
||||||
aFunction( static_cast<MODULE_ZONE_CONTAINER*>( zone ) );
|
aFunction( static_cast<MODULE_ZONE_CONTAINER*>( zone ) );
|
||||||
|
|
||||||
|
for( PCB_GROUP* group : m_fp_groups )
|
||||||
|
aFunction( static_cast<PCB_GROUP*>( group ) );
|
||||||
|
|
||||||
for( BOARD_ITEM* drawing : m_drawings )
|
for( BOARD_ITEM* drawing : m_drawings )
|
||||||
aFunction( static_cast<BOARD_ITEM*>( drawing ) );
|
aFunction( static_cast<BOARD_ITEM*>( drawing ) );
|
||||||
|
|
||||||
|
@ -1310,14 +1374,14 @@ void MODULE::MoveAnchorPosition( const wxPoint& aMoveVector )
|
||||||
m_Value->SetDrawCoord();
|
m_Value->SetDrawCoord();
|
||||||
|
|
||||||
// Update the pad local coordinates.
|
// Update the pad local coordinates.
|
||||||
for( auto pad : m_pads )
|
for( D_PAD* pad : m_pads )
|
||||||
{
|
{
|
||||||
pad->SetPos0( pad->GetPos0() + moveVector );
|
pad->SetPos0( pad->GetPos0() + moveVector );
|
||||||
pad->SetDrawCoord();
|
pad->SetDrawCoord();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the draw element coordinates.
|
// Update the draw element coordinates.
|
||||||
for( auto item : GraphicalItems() )
|
for( BOARD_ITEM* item : GraphicalItems() )
|
||||||
{
|
{
|
||||||
switch( item->Type() )
|
switch( item->Type() )
|
||||||
{
|
{
|
||||||
|
@ -1353,13 +1417,13 @@ void MODULE::SetOrientation( double aNewAngle )
|
||||||
|
|
||||||
m_Orient = aNewAngle;
|
m_Orient = aNewAngle;
|
||||||
|
|
||||||
for( auto pad : m_pads )
|
for( D_PAD* pad : m_pads )
|
||||||
{
|
{
|
||||||
pad->SetOrientation( pad->GetOrientation() + angleChange );
|
pad->SetOrientation( pad->GetOrientation() + angleChange );
|
||||||
pad->SetDrawCoord();
|
pad->SetDrawCoord();
|
||||||
}
|
}
|
||||||
|
|
||||||
for( auto zone : m_fp_zones )
|
for( ZONE_CONTAINER* zone : m_fp_zones )
|
||||||
{
|
{
|
||||||
zone->Rotate( GetPosition(), angleChange );
|
zone->Rotate( GetPosition(), angleChange );
|
||||||
}
|
}
|
||||||
|
@ -1369,7 +1433,7 @@ void MODULE::SetOrientation( double aNewAngle )
|
||||||
m_Value->SetDrawCoord();
|
m_Value->SetDrawCoord();
|
||||||
|
|
||||||
// Displace contours and text of the footprint.
|
// Displace contours and text of the footprint.
|
||||||
for( auto item : m_drawings )
|
for( BOARD_ITEM* item : m_drawings )
|
||||||
{
|
{
|
||||||
if( item->Type() == PCB_MODULE_EDGE_T )
|
if( item->Type() == PCB_MODULE_EDGE_T )
|
||||||
{
|
{
|
||||||
|
@ -1454,7 +1518,7 @@ BOARD_ITEM* MODULE::DuplicateItem( const BOARD_ITEM* aItem, bool aAddToModule )
|
||||||
|
|
||||||
case PCB_MODULE_EDGE_T:
|
case PCB_MODULE_EDGE_T:
|
||||||
{
|
{
|
||||||
EDGE_MODULE* new_edge = new EDGE_MODULE( *static_cast<const EDGE_MODULE*>(aItem) );
|
EDGE_MODULE* new_edge = new EDGE_MODULE( *static_cast<const EDGE_MODULE*>( aItem ) );
|
||||||
const_cast<KIID&>( new_edge->m_Uuid ) = KIID();
|
const_cast<KIID&>( new_edge->m_Uuid ) = KIID();
|
||||||
|
|
||||||
if( aAddToModule )
|
if( aAddToModule )
|
||||||
|
@ -1464,6 +1528,10 @@ BOARD_ITEM* MODULE::DuplicateItem( const BOARD_ITEM* aItem, bool aAddToModule )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case PCB_GROUP_T:
|
||||||
|
new_item = static_cast<const PCB_GROUP*>( aItem )->DeepDuplicate();
|
||||||
|
break;
|
||||||
|
|
||||||
case PCB_MODULE_T:
|
case PCB_MODULE_T:
|
||||||
// Ignore the module itself
|
// Ignore the module itself
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -101,6 +101,7 @@ public:
|
||||||
DECL_DEQ_FOR_SWIG( PADS, D_PAD* )
|
DECL_DEQ_FOR_SWIG( PADS, D_PAD* )
|
||||||
DECL_DEQ_FOR_SWIG( DRAWINGS, BOARD_ITEM* )
|
DECL_DEQ_FOR_SWIG( DRAWINGS, BOARD_ITEM* )
|
||||||
DECL_VEC_FOR_SWIG( MODULE_ZONE_CONTAINERS, MODULE_ZONE_CONTAINER* )
|
DECL_VEC_FOR_SWIG( MODULE_ZONE_CONTAINERS, MODULE_ZONE_CONTAINER* )
|
||||||
|
DECL_VEC_FOR_SWIG( MODULE_GROUPS, PCB_GROUP* )
|
||||||
DECL_DEQ_FOR_SWIG( MODULES, MODULE* )
|
DECL_DEQ_FOR_SWIG( MODULES, MODULE* )
|
||||||
|
|
||||||
class MODULE : public BOARD_ITEM_CONTAINER
|
class MODULE : public BOARD_ITEM_CONTAINER
|
||||||
|
@ -178,36 +179,17 @@ public:
|
||||||
|
|
||||||
const EDA_RECT GetBoundingBox( bool aIncludeInvisibleText ) const;
|
const EDA_RECT GetBoundingBox( bool aIncludeInvisibleText ) const;
|
||||||
|
|
||||||
PADS& Pads()
|
PADS& Pads() { return m_pads; }
|
||||||
{
|
const PADS& Pads() const { return m_pads; }
|
||||||
return m_pads;
|
|
||||||
}
|
|
||||||
|
|
||||||
const PADS& Pads() const
|
DRAWINGS& GraphicalItems() { return m_drawings; }
|
||||||
{
|
const DRAWINGS& GraphicalItems() const { return m_drawings; }
|
||||||
return m_pads;
|
|
||||||
}
|
|
||||||
|
|
||||||
DRAWINGS& GraphicalItems()
|
MODULE_ZONE_CONTAINERS& Zones() { return m_fp_zones; }
|
||||||
{
|
const MODULE_ZONE_CONTAINERS& Zones() const { return m_fp_zones; }
|
||||||
return m_drawings;
|
|
||||||
}
|
|
||||||
|
|
||||||
const DRAWINGS& GraphicalItems() const
|
MODULE_GROUPS& Groups() { return m_fp_groups; }
|
||||||
{
|
const MODULE_GROUPS& Groups() const { return m_fp_groups; }
|
||||||
return m_drawings;
|
|
||||||
}
|
|
||||||
|
|
||||||
MODULE_ZONE_CONTAINERS& Zones()
|
|
||||||
{
|
|
||||||
return m_fp_zones;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const MODULE_ZONE_CONTAINERS& Zones() const
|
|
||||||
{
|
|
||||||
return m_fp_zones;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HasThroughHolePads() const;
|
bool HasThroughHolePads() const;
|
||||||
|
|
||||||
|
@ -713,6 +695,7 @@ private:
|
||||||
DRAWINGS m_drawings; // BOARD_ITEMs for drawings on the board, owned by pointer.
|
DRAWINGS m_drawings; // BOARD_ITEMs for drawings on the board, owned by pointer.
|
||||||
PADS m_pads; // D_PAD items, owned by pointer
|
PADS m_pads; // D_PAD items, owned by pointer
|
||||||
MODULE_ZONE_CONTAINERS m_fp_zones; // MODULE_ZONE_CONTAINER items, owned by pointer
|
MODULE_ZONE_CONTAINERS m_fp_zones; // MODULE_ZONE_CONTAINER items, owned by pointer
|
||||||
|
MODULE_GROUPS m_fp_groups; // PCB_GROUP items, owned by pointer
|
||||||
|
|
||||||
double m_Orient; // Orientation in tenths of a degree, 900=90.0 degrees.
|
double m_Orient; // Orientation in tenths of a degree, 900=90.0 degrees.
|
||||||
wxPoint m_Pos; // Position of module on the board in internal units.
|
wxPoint m_Pos; // Position of module on the board in internal units.
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
#include <msgpanel.h>
|
#include <msgpanel.h>
|
||||||
#include <view/view.h>
|
#include <view/view.h>
|
||||||
|
|
||||||
PCB_GROUP::PCB_GROUP( BOARD*aParent ) :
|
PCB_GROUP::PCB_GROUP( BOARD_ITEM* aParent ) :
|
||||||
BOARD_ITEM( aParent, PCB_GROUP_T )
|
BOARD_ITEM( aParent, PCB_GROUP_T )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -71,11 +71,11 @@ void PCB_GROUP::RemoveAll()
|
||||||
|
|
||||||
PCB_GROUP* PCB_GROUP::TopLevelGroup( BOARD_ITEM* item, PCB_GROUP* scope )
|
PCB_GROUP* PCB_GROUP::TopLevelGroup( BOARD_ITEM* item, PCB_GROUP* scope )
|
||||||
{
|
{
|
||||||
if( item->GetParent() && item->GetParent()->Type() == PCB_MODULE_T )
|
|
||||||
item = item->GetParent();
|
|
||||||
|
|
||||||
PCB_GROUP* candidate = item->GetParentGroup();
|
PCB_GROUP* candidate = item->GetParentGroup();
|
||||||
|
|
||||||
|
if( !candidate && item->GetParent() && item->GetParent()->Type() == PCB_MODULE_T )
|
||||||
|
candidate = item->GetParent()->GetParentGroup();
|
||||||
|
|
||||||
while( candidate && candidate->GetParentGroup() && candidate->GetParentGroup() != scope )
|
while( candidate && candidate->GetParentGroup() && candidate->GetParentGroup() != scope )
|
||||||
candidate = candidate->GetParentGroup();
|
candidate = candidate->GetParentGroup();
|
||||||
|
|
||||||
|
|
|
@ -134,6 +134,7 @@ const KICAD_T GENERAL_COLLECTOR::ModulesAndTheirItems[] = {
|
||||||
PCB_MODULE_EDGE_T,
|
PCB_MODULE_EDGE_T,
|
||||||
PCB_PAD_T,
|
PCB_PAD_T,
|
||||||
PCB_MODULE_ZONE_AREA_T,
|
PCB_MODULE_ZONE_AREA_T,
|
||||||
|
PCB_GROUP_T,
|
||||||
EOT
|
EOT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -143,6 +144,7 @@ const KICAD_T GENERAL_COLLECTOR::ModuleItems[] = {
|
||||||
PCB_MODULE_EDGE_T,
|
PCB_MODULE_EDGE_T,
|
||||||
PCB_PAD_T,
|
PCB_PAD_T,
|
||||||
PCB_MODULE_ZONE_AREA_T,
|
PCB_MODULE_ZONE_AREA_T,
|
||||||
|
PCB_GROUP_T,
|
||||||
EOT
|
EOT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
#include <tool/zoom_tool.h>
|
#include <tool/zoom_tool.h>
|
||||||
#include <tools/pcb_editor_conditions.h>
|
#include <tools/pcb_editor_conditions.h>
|
||||||
#include <tools/pcb_viewer_tools.h>
|
#include <tools/pcb_viewer_tools.h>
|
||||||
|
#include <tools/group_tool.h>
|
||||||
#include <tools/position_relative_tool.h>
|
#include <tools/position_relative_tool.h>
|
||||||
#include <widgets/appearance_controls.h>
|
#include <widgets/appearance_controls.h>
|
||||||
#include <widgets/infobar.h>
|
#include <widgets/infobar.h>
|
||||||
|
@ -862,6 +863,7 @@ void FOOTPRINT_EDIT_FRAME::setupTools()
|
||||||
m_toolManager->RegisterTool( new PCBNEW_PICKER_TOOL );
|
m_toolManager->RegisterTool( new PCBNEW_PICKER_TOOL );
|
||||||
m_toolManager->RegisterTool( new POSITION_RELATIVE_TOOL );
|
m_toolManager->RegisterTool( new POSITION_RELATIVE_TOOL );
|
||||||
m_toolManager->RegisterTool( new PCB_VIEWER_TOOLS );
|
m_toolManager->RegisterTool( new PCB_VIEWER_TOOLS );
|
||||||
|
m_toolManager->RegisterTool( new GROUP_TOOL );
|
||||||
m_toolManager->RegisterTool( new CONVERT_TOOL );
|
m_toolManager->RegisterTool( new CONVERT_TOOL );
|
||||||
|
|
||||||
m_toolManager->GetTool<SELECTION_TOOL>()->SetEditModules( true );
|
m_toolManager->GetTool<SELECTION_TOOL>()->SetEditModules( true );
|
||||||
|
@ -872,6 +874,7 @@ void FOOTPRINT_EDIT_FRAME::setupTools()
|
||||||
m_toolManager->GetTool<PCBNEW_CONTROL>()->SetEditModules( true );
|
m_toolManager->GetTool<PCBNEW_CONTROL>()->SetEditModules( true );
|
||||||
m_toolManager->GetTool<PCBNEW_PICKER_TOOL>()->SetEditModules( true );
|
m_toolManager->GetTool<PCBNEW_PICKER_TOOL>()->SetEditModules( true );
|
||||||
m_toolManager->GetTool<POSITION_RELATIVE_TOOL>()->SetEditModules( true );
|
m_toolManager->GetTool<POSITION_RELATIVE_TOOL>()->SetEditModules( true );
|
||||||
|
m_toolManager->GetTool<GROUP_TOOL>()->SetEditModules( true );
|
||||||
|
|
||||||
m_toolManager->GetTool<PCB_VIEWER_TOOLS>()->SetFootprintFrame( true );
|
m_toolManager->GetTool<PCB_VIEWER_TOOLS>()->SetFootprintFrame( true );
|
||||||
m_toolManager->InitTools();
|
m_toolManager->InitTools();
|
||||||
|
|
|
@ -148,9 +148,9 @@ static IO_MGR::PCB_FILE_T detect_file_type( FILE* aFile, const wxFileName& aFile
|
||||||
* @param aFileType - type of the file
|
* @param aFileType - type of the file
|
||||||
* @param aName - name of the footprint
|
* @param aName - name of the footprint
|
||||||
*/
|
*/
|
||||||
static MODULE* parse_module_with_plugin(
|
static MODULE* parse_module_with_plugin( const wxFileName& aFileName,
|
||||||
const wxFileName& aFileName, IO_MGR::PCB_FILE_T aFileType,
|
IO_MGR::PCB_FILE_T aFileType,
|
||||||
const wxString& aName )
|
const wxString& aName )
|
||||||
{
|
{
|
||||||
wxString path;
|
wxString path;
|
||||||
|
|
||||||
|
|
|
@ -414,7 +414,7 @@ public:
|
||||||
* is thrown in the case where aFootprintName cannot be found.
|
* is thrown in the case where aFootprintName cannot be found.
|
||||||
*/
|
*/
|
||||||
virtual MODULE* FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName,
|
virtual MODULE* FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName,
|
||||||
const PROPERTIES* aProperties = NULL );
|
const PROPERTIES* aProperties = NULL );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function GetEnumeratedFootprint
|
* Function GetEnumeratedFootprint
|
||||||
|
|
|
@ -633,14 +633,14 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const
|
||||||
formatHeader( aBoard, aNestLevel );
|
formatHeader( aBoard, aNestLevel );
|
||||||
|
|
||||||
// Save the modules.
|
// Save the modules.
|
||||||
for( auto module : sorted_modules )
|
for( BOARD_ITEM* module : sorted_modules )
|
||||||
{
|
{
|
||||||
Format( module, aNestLevel );
|
Format( module, aNestLevel );
|
||||||
m_out->Print( 0, "\n" );
|
m_out->Print( 0, "\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the graphical items on the board (not owned by a module)
|
// Save the graphical items on the board (not owned by a module)
|
||||||
for( auto item : sorted_drawings )
|
for( BOARD_ITEM* item : sorted_drawings )
|
||||||
Format( item, aNestLevel );
|
Format( item, aNestLevel );
|
||||||
|
|
||||||
if( sorted_drawings.size() )
|
if( sorted_drawings.size() )
|
||||||
|
@ -649,7 +649,7 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const
|
||||||
// Do not save MARKER_PCBs, they can be regenerated easily.
|
// Do not save MARKER_PCBs, they can be regenerated easily.
|
||||||
|
|
||||||
// Save the tracks and vias.
|
// Save the tracks and vias.
|
||||||
for( auto track : sorted_tracks )
|
for( TRACK* track : sorted_tracks )
|
||||||
Format( track, aNestLevel );
|
Format( track, aNestLevel );
|
||||||
|
|
||||||
if( sorted_tracks.size() )
|
if( sorted_tracks.size() )
|
||||||
|
@ -660,7 +660,7 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const
|
||||||
Format( zone, aNestLevel );
|
Format( zone, aNestLevel );
|
||||||
|
|
||||||
// Save the groups
|
// Save the groups
|
||||||
for( const auto group : sorted_groups )
|
for( BOARD_ITEM* group : sorted_groups )
|
||||||
Format( group, aNestLevel );
|
Format( group, aNestLevel );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1083,20 +1083,26 @@ void PCB_IO::format( MODULE* aModule, int aNestLevel ) const
|
||||||
aModule->GraphicalItems().end() );
|
aModule->GraphicalItems().end() );
|
||||||
std::set<BOARD_ITEM*, BOARD_ITEM::ptr_cmp> sorted_zones( aModule->Zones().begin(),
|
std::set<BOARD_ITEM*, BOARD_ITEM::ptr_cmp> sorted_zones( aModule->Zones().begin(),
|
||||||
aModule->Zones().end() );
|
aModule->Zones().end() );
|
||||||
|
std::set<BOARD_ITEM*, PCB_GROUP::ptr_cmp> sorted_groups( aModule->Groups().begin(),
|
||||||
|
aModule->Groups().end() );
|
||||||
|
|
||||||
// Save drawing elements.
|
// Save drawing elements.
|
||||||
|
|
||||||
for( auto gr : sorted_drawings )
|
for( BOARD_ITEM* gr : sorted_drawings )
|
||||||
Format( gr, aNestLevel+1 );
|
Format( gr, aNestLevel+1 );
|
||||||
|
|
||||||
// Save pads.
|
// Save pads.
|
||||||
for( auto pad : sorted_pads )
|
for( D_PAD* pad : sorted_pads )
|
||||||
Format( pad, aNestLevel+1 );
|
Format( pad, aNestLevel+1 );
|
||||||
|
|
||||||
// Save zones.
|
// Save zones.
|
||||||
for( auto zone : sorted_zones )
|
for( BOARD_ITEM* zone : sorted_zones )
|
||||||
Format( zone, aNestLevel + 1 );
|
Format( zone, aNestLevel + 1 );
|
||||||
|
|
||||||
|
// Save groups.
|
||||||
|
for( BOARD_ITEM* group : sorted_groups )
|
||||||
|
Format( group, aNestLevel + 1 );
|
||||||
|
|
||||||
// Save 3D info.
|
// Save 3D info.
|
||||||
auto bs3D = aModule->Models().begin();
|
auto bs3D = aModule->Models().begin();
|
||||||
auto es3D = aModule->Models().end();
|
auto es3D = aModule->Models().end();
|
||||||
|
@ -2291,7 +2297,7 @@ void PCB_IO::FootprintSave( const wxString& aLibraryPath, const MODULE* aFootpri
|
||||||
}
|
}
|
||||||
|
|
||||||
// I need my own copy for the cache
|
// I need my own copy for the cache
|
||||||
MODULE* module = static_cast<MODULE*>( aFootprint->Duplicate() );
|
MODULE* module = static_cast<MODULE*>( aFootprint->Clone() );
|
||||||
|
|
||||||
// It should have no parent, orientation should be zero, and it should be on the front layer.
|
// It should have no parent, orientation should be zero, and it should be on the front layer.
|
||||||
module->SetParent( nullptr );
|
module->SetParent( nullptr );
|
||||||
|
|
|
@ -86,8 +86,9 @@ class TEXTE_PCB;
|
||||||
//#define SEXPR_BOARD_FILE_VERSION 20200909 // Change DIMENSION format
|
//#define SEXPR_BOARD_FILE_VERSION 20200909 // Change DIMENSION format
|
||||||
//#define SEXPR_BOARD_FILE_VERSION 20200913 // Add leader dimension
|
//#define SEXPR_BOARD_FILE_VERSION 20200913 // Add leader dimension
|
||||||
//#define SEXPR_BOARD_FILE_VERSION 20200916 // Add center dimension
|
//#define SEXPR_BOARD_FILE_VERSION 20200916 // Add center dimension
|
||||||
//#define SEXPR_BOARD_FILE_VERSION 20200921 // Add orthogonal dimension
|
//#define SEXPR_BOARD_FILE_VERSION 20200921 // Add orthogonal dimension
|
||||||
#define SEXPR_BOARD_FILE_VERSION 20200922 // Add user name to layer definition.
|
//#define SEXPR_BOARD_FILE_VERSION 20200922 // Add user name to layer definition.
|
||||||
|
#define SEXPR_BOARD_FILE_VERSION 20201002 // Add groups in footprints (for footprint editor).
|
||||||
|
|
||||||
|
|
||||||
#define BOARD_FILE_HOST_VERSION 20200825 ///< Earlier files than this include the host tag
|
#define BOARD_FILE_HOST_VERSION 20200825 ///< Earlier files than this include the host tag
|
||||||
|
|
|
@ -195,14 +195,14 @@ void PCB_BASE_FRAME::FocusOnItem( BOARD_ITEM* aItem )
|
||||||
static_cast<MODULE*>( lastItem )->RunOnChildren( [&]( BOARD_ITEM* child )
|
static_cast<MODULE*>( lastItem )->RunOnChildren( [&]( BOARD_ITEM* child )
|
||||||
{
|
{
|
||||||
child->ClearBrightened();
|
child->ClearBrightened();
|
||||||
});
|
} );
|
||||||
}
|
}
|
||||||
else if( lastItem->Type() == PCB_GROUP_T )
|
else if( lastItem->Type() == PCB_GROUP_T )
|
||||||
{
|
{
|
||||||
static_cast<PCB_GROUP*>( lastItem )->RunOnChildren( [&] ( BOARD_ITEM* child )
|
static_cast<PCB_GROUP*>( lastItem )->RunOnChildren( [&]( BOARD_ITEM* child )
|
||||||
{
|
{
|
||||||
child->ClearBrightened();
|
child->ClearBrightened();
|
||||||
});
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
GetCanvas()->GetView()->Update( lastItem );
|
GetCanvas()->GetView()->Update( lastItem );
|
||||||
|
|
|
@ -516,6 +516,8 @@ BOARD_ITEM* PCB_PARSER::Parse()
|
||||||
THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
|
THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resolveGroups( item );
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,7 +620,7 @@ BOARD* PCB_PARSER::parseBOARD_unchecked()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_group:
|
case T_group:
|
||||||
parseGROUP();
|
parseGROUP( m_board );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_via:
|
case T_via:
|
||||||
|
@ -721,91 +723,81 @@ BOARD* PCB_PARSER::parseBOARD_unchecked()
|
||||||
m_undefinedLayers.clear();
|
m_undefinedLayers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we've parsed the other Uuids in the file we can resolve
|
return m_board;
|
||||||
// the uuids referred to in the group declarations we saw.
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PCB_PARSER::resolveGroups( BOARD_ITEM* aParent )
|
||||||
|
{
|
||||||
|
auto getItem = [&]( const KIID& aId )
|
||||||
|
{
|
||||||
|
BOARD_ITEM* aItem = nullptr;
|
||||||
|
|
||||||
|
if( dynamic_cast<BOARD*>( aParent ) )
|
||||||
|
{
|
||||||
|
aItem = static_cast<BOARD*>( aParent )->GetItem( aId );
|
||||||
|
}
|
||||||
|
else if( aParent->Type() == PCB_MODULE_T )
|
||||||
|
{
|
||||||
|
static_cast<MODULE*>( aParent )->RunOnChildren(
|
||||||
|
[&]( BOARD_ITEM* child )
|
||||||
|
{
|
||||||
|
if( child->m_Uuid == aId )
|
||||||
|
aItem = child;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
return aItem;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Now that we've parsed the other Uuids in the file we can resolve the uuids referred
|
||||||
|
// to in the group declarations we saw.
|
||||||
//
|
//
|
||||||
// First add all group objects so subsequent GetItem() calls for nested
|
// First add all group objects so subsequent GetItem() calls for nested groups work.
|
||||||
// groups work.
|
|
||||||
|
|
||||||
for( size_t idx = 0; idx < m_groupInfos.size(); idx++ )
|
for( size_t idx = 0; idx < m_groupInfos.size(); idx++ )
|
||||||
{
|
{
|
||||||
auto& aGrp = m_groupInfos[idx];
|
GROUP_INFO& aGrp = m_groupInfos[idx];
|
||||||
PCB_GROUP* group = new PCB_GROUP( m_board );
|
PCB_GROUP* group = new PCB_GROUP( aGrp.parent );
|
||||||
|
|
||||||
group->SetName( aGrp.name );
|
group->SetName( aGrp.name );
|
||||||
const_cast<KIID&>( group->m_Uuid ) = aGrp.uuid;
|
const_cast<KIID&>( group->m_Uuid ) = aGrp.uuid;
|
||||||
m_board->Add( group );
|
|
||||||
|
if( aGrp.parent->Type() == PCB_MODULE_T )
|
||||||
|
static_cast<MODULE*>( aGrp.parent )->Add( group );
|
||||||
|
else
|
||||||
|
static_cast<BOARD*>( aGrp.parent )->Add( group );
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString error;
|
wxString error;
|
||||||
|
|
||||||
for( size_t idx = 0; idx < m_groupInfos.size(); idx++ )
|
for( size_t idx = 0; idx < m_groupInfos.size(); idx++ )
|
||||||
{
|
{
|
||||||
auto& aGrp = m_groupInfos[idx];
|
GROUP_INFO& aGrp = m_groupInfos[idx];
|
||||||
BOARD_ITEM* bItem = m_board->GetItem( aGrp.uuid );
|
BOARD_ITEM* bItem = getItem( aGrp.uuid );
|
||||||
|
|
||||||
if( bItem == nullptr || bItem->Type() != PCB_GROUP_T )
|
if( bItem == nullptr || bItem->Type() != PCB_GROUP_T )
|
||||||
{
|
|
||||||
error = wxString::Format( _( "Group %s not found in board" ),
|
|
||||||
aGrp.uuid.AsString() );
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
PCB_GROUP* group = static_cast<PCB_GROUP*>( bItem );
|
PCB_GROUP* group = static_cast<PCB_GROUP*>( bItem );
|
||||||
|
|
||||||
for( const auto& aUuid : aGrp.memberUuids )
|
for( const KIID& aUuid : aGrp.memberUuids )
|
||||||
{
|
{
|
||||||
KIID tUuid = aUuid;
|
BOARD_ITEM* item;
|
||||||
|
|
||||||
if( m_resetKIIDs )
|
if( m_resetKIIDs )
|
||||||
{
|
item = getItem( m_resetKIIDMap[ aUuid.AsString() ] );
|
||||||
if( m_resetKIIDMap.find( aUuid.AsString() ) == m_resetKIIDMap.end() )
|
|
||||||
{
|
|
||||||
if( error == wxEmptyString )
|
|
||||||
{
|
|
||||||
error = wxString::Format( _( "Group %s references missing item %s" ),
|
|
||||||
aGrp.uuid.AsString(), aUuid.AsString() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tUuid = m_resetKIIDMap[ aUuid.AsString() ];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOARD_ITEM* item = m_board->GetItem( tUuid );
|
|
||||||
|
|
||||||
if( ( item == nullptr ) || ( item->Type() == NOT_USED ) )
|
|
||||||
{
|
|
||||||
if( error == wxEmptyString )
|
|
||||||
{
|
|
||||||
error = wxString::Format( _( "Group %s references missing item %s" ),
|
|
||||||
aGrp.uuid.AsString(), tUuid.AsString() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
item = getItem( aUuid );
|
||||||
|
|
||||||
|
if( item && item->Type() != NOT_USED )
|
||||||
group->AddItem( item );
|
group->AddItem( item );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString sanityResult = m_board->GroupsSanityCheck();
|
// Don't allow group cycles
|
||||||
|
if( m_board )
|
||||||
if( error != wxEmptyString || sanityResult != wxEmptyString )
|
|
||||||
{
|
|
||||||
wxString errMsg = ( error != wxEmptyString ) ? error : sanityResult;
|
|
||||||
KIDIALOG dlg( nullptr, wxString::Format(
|
|
||||||
_( "Error in group structure in file: %s\n\nAttempt repair?" ), errMsg ),
|
|
||||||
_( "File data error" ), wxOK | wxCANCEL | wxICON_ERROR );
|
|
||||||
dlg.SetOKLabel( _( "Attempt repair" ) );
|
|
||||||
|
|
||||||
if( dlg.ShowModal() == wxID_CANCEL )
|
|
||||||
THROW_IO_ERROR( _( "File read canceled" ) );
|
|
||||||
|
|
||||||
m_board->GroupsSanityCheck( true );
|
m_board->GroupsSanityCheck( true );
|
||||||
}
|
|
||||||
|
|
||||||
return m_board;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3012,7 +3004,7 @@ MODULE* PCB_PARSER::parseMODULE_unchecked( wxArrayString* aInitialComments )
|
||||||
module->Add( text, ADD_MODE::APPEND );
|
module->Add( text, ADD_MODE::APPEND );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_fp_arc:
|
case T_fp_arc:
|
||||||
{
|
{
|
||||||
|
@ -3028,8 +3020,7 @@ MODULE* PCB_PARSER::parseMODULE_unchecked( wxArrayString* aInitialComments )
|
||||||
else
|
else
|
||||||
delete em;
|
delete em;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case T_fp_circle:
|
case T_fp_circle:
|
||||||
case T_fp_curve:
|
case T_fp_curve:
|
||||||
|
@ -3042,8 +3033,7 @@ MODULE* PCB_PARSER::parseMODULE_unchecked( wxArrayString* aInitialComments )
|
||||||
em->SetDrawCoord();
|
em->SetDrawCoord();
|
||||||
module->Add( em, ADD_MODE::APPEND );
|
module->Add( em, ADD_MODE::APPEND );
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case T_pad:
|
case T_pad:
|
||||||
{
|
{
|
||||||
|
@ -3054,8 +3044,7 @@ MODULE* PCB_PARSER::parseMODULE_unchecked( wxArrayString* aInitialComments )
|
||||||
pad->SetPosition( pt + module->GetPosition() );
|
pad->SetPosition( pt + module->GetPosition() );
|
||||||
module->Add( pad, ADD_MODE::APPEND );
|
module->Add( pad, ADD_MODE::APPEND );
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case T_model:
|
case T_model:
|
||||||
module->Add3DModel( parse3DModel() );
|
module->Add3DModel( parse3DModel() );
|
||||||
|
@ -3066,7 +3055,11 @@ MODULE* PCB_PARSER::parseMODULE_unchecked( wxArrayString* aInitialComments )
|
||||||
ZONE_CONTAINER* zone = parseZONE_CONTAINER( module.get() );
|
ZONE_CONTAINER* zone = parseZONE_CONTAINER( module.get() );
|
||||||
module->Add( zone, ADD_MODE::APPEND );
|
module->Add( zone, ADD_MODE::APPEND );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case T_group:
|
||||||
|
parseGROUP( module.get() );
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Expecting(
|
Expecting(
|
||||||
|
@ -3075,7 +3068,7 @@ MODULE* PCB_PARSER::parseMODULE_unchecked( wxArrayString* aInitialComments )
|
||||||
"solder_paste_margin, solder_paste_ratio, clearance, "
|
"solder_paste_margin, solder_paste_ratio, clearance, "
|
||||||
"zone_connect, thermal_width, thermal_gap, attr, fp_text, "
|
"zone_connect, thermal_width, thermal_gap, attr, fp_text, "
|
||||||
"fp_arc, fp_circle, fp_curve, fp_line, fp_poly, fp_rect, pad, "
|
"fp_arc, fp_circle, fp_curve, fp_line, fp_poly, fp_rect, pad, "
|
||||||
"zone, or model" );
|
"zone, group, or model" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3945,7 +3938,7 @@ bool PCB_PARSER::parseD_PAD_option( D_PAD* aPad )
|
||||||
// (group <(name “groupName”)> (id 12345679)
|
// (group <(name “groupName”)> (id 12345679)
|
||||||
// (members id_1 id_2 … id_last )
|
// (members id_1 id_2 … id_last )
|
||||||
// )
|
// )
|
||||||
void PCB_PARSER::parseGROUP()
|
void PCB_PARSER::parseGROUP( BOARD_ITEM* aParent )
|
||||||
{
|
{
|
||||||
wxCHECK_RET( CurTok() == T_group,
|
wxCHECK_RET( CurTok() == T_group,
|
||||||
wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as PCB_GROUP." ) );
|
wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as PCB_GROUP." ) );
|
||||||
|
@ -3953,8 +3946,9 @@ void PCB_PARSER::parseGROUP()
|
||||||
wxPoint pt;
|
wxPoint pt;
|
||||||
T token;
|
T token;
|
||||||
|
|
||||||
m_groupInfos.push_back( GroupInfo() );
|
m_groupInfos.push_back( GROUP_INFO() );
|
||||||
GroupInfo& groupInfo = m_groupInfos.back();
|
GROUP_INFO& groupInfo = m_groupInfos.back();
|
||||||
|
groupInfo.parent = aParent;
|
||||||
|
|
||||||
token = NextTok();
|
token = NextTok();
|
||||||
|
|
||||||
|
@ -3991,9 +3985,9 @@ void PCB_PARSER::parseGROUP()
|
||||||
while( ( token = NextTok() ) != T_RIGHT )
|
while( ( token = NextTok() ) != T_RIGHT )
|
||||||
{
|
{
|
||||||
// This token is the Uuid of the item in the group.
|
// This token is the Uuid of the item in the group.
|
||||||
// Since groups are serialized at the end of the file, the
|
// Since groups are serialized at the end of the file/module, the Uuid should already
|
||||||
// Uuid should already have been seen and exist in the board.
|
// have been seen and exist in the board.
|
||||||
KIID uuid( CurStr() );
|
KIID uuid( CurStr() );
|
||||||
groupInfo.memberUuids.push_back( uuid );
|
groupInfo.memberUuids.push_back( uuid );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4865,16 +4859,19 @@ PCB_TARGET* PCB_PARSER::parsePCB_TARGET()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
KIID PCB_PARSER::CurStrToKIID() {
|
KIID PCB_PARSER::CurStrToKIID()
|
||||||
KIID aid;
|
{
|
||||||
|
KIID aId;
|
||||||
|
|
||||||
if( m_resetKIIDs )
|
if( m_resetKIIDs )
|
||||||
{
|
{
|
||||||
aid = KIID();
|
aId = KIID();
|
||||||
m_resetKIIDMap.insert( std::make_pair( CurStr(), aid ) );
|
m_resetKIIDMap.insert( std::make_pair( CurStr(), aId ) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
aid = KIID( CurStr() );
|
aId = KIID( CurStr() );
|
||||||
}
|
}
|
||||||
return aid;
|
|
||||||
|
return aId;
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,12 +91,13 @@ class PCB_PARSER : public PCB_LEXER
|
||||||
// them into BOARD_ITEM* after we've parsed the rest of the file.
|
// them into BOARD_ITEM* after we've parsed the rest of the file.
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
BOARD_ITEM* parent;
|
||||||
wxString name;
|
wxString name;
|
||||||
KIID uuid;
|
KIID uuid;
|
||||||
std::vector<KIID> memberUuids;
|
std::vector<KIID> memberUuids;
|
||||||
} GroupInfo;
|
} GROUP_INFO;
|
||||||
|
|
||||||
std::vector<GroupInfo> m_groupInfos;
|
std::vector<GROUP_INFO> m_groupInfos;
|
||||||
|
|
||||||
///> Converts net code using the mapping table if available,
|
///> Converts net code using the mapping table if available,
|
||||||
///> otherwise returns unchanged net code if < 0 or if is is out of range
|
///> otherwise returns unchanged net code if < 0 or if is is out of range
|
||||||
|
@ -181,7 +182,7 @@ class PCB_PARSER : public PCB_LEXER
|
||||||
PCB_TARGET* parsePCB_TARGET();
|
PCB_TARGET* parsePCB_TARGET();
|
||||||
MARKER_PCB* parseMARKER( BOARD_ITEM_CONTAINER* aParent );
|
MARKER_PCB* parseMARKER( BOARD_ITEM_CONTAINER* aParent );
|
||||||
BOARD* parseBOARD();
|
BOARD* parseBOARD();
|
||||||
void parseGROUP();
|
void parseGROUP( BOARD_ITEM* aParent );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function parseBOARD_unchecked
|
* Function parseBOARD_unchecked
|
||||||
|
@ -189,7 +190,6 @@ class PCB_PARSER : public PCB_LEXER
|
||||||
*/
|
*/
|
||||||
BOARD* parseBOARD_unchecked();
|
BOARD* parseBOARD_unchecked();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function lookUpLayer
|
* Function lookUpLayer
|
||||||
* parses the current token for the layer definition of a #BOARD_ITEM object.
|
* parses the current token for the layer definition of a #BOARD_ITEM object.
|
||||||
|
@ -340,6 +340,12 @@ class PCB_PARSER : public PCB_LEXER
|
||||||
*/
|
*/
|
||||||
KIID CurStrToKIID();
|
KIID CurStrToKIID();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called after parsing a footprint definition or board to build the group membership
|
||||||
|
* lists.
|
||||||
|
*/
|
||||||
|
void resolveGroups( BOARD_ITEM* aParent );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PCB_PARSER( LINE_READER* aReader = NULL ) :
|
PCB_PARSER( LINE_READER* aReader = NULL ) :
|
||||||
|
|
|
@ -35,12 +35,12 @@
|
||||||
class DIALOG_GROUP_PROPERTIES : public DIALOG_GROUP_PROPERTIES_BASE
|
class DIALOG_GROUP_PROPERTIES : public DIALOG_GROUP_PROPERTIES_BASE
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
PCB_EDIT_FRAME* m_brdEditor;
|
PCB_BASE_EDIT_FRAME* m_brdEditor;
|
||||||
TOOL_MANAGER* m_toolMgr;
|
TOOL_MANAGER* m_toolMgr;
|
||||||
PCB_GROUP* m_group;
|
PCB_GROUP* m_group;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DIALOG_GROUP_PROPERTIES( PCB_EDIT_FRAME* aParent, PCB_GROUP* aTarget );
|
DIALOG_GROUP_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, PCB_GROUP* aTarget );
|
||||||
~DIALOG_GROUP_PROPERTIES() { }
|
~DIALOG_GROUP_PROPERTIES() { }
|
||||||
|
|
||||||
void OnMemberSelected( wxCommandEvent& event ) override;
|
void OnMemberSelected( wxCommandEvent& event ) override;
|
||||||
|
@ -55,7 +55,8 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
DIALOG_GROUP_PROPERTIES::DIALOG_GROUP_PROPERTIES( PCB_EDIT_FRAME* aParent, PCB_GROUP* aGroup ) :
|
DIALOG_GROUP_PROPERTIES::DIALOG_GROUP_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent,
|
||||||
|
PCB_GROUP* aGroup ) :
|
||||||
DIALOG_GROUP_PROPERTIES_BASE( aParent ),
|
DIALOG_GROUP_PROPERTIES_BASE( aParent ),
|
||||||
m_brdEditor( aParent ),
|
m_brdEditor( aParent ),
|
||||||
m_toolMgr( aParent->GetToolManager() ),
|
m_toolMgr( aParent->GetToolManager() ),
|
||||||
|
@ -165,8 +166,49 @@ void DIALOG_GROUP_PROPERTIES::OnRemoveMember( wxCommandEvent& event )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class GROUP_CONTEXT_MENU : public ACTION_MENU
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GROUP_CONTEXT_MENU( ) : ACTION_MENU( true )
|
||||||
|
{
|
||||||
|
SetIcon( locked_xpm ); // fixme
|
||||||
|
SetTitle( _( "Grouping" ) );
|
||||||
|
|
||||||
|
Add( PCB_ACTIONS::groupCreate );
|
||||||
|
Add( PCB_ACTIONS::groupUngroup );
|
||||||
|
Add( PCB_ACTIONS::groupRemoveItems );
|
||||||
|
Add( PCB_ACTIONS::groupEnter );
|
||||||
|
}
|
||||||
|
|
||||||
|
ACTION_MENU* create() const override
|
||||||
|
{
|
||||||
|
return new GROUP_CONTEXT_MENU();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void update() override
|
||||||
|
{
|
||||||
|
SELECTION_TOOL* selTool = getToolManager()->GetTool<SELECTION_TOOL>();
|
||||||
|
BOARD* board = selTool->GetBoard();
|
||||||
|
|
||||||
|
const auto& selection = selTool->GetSelection();
|
||||||
|
|
||||||
|
wxString check = board->GroupsSanityCheck();
|
||||||
|
wxCHECK_RET( check == wxEmptyString, _( "Group is in inconsistent state: " ) + check );
|
||||||
|
|
||||||
|
BOARD::GroupLegalOpsField legalOps = board->GroupLegalOps( selection );
|
||||||
|
|
||||||
|
Enable( PCB_ACTIONS::groupCreate.GetUIId(), legalOps.create );
|
||||||
|
Enable( PCB_ACTIONS::groupUngroup.GetUIId(), legalOps.ungroup );
|
||||||
|
Enable( PCB_ACTIONS::groupRemoveItems.GetUIId(), legalOps.removeItems );
|
||||||
|
Enable( PCB_ACTIONS::groupEnter.GetUIId(), legalOps.enter );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
GROUP_TOOL::GROUP_TOOL() :
|
GROUP_TOOL::GROUP_TOOL() :
|
||||||
PCB_TOOL_BASE( "pcbnew.Groups" ),
|
PCB_TOOL_BASE( "pcbnew.Groups" ),
|
||||||
|
m_frame( nullptr ),
|
||||||
m_propertiesDialog( nullptr ),
|
m_propertiesDialog( nullptr ),
|
||||||
m_selectionTool( nullptr )
|
m_selectionTool( nullptr )
|
||||||
{
|
{
|
||||||
|
@ -175,6 +217,8 @@ GROUP_TOOL::GROUP_TOOL() :
|
||||||
|
|
||||||
void GROUP_TOOL::Reset( RESET_REASON aReason )
|
void GROUP_TOOL::Reset( RESET_REASON aReason )
|
||||||
{
|
{
|
||||||
|
m_frame = getEditFrame<PCB_BASE_EDIT_FRAME>();
|
||||||
|
|
||||||
if( aReason != RUN )
|
if( aReason != RUN )
|
||||||
m_commit = std::make_unique<BOARD_COMMIT>( this );
|
m_commit = std::make_unique<BOARD_COMMIT>( this );
|
||||||
}
|
}
|
||||||
|
@ -182,17 +226,33 @@ void GROUP_TOOL::Reset( RESET_REASON aReason )
|
||||||
|
|
||||||
bool GROUP_TOOL::Init()
|
bool GROUP_TOOL::Init()
|
||||||
{
|
{
|
||||||
|
m_frame = getEditFrame<PCB_BASE_EDIT_FRAME>();
|
||||||
|
|
||||||
// Find the selection tool, so they can cooperate
|
// Find the selection tool, so they can cooperate
|
||||||
m_selectionTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
m_selectionTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
||||||
|
|
||||||
return m_selectionTool != nullptr;
|
auto groupMenu = std::make_shared<GROUP_CONTEXT_MENU>();
|
||||||
|
groupMenu->SetTool( this );
|
||||||
|
|
||||||
|
// Add the group control menus to relevant other tools
|
||||||
|
if( m_selectionTool )
|
||||||
|
{
|
||||||
|
auto& toolMenu = m_selectionTool->GetToolMenu();
|
||||||
|
auto& menu = toolMenu.GetMenu();
|
||||||
|
|
||||||
|
toolMenu.AddSubMenu( groupMenu );
|
||||||
|
|
||||||
|
menu.AddMenu( groupMenu.get(), SELECTION_CONDITIONS::NotEmpty, 100 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int GROUP_TOOL::GroupProperties( const TOOL_EVENT& aEvent )
|
int GROUP_TOOL::GroupProperties( const TOOL_EVENT& aEvent )
|
||||||
{
|
{
|
||||||
PCB_EDIT_FRAME* editFrame = getEditFrame<PCB_EDIT_FRAME>();
|
PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
|
||||||
PCB_GROUP* group = aEvent.Parameter<PCB_GROUP*>();
|
PCB_GROUP* group = aEvent.Parameter<PCB_GROUP*>();
|
||||||
|
|
||||||
if( m_propertiesDialog )
|
if( m_propertiesDialog )
|
||||||
m_propertiesDialog->Destroy();
|
m_propertiesDialog->Destroy();
|
||||||
|
@ -277,8 +337,175 @@ int GROUP_TOOL::PickNewMember( const TOOL_EVENT& aEvent )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int GROUP_TOOL::Group( const TOOL_EVENT& aEvent )
|
||||||
|
{
|
||||||
|
SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
||||||
|
const PCBNEW_SELECTION& selection = selTool->GetSelection();
|
||||||
|
BOARD* board = getModel<BOARD>();
|
||||||
|
PCB_GROUP* group = nullptr;
|
||||||
|
|
||||||
|
if( selection.Empty() )
|
||||||
|
m_toolMgr->RunAction( PCB_ACTIONS::selectionCursor, true );
|
||||||
|
|
||||||
|
if( m_editModules )
|
||||||
|
{
|
||||||
|
MODULE* module = board->GetFirstModule();
|
||||||
|
|
||||||
|
m_frame->SaveCopyInUndoList( module, UNDO_REDO::CHANGED );
|
||||||
|
|
||||||
|
group = new PCB_GROUP( module );
|
||||||
|
module->Add( group );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PICKED_ITEMS_LIST undoList;
|
||||||
|
|
||||||
|
group = new PCB_GROUP( board );
|
||||||
|
board->Add( group );
|
||||||
|
|
||||||
|
undoList.PushItem( ITEM_PICKER( nullptr, group, UNDO_REDO::NEWITEM ) );
|
||||||
|
|
||||||
|
for( EDA_ITEM* item : selection )
|
||||||
|
{
|
||||||
|
group->AddItem( static_cast<BOARD_ITEM*>( item ) );
|
||||||
|
undoList.PushItem( ITEM_PICKER( nullptr, item, UNDO_REDO::GROUP ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_frame->SaveCopyInUndoList( undoList, UNDO_REDO::GROUP );
|
||||||
|
}
|
||||||
|
|
||||||
|
selTool->ClearSelection();
|
||||||
|
selTool->select( group );
|
||||||
|
|
||||||
|
m_toolMgr->PostEvent( EVENTS::SelectedItemsModified );
|
||||||
|
m_frame->OnModify();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int GROUP_TOOL::Ungroup( const TOOL_EVENT& aEvent )
|
||||||
|
{
|
||||||
|
const PCBNEW_SELECTION& selection = m_toolMgr->GetTool<SELECTION_TOOL>()->GetSelection();
|
||||||
|
BOARD* board = getModel<BOARD>();
|
||||||
|
std::vector<BOARD_ITEM*> members;
|
||||||
|
|
||||||
|
if( selection.Empty() )
|
||||||
|
m_toolMgr->RunAction( PCB_ACTIONS::selectionCursor, true );
|
||||||
|
|
||||||
|
PCBNEW_SELECTION selCopy = selection;
|
||||||
|
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
||||||
|
|
||||||
|
for( EDA_ITEM* item : selCopy )
|
||||||
|
{
|
||||||
|
PCB_GROUP* group = dynamic_cast<PCB_GROUP*>( item );
|
||||||
|
|
||||||
|
if( group )
|
||||||
|
{
|
||||||
|
if( m_editModules )
|
||||||
|
{
|
||||||
|
MODULE* module = board->GetFirstModule();
|
||||||
|
|
||||||
|
m_frame->SaveCopyInUndoList( module, UNDO_REDO::CHANGED );
|
||||||
|
|
||||||
|
group->RemoveAll();
|
||||||
|
module->Remove( group );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PICKED_ITEMS_LIST undoList;
|
||||||
|
|
||||||
|
for( BOARD_ITEM* member : group->GetItems() )
|
||||||
|
{
|
||||||
|
undoList.PushItem( ITEM_PICKER( nullptr, member, UNDO_REDO::UNGROUP ) );
|
||||||
|
members.push_back( member );
|
||||||
|
}
|
||||||
|
|
||||||
|
group->RemoveAll();
|
||||||
|
board->Remove( group );
|
||||||
|
|
||||||
|
undoList.PushItem( ITEM_PICKER( nullptr, group, UNDO_REDO::DELETED ) );
|
||||||
|
|
||||||
|
m_frame->SaveCopyInUndoList( undoList, UNDO_REDO::UNGROUP );
|
||||||
|
}
|
||||||
|
|
||||||
|
group->SetSelected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_toolMgr->RunAction( PCB_ACTIONS::selectItems, true, &members );
|
||||||
|
|
||||||
|
m_toolMgr->PostEvent( EVENTS::SelectedItemsModified );
|
||||||
|
m_frame->OnModify();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int GROUP_TOOL::RemoveFromGroup( const TOOL_EVENT& aEvent )
|
||||||
|
{
|
||||||
|
SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
||||||
|
const PCBNEW_SELECTION& selection = selTool->GetSelection();
|
||||||
|
BOARD_COMMIT commit( m_frame );
|
||||||
|
|
||||||
|
if( selection.Empty() )
|
||||||
|
m_toolMgr->RunAction( PCB_ACTIONS::selectionCursor, true );
|
||||||
|
|
||||||
|
std::map<PCB_GROUP*, std::vector<BOARD_ITEM*>> groupMap;
|
||||||
|
|
||||||
|
for( EDA_ITEM* item : selection )
|
||||||
|
{
|
||||||
|
BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
|
||||||
|
PCB_GROUP* group = boardItem->GetParentGroup();
|
||||||
|
|
||||||
|
if( group )
|
||||||
|
groupMap[ group ].push_back( boardItem );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( std::pair<PCB_GROUP*, std::vector<BOARD_ITEM*>> pair : groupMap )
|
||||||
|
{
|
||||||
|
commit.Modify( pair.first );
|
||||||
|
|
||||||
|
for( BOARD_ITEM* item : pair.second )
|
||||||
|
pair.first->RemoveItem( item );
|
||||||
|
}
|
||||||
|
|
||||||
|
commit.Push( "Remove Group Items" );
|
||||||
|
|
||||||
|
m_toolMgr->PostEvent( EVENTS::SelectedItemsModified );
|
||||||
|
m_frame->OnModify();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int GROUP_TOOL::EnterGroup( const TOOL_EVENT& aEvent )
|
||||||
|
{
|
||||||
|
SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
||||||
|
const PCBNEW_SELECTION& selection = selTool->GetSelection();
|
||||||
|
|
||||||
|
if( selection.GetSize() == 1 && selection[0]->Type() == PCB_GROUP_T )
|
||||||
|
selTool->EnterGroup();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int GROUP_TOOL::LeaveGroup( const TOOL_EVENT& aEvent )
|
||||||
|
{
|
||||||
|
m_toolMgr->GetTool<SELECTION_TOOL>()->ExitGroup( true /* Select the group */ );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void GROUP_TOOL::setTransitions()
|
void GROUP_TOOL::setTransitions()
|
||||||
{
|
{
|
||||||
Go( &GROUP_TOOL::GroupProperties, PCB_ACTIONS::groupProperties.MakeEvent() );
|
Go( &GROUP_TOOL::GroupProperties, PCB_ACTIONS::groupProperties.MakeEvent() );
|
||||||
Go( &GROUP_TOOL::PickNewMember, PCB_ACTIONS::pickNewGroupMember.MakeEvent() );
|
Go( &GROUP_TOOL::PickNewMember, PCB_ACTIONS::pickNewGroupMember.MakeEvent() );
|
||||||
|
|
||||||
|
Go( &GROUP_TOOL::Group, PCB_ACTIONS::groupCreate.MakeEvent() );
|
||||||
|
Go( &GROUP_TOOL::Ungroup, PCB_ACTIONS::groupUngroup.MakeEvent() );
|
||||||
|
Go( &GROUP_TOOL::RemoveFromGroup, PCB_ACTIONS::groupRemoveItems.MakeEvent() );
|
||||||
|
Go( &GROUP_TOOL::EnterGroup, PCB_ACTIONS::groupEnter.MakeEvent() );
|
||||||
|
Go( &GROUP_TOOL::LeaveGroup, PCB_ACTIONS::groupLeave.MakeEvent() );
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,10 +53,27 @@ public:
|
||||||
*/
|
*/
|
||||||
int PickNewMember( const TOOL_EVENT& aEvent );
|
int PickNewMember( const TOOL_EVENT& aEvent );
|
||||||
|
|
||||||
|
///> Groups selected items.
|
||||||
|
int Group( const TOOL_EVENT& aEvent );
|
||||||
|
|
||||||
|
///> Ungroups selected items.
|
||||||
|
int Ungroup( const TOOL_EVENT& aEvent );
|
||||||
|
|
||||||
|
///> Remove selection from group.
|
||||||
|
int RemoveFromGroup( const TOOL_EVENT& aEvent );
|
||||||
|
|
||||||
|
///> Restrict seletion to only member of the group.
|
||||||
|
int EnterGroup( const TOOL_EVENT& aEvent );
|
||||||
|
|
||||||
|
///> Leave the current group (deselect its members and select the group as a whole)
|
||||||
|
int LeaveGroup( const TOOL_EVENT& aEvent );
|
||||||
|
|
||||||
|
private:
|
||||||
///> Sets up handlers for various events.
|
///> Sets up handlers for various events.
|
||||||
void setTransitions() override;
|
void setTransitions() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
PCB_BASE_EDIT_FRAME* m_frame;
|
||||||
DIALOG_GROUP_PROPERTIES* m_propertiesDialog;
|
DIALOG_GROUP_PROPERTIES* m_propertiesDialog;
|
||||||
SELECTION_TOOL* m_selectionTool;
|
SELECTION_TOOL* m_selectionTool;
|
||||||
std::unique_ptr<BOARD_COMMIT> m_commit;
|
std::unique_ptr<BOARD_COMMIT> m_commit;
|
||||||
|
|
|
@ -119,46 +119,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class GROUP_CONTEXT_MENU : public ACTION_MENU
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GROUP_CONTEXT_MENU( ) : ACTION_MENU( true )
|
|
||||||
{
|
|
||||||
SetIcon( locked_xpm ); // fixme
|
|
||||||
SetTitle( _( "Grouping" ) );
|
|
||||||
|
|
||||||
Add( PCB_ACTIONS::groupCreate );
|
|
||||||
Add( PCB_ACTIONS::groupUngroup );
|
|
||||||
Add( PCB_ACTIONS::groupRemoveItems );
|
|
||||||
Add( PCB_ACTIONS::groupEnter );
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTION_MENU* create() const override
|
|
||||||
{
|
|
||||||
return new GROUP_CONTEXT_MENU();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void update() override
|
|
||||||
{
|
|
||||||
SELECTION_TOOL* selTool = getToolManager()->GetTool<SELECTION_TOOL>();
|
|
||||||
BOARD* board = selTool->GetBoard();
|
|
||||||
|
|
||||||
const auto& selection = selTool->GetSelection();
|
|
||||||
|
|
||||||
wxString check = board->GroupsSanityCheck();
|
|
||||||
wxCHECK_RET( check == wxEmptyString, _( "Group is in inconsistent state: " ) + check );
|
|
||||||
|
|
||||||
BOARD::GroupLegalOpsField legalOps = board->GroupLegalOps( selection );
|
|
||||||
|
|
||||||
Enable( PCB_ACTIONS::groupCreate.GetUIId(), legalOps.create );
|
|
||||||
Enable( PCB_ACTIONS::groupUngroup.GetUIId(), legalOps.ungroup );
|
|
||||||
Enable( PCB_ACTIONS::groupRemoveItems.GetUIId(), legalOps.removeItems );
|
|
||||||
Enable( PCB_ACTIONS::groupEnter.GetUIId(), legalOps.enter );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
PCB_EDITOR_CONTROL::PCB_EDITOR_CONTROL() :
|
PCB_EDITOR_CONTROL::PCB_EDITOR_CONTROL() :
|
||||||
PCB_TOOL_BASE( "pcbnew.EditorControl" ),
|
PCB_TOOL_BASE( "pcbnew.EditorControl" ),
|
||||||
m_frame( nullptr )
|
m_frame( nullptr )
|
||||||
|
@ -219,9 +179,6 @@ bool PCB_EDITOR_CONTROL::Init()
|
||||||
auto lockMenu = std::make_shared<LOCK_CONTEXT_MENU>();
|
auto lockMenu = std::make_shared<LOCK_CONTEXT_MENU>();
|
||||||
lockMenu->SetTool( this );
|
lockMenu->SetTool( this );
|
||||||
|
|
||||||
auto groupMenu = std::make_shared<GROUP_CONTEXT_MENU>();
|
|
||||||
groupMenu->SetTool( this );
|
|
||||||
|
|
||||||
// Add the PCB control menus to relevant other tools
|
// Add the PCB control menus to relevant other tools
|
||||||
|
|
||||||
SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
||||||
|
@ -237,9 +194,7 @@ bool PCB_EDITOR_CONTROL::Init()
|
||||||
|
|
||||||
toolMenu.AddSubMenu( zoneMenu );
|
toolMenu.AddSubMenu( zoneMenu );
|
||||||
toolMenu.AddSubMenu( lockMenu );
|
toolMenu.AddSubMenu( lockMenu );
|
||||||
toolMenu.AddSubMenu( groupMenu );
|
|
||||||
|
|
||||||
menu.AddMenu( groupMenu.get(), SELECTION_CONDITIONS::NotEmpty, 100 );
|
|
||||||
menu.AddMenu( lockMenu.get(), SELECTION_CONDITIONS::OnlyTypes( GENERAL_COLLECTOR::LockableItems ), 100 );
|
menu.AddMenu( lockMenu.get(), SELECTION_CONDITIONS::OnlyTypes( GENERAL_COLLECTOR::LockableItems ), 100 );
|
||||||
|
|
||||||
menu.AddMenu( zoneMenu.get(), SELECTION_CONDITIONS::OnlyType( PCB_ZONE_AREA_T ), 200 );
|
menu.AddMenu( zoneMenu.get(), SELECTION_CONDITIONS::OnlyType( PCB_ZONE_AREA_T ), 200 );
|
||||||
|
@ -995,138 +950,6 @@ int PCB_EDITOR_CONTROL::modifyLockSelected( MODIFY_MODE aMode )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int PCB_EDITOR_CONTROL::Group( const TOOL_EVENT& aEvent )
|
|
||||||
{
|
|
||||||
SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
|
||||||
const PCBNEW_SELECTION& selection = selTool->GetSelection();
|
|
||||||
BOARD* board = getModel<BOARD>();
|
|
||||||
PICKED_ITEMS_LIST undoList;
|
|
||||||
|
|
||||||
if( selection.Empty() )
|
|
||||||
m_toolMgr->RunAction( PCB_ACTIONS::selectionCursor, true );
|
|
||||||
|
|
||||||
PCB_GROUP* group = new PCB_GROUP( board );
|
|
||||||
board->Add( group );
|
|
||||||
|
|
||||||
undoList.PushItem( ITEM_PICKER( nullptr, group, UNDO_REDO::NEWITEM ) );
|
|
||||||
|
|
||||||
for( EDA_ITEM* item : selection )
|
|
||||||
{
|
|
||||||
group->AddItem( static_cast<BOARD_ITEM*>( item ) );
|
|
||||||
undoList.PushItem( ITEM_PICKER( nullptr, item, UNDO_REDO::GROUP ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
m_frame->SaveCopyInUndoList( undoList, UNDO_REDO::GROUP );
|
|
||||||
|
|
||||||
selTool->ClearSelection();
|
|
||||||
selTool->select( group );
|
|
||||||
|
|
||||||
m_toolMgr->PostEvent( EVENTS::SelectedItemsModified );
|
|
||||||
m_frame->OnModify();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int PCB_EDITOR_CONTROL::Ungroup( const TOOL_EVENT& aEvent )
|
|
||||||
{
|
|
||||||
const PCBNEW_SELECTION& selection = m_toolMgr->GetTool<SELECTION_TOOL>()->GetSelection();
|
|
||||||
PICKED_ITEMS_LIST undoList;
|
|
||||||
std::vector<BOARD_ITEM*> members;
|
|
||||||
|
|
||||||
if( selection.Empty() )
|
|
||||||
m_toolMgr->RunAction( PCB_ACTIONS::selectionCursor, true );
|
|
||||||
|
|
||||||
PCBNEW_SELECTION selCopy = selection;
|
|
||||||
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
|
||||||
|
|
||||||
for( EDA_ITEM* item : selCopy )
|
|
||||||
{
|
|
||||||
PCB_GROUP* group = dynamic_cast<PCB_GROUP*>( item );
|
|
||||||
|
|
||||||
if( group )
|
|
||||||
{
|
|
||||||
for( BOARD_ITEM* member : group->GetItems() )
|
|
||||||
{
|
|
||||||
undoList.PushItem( ITEM_PICKER( nullptr, member, UNDO_REDO::UNGROUP ) );
|
|
||||||
members.push_back( member );
|
|
||||||
}
|
|
||||||
|
|
||||||
group->RemoveAll();
|
|
||||||
m_frame->GetBoard()->Remove( group );
|
|
||||||
|
|
||||||
group->SetSelected();
|
|
||||||
undoList.PushItem( ITEM_PICKER( nullptr, group, UNDO_REDO::DELETED ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_frame->SaveCopyInUndoList( undoList, UNDO_REDO::UNGROUP );
|
|
||||||
|
|
||||||
m_toolMgr->RunAction( PCB_ACTIONS::selectItems, true, &members );
|
|
||||||
|
|
||||||
m_toolMgr->PostEvent( EVENTS::SelectedItemsModified );
|
|
||||||
m_frame->OnModify();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int PCB_EDITOR_CONTROL::RemoveFromGroup( const TOOL_EVENT& aEvent )
|
|
||||||
{
|
|
||||||
SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
|
||||||
const PCBNEW_SELECTION& selection = selTool->GetSelection();
|
|
||||||
BOARD_COMMIT commit( m_frame );
|
|
||||||
|
|
||||||
if( selection.Empty() )
|
|
||||||
m_toolMgr->RunAction( PCB_ACTIONS::selectionCursor, true );
|
|
||||||
|
|
||||||
std::map<PCB_GROUP*, std::vector<BOARD_ITEM*>> groupMap;
|
|
||||||
|
|
||||||
for( EDA_ITEM* item : selection )
|
|
||||||
{
|
|
||||||
BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
|
|
||||||
PCB_GROUP* group = boardItem->GetParentGroup();
|
|
||||||
|
|
||||||
if( group )
|
|
||||||
groupMap[ group ].push_back( boardItem );
|
|
||||||
}
|
|
||||||
|
|
||||||
for( std::pair<PCB_GROUP*, std::vector<BOARD_ITEM*>> pair : groupMap )
|
|
||||||
{
|
|
||||||
commit.Modify( pair.first );
|
|
||||||
|
|
||||||
for( BOARD_ITEM* item : pair.second )
|
|
||||||
pair.first->RemoveItem( item );
|
|
||||||
}
|
|
||||||
|
|
||||||
commit.Push( "Remove Group Items" );
|
|
||||||
|
|
||||||
m_toolMgr->PostEvent( EVENTS::SelectedItemsModified );
|
|
||||||
m_frame->OnModify();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int PCB_EDITOR_CONTROL::EnterGroup( const TOOL_EVENT& aEvent )
|
|
||||||
{
|
|
||||||
SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
|
||||||
const PCBNEW_SELECTION& selection = selTool->GetSelection();
|
|
||||||
|
|
||||||
if( selection.GetSize() == 1 && selection[0]->Type() == PCB_GROUP_T )
|
|
||||||
selTool->EnterGroup();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int PCB_EDITOR_CONTROL::LeaveGroup( const TOOL_EVENT& aEvent )
|
|
||||||
{
|
|
||||||
m_toolMgr->GetTool<SELECTION_TOOL>()->ExitGroup( true /* Select the group */ );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int PCB_EDITOR_CONTROL::PlaceTarget( const TOOL_EVENT& aEvent )
|
int PCB_EDITOR_CONTROL::PlaceTarget( const TOOL_EVENT& aEvent )
|
||||||
{
|
{
|
||||||
KIGFX::VIEW* view = getView();
|
KIGFX::VIEW* view = getView();
|
||||||
|
@ -1492,11 +1315,6 @@ void PCB_EDITOR_CONTROL::setTransitions()
|
||||||
Go( &PCB_EDITOR_CONTROL::ToggleLockSelected, PCB_ACTIONS::toggleLock.MakeEvent() );
|
Go( &PCB_EDITOR_CONTROL::ToggleLockSelected, PCB_ACTIONS::toggleLock.MakeEvent() );
|
||||||
Go( &PCB_EDITOR_CONTROL::LockSelected, PCB_ACTIONS::lock.MakeEvent() );
|
Go( &PCB_EDITOR_CONTROL::LockSelected, PCB_ACTIONS::lock.MakeEvent() );
|
||||||
Go( &PCB_EDITOR_CONTROL::UnlockSelected, PCB_ACTIONS::unlock.MakeEvent() );
|
Go( &PCB_EDITOR_CONTROL::UnlockSelected, PCB_ACTIONS::unlock.MakeEvent() );
|
||||||
Go( &PCB_EDITOR_CONTROL::Group, PCB_ACTIONS::groupCreate.MakeEvent() );
|
|
||||||
Go( &PCB_EDITOR_CONTROL::Ungroup, PCB_ACTIONS::groupUngroup.MakeEvent() );
|
|
||||||
Go( &PCB_EDITOR_CONTROL::RemoveFromGroup, PCB_ACTIONS::groupRemoveItems.MakeEvent() );
|
|
||||||
Go( &PCB_EDITOR_CONTROL::EnterGroup, PCB_ACTIONS::groupEnter.MakeEvent() );
|
|
||||||
Go( &PCB_EDITOR_CONTROL::LeaveGroup, PCB_ACTIONS::groupLeave.MakeEvent() );
|
|
||||||
|
|
||||||
Go( &PCB_EDITOR_CONTROL::UpdatePCBFromSchematic, ACTIONS::updatePcbFromSchematic.MakeEvent() );
|
Go( &PCB_EDITOR_CONTROL::UpdatePCBFromSchematic, ACTIONS::updatePcbFromSchematic.MakeEvent() );
|
||||||
Go( &PCB_EDITOR_CONTROL::UpdateSchematicFromPCB, ACTIONS::updateSchematicFromPcb.MakeEvent() );
|
Go( &PCB_EDITOR_CONTROL::UpdateSchematicFromPCB, ACTIONS::updateSchematicFromPcb.MakeEvent() );
|
||||||
|
|
|
@ -109,21 +109,6 @@ public:
|
||||||
///> Unlocks selected items.
|
///> Unlocks selected items.
|
||||||
int UnlockSelected( const TOOL_EVENT& aEvent );
|
int UnlockSelected( const TOOL_EVENT& aEvent );
|
||||||
|
|
||||||
///> Groups selected items.
|
|
||||||
int Group( const TOOL_EVENT& aEvent );
|
|
||||||
|
|
||||||
///> Ungroups selected items.
|
|
||||||
int Ungroup( const TOOL_EVENT& aEvent );
|
|
||||||
|
|
||||||
///> Remove selection from group.
|
|
||||||
int RemoveFromGroup( const TOOL_EVENT& aEvent );
|
|
||||||
|
|
||||||
///> Restrict seletion to only member of the group.
|
|
||||||
int EnterGroup( const TOOL_EVENT& aEvent );
|
|
||||||
|
|
||||||
///> Leave the current group (deselect its members and select the group as a whole)
|
|
||||||
int LeaveGroup( const TOOL_EVENT& aEvent );
|
|
||||||
|
|
||||||
///> Runs the drill origin tool for setting the origin for drill and pick-and-place files.
|
///> Runs the drill origin tool for setting the origin for drill and pick-and-place files.
|
||||||
int DrillOrigin( const TOOL_EVENT& aEvent );
|
int DrillOrigin( const TOOL_EVENT& aEvent );
|
||||||
|
|
||||||
|
|
|
@ -114,28 +114,25 @@ using namespace std::placeholders;
|
||||||
|
|
||||||
static bool TestForExistingItem( BOARD* aPcb, BOARD_ITEM* aItem )
|
static bool TestForExistingItem( BOARD* aPcb, BOARD_ITEM* aItem )
|
||||||
{
|
{
|
||||||
for( auto item : aPcb->Tracks() )
|
for( TRACK* item : aPcb->Tracks() )
|
||||||
{
|
{
|
||||||
if( aItem == static_cast<BOARD_ITEM*>( item ) )
|
if( aItem == static_cast<BOARD_ITEM*>( item ) )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append modules:
|
for( MODULE* item : aPcb->Modules() )
|
||||||
for( auto item : aPcb->Modules() )
|
|
||||||
{
|
{
|
||||||
if( aItem == static_cast<BOARD_ITEM*>( item ) )
|
if( aItem == static_cast<BOARD_ITEM*>( item ) )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append drawings
|
for( BOARD_ITEM* item : aPcb->Drawings() )
|
||||||
for( auto item : aPcb->Drawings() )
|
|
||||||
{
|
{
|
||||||
if( aItem == static_cast<BOARD_ITEM*>( item ) )
|
if( aItem == static_cast<BOARD_ITEM*>( item ) )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append zones outlines
|
for( ZONE_CONTAINER* item : aPcb->Zones() )
|
||||||
for( auto item : aPcb->Zones() )
|
|
||||||
{
|
{
|
||||||
if( aItem == static_cast<BOARD_ITEM*>( item ) )
|
if( aItem == static_cast<BOARD_ITEM*>( item ) )
|
||||||
return true;
|
return true;
|
||||||
|
@ -149,8 +146,7 @@ static bool TestForExistingItem( BOARD* aPcb, BOARD_ITEM* aItem )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append groups:
|
for( PCB_GROUP* item : aPcb->Groups() )
|
||||||
for( auto item : aPcb->Groups() )
|
|
||||||
{
|
{
|
||||||
if( aItem == static_cast<BOARD_ITEM*>( item ) )
|
if( aItem == static_cast<BOARD_ITEM*>( item ) )
|
||||||
return true;
|
return true;
|
||||||
|
@ -195,8 +191,6 @@ void PCB_BASE_EDIT_FRAME::SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsLis
|
||||||
UNDO_REDO aTypeCommand,
|
UNDO_REDO aTypeCommand,
|
||||||
const wxPoint& aTransformPoint )
|
const wxPoint& aTransformPoint )
|
||||||
{
|
{
|
||||||
static KICAD_T moduleChildren[] = { PCB_MODULE_TEXT_T, PCB_MODULE_EDGE_T, PCB_PAD_T, EOT };
|
|
||||||
|
|
||||||
PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST();
|
PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST();
|
||||||
|
|
||||||
commandToUndo->m_TransformPoint = aTransformPoint;
|
commandToUndo->m_TransformPoint = aTransformPoint;
|
||||||
|
@ -210,14 +204,9 @@ void PCB_BASE_EDIT_FRAME::SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsLis
|
||||||
BOARD_ITEM* item = dynamic_cast<BOARD_ITEM*>( aItemsList.GetPickedItem( ii ) );
|
BOARD_ITEM* item = dynamic_cast<BOARD_ITEM*>( aItemsList.GetPickedItem( ii ) );
|
||||||
|
|
||||||
// For items belonging to modules, we need to save state of the parent module
|
// For items belonging to modules, we need to save state of the parent module
|
||||||
if( item && item->IsType( moduleChildren ) )
|
if( item && item->GetParent() && item->GetParent()->Type() == PCB_MODULE_T )
|
||||||
{
|
{
|
||||||
// Item to be stored in the undo buffer is the parent module
|
|
||||||
item = item->GetParent();
|
item = item->GetParent();
|
||||||
wxASSERT( item && item->Type() == PCB_MODULE_T );
|
|
||||||
|
|
||||||
if( item == NULL )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Check if the parent module has already been saved in another entry
|
// Check if the parent module has already been saved in another entry
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
Loading…
Reference in New Issue