Refactored LIB_PART data storage
Instead of keeping all items in a boost::ptr_vector(), LIB_ITEMs are now stored in an integer (KICAD_T) to LIB_ITEMS map. The map allows to quickly access a subset of items of given type. As the items are stored per type, there is no need to call LIB_ITEMS::sort() to assure the correct drawing order. As a result, libraries load faster. To retain the old interface, there is a LIB_ITEMS_LIST wrapper for the map, allowing the developers to access the items as if it was a flat list-like structure.
This commit is contained in:
parent
90873a101b
commit
352919658d
|
@ -138,6 +138,7 @@ set( EESCHEMA_SRCS
|
||||||
lib_draw_item.cpp
|
lib_draw_item.cpp
|
||||||
lib_export.cpp
|
lib_export.cpp
|
||||||
lib_field.cpp
|
lib_field.cpp
|
||||||
|
lib_items.cpp
|
||||||
lib_pin.cpp
|
lib_pin.cpp
|
||||||
lib_polyline.cpp
|
lib_polyline.cpp
|
||||||
lib_rectangle.cpp
|
lib_rectangle.cpp
|
||||||
|
|
|
@ -178,7 +178,7 @@ struct null_deleter
|
||||||
|
|
||||||
LIB_PART::LIB_PART( const wxString& aName, PART_LIB* aLibrary ) :
|
LIB_PART::LIB_PART( const wxString& aName, PART_LIB* aLibrary ) :
|
||||||
EDA_ITEM( LIB_PART_T ),
|
EDA_ITEM( LIB_PART_T ),
|
||||||
m_me( this, null_deleter() )
|
m_me( this, null_deleter() ), drawings( drawingsMap )
|
||||||
{
|
{
|
||||||
m_name = aName;
|
m_name = aName;
|
||||||
m_library = aLibrary;
|
m_library = aLibrary;
|
||||||
|
@ -198,17 +198,17 @@ LIB_PART::LIB_PART( const wxString& aName, PART_LIB* aLibrary ) :
|
||||||
// when the field editors are invoked.
|
// when the field editors are invoked.
|
||||||
LIB_FIELD* value = new LIB_FIELD( this, VALUE );
|
LIB_FIELD* value = new LIB_FIELD( this, VALUE );
|
||||||
value->SetText( aName );
|
value->SetText( aName );
|
||||||
drawings.push_back( value );
|
drawingsMap[LIB_FIELD_T].push_back( value );
|
||||||
|
|
||||||
drawings.push_back( new LIB_FIELD( this, REFERENCE ) );
|
drawingsMap[LIB_FIELD_T].push_back( new LIB_FIELD( this, REFERENCE ) );
|
||||||
drawings.push_back( new LIB_FIELD( this, FOOTPRINT ) );
|
drawingsMap[LIB_FIELD_T].push_back( new LIB_FIELD( this, FOOTPRINT ) );
|
||||||
drawings.push_back( new LIB_FIELD( this, DATASHEET ) );
|
drawingsMap[LIB_FIELD_T].push_back( new LIB_FIELD( this, DATASHEET ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LIB_PART::LIB_PART( LIB_PART& aPart, PART_LIB* aLibrary ) :
|
LIB_PART::LIB_PART( LIB_PART& aPart, PART_LIB* aLibrary ) :
|
||||||
EDA_ITEM( aPart ),
|
EDA_ITEM( aPart ),
|
||||||
m_me( this, null_deleter() )
|
m_me( this, null_deleter() ), drawings( drawingsMap )
|
||||||
{
|
{
|
||||||
LIB_ITEM* newItem;
|
LIB_ITEM* newItem;
|
||||||
|
|
||||||
|
@ -223,7 +223,7 @@ LIB_PART::LIB_PART( LIB_PART& aPart, PART_LIB* aLibrary ) :
|
||||||
m_dateModified = aPart.m_dateModified;
|
m_dateModified = aPart.m_dateModified;
|
||||||
m_options = aPart.m_options;
|
m_options = aPart.m_options;
|
||||||
|
|
||||||
for( LIB_ITEM& oldItem : aPart.GetDrawItemList() )
|
for( LIB_ITEM& oldItem : aPart.drawings )
|
||||||
{
|
{
|
||||||
if( oldItem.IsNew() )
|
if( oldItem.IsNew() )
|
||||||
continue;
|
continue;
|
||||||
|
@ -351,7 +351,7 @@ void LIB_PART::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDc, const wxPoint& aOffset,
|
||||||
if( drawItem.Type() == LIB_FIELD_T )
|
if( drawItem.Type() == LIB_FIELD_T )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( drawItem.Type() == LIB_FIELD_T )
|
if( drawItem.Type() == LIB_FIELD_T ) // TODO dead code?
|
||||||
{
|
{
|
||||||
drawItem.Draw( aPanel, aDc, aOffset, aOpts.color,
|
drawItem.Draw( aPanel, aDc, aOffset, aOpts.color,
|
||||||
aOpts.draw_mode, (void*) NULL, aOpts.transform );
|
aOpts.draw_mode, (void*) NULL, aOpts.transform );
|
||||||
|
@ -428,7 +428,6 @@ void LIB_PART::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDc, const wxPoint& aOffset,
|
||||||
aOpts.draw_mode, (void*) forceNoFill,
|
aOpts.draw_mode, (void*) forceNoFill,
|
||||||
aOpts.transform );
|
aOpts.transform );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable this to draw the anchor of the component.
|
// Enable this to draw the anchor of the component.
|
||||||
|
@ -553,9 +552,9 @@ void LIB_PART::RemoveDrawItem( LIB_ITEM* aItem, EDA_DRAW_PANEL* aPanel, wxDC* aD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LIB_ITEMS::iterator i;
|
LIB_ITEMS& items = drawingsMap[aItem->Type()];
|
||||||
|
|
||||||
for( i = drawings.begin(); i != drawings.end(); i++ )
|
for( LIB_ITEMS::iterator i = items.begin(); i != items.end(); i++ )
|
||||||
{
|
{
|
||||||
if( *i == aItem )
|
if( *i == aItem )
|
||||||
{
|
{
|
||||||
|
@ -563,7 +562,7 @@ void LIB_PART::RemoveDrawItem( LIB_ITEM* aItem, EDA_DRAW_PANEL* aPanel, wxDC* aD
|
||||||
aItem->Draw( aPanel, aDc, wxPoint( 0, 0 ), COLOR4D::UNSPECIFIED,
|
aItem->Draw( aPanel, aDc, wxPoint( 0, 0 ), COLOR4D::UNSPECIFIED,
|
||||||
g_XorMode, NULL, DefaultTransform );
|
g_XorMode, NULL, DefaultTransform );
|
||||||
|
|
||||||
drawings.erase( i );
|
items.erase( i );
|
||||||
SetModified();
|
SetModified();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -576,7 +575,6 @@ void LIB_PART::AddDrawItem( LIB_ITEM* aItem )
|
||||||
wxASSERT( aItem != NULL );
|
wxASSERT( aItem != NULL );
|
||||||
|
|
||||||
drawings.push_back( aItem );
|
drawings.push_back( aItem );
|
||||||
drawings.sort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -619,17 +617,17 @@ LIB_ITEM* LIB_PART::GetNextDrawItem( LIB_ITEM* aItem, KICAD_T aType )
|
||||||
|
|
||||||
void LIB_PART::GetPins( LIB_PINS& aList, int aUnit, int aConvert )
|
void LIB_PART::GetPins( LIB_PINS& aList, int aUnit, int aConvert )
|
||||||
{
|
{
|
||||||
|
if( drawingsMap.count( LIB_PIN_T ) == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
/* Notes:
|
/* Notes:
|
||||||
* when aUnit == 0: no unit filtering
|
* when aUnit == 0: no unit filtering
|
||||||
* when aConvert == 0: no convert (shape selection) filtering
|
* when aConvert == 0: no convert (shape selection) filtering
|
||||||
* when .m_Unit == 0, the body item is common to units
|
* when .m_Unit == 0, the body item is common to units
|
||||||
* when .m_Convert == 0, the body item is common to shapes
|
* when .m_Convert == 0, the body item is common to shapes
|
||||||
*/
|
*/
|
||||||
for( LIB_ITEM& item : drawings )
|
for( LIB_ITEM& item : drawingsMap[LIB_PIN_T] )
|
||||||
{
|
{
|
||||||
if( item.Type() != LIB_PIN_T ) // we search pins only
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Unit filtering:
|
// Unit filtering:
|
||||||
if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
|
if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
|
||||||
continue;
|
continue;
|
||||||
|
@ -994,7 +992,6 @@ bool LIB_PART::Load( LINE_READER& aLineReader, wxString& aErrorMsg )
|
||||||
|
|
||||||
ok:
|
ok:
|
||||||
// If we are here, this part is O.k. - put it in:
|
// If we are here, this part is O.k. - put it in:
|
||||||
drawings.sort();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1132,7 +1129,7 @@ bool LIB_PART::LoadField( LINE_READER& aLineReader, wxString& aErrorMsg )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
drawings.push_back( field );
|
drawingsMap[LIB_FIELD_T].push_back( field );
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1169,10 +1166,8 @@ const EDA_RECT LIB_PART::GetUnitBoundingBox( int aUnit, int aConvert ) const
|
||||||
EDA_RECT bBox;
|
EDA_RECT bBox;
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
|
|
||||||
for( unsigned ii = 0; ii < drawings.size(); ii++ )
|
for( const LIB_ITEM& item : drawings )
|
||||||
{
|
{
|
||||||
const LIB_ITEM& item = drawings[ii];
|
|
||||||
|
|
||||||
if( ( item.m_Unit > 0 ) && ( ( m_unitCount > 1 ) && ( aUnit > 0 )
|
if( ( item.m_Unit > 0 ) && ( ( m_unitCount > 1 ) && ( aUnit > 0 )
|
||||||
&& ( aUnit != item.m_Unit ) ) )
|
&& ( aUnit != item.m_Unit ) ) )
|
||||||
continue;
|
continue;
|
||||||
|
@ -1201,10 +1196,8 @@ const EDA_RECT LIB_PART::GetBodyBoundingBox( int aUnit, int aConvert ) const
|
||||||
EDA_RECT bBox;
|
EDA_RECT bBox;
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
|
|
||||||
for( unsigned ii = 0; ii < drawings.size(); ii++ )
|
for( const LIB_ITEM& item : drawings )
|
||||||
{
|
{
|
||||||
const LIB_ITEM& item = drawings[ii];
|
|
||||||
|
|
||||||
if( ( item.m_Unit > 0 ) && ( ( m_unitCount > 1 ) && ( aUnit > 0 )
|
if( ( item.m_Unit > 0 ) && ( ( m_unitCount > 1 ) && ( aUnit > 0 )
|
||||||
&& ( aUnit != item.m_Unit ) ) )
|
&& ( aUnit != item.m_Unit ) ) )
|
||||||
continue;
|
continue;
|
||||||
|
@ -1230,19 +1223,7 @@ const EDA_RECT LIB_PART::GetBodyBoundingBox( int aUnit, int aConvert ) const
|
||||||
|
|
||||||
void LIB_PART::deleteAllFields()
|
void LIB_PART::deleteAllFields()
|
||||||
{
|
{
|
||||||
LIB_ITEMS::iterator it;
|
drawingsMap[LIB_FIELD_T].clear();
|
||||||
|
|
||||||
for( it = drawings.begin(); it != drawings.end(); /* deleting */ )
|
|
||||||
{
|
|
||||||
if( it->Type() != LIB_FIELD_T )
|
|
||||||
{
|
|
||||||
++it;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 'it' is not advanced, but should point to next in list after erase()
|
|
||||||
it = drawings.erase( it );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1256,12 +1237,8 @@ void LIB_PART::SetFields( const std::vector <LIB_FIELD>& aFields )
|
||||||
LIB_FIELD* field = new LIB_FIELD( aFields[i] );
|
LIB_FIELD* field = new LIB_FIELD( aFields[i] );
|
||||||
|
|
||||||
field->SetParent( this );
|
field->SetParent( this );
|
||||||
drawings.push_back( field );
|
drawingsMap[LIB_FIELD_T].push_back( field );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reorder drawings: transparent polygons first, pins and text last.
|
|
||||||
// so texts have priority on screen.
|
|
||||||
drawings.sort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1285,11 +1262,8 @@ void LIB_PART::GetFields( LIB_FIELDS& aList )
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now grab all the rest of fields.
|
// Now grab all the rest of fields.
|
||||||
for( LIB_ITEM& item : drawings )
|
for( LIB_ITEM& item : drawingsMap[LIB_FIELD_T] )
|
||||||
{
|
{
|
||||||
if( item.Type() != LIB_FIELD_T )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
field = ( LIB_FIELD* ) &item;
|
field = ( LIB_FIELD* ) &item;
|
||||||
|
|
||||||
if( (unsigned) field->GetId() < MANDATORY_FIELDS )
|
if( (unsigned) field->GetId() < MANDATORY_FIELDS )
|
||||||
|
@ -1302,11 +1276,8 @@ void LIB_PART::GetFields( LIB_FIELDS& aList )
|
||||||
|
|
||||||
LIB_FIELD* LIB_PART::GetField( int aId )
|
LIB_FIELD* LIB_PART::GetField( int aId )
|
||||||
{
|
{
|
||||||
for( LIB_ITEM& item : drawings )
|
for( LIB_ITEM& item : drawingsMap[LIB_FIELD_T] )
|
||||||
{
|
{
|
||||||
if( item.Type() != LIB_FIELD_T )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
LIB_FIELD* field = ( LIB_FIELD* ) &item;
|
LIB_FIELD* field = ( LIB_FIELD* ) &item;
|
||||||
|
|
||||||
if( field->GetId() == aId )
|
if( field->GetId() == aId )
|
||||||
|
@ -1319,11 +1290,8 @@ LIB_FIELD* LIB_PART::GetField( int aId )
|
||||||
|
|
||||||
LIB_FIELD* LIB_PART::FindField( const wxString& aFieldName )
|
LIB_FIELD* LIB_PART::FindField( const wxString& aFieldName )
|
||||||
{
|
{
|
||||||
for( LIB_ITEM& item : drawings )
|
for( LIB_ITEM& item : drawingsMap[LIB_FIELD_T] )
|
||||||
{
|
{
|
||||||
if( item.Type() != LIB_FIELD_T )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
LIB_FIELD* field = ( LIB_FIELD* ) &item;
|
LIB_FIELD* field = ( LIB_FIELD* ) &item;
|
||||||
|
|
||||||
if( field->GetName() == aFieldName )
|
if( field->GetName() == aFieldName )
|
||||||
|
@ -1400,23 +1368,21 @@ bool LIB_PART::LoadDateAndTime( char* aLine )
|
||||||
void LIB_PART::SetOffset( const wxPoint& aOffset )
|
void LIB_PART::SetOffset( const wxPoint& aOffset )
|
||||||
{
|
{
|
||||||
for( LIB_ITEM& item : drawings )
|
for( LIB_ITEM& item : drawings )
|
||||||
{
|
|
||||||
item.SetOffset( aOffset );
|
item.SetOffset( aOffset );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LIB_PART::RemoveDuplicateDrawItems()
|
void LIB_PART::RemoveDuplicateDrawItems()
|
||||||
{
|
{
|
||||||
drawings.unique();
|
for( auto& itemTypes : drawingsMap )
|
||||||
|
itemTypes.second.unique();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool LIB_PART::HasConversion() const
|
bool LIB_PART::HasConversion() const
|
||||||
{
|
{
|
||||||
for( unsigned ii = 0; ii < drawings.size(); ii++ )
|
for( const LIB_ITEM& item : drawings )
|
||||||
{
|
{
|
||||||
const LIB_ITEM& item = drawings[ii];
|
|
||||||
if( item.m_Convert > 1 )
|
if( item.m_Convert > 1 )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1475,8 +1441,6 @@ void LIB_PART::MoveSelectedItems( const wxPoint& aOffset )
|
||||||
item.SetOffset( aOffset );
|
item.SetOffset( aOffset );
|
||||||
item.m_Flags = 0;
|
item.m_Flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
drawings.sort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1491,7 +1455,7 @@ void LIB_PART::ClearSelectedItems()
|
||||||
|
|
||||||
void LIB_PART::DeleteSelectedItems()
|
void LIB_PART::DeleteSelectedItems()
|
||||||
{
|
{
|
||||||
LIB_ITEMS::iterator item = drawings.begin();
|
LIB_ITEMS_LIST::ITERATOR item = drawings.begin();
|
||||||
|
|
||||||
// We *do not* remove the 2 mandatory fields: reference and value
|
// We *do not* remove the 2 mandatory fields: reference and value
|
||||||
// so skip them (do not remove) if they are flagged selected.
|
// so skip them (do not remove) if they are flagged selected.
|
||||||
|
@ -1512,7 +1476,7 @@ void LIB_PART::DeleteSelectedItems()
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !item->IsSelected() )
|
if( !item->IsSelected() )
|
||||||
item++;
|
++item;
|
||||||
else
|
else
|
||||||
item = drawings.erase( item );
|
item = drawings.erase( item );
|
||||||
}
|
}
|
||||||
|
@ -1547,11 +1511,9 @@ void LIB_PART::CopySelectedItems( const wxPoint& aOffset )
|
||||||
}
|
}
|
||||||
|
|
||||||
MoveSelectedItems( aOffset );
|
MoveSelectedItems( aOffset );
|
||||||
drawings.sort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void LIB_PART::MirrorSelectedItemsH( const wxPoint& aCenter )
|
void LIB_PART::MirrorSelectedItemsH( const wxPoint& aCenter )
|
||||||
{
|
{
|
||||||
for( LIB_ITEM& item : drawings )
|
for( LIB_ITEM& item : drawings )
|
||||||
|
@ -1562,10 +1524,9 @@ void LIB_PART::MirrorSelectedItemsH( const wxPoint& aCenter )
|
||||||
item.MirrorHorizontal( aCenter );
|
item.MirrorHorizontal( aCenter );
|
||||||
item.m_Flags = 0;
|
item.m_Flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
drawings.sort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LIB_PART::MirrorSelectedItemsV( const wxPoint& aCenter )
|
void LIB_PART::MirrorSelectedItemsV( const wxPoint& aCenter )
|
||||||
{
|
{
|
||||||
for( LIB_ITEM& item : drawings )
|
for( LIB_ITEM& item : drawings )
|
||||||
|
@ -1576,10 +1537,9 @@ void LIB_PART::MirrorSelectedItemsV( const wxPoint& aCenter )
|
||||||
item.MirrorVertical( aCenter );
|
item.MirrorVertical( aCenter );
|
||||||
item.m_Flags = 0;
|
item.m_Flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
drawings.sort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LIB_PART::RotateSelectedItems( const wxPoint& aCenter )
|
void LIB_PART::RotateSelectedItems( const wxPoint& aCenter )
|
||||||
{
|
{
|
||||||
for( LIB_ITEM& item : drawings )
|
for( LIB_ITEM& item : drawings )
|
||||||
|
@ -1590,12 +1550,9 @@ void LIB_PART::RotateSelectedItems( const wxPoint& aCenter )
|
||||||
item.Rotate( aCenter );
|
item.Rotate( aCenter );
|
||||||
item.m_Flags = 0;
|
item.m_Flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
drawings.sort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
LIB_ITEM* LIB_PART::LocateDrawItem( int aUnit, int aConvert,
|
LIB_ITEM* LIB_PART::LocateDrawItem( int aUnit, int aConvert,
|
||||||
KICAD_T aType, const wxPoint& aPoint )
|
KICAD_T aType, const wxPoint& aPoint )
|
||||||
{
|
{
|
||||||
|
@ -1642,15 +1599,14 @@ void LIB_PART::SetUnitCount( int aCount )
|
||||||
|
|
||||||
if( aCount < m_unitCount )
|
if( aCount < m_unitCount )
|
||||||
{
|
{
|
||||||
LIB_ITEMS::iterator i;
|
LIB_ITEMS_LIST::ITERATOR i = drawings.begin();
|
||||||
i = drawings.begin();
|
|
||||||
|
|
||||||
while( i != drawings.end() )
|
while( i != drawings.end() )
|
||||||
{
|
{
|
||||||
if( i->m_Unit > aCount )
|
if( i->m_Unit > aCount )
|
||||||
i = drawings.erase( i );
|
i = drawings.erase( i );
|
||||||
else
|
else
|
||||||
i++;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1674,8 +1630,6 @@ void LIB_PART::SetUnitCount( int aCount )
|
||||||
drawings.push_back( newItem );
|
drawings.push_back( newItem );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drawings.sort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_unitCount = aCount;
|
m_unitCount = aCount;
|
||||||
|
@ -1714,14 +1668,14 @@ void LIB_PART::SetConversion( bool aSetConvert )
|
||||||
{
|
{
|
||||||
// Delete converted shape items because the converted shape does
|
// Delete converted shape items because the converted shape does
|
||||||
// not exist
|
// not exist
|
||||||
LIB_ITEMS::iterator i = drawings.begin();
|
LIB_ITEMS_LIST::ITERATOR i = drawings.begin();
|
||||||
|
|
||||||
while( i != drawings.end() )
|
while( i != drawings.end() )
|
||||||
{
|
{
|
||||||
if( i->m_Convert > 1 )
|
if( i->m_Convert > 1 )
|
||||||
i = drawings.erase( i );
|
i = drawings.erase( i );
|
||||||
else
|
else
|
||||||
i++;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,8 +34,8 @@
|
||||||
#include <lib_id.h>
|
#include <lib_id.h>
|
||||||
#include <lib_draw_item.h>
|
#include <lib_draw_item.h>
|
||||||
#include <lib_field.h>
|
#include <lib_field.h>
|
||||||
|
#include <lib_items.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
class EDA_RECT;
|
class EDA_RECT;
|
||||||
class LINE_READER;
|
class LINE_READER;
|
||||||
|
@ -236,7 +236,8 @@ class LIB_PART : public EDA_ITEM
|
||||||
long m_dateModified; ///< Date the part was last modified.
|
long m_dateModified; ///< Date the part was last modified.
|
||||||
LIBRENTRYOPTIONS m_options; ///< Special part features such as POWER or NORMAL.)
|
LIBRENTRYOPTIONS m_options; ///< Special part features such as POWER or NORMAL.)
|
||||||
int m_unitCount; ///< Number of units (parts) per package.
|
int m_unitCount; ///< Number of units (parts) per package.
|
||||||
LIB_ITEMS drawings; ///< How to draw this part.
|
LIB_ITEMS_MAP drawingsMap; ///< How to draw this part.
|
||||||
|
LIB_ITEMS_LIST drawings; ///< Wrapper to drawingsMap to present as a flat structure
|
||||||
wxArrayString m_FootprintList; /**< List of suitable footprint names for the
|
wxArrayString m_FootprintList; /**< List of suitable footprint names for the
|
||||||
part (wild card names accepted). */
|
part (wild card names accepted). */
|
||||||
LIB_ALIASES m_aliases; ///< List of alias object pointers associated with the
|
LIB_ALIASES m_aliases; ///< List of alias object pointers associated with the
|
||||||
|
@ -682,9 +683,20 @@ public:
|
||||||
/**
|
/**
|
||||||
* Return a reference to the draw item list.
|
* Return a reference to the draw item list.
|
||||||
*
|
*
|
||||||
* @return LIB_ITEMS& - Reference to the draw item object list.
|
* @return LIB_ITEMS_LIST& - Reference to the draw item object list.
|
||||||
*/
|
*/
|
||||||
LIB_ITEMS& GetDrawItemList() { return drawings; }
|
LIB_ITEMS_LIST& GetDrawItemList()
|
||||||
|
{
|
||||||
|
return drawings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a reference to the draw item map that stores items per their type.
|
||||||
|
*/
|
||||||
|
LIB_ITEMS_MAP& GetDrawItemMap()
|
||||||
|
{
|
||||||
|
return drawingsMap;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the units per part count.
|
* Set the units per part count.
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <general.h>
|
#include <general.h>
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
#include <lib_collectors.h>
|
#include <lib_collectors.h>
|
||||||
|
#include <lib_items.h>
|
||||||
|
|
||||||
|
|
||||||
const KICAD_T LIB_COLLECTOR::AllItems[] = {
|
const KICAD_T LIB_COLLECTOR::AllItems[] = {
|
||||||
|
@ -110,7 +111,7 @@ SEARCH_RESULT LIB_COLLECTOR::Inspect( EDA_ITEM* aItem, void* testData )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LIB_COLLECTOR::Collect( LIB_ITEMS& aItems, const KICAD_T aFilterList[],
|
void LIB_COLLECTOR::Collect( LIB_ITEMS_LIST& aItems, const KICAD_T aFilterList[],
|
||||||
const wxPoint& aPosition, int aUnit, int aConvert )
|
const wxPoint& aPosition, int aUnit, int aConvert )
|
||||||
{
|
{
|
||||||
Empty(); // empty the collection just in case
|
Empty(); // empty the collection just in case
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <lib_draw_item.h>
|
#include <lib_draw_item.h>
|
||||||
|
|
||||||
|
|
||||||
|
class LIB_ITEMS_LIST;
|
||||||
class LIB_COLLECTOR;
|
class LIB_COLLECTOR;
|
||||||
|
|
||||||
|
|
||||||
|
@ -127,7 +128,7 @@ public:
|
||||||
* @param aUnit The unit of the items to collect or zero if all units.
|
* @param aUnit The unit of the items to collect or zero if all units.
|
||||||
* @param aConvert The convert of the items to collect or zero if all conversions.
|
* @param aConvert The convert of the items to collect or zero if all conversions.
|
||||||
*/
|
*/
|
||||||
void Collect( LIB_ITEMS& aItem, const KICAD_T aFilterList[], const wxPoint& aPosition,
|
void Collect( LIB_ITEMS_LIST& aItem, const KICAD_T aFilterList[], const wxPoint& aPosition,
|
||||||
int aUnit = 0, int aConvert = 0 );
|
int aUnit = 0, int aConvert = 0 );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,6 @@
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
#include <gr_basic.h>
|
#include <gr_basic.h>
|
||||||
|
|
||||||
#include <boost/ptr_container/ptr_vector.hpp>
|
|
||||||
|
|
||||||
|
|
||||||
class LINE_READER;
|
class LINE_READER;
|
||||||
class OUTPUTFORMATTER;
|
class OUTPUTFORMATTER;
|
||||||
|
@ -54,14 +52,6 @@ extern const int fill_tab[];
|
||||||
#define MINIMUM_SELECTION_DISTANCE 2 // Minimum selection distance in internal units
|
#define MINIMUM_SELECTION_DISTANCE 2 // Minimum selection distance in internal units
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper for defining a list of library draw object pointers. The Boost
|
|
||||||
* pointer containers are responsible for deleting object pointers placed
|
|
||||||
* in them. If you access a object pointer from the list, do not delete
|
|
||||||
* it directly.
|
|
||||||
*/
|
|
||||||
typedef boost::ptr_vector< LIB_ITEM > LIB_ITEMS;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper for defining a list of pin object pointers. The list does not
|
* Helper for defining a list of pin object pointers. The list does not
|
||||||
* use a Boost pointer class so the object pointers do not accidentally get
|
* use a Boost pointer class so the object pointers do not accidentally get
|
||||||
|
|
|
@ -0,0 +1,211 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright 2017 CERN
|
||||||
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <lib_items.h>
|
||||||
|
#include <lib_draw_item.h>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <wx/debug.h>
|
||||||
|
|
||||||
|
|
||||||
|
LIB_ITEMS_LIST::ITERATOR::ITERATOR( LIB_ITEMS_MAP& aItems, int aType )
|
||||||
|
: m_parent( &aItems )
|
||||||
|
{
|
||||||
|
m_filter = ( aType != TYPE_NOT_INIT );
|
||||||
|
m_type = m_filter ? aType : FIRST_TYPE;
|
||||||
|
m_it = (*m_parent)[m_type].begin();
|
||||||
|
|
||||||
|
// be sure the enum order is correct for the type assert
|
||||||
|
static_assert( (int) ( ITERATOR::FIRST_TYPE ) < (int) ( ITERATOR::LAST_TYPE ),
|
||||||
|
"fix FIRST_TYPE and LAST_TYPE definitions" );
|
||||||
|
wxASSERT( m_type >= ITERATOR::FIRST_TYPE && m_type <= ITERATOR::LAST_TYPE );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LIB_ITEMS_LIST::ITERATOR LIB_ITEMS_LIST::begin( int aType ) const
|
||||||
|
{
|
||||||
|
LIB_ITEMS_LIST::ITERATOR it( m_data, aType );
|
||||||
|
|
||||||
|
if( it.m_filter ) // iterates over a specific type
|
||||||
|
{
|
||||||
|
it.m_it = (*it.m_parent)[it.m_type].begin();
|
||||||
|
}
|
||||||
|
else // iterates over all items
|
||||||
|
{
|
||||||
|
// find a not empty container
|
||||||
|
auto i = m_data.begin();
|
||||||
|
|
||||||
|
while( i->second.empty() && i != m_data.end() )
|
||||||
|
++i;
|
||||||
|
|
||||||
|
if( i == m_data.end() )
|
||||||
|
--i;
|
||||||
|
|
||||||
|
it.m_it = i->second.begin();
|
||||||
|
it.m_type = i->first;
|
||||||
|
}
|
||||||
|
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LIB_ITEMS_LIST::ITERATOR LIB_ITEMS_LIST::end( int aType ) const
|
||||||
|
{
|
||||||
|
LIB_ITEMS_LIST::ITERATOR it( m_data, aType );
|
||||||
|
|
||||||
|
if( it.m_filter ) // iterates over a specific type
|
||||||
|
{
|
||||||
|
it.m_it = (*it.m_parent)[it.m_type].end();
|
||||||
|
}
|
||||||
|
else // iterates over all items
|
||||||
|
{
|
||||||
|
// find a not empty container
|
||||||
|
auto i = m_data.rbegin();
|
||||||
|
|
||||||
|
while( i->second.empty() && i != m_data.rend() )
|
||||||
|
++i;
|
||||||
|
|
||||||
|
if( i == m_data.rend() )
|
||||||
|
--i;
|
||||||
|
|
||||||
|
it.m_it = i->second.end();
|
||||||
|
it.m_type = i->first;
|
||||||
|
}
|
||||||
|
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LIB_ITEMS_LIST::push_back( LIB_ITEM* aItem )
|
||||||
|
{
|
||||||
|
wxASSERT( aItem->Type() >= ITERATOR::FIRST_TYPE && aItem->Type() <= ITERATOR::LAST_TYPE );
|
||||||
|
m_data[aItem->Type()].push_back( aItem );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LIB_ITEMS_LIST::ITERATOR LIB_ITEMS_LIST::erase( const ITERATOR& aIterator )
|
||||||
|
{
|
||||||
|
LIB_ITEMS_LIST::ITERATOR it( aIterator );
|
||||||
|
it.m_it = (*aIterator.m_parent)[aIterator.m_type].erase( aIterator.m_it );
|
||||||
|
|
||||||
|
// if we reached the end, then move to the next type
|
||||||
|
if( it.m_it == (*it.m_parent)[it.m_type].end() && !it.m_filter )
|
||||||
|
++it;
|
||||||
|
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t LIB_ITEMS_LIST::size() const
|
||||||
|
{
|
||||||
|
size_t counter = 0;
|
||||||
|
|
||||||
|
for( auto& type : m_data )
|
||||||
|
counter += type.second.size();
|
||||||
|
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool LIB_ITEMS_LIST::empty() const
|
||||||
|
{
|
||||||
|
for( auto& type : m_data )
|
||||||
|
{
|
||||||
|
if( !type.second.empty() )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LIB_ITEMS_LIST::sort()
|
||||||
|
{
|
||||||
|
for( auto& itemType : m_data )
|
||||||
|
itemType.second.sort();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LIB_ITEM& LIB_ITEMS_LIST::operator[]( unsigned int aIdx )
|
||||||
|
{
|
||||||
|
int counter = 0;
|
||||||
|
|
||||||
|
for( auto& type : m_data )
|
||||||
|
{
|
||||||
|
if( aIdx < counter + type.second.size() )
|
||||||
|
return type.second[aIdx - counter];
|
||||||
|
else
|
||||||
|
counter += type.second.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw std::out_of_range( "LIB_ITEMS_LIST out of range" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const LIB_ITEM& LIB_ITEMS_LIST::operator[]( unsigned int aIdx ) const
|
||||||
|
{
|
||||||
|
int counter = 0;
|
||||||
|
|
||||||
|
for( const auto& type : m_data )
|
||||||
|
{
|
||||||
|
if( counter + type.second.size() < aIdx )
|
||||||
|
return type.second[aIdx - counter];
|
||||||
|
else
|
||||||
|
counter += type.second.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw std::out_of_range( "LIB_ITEMS_LIST out of range" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LIB_ITEMS_LIST::ITERATOR& LIB_ITEMS_LIST::ITERATOR::operator++()
|
||||||
|
{
|
||||||
|
if( m_it != (*m_parent)[m_type].end() )
|
||||||
|
++m_it;
|
||||||
|
|
||||||
|
if( m_it == (*m_parent)[m_type].end() && !m_filter && m_type < LAST_TYPE )
|
||||||
|
{
|
||||||
|
// switch to the next type for not filtered iterator
|
||||||
|
do
|
||||||
|
++m_type;
|
||||||
|
while( ( !m_parent->count( m_type ) || (*m_parent)[m_type].empty() ) && m_type < LAST_TYPE );
|
||||||
|
|
||||||
|
// is it the real end of the list?
|
||||||
|
if( m_type == LAST_TYPE && (*m_parent)[LAST_TYPE].empty() )
|
||||||
|
m_it = (*m_parent)[LAST_TYPE].end();
|
||||||
|
else
|
||||||
|
m_it = (*m_parent)[m_type].begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool LIB_ITEMS_LIST::ITERATOR::operator!=( const LIB_ITEMS_LIST::ITERATOR& aOther ) const
|
||||||
|
{
|
||||||
|
wxASSERT( aOther.m_parent == m_parent );
|
||||||
|
wxASSERT( aOther.m_filter == m_filter );
|
||||||
|
wxASSERT( !m_filter || aOther.m_type == m_type );
|
||||||
|
|
||||||
|
return aOther.m_it != m_it;
|
||||||
|
}
|
|
@ -0,0 +1,128 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright 2017 CERN
|
||||||
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIB_ITEMS_H
|
||||||
|
#define LIB_ITEMS_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LIB_ITEM containers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <core/typeinfo.h>
|
||||||
|
#include <boost/ptr_container/ptr_vector.hpp>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
class LIB_ITEM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper for defining a list of library draw object pointers. The Boost
|
||||||
|
* pointer containers are responsible for deleting object pointers placed
|
||||||
|
* in them. If you access a object pointer from the list, do not delete
|
||||||
|
* it directly.
|
||||||
|
*/
|
||||||
|
typedef boost::ptr_vector<LIB_ITEM> LIB_ITEMS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LIB_ITEM container to keep them sorted by their type.
|
||||||
|
*/
|
||||||
|
typedef std::map<int, LIB_ITEMS> LIB_ITEMS_MAP;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for LIB_ITEMS_MAP to provide flat (list-like) access to the items
|
||||||
|
* stored in the map (@see LIB_ITEMS_MAP).
|
||||||
|
*/
|
||||||
|
class LIB_ITEMS_LIST
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class ITERATOR
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ITERATOR& operator++();
|
||||||
|
|
||||||
|
LIB_ITEM& operator*()
|
||||||
|
{
|
||||||
|
return *m_it;
|
||||||
|
}
|
||||||
|
|
||||||
|
LIB_ITEM* operator->()
|
||||||
|
{
|
||||||
|
return &(*m_it);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=( const ITERATOR& aOther ) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
* @param aItems is the container to wrap.
|
||||||
|
* @param aType enables item type filtering. When aType is TYPE_NOT_INIT, there is no
|
||||||
|
* filtering and all item types are accessible by the iterator.
|
||||||
|
*/
|
||||||
|
ITERATOR( LIB_ITEMS_MAP& aItems, int aType = TYPE_NOT_INIT );
|
||||||
|
|
||||||
|
///> Wrapped container
|
||||||
|
LIB_ITEMS_MAP* m_parent;
|
||||||
|
|
||||||
|
///> Flag indicating whether type filtering is enabled
|
||||||
|
bool m_filter;
|
||||||
|
|
||||||
|
///> Type of the currently iterated items (@see KICAD_T)
|
||||||
|
int m_type;
|
||||||
|
|
||||||
|
///> Iterator for one of the LIB_ITEMS containers stored in the map
|
||||||
|
LIB_ITEMS::iterator m_it;
|
||||||
|
|
||||||
|
// Range of valid types handled by the iterator
|
||||||
|
static constexpr KICAD_T FIRST_TYPE = LIB_ARC_T;
|
||||||
|
static constexpr KICAD_T LAST_TYPE = LIB_FIELD_T;
|
||||||
|
|
||||||
|
friend class LIB_ITEMS_LIST;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
LIB_ITEMS_LIST( LIB_ITEMS_MAP& aData )
|
||||||
|
: m_data( aData )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ITERATOR begin( int aType = TYPE_NOT_INIT ) const;
|
||||||
|
ITERATOR end( int aType = TYPE_NOT_INIT ) const;
|
||||||
|
|
||||||
|
void push_back( LIB_ITEM* aItem );
|
||||||
|
ITERATOR erase( const ITERATOR& aIterator );
|
||||||
|
|
||||||
|
size_t size() const;
|
||||||
|
bool empty() const;
|
||||||
|
void sort();
|
||||||
|
|
||||||
|
LIB_ITEM& operator[]( unsigned int aIdx );
|
||||||
|
const LIB_ITEM& operator[]( unsigned int aIdx ) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
///> Wrapped container
|
||||||
|
LIB_ITEMS_MAP& m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* LIB_ITEMS_H */
|
|
@ -113,9 +113,6 @@ void LIB_EDIT_FRAME::EditGraphicSymbol( wxDC* DC, LIB_ITEM* DrawItem )
|
||||||
|
|
||||||
DrawItem->SetWidth( m_drawLineWidth );
|
DrawItem->SetWidth( m_drawLineWidth );
|
||||||
|
|
||||||
if( component )
|
|
||||||
component->GetDrawItemList().sort();
|
|
||||||
|
|
||||||
OnModify( );
|
OnModify( );
|
||||||
|
|
||||||
MSG_PANEL_ITEMS items;
|
MSG_PANEL_ITEMS items;
|
||||||
|
|
|
@ -110,7 +110,7 @@ void LIB_EDIT_FRAME::LoadOneSymbol()
|
||||||
wxCHECK_RET( !aliasNames.IsEmpty(), "No aliases found in library " + filename );
|
wxCHECK_RET( !aliasNames.IsEmpty(), "No aliases found in library " + filename );
|
||||||
|
|
||||||
LIB_PART* first = lib->FindAlias( aliasNames[0] )->GetPart();
|
LIB_PART* first = lib->FindAlias( aliasNames[0] )->GetPart();
|
||||||
LIB_ITEMS& drawList = first->GetDrawItemList();
|
LIB_ITEMS_LIST& drawList = first->GetDrawItemList();
|
||||||
|
|
||||||
for( LIB_ITEM& item : drawList )
|
for( LIB_ITEM& item : drawList )
|
||||||
{
|
{
|
||||||
|
@ -213,7 +213,7 @@ void LIB_EDIT_FRAME::SaveOneSymbol()
|
||||||
part->GetValueField().Save( formatter );
|
part->GetValueField().Save( formatter );
|
||||||
formatter.Print( 0, "DRAW\n" );
|
formatter.Print( 0, "DRAW\n" );
|
||||||
|
|
||||||
LIB_ITEMS& drawList = part->GetDrawItemList();
|
LIB_ITEMS_LIST& drawList = part->GetDrawItemList();
|
||||||
|
|
||||||
for( LIB_ITEM& item : drawList )
|
for( LIB_ITEM& item : drawList )
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue