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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()
|
||||
* Sets a group id for the item and the layer combination.
|
||||
|
|
|
@ -51,7 +51,7 @@ class VIEW;
|
|||
class PCB_GROUP : public BOARD_ITEM
|
||||
{
|
||||
public:
|
||||
PCB_GROUP( BOARD* aParent );
|
||||
PCB_GROUP( BOARD_ITEM* aParent );
|
||||
|
||||
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 )
|
||||
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() )
|
||||
|
|
|
@ -92,36 +92,48 @@ MODULE::MODULE( const MODULE& aModule ) :
|
|||
m_Value = new TEXTE_MODULE( *aModule.m_Value );
|
||||
m_Value->SetParent( this );
|
||||
|
||||
// Copy auxiliary data: Pads
|
||||
for( D_PAD* pad : aModule.Pads() )
|
||||
Add( static_cast<D_PAD*>( pad->Clone() ) );
|
||||
std::map<BOARD_ITEM*, BOARD_ITEM*> ptrMap;
|
||||
|
||||
// Copy auxiliary data: Zones
|
||||
for( MODULE_ZONE_CONTAINER* item : aModule.Zones() )
|
||||
// Copy pads
|
||||
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
|
||||
// living in the current 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.
|
||||
item->SetNetCode( -1 );
|
||||
newZone->SetNetCode( -1 );
|
||||
}
|
||||
|
||||
// Copy auxiliary data: Drawings
|
||||
// Copy drawings
|
||||
for( BOARD_ITEM* item : aModule.GraphicalItems() )
|
||||
{
|
||||
switch( item->Type() )
|
||||
{
|
||||
case PCB_MODULE_TEXT_T:
|
||||
case PCB_MODULE_EDGE_T:
|
||||
Add( static_cast<BOARD_ITEM*>( item->Clone() ) );
|
||||
break;
|
||||
BOARD_ITEM* newItem = static_cast<BOARD_ITEM*>( item->Clone() );
|
||||
ptrMap[ item ] = newItem;
|
||||
Add( newItem );
|
||||
}
|
||||
|
||||
default:
|
||||
wxLogMessage( wxT( "Class MODULE copy constructor internal error: unknown type" ) );
|
||||
break;
|
||||
}
|
||||
// Copy groups
|
||||
for( PCB_GROUP* group : aModule.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
|
||||
|
@ -160,11 +172,16 @@ MODULE::~MODULE()
|
|||
|
||||
m_pads.clear();
|
||||
|
||||
for( MODULE_ZONE_CONTAINER* p : m_fp_zones )
|
||||
delete p;
|
||||
for( MODULE_ZONE_CONTAINER* zone : m_fp_zones )
|
||||
delete zone;
|
||||
|
||||
m_fp_zones.clear();
|
||||
|
||||
for( PCB_GROUP* group : m_fp_groups )
|
||||
delete group;
|
||||
|
||||
m_fp_groups.clear();
|
||||
|
||||
for( BOARD_ITEM* d : m_drawings )
|
||||
delete d;
|
||||
|
||||
|
@ -209,12 +226,14 @@ MODULE& MODULE::operator=( MODULE&& aOther )
|
|||
for( D_PAD* pad : aOther.Pads() )
|
||||
Add( pad );
|
||||
|
||||
aOther.Pads().clear();
|
||||
|
||||
// Move the zones
|
||||
m_fp_zones.clear();
|
||||
|
||||
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
|
||||
// living in the current board
|
||||
|
@ -223,23 +242,23 @@ MODULE& MODULE::operator=( MODULE&& aOther )
|
|||
item->SetNetCode( -1 );
|
||||
}
|
||||
|
||||
aOther.Zones().clear();
|
||||
|
||||
// Move the drawings
|
||||
m_drawings.clear();
|
||||
|
||||
for( BOARD_ITEM* item : aOther.GraphicalItems() )
|
||||
{
|
||||
switch( item->Type() )
|
||||
{
|
||||
case PCB_MODULE_TEXT_T:
|
||||
case PCB_MODULE_EDGE_T:
|
||||
Add( static_cast<BOARD_ITEM*>( item ) );
|
||||
break;
|
||||
Add( item );
|
||||
|
||||
default:
|
||||
wxLogMessage( wxT( "MODULE::operator=() internal error: unknown type" ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
aOther.GraphicalItems().clear();
|
||||
|
||||
// Move the groups
|
||||
m_fp_groups.clear();
|
||||
|
||||
for( PCB_GROUP* group : aOther.Groups() )
|
||||
Add( group );
|
||||
|
||||
aOther.Groups().clear();
|
||||
|
||||
// Copy auxiliary data: 3D_Drawings info
|
||||
m_3D_Drawings.clear();
|
||||
|
@ -295,42 +314,56 @@ MODULE& MODULE::operator=( const MODULE& aOther )
|
|||
*m_Value = *aOther.m_Value;
|
||||
m_Value->SetParent( this );
|
||||
|
||||
// Copy auxiliary data: Pads
|
||||
std::map<BOARD_ITEM*, BOARD_ITEM*> ptrMap;
|
||||
|
||||
// Copy pads
|
||||
m_pads.clear();
|
||||
|
||||
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();
|
||||
|
||||
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
|
||||
// living in the current 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.
|
||||
item->SetNetCode( -1 );
|
||||
newZone->SetNetCode( -1 );
|
||||
}
|
||||
|
||||
// Copy auxiliary data: Drawings
|
||||
// Copy drawings
|
||||
m_drawings.clear();
|
||||
|
||||
for( BOARD_ITEM* item : aOther.GraphicalItems() )
|
||||
{
|
||||
switch( item->Type() )
|
||||
{
|
||||
case PCB_MODULE_TEXT_T:
|
||||
case PCB_MODULE_EDGE_T:
|
||||
Add( static_cast<BOARD_ITEM*>( item->Clone() ) );
|
||||
break;
|
||||
BOARD_ITEM* newItem = static_cast<BOARD_ITEM*>( item->Clone() );
|
||||
ptrMap[ item ] = newItem;
|
||||
Add( newItem );
|
||||
}
|
||||
|
||||
default:
|
||||
wxLogMessage( wxT( "MODULE::operator=() internal error: unknown type" ) );
|
||||
break;
|
||||
}
|
||||
// Copy groups
|
||||
m_fp_groups.clear();
|
||||
|
||||
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
|
||||
|
@ -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 ) );
|
||||
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:
|
||||
{
|
||||
wxString msg;
|
||||
|
@ -487,6 +527,18 @@ void MODULE::Remove( BOARD_ITEM* aBoardItem )
|
|||
|
||||
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:
|
||||
{
|
||||
wxString msg;
|
||||
|
@ -532,6 +584,8 @@ EDA_RECT MODULE::GetFootprintRect() const
|
|||
for( MODULE_ZONE_CONTAINER* zone : m_fp_zones )
|
||||
area.Merge( zone->GetBoundingBox() );
|
||||
|
||||
// Groups do not contribute to the rect, only their members
|
||||
|
||||
return area;
|
||||
}
|
||||
|
||||
|
@ -770,6 +824,8 @@ bool MODULE::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) co
|
|||
return true;
|
||||
}
|
||||
|
||||
// Groups are not hit-tested; only their members
|
||||
|
||||
// No items were hit
|
||||
return false;
|
||||
}
|
||||
|
@ -955,6 +1011,11 @@ SEARCH_RESULT MODULE::Visit( INSPECTOR inspector, void* testData, const KICAD_T
|
|||
|
||||
break;
|
||||
|
||||
case PCB_GROUP_T:
|
||||
result = IterateForward<PCB_GROUP*>( m_fp_groups, inspector, testData, p );
|
||||
++p;
|
||||
break;
|
||||
|
||||
default:
|
||||
done = true;
|
||||
break;
|
||||
|
@ -1001,6 +1062,9 @@ void MODULE::RunOnChildren( const std::function<void (BOARD_ITEM*)>& aFunction )
|
|||
for( MODULE_ZONE_CONTAINER* zone : m_fp_zones )
|
||||
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 )
|
||||
aFunction( static_cast<BOARD_ITEM*>( drawing ) );
|
||||
|
||||
|
@ -1310,14 +1374,14 @@ void MODULE::MoveAnchorPosition( const wxPoint& aMoveVector )
|
|||
m_Value->SetDrawCoord();
|
||||
|
||||
// Update the pad local coordinates.
|
||||
for( auto pad : m_pads )
|
||||
for( D_PAD* pad : m_pads )
|
||||
{
|
||||
pad->SetPos0( pad->GetPos0() + moveVector );
|
||||
pad->SetDrawCoord();
|
||||
}
|
||||
|
||||
// Update the draw element coordinates.
|
||||
for( auto item : GraphicalItems() )
|
||||
for( BOARD_ITEM* item : GraphicalItems() )
|
||||
{
|
||||
switch( item->Type() )
|
||||
{
|
||||
|
@ -1353,13 +1417,13 @@ void MODULE::SetOrientation( double aNewAngle )
|
|||
|
||||
m_Orient = aNewAngle;
|
||||
|
||||
for( auto pad : m_pads )
|
||||
for( D_PAD* pad : m_pads )
|
||||
{
|
||||
pad->SetOrientation( pad->GetOrientation() + angleChange );
|
||||
pad->SetDrawCoord();
|
||||
}
|
||||
|
||||
for( auto zone : m_fp_zones )
|
||||
for( ZONE_CONTAINER* zone : m_fp_zones )
|
||||
{
|
||||
zone->Rotate( GetPosition(), angleChange );
|
||||
}
|
||||
|
@ -1369,7 +1433,7 @@ void MODULE::SetOrientation( double aNewAngle )
|
|||
m_Value->SetDrawCoord();
|
||||
|
||||
// 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 )
|
||||
{
|
||||
|
@ -1454,7 +1518,7 @@ BOARD_ITEM* MODULE::DuplicateItem( const BOARD_ITEM* aItem, bool aAddToModule )
|
|||
|
||||
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();
|
||||
|
||||
if( aAddToModule )
|
||||
|
@ -1464,6 +1528,10 @@ BOARD_ITEM* MODULE::DuplicateItem( const BOARD_ITEM* aItem, bool aAddToModule )
|
|||
break;
|
||||
}
|
||||
|
||||
case PCB_GROUP_T:
|
||||
new_item = static_cast<const PCB_GROUP*>( aItem )->DeepDuplicate();
|
||||
break;
|
||||
|
||||
case PCB_MODULE_T:
|
||||
// Ignore the module itself
|
||||
break;
|
||||
|
|
|
@ -101,6 +101,7 @@ public:
|
|||
DECL_DEQ_FOR_SWIG( PADS, D_PAD* )
|
||||
DECL_DEQ_FOR_SWIG( DRAWINGS, BOARD_ITEM* )
|
||||
DECL_VEC_FOR_SWIG( MODULE_ZONE_CONTAINERS, MODULE_ZONE_CONTAINER* )
|
||||
DECL_VEC_FOR_SWIG( MODULE_GROUPS, PCB_GROUP* )
|
||||
DECL_DEQ_FOR_SWIG( MODULES, MODULE* )
|
||||
|
||||
class MODULE : public BOARD_ITEM_CONTAINER
|
||||
|
@ -178,36 +179,17 @@ public:
|
|||
|
||||
const EDA_RECT GetBoundingBox( bool aIncludeInvisibleText ) const;
|
||||
|
||||
PADS& Pads()
|
||||
{
|
||||
return m_pads;
|
||||
}
|
||||
PADS& Pads() { return m_pads; }
|
||||
const PADS& Pads() const { return m_pads; }
|
||||
|
||||
const PADS& Pads() const
|
||||
{
|
||||
return m_pads;
|
||||
}
|
||||
DRAWINGS& GraphicalItems() { return m_drawings; }
|
||||
const DRAWINGS& GraphicalItems() const { return m_drawings; }
|
||||
|
||||
DRAWINGS& GraphicalItems()
|
||||
{
|
||||
return m_drawings;
|
||||
}
|
||||
MODULE_ZONE_CONTAINERS& Zones() { return m_fp_zones; }
|
||||
const MODULE_ZONE_CONTAINERS& Zones() const { return m_fp_zones; }
|
||||
|
||||
const DRAWINGS& GraphicalItems() const
|
||||
{
|
||||
return m_drawings;
|
||||
}
|
||||
|
||||
MODULE_ZONE_CONTAINERS& Zones()
|
||||
{
|
||||
return m_fp_zones;
|
||||
}
|
||||
|
||||
|
||||
const MODULE_ZONE_CONTAINERS& Zones() const
|
||||
{
|
||||
return m_fp_zones;
|
||||
}
|
||||
MODULE_GROUPS& Groups() { return m_fp_groups; }
|
||||
const MODULE_GROUPS& Groups() const { return m_fp_groups; }
|
||||
|
||||
bool HasThroughHolePads() const;
|
||||
|
||||
|
@ -713,6 +695,7 @@ private:
|
|||
DRAWINGS m_drawings; // BOARD_ITEMs for drawings on the board, 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_GROUPS m_fp_groups; // PCB_GROUP items, owned by pointer
|
||||
|
||||
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.
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include <msgpanel.h>
|
||||
#include <view/view.h>
|
||||
|
||||
PCB_GROUP::PCB_GROUP( BOARD*aParent ) :
|
||||
PCB_GROUP::PCB_GROUP( BOARD_ITEM* aParent ) :
|
||||
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 )
|
||||
{
|
||||
if( item->GetParent() && item->GetParent()->Type() == PCB_MODULE_T )
|
||||
item = item->GetParent();
|
||||
|
||||
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 )
|
||||
candidate = candidate->GetParentGroup();
|
||||
|
||||
|
|
|
@ -134,6 +134,7 @@ const KICAD_T GENERAL_COLLECTOR::ModulesAndTheirItems[] = {
|
|||
PCB_MODULE_EDGE_T,
|
||||
PCB_PAD_T,
|
||||
PCB_MODULE_ZONE_AREA_T,
|
||||
PCB_GROUP_T,
|
||||
EOT
|
||||
};
|
||||
|
||||
|
@ -143,6 +144,7 @@ const KICAD_T GENERAL_COLLECTOR::ModuleItems[] = {
|
|||
PCB_MODULE_EDGE_T,
|
||||
PCB_PAD_T,
|
||||
PCB_MODULE_ZONE_AREA_T,
|
||||
PCB_GROUP_T,
|
||||
EOT
|
||||
};
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
#include <tool/zoom_tool.h>
|
||||
#include <tools/pcb_editor_conditions.h>
|
||||
#include <tools/pcb_viewer_tools.h>
|
||||
#include <tools/group_tool.h>
|
||||
#include <tools/position_relative_tool.h>
|
||||
#include <widgets/appearance_controls.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 POSITION_RELATIVE_TOOL );
|
||||
m_toolManager->RegisterTool( new PCB_VIEWER_TOOLS );
|
||||
m_toolManager->RegisterTool( new GROUP_TOOL );
|
||||
m_toolManager->RegisterTool( new CONVERT_TOOL );
|
||||
|
||||
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_PICKER_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->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 aName - name of the footprint
|
||||
*/
|
||||
static MODULE* parse_module_with_plugin(
|
||||
const wxFileName& aFileName, IO_MGR::PCB_FILE_T aFileType,
|
||||
const wxString& aName )
|
||||
static MODULE* parse_module_with_plugin( const wxFileName& aFileName,
|
||||
IO_MGR::PCB_FILE_T aFileType,
|
||||
const wxString& aName )
|
||||
{
|
||||
wxString path;
|
||||
|
||||
|
|
|
@ -414,7 +414,7 @@ public:
|
|||
* is thrown in the case where aFootprintName cannot be found.
|
||||
*/
|
||||
virtual MODULE* FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName,
|
||||
const PROPERTIES* aProperties = NULL );
|
||||
const PROPERTIES* aProperties = NULL );
|
||||
|
||||
/**
|
||||
* Function GetEnumeratedFootprint
|
||||
|
|
|
@ -633,14 +633,14 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const
|
|||
formatHeader( aBoard, aNestLevel );
|
||||
|
||||
// Save the modules.
|
||||
for( auto module : sorted_modules )
|
||||
for( BOARD_ITEM* module : sorted_modules )
|
||||
{
|
||||
Format( module, aNestLevel );
|
||||
m_out->Print( 0, "\n" );
|
||||
}
|
||||
|
||||
// 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 );
|
||||
|
||||
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.
|
||||
|
||||
// Save the tracks and vias.
|
||||
for( auto track : sorted_tracks )
|
||||
for( TRACK* track : sorted_tracks )
|
||||
Format( track, aNestLevel );
|
||||
|
||||
if( sorted_tracks.size() )
|
||||
|
@ -660,7 +660,7 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const
|
|||
Format( zone, aNestLevel );
|
||||
|
||||
// Save the groups
|
||||
for( const auto group : sorted_groups )
|
||||
for( BOARD_ITEM* group : sorted_groups )
|
||||
Format( group, aNestLevel );
|
||||
}
|
||||
|
||||
|
@ -1083,20 +1083,26 @@ void PCB_IO::format( MODULE* aModule, int aNestLevel ) const
|
|||
aModule->GraphicalItems().end() );
|
||||
std::set<BOARD_ITEM*, BOARD_ITEM::ptr_cmp> sorted_zones( aModule->Zones().begin(),
|
||||
aModule->Zones().end() );
|
||||
std::set<BOARD_ITEM*, PCB_GROUP::ptr_cmp> sorted_groups( aModule->Groups().begin(),
|
||||
aModule->Groups().end() );
|
||||
|
||||
// Save drawing elements.
|
||||
|
||||
for( auto gr : sorted_drawings )
|
||||
for( BOARD_ITEM* gr : sorted_drawings )
|
||||
Format( gr, aNestLevel+1 );
|
||||
|
||||
// Save pads.
|
||||
for( auto pad : sorted_pads )
|
||||
for( D_PAD* pad : sorted_pads )
|
||||
Format( pad, aNestLevel+1 );
|
||||
|
||||
// Save zones.
|
||||
for( auto zone : sorted_zones )
|
||||
for( BOARD_ITEM* zone : sorted_zones )
|
||||
Format( zone, aNestLevel + 1 );
|
||||
|
||||
// Save groups.
|
||||
for( BOARD_ITEM* group : sorted_groups )
|
||||
Format( group, aNestLevel + 1 );
|
||||
|
||||
// Save 3D info.
|
||||
auto bs3D = aModule->Models().begin();
|
||||
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
|
||||
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.
|
||||
module->SetParent( nullptr );
|
||||
|
|
|
@ -86,8 +86,9 @@ class TEXTE_PCB;
|
|||
//#define SEXPR_BOARD_FILE_VERSION 20200909 // Change DIMENSION format
|
||||
//#define SEXPR_BOARD_FILE_VERSION 20200913 // Add leader dimension
|
||||
//#define SEXPR_BOARD_FILE_VERSION 20200916 // Add center 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 20200921 // Add orthogonal dimension
|
||||
//#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
|
||||
|
|
|
@ -195,14 +195,14 @@ void PCB_BASE_FRAME::FocusOnItem( BOARD_ITEM* aItem )
|
|||
static_cast<MODULE*>( lastItem )->RunOnChildren( [&]( BOARD_ITEM* child )
|
||||
{
|
||||
child->ClearBrightened();
|
||||
});
|
||||
} );
|
||||
}
|
||||
else if( lastItem->Type() == PCB_GROUP_T )
|
||||
{
|
||||
static_cast<PCB_GROUP*>( lastItem )->RunOnChildren( [&] ( BOARD_ITEM* child )
|
||||
{
|
||||
child->ClearBrightened();
|
||||
});
|
||||
static_cast<PCB_GROUP*>( lastItem )->RunOnChildren( [&]( BOARD_ITEM* child )
|
||||
{
|
||||
child->ClearBrightened();
|
||||
} );
|
||||
}
|
||||
|
||||
GetCanvas()->GetView()->Update( lastItem );
|
||||
|
|
|
@ -516,6 +516,8 @@ BOARD_ITEM* PCB_PARSER::Parse()
|
|||
THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
|
||||
}
|
||||
|
||||
resolveGroups( item );
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
|
@ -618,7 +620,7 @@ BOARD* PCB_PARSER::parseBOARD_unchecked()
|
|||
break;
|
||||
|
||||
case T_group:
|
||||
parseGROUP();
|
||||
parseGROUP( m_board );
|
||||
break;
|
||||
|
||||
case T_via:
|
||||
|
@ -721,91 +723,81 @@ BOARD* PCB_PARSER::parseBOARD_unchecked()
|
|||
m_undefinedLayers.clear();
|
||||
}
|
||||
|
||||
// Now that we've parsed the other Uuids in the file we can resolve
|
||||
// the uuids referred to in the group declarations we saw.
|
||||
return m_board;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
// groups work.
|
||||
// First add all group objects so subsequent GetItem() calls for nested groups work.
|
||||
|
||||
for( size_t idx = 0; idx < m_groupInfos.size(); idx++ )
|
||||
{
|
||||
auto& aGrp = m_groupInfos[idx];
|
||||
PCB_GROUP* group = new PCB_GROUP( m_board );
|
||||
GROUP_INFO& aGrp = m_groupInfos[idx];
|
||||
PCB_GROUP* group = new PCB_GROUP( aGrp.parent );
|
||||
|
||||
group->SetName( aGrp.name );
|
||||
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;
|
||||
|
||||
for( size_t idx = 0; idx < m_groupInfos.size(); idx++ )
|
||||
{
|
||||
auto& aGrp = m_groupInfos[idx];
|
||||
BOARD_ITEM* bItem = m_board->GetItem( aGrp.uuid );
|
||||
GROUP_INFO& aGrp = m_groupInfos[idx];
|
||||
BOARD_ITEM* bItem = getItem( aGrp.uuid );
|
||||
|
||||
if( bItem == nullptr || bItem->Type() != PCB_GROUP_T )
|
||||
{
|
||||
error = wxString::Format( _( "Group %s not found in board" ),
|
||||
aGrp.uuid.AsString() );
|
||||
continue;
|
||||
}
|
||||
|
||||
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_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() );
|
||||
}
|
||||
}
|
||||
item = getItem( m_resetKIIDMap[ aUuid.AsString() ] );
|
||||
else
|
||||
{
|
||||
item = getItem( aUuid );
|
||||
|
||||
if( item && item->Type() != NOT_USED )
|
||||
group->AddItem( item );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wxString sanityResult = m_board->GroupsSanityCheck();
|
||||
|
||||
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" ) );
|
||||
|
||||
// Don't allow group cycles
|
||||
if( m_board )
|
||||
m_board->GroupsSanityCheck( true );
|
||||
}
|
||||
|
||||
return m_board;
|
||||
}
|
||||
|
||||
|
||||
|
@ -3012,7 +3004,7 @@ MODULE* PCB_PARSER::parseMODULE_unchecked( wxArrayString* aInitialComments )
|
|||
module->Add( text, ADD_MODE::APPEND );
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case T_fp_arc:
|
||||
{
|
||||
|
@ -3028,8 +3020,7 @@ MODULE* PCB_PARSER::parseMODULE_unchecked( wxArrayString* aInitialComments )
|
|||
else
|
||||
delete em;
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case T_fp_circle:
|
||||
case T_fp_curve:
|
||||
|
@ -3042,8 +3033,7 @@ MODULE* PCB_PARSER::parseMODULE_unchecked( wxArrayString* aInitialComments )
|
|||
em->SetDrawCoord();
|
||||
module->Add( em, ADD_MODE::APPEND );
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case T_pad:
|
||||
{
|
||||
|
@ -3054,8 +3044,7 @@ MODULE* PCB_PARSER::parseMODULE_unchecked( wxArrayString* aInitialComments )
|
|||
pad->SetPosition( pt + module->GetPosition() );
|
||||
module->Add( pad, ADD_MODE::APPEND );
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case T_model:
|
||||
module->Add3DModel( parse3DModel() );
|
||||
|
@ -3066,7 +3055,11 @@ MODULE* PCB_PARSER::parseMODULE_unchecked( wxArrayString* aInitialComments )
|
|||
ZONE_CONTAINER* zone = parseZONE_CONTAINER( module.get() );
|
||||
module->Add( zone, ADD_MODE::APPEND );
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case T_group:
|
||||
parseGROUP( module.get() );
|
||||
break;
|
||||
|
||||
default:
|
||||
Expecting(
|
||||
|
@ -3075,7 +3068,7 @@ MODULE* PCB_PARSER::parseMODULE_unchecked( wxArrayString* aInitialComments )
|
|||
"solder_paste_margin, solder_paste_ratio, clearance, "
|
||||
"zone_connect, thermal_width, thermal_gap, attr, fp_text, "
|
||||
"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)
|
||||
// (members id_1 id_2 … id_last )
|
||||
// )
|
||||
void PCB_PARSER::parseGROUP()
|
||||
void PCB_PARSER::parseGROUP( BOARD_ITEM* aParent )
|
||||
{
|
||||
wxCHECK_RET( CurTok() == T_group,
|
||||
wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as PCB_GROUP." ) );
|
||||
|
@ -3953,8 +3946,9 @@ void PCB_PARSER::parseGROUP()
|
|||
wxPoint pt;
|
||||
T token;
|
||||
|
||||
m_groupInfos.push_back( GroupInfo() );
|
||||
GroupInfo& groupInfo = m_groupInfos.back();
|
||||
m_groupInfos.push_back( GROUP_INFO() );
|
||||
GROUP_INFO& groupInfo = m_groupInfos.back();
|
||||
groupInfo.parent = aParent;
|
||||
|
||||
token = NextTok();
|
||||
|
||||
|
@ -3991,9 +3985,9 @@ void PCB_PARSER::parseGROUP()
|
|||
while( ( token = NextTok() ) != T_RIGHT )
|
||||
{
|
||||
// This token is the Uuid of the item in the group.
|
||||
// Since groups are serialized at the end of the file, the
|
||||
// Uuid should already have been seen and exist in the board.
|
||||
KIID uuid( CurStr() );
|
||||
// Since groups are serialized at the end of the file/module, the Uuid should already
|
||||
// have been seen and exist in the board.
|
||||
KIID uuid( CurStr() );
|
||||
groupInfo.memberUuids.push_back( uuid );
|
||||
}
|
||||
|
||||
|
@ -4865,16 +4859,19 @@ PCB_TARGET* PCB_PARSER::parsePCB_TARGET()
|
|||
}
|
||||
|
||||
|
||||
KIID PCB_PARSER::CurStrToKIID() {
|
||||
KIID aid;
|
||||
KIID PCB_PARSER::CurStrToKIID()
|
||||
{
|
||||
KIID aId;
|
||||
|
||||
if( m_resetKIIDs )
|
||||
{
|
||||
aid = KIID();
|
||||
m_resetKIIDMap.insert( std::make_pair( CurStr(), aid ) );
|
||||
aId = KIID();
|
||||
m_resetKIIDMap.insert( std::make_pair( CurStr(), aId ) );
|
||||
}
|
||||
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.
|
||||
typedef struct
|
||||
{
|
||||
BOARD_ITEM* parent;
|
||||
wxString name;
|
||||
KIID uuid;
|
||||
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,
|
||||
///> 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();
|
||||
MARKER_PCB* parseMARKER( BOARD_ITEM_CONTAINER* aParent );
|
||||
BOARD* parseBOARD();
|
||||
void parseGROUP();
|
||||
void parseGROUP( BOARD_ITEM* aParent );
|
||||
|
||||
/**
|
||||
* Function parseBOARD_unchecked
|
||||
|
@ -189,7 +190,6 @@ class PCB_PARSER : public PCB_LEXER
|
|||
*/
|
||||
BOARD* parseBOARD_unchecked();
|
||||
|
||||
|
||||
/**
|
||||
* Function lookUpLayer
|
||||
* 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();
|
||||
|
||||
/**
|
||||
* Called after parsing a footprint definition or board to build the group membership
|
||||
* lists.
|
||||
*/
|
||||
void resolveGroups( BOARD_ITEM* aParent );
|
||||
|
||||
public:
|
||||
|
||||
PCB_PARSER( LINE_READER* aReader = NULL ) :
|
||||
|
|
|
@ -35,12 +35,12 @@
|
|||
class DIALOG_GROUP_PROPERTIES : public DIALOG_GROUP_PROPERTIES_BASE
|
||||
{
|
||||
private:
|
||||
PCB_EDIT_FRAME* m_brdEditor;
|
||||
TOOL_MANAGER* m_toolMgr;
|
||||
PCB_GROUP* m_group;
|
||||
PCB_BASE_EDIT_FRAME* m_brdEditor;
|
||||
TOOL_MANAGER* m_toolMgr;
|
||||
PCB_GROUP* m_group;
|
||||
|
||||
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() { }
|
||||
|
||||
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 ),
|
||||
m_brdEditor( aParent ),
|
||||
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() :
|
||||
PCB_TOOL_BASE( "pcbnew.Groups" ),
|
||||
m_frame( nullptr ),
|
||||
m_propertiesDialog( nullptr ),
|
||||
m_selectionTool( nullptr )
|
||||
{
|
||||
|
@ -175,6 +217,8 @@ GROUP_TOOL::GROUP_TOOL() :
|
|||
|
||||
void GROUP_TOOL::Reset( RESET_REASON aReason )
|
||||
{
|
||||
m_frame = getEditFrame<PCB_BASE_EDIT_FRAME>();
|
||||
|
||||
if( aReason != RUN )
|
||||
m_commit = std::make_unique<BOARD_COMMIT>( this );
|
||||
}
|
||||
|
@ -182,17 +226,33 @@ void GROUP_TOOL::Reset( RESET_REASON aReason )
|
|||
|
||||
bool GROUP_TOOL::Init()
|
||||
{
|
||||
m_frame = getEditFrame<PCB_BASE_EDIT_FRAME>();
|
||||
|
||||
// Find the selection tool, so they can cooperate
|
||||
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 )
|
||||
{
|
||||
PCB_EDIT_FRAME* editFrame = getEditFrame<PCB_EDIT_FRAME>();
|
||||
PCB_GROUP* group = aEvent.Parameter<PCB_GROUP*>();
|
||||
PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
|
||||
PCB_GROUP* group = aEvent.Parameter<PCB_GROUP*>();
|
||||
|
||||
if( m_propertiesDialog )
|
||||
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()
|
||||
{
|
||||
Go( &GROUP_TOOL::GroupProperties, PCB_ACTIONS::groupProperties.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 );
|
||||
|
||||
///> 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.
|
||||
void setTransitions() override;
|
||||
|
||||
private:
|
||||
PCB_BASE_EDIT_FRAME* m_frame;
|
||||
DIALOG_GROUP_PROPERTIES* m_propertiesDialog;
|
||||
SELECTION_TOOL* m_selectionTool;
|
||||
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_TOOL_BASE( "pcbnew.EditorControl" ),
|
||||
m_frame( nullptr )
|
||||
|
@ -219,9 +179,6 @@ bool PCB_EDITOR_CONTROL::Init()
|
|||
auto lockMenu = std::make_shared<LOCK_CONTEXT_MENU>();
|
||||
lockMenu->SetTool( this );
|
||||
|
||||
auto groupMenu = std::make_shared<GROUP_CONTEXT_MENU>();
|
||||
groupMenu->SetTool( this );
|
||||
|
||||
// Add the PCB control menus to relevant other tools
|
||||
|
||||
SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
||||
|
@ -237,9 +194,7 @@ bool PCB_EDITOR_CONTROL::Init()
|
|||
|
||||
toolMenu.AddSubMenu( zoneMenu );
|
||||
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( 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 )
|
||||
{
|
||||
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::LockSelected, PCB_ACTIONS::lock.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::UpdateSchematicFromPCB, ACTIONS::updateSchematicFromPcb.MakeEvent() );
|
||||
|
|
|
@ -109,21 +109,6 @@ public:
|
|||
///> Unlocks selected items.
|
||||
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.
|
||||
int DrillOrigin( const TOOL_EVENT& aEvent );
|
||||
|
||||
|
|
|
@ -114,28 +114,25 @@ using namespace std::placeholders;
|
|||
|
||||
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 ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
// Append modules:
|
||||
for( auto item : aPcb->Modules() )
|
||||
for( MODULE* item : aPcb->Modules() )
|
||||
{
|
||||
if( aItem == static_cast<BOARD_ITEM*>( item ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
// Append drawings
|
||||
for( auto item : aPcb->Drawings() )
|
||||
for( BOARD_ITEM* item : aPcb->Drawings() )
|
||||
{
|
||||
if( aItem == static_cast<BOARD_ITEM*>( item ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
// Append zones outlines
|
||||
for( auto item : aPcb->Zones() )
|
||||
for( ZONE_CONTAINER* item : aPcb->Zones() )
|
||||
{
|
||||
if( aItem == static_cast<BOARD_ITEM*>( item ) )
|
||||
return true;
|
||||
|
@ -149,8 +146,7 @@ static bool TestForExistingItem( BOARD* aPcb, BOARD_ITEM* aItem )
|
|||
return true;
|
||||
}
|
||||
|
||||
// Append groups:
|
||||
for( auto item : aPcb->Groups() )
|
||||
for( PCB_GROUP* item : aPcb->Groups() )
|
||||
{
|
||||
if( aItem == static_cast<BOARD_ITEM*>( item ) )
|
||||
return true;
|
||||
|
@ -195,8 +191,6 @@ void PCB_BASE_EDIT_FRAME::SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsLis
|
|||
UNDO_REDO aTypeCommand,
|
||||
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();
|
||||
|
||||
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 ) );
|
||||
|
||||
// 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();
|
||||
wxASSERT( item && item->Type() == PCB_MODULE_T );
|
||||
|
||||
if( item == NULL )
|
||||
continue;
|
||||
|
||||
// Check if the parent module has already been saved in another entry
|
||||
bool found = false;
|
||||
|
|
Loading…
Reference in New Issue