LIB_ITEMS_CONTAINER reimplemented using C-style array of boost::ptr_vector
Fixes: lp:1714974 * https://bugs.launchpad.net/kicad/+bug/1714974
This commit is contained in:
parent
b00174c5a4
commit
0be357ec3e
|
@ -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() ), drawings( drawingsMap )
|
m_me( this, null_deleter() )
|
||||||
{
|
{
|
||||||
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 );
|
||||||
drawingsMap[LIB_FIELD_T].push_back( value );
|
m_drawings[LIB_FIELD_T].push_back( value );
|
||||||
|
|
||||||
drawingsMap[LIB_FIELD_T].push_back( new LIB_FIELD( this, REFERENCE ) );
|
m_drawings[LIB_FIELD_T].push_back( new LIB_FIELD( this, REFERENCE ) );
|
||||||
drawingsMap[LIB_FIELD_T].push_back( new LIB_FIELD( this, FOOTPRINT ) );
|
m_drawings[LIB_FIELD_T].push_back( new LIB_FIELD( this, FOOTPRINT ) );
|
||||||
drawingsMap[LIB_FIELD_T].push_back( new LIB_FIELD( this, DATASHEET ) );
|
m_drawings[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() ), drawings( drawingsMap )
|
m_me( this, null_deleter() )
|
||||||
{
|
{
|
||||||
LIB_ITEM* newItem;
|
LIB_ITEM* newItem;
|
||||||
|
|
||||||
|
@ -223,14 +223,14 @@ 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.drawings )
|
for( LIB_ITEM& oldItem : aPart.m_drawings )
|
||||||
{
|
{
|
||||||
if( oldItem.IsNew() )
|
if( oldItem.IsNew() )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
newItem = (LIB_ITEM*) oldItem.Clone();
|
newItem = (LIB_ITEM*) oldItem.Clone();
|
||||||
newItem->SetParent( this );
|
newItem->SetParent( this );
|
||||||
drawings.push_back( newItem );
|
m_drawings.push_back( newItem );
|
||||||
}
|
}
|
||||||
|
|
||||||
for( size_t i = 0; i < aPart.m_aliases.size(); i++ )
|
for( size_t i = 0; i < aPart.m_aliases.size(); i++ )
|
||||||
|
@ -329,7 +329,7 @@ void LIB_PART::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDc, const wxPoint& aOffset,
|
||||||
if( ! ( screen && screen->m_IsPrinting && GetGRForceBlackPenState() )
|
if( ! ( screen && screen->m_IsPrinting && GetGRForceBlackPenState() )
|
||||||
&& ( aOpts.color == COLOR4D::UNSPECIFIED ) )
|
&& ( aOpts.color == COLOR4D::UNSPECIFIED ) )
|
||||||
{
|
{
|
||||||
for( LIB_ITEM& drawItem : drawings )
|
for( LIB_ITEM& drawItem : m_drawings )
|
||||||
{
|
{
|
||||||
if( drawItem.m_Fill != FILLED_WITH_BG_BODYCOLOR )
|
if( drawItem.m_Fill != FILLED_WITH_BG_BODYCOLOR )
|
||||||
continue;
|
continue;
|
||||||
|
@ -367,7 +367,7 @@ void LIB_PART::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDc, const wxPoint& aOffset,
|
||||||
// Track the index into the dangling pins list
|
// Track the index into the dangling pins list
|
||||||
size_t pin_index = 0;
|
size_t pin_index = 0;
|
||||||
|
|
||||||
for( LIB_ITEM& drawItem : drawings )
|
for( LIB_ITEM& drawItem : m_drawings )
|
||||||
{
|
{
|
||||||
if( aOpts.only_selected && !drawItem.IsSelected() )
|
if( aOpts.only_selected && !drawItem.IsSelected() )
|
||||||
continue;
|
continue;
|
||||||
|
@ -463,7 +463,7 @@ void LIB_PART::Plot( PLOTTER* aPlotter, int aUnit, int aConvert,
|
||||||
|
|
||||||
// draw background for filled items using background option
|
// draw background for filled items using background option
|
||||||
// Solid lines will be drawn after the background
|
// Solid lines will be drawn after the background
|
||||||
for( LIB_ITEM& item : drawings )
|
for( LIB_ITEM& item : m_drawings )
|
||||||
{
|
{
|
||||||
// Lib Fields are not plotted here, because this plot function
|
// Lib Fields are not plotted here, because this plot function
|
||||||
// is used to plot schematic items, which have they own fields
|
// is used to plot schematic items, which have they own fields
|
||||||
|
@ -482,7 +482,7 @@ void LIB_PART::Plot( PLOTTER* aPlotter, int aUnit, int aConvert,
|
||||||
|
|
||||||
// Not filled items and filled shapes are now plotted
|
// Not filled items and filled shapes are now plotted
|
||||||
// (plot only items which are not already plotted)
|
// (plot only items which are not already plotted)
|
||||||
for( LIB_ITEM& item : drawings )
|
for( LIB_ITEM& item : m_drawings )
|
||||||
{
|
{
|
||||||
if( item.Type() == LIB_FIELD_T )
|
if( item.Type() == LIB_FIELD_T )
|
||||||
continue;
|
continue;
|
||||||
|
@ -506,7 +506,7 @@ void LIB_PART::PlotLibFields( PLOTTER* aPlotter, int aUnit, int aConvert,
|
||||||
aPlotter->SetColor( GetLayerColor( LAYER_FIELDS ) );
|
aPlotter->SetColor( GetLayerColor( LAYER_FIELDS ) );
|
||||||
bool fill = aPlotter->GetColorMode();
|
bool fill = aPlotter->GetColorMode();
|
||||||
|
|
||||||
for( LIB_ITEM& item : drawings )
|
for( LIB_ITEM& item : m_drawings )
|
||||||
{
|
{
|
||||||
if( item.Type() != LIB_FIELD_T )
|
if( item.Type() != LIB_FIELD_T )
|
||||||
continue;
|
continue;
|
||||||
|
@ -552,7 +552,7 @@ void LIB_PART::RemoveDrawItem( LIB_ITEM* aItem, EDA_DRAW_PANEL* aPanel, wxDC* aD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LIB_ITEMS& items = drawingsMap[aItem->Type()];
|
LIB_ITEMS& items = m_drawings[ aItem->Type() ];
|
||||||
|
|
||||||
for( LIB_ITEMS::iterator i = items.begin(); i != items.end(); i++ )
|
for( LIB_ITEMS::iterator i = items.begin(); i != items.end(); i++ )
|
||||||
{
|
{
|
||||||
|
@ -574,7 +574,7 @@ void LIB_PART::AddDrawItem( LIB_ITEM* aItem )
|
||||||
{
|
{
|
||||||
wxASSERT( aItem != NULL );
|
wxASSERT( aItem != NULL );
|
||||||
|
|
||||||
drawings.push_back( aItem );
|
m_drawings.push_back( aItem );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -583,32 +583,24 @@ LIB_ITEM* LIB_PART::GetNextDrawItem( LIB_ITEM* aItem, KICAD_T aType )
|
||||||
/* Return the next draw object pointer.
|
/* Return the next draw object pointer.
|
||||||
* If item is NULL return the first item of type in the list.
|
* If item is NULL return the first item of type in the list.
|
||||||
*/
|
*/
|
||||||
if( drawings.empty() )
|
if( m_drawings.empty( aType ) )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if( aItem == NULL && aType == TYPE_NOT_INIT ) // type is unspecified
|
if( aItem == NULL )
|
||||||
return &drawings[0];
|
return &( *( m_drawings.begin( aType ) ) );
|
||||||
|
|
||||||
// Search for last item
|
// Search for last item, assume aItem is of type aType
|
||||||
size_t idx = 0;
|
wxASSERT( ( aType == TYPE_NOT_INIT ) || ( aType == aItem->Type() ) );
|
||||||
|
LIB_ITEMS_CONTAINER::ITERATOR it = m_drawings.begin( aType );
|
||||||
if( aItem )
|
while( ( it != m_drawings.end( aType ) ) && ( aItem != &( *it ) ) )
|
||||||
{
|
++it;
|
||||||
for( ; idx < drawings.size(); idx++ )
|
|
||||||
{
|
|
||||||
if( aItem == &drawings[idx] )
|
|
||||||
{
|
|
||||||
idx++; // Prepare the next item search
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search the next item
|
// Search the next item
|
||||||
for( ; idx < drawings.size(); idx++ )
|
if( it != m_drawings.end( aType ) )
|
||||||
{
|
{
|
||||||
if( aType == TYPE_NOT_INIT || drawings[ idx ].Type() == aType )
|
++it;
|
||||||
return &drawings[ idx ];
|
if( it != m_drawings.end( aType ) )
|
||||||
|
return &( *it );
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -617,7 +609,7 @@ 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 )
|
if( m_drawings.empty( LIB_PIN_T ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Notes:
|
/* Notes:
|
||||||
|
@ -626,7 +618,7 @@ void LIB_PART::GetPins( LIB_PINS& aList, int aUnit, int aConvert )
|
||||||
* 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 : drawingsMap[LIB_PIN_T] )
|
for( LIB_ITEM& item : m_drawings[ LIB_PIN_T ] )
|
||||||
{
|
{
|
||||||
// Unit filtering:
|
// Unit filtering:
|
||||||
if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
|
if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
|
||||||
|
@ -816,15 +808,15 @@ bool LIB_PART::Save( OUTPUTFORMATTER& aFormatter )
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save graphics items (including pins)
|
// Save graphics items (including pins)
|
||||||
if( !drawings.empty() )
|
if( !m_drawings.empty() )
|
||||||
{
|
{
|
||||||
/* we sort the draw items, in order to have an edition more easy,
|
/* we sort the draw items, in order to have an edition more easy,
|
||||||
* when a file editing "by hand" is made */
|
* when a file editing "by hand" is made */
|
||||||
drawings.sort();
|
m_drawings.sort();
|
||||||
|
|
||||||
aFormatter.Print( 0, "DRAW\n" );
|
aFormatter.Print( 0, "DRAW\n" );
|
||||||
|
|
||||||
for( LIB_ITEM& item : drawings )
|
for( LIB_ITEM& item : m_drawings )
|
||||||
{
|
{
|
||||||
if( item.Type() == LIB_FIELD_T )
|
if( item.Type() == LIB_FIELD_T )
|
||||||
continue;
|
continue;
|
||||||
|
@ -1073,7 +1065,7 @@ bool LIB_PART::LoadDrawEntries( LINE_READER& aLineReader, wxString& aErrorMsg )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
drawings.push_back( newEntry );
|
m_drawings.push_back( newEntry );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1123,7 +1115,7 @@ bool LIB_PART::LoadField( LINE_READER& aLineReader, wxString& aErrorMsg )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
drawingsMap[LIB_FIELD_T].push_back( field );
|
m_drawings.push_back( field );
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1160,7 +1152,7 @@ const EDA_RECT LIB_PART::GetUnitBoundingBox( int aUnit, int aConvert ) const
|
||||||
EDA_RECT bBox;
|
EDA_RECT bBox;
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
|
|
||||||
for( const LIB_ITEM& item : drawings )
|
for( const LIB_ITEM& item : m_drawings )
|
||||||
{
|
{
|
||||||
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 ) ) )
|
||||||
|
@ -1190,7 +1182,7 @@ const EDA_RECT LIB_PART::GetBodyBoundingBox( int aUnit, int aConvert ) const
|
||||||
EDA_RECT bBox;
|
EDA_RECT bBox;
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
|
|
||||||
for( const LIB_ITEM& item : drawings )
|
for( const LIB_ITEM& item : m_drawings )
|
||||||
{
|
{
|
||||||
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 ) ) )
|
||||||
|
@ -1217,7 +1209,7 @@ const EDA_RECT LIB_PART::GetBodyBoundingBox( int aUnit, int aConvert ) const
|
||||||
|
|
||||||
void LIB_PART::deleteAllFields()
|
void LIB_PART::deleteAllFields()
|
||||||
{
|
{
|
||||||
drawingsMap[LIB_FIELD_T].clear();
|
m_drawings[ LIB_FIELD_T ].clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1231,7 +1223,7 @@ 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 );
|
||||||
drawingsMap[LIB_FIELD_T].push_back( field );
|
m_drawings.push_back( field );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1256,7 +1248,7 @@ 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 : drawingsMap[LIB_FIELD_T] )
|
for( LIB_ITEM& item : m_drawings[ LIB_FIELD_T ] )
|
||||||
{
|
{
|
||||||
field = ( LIB_FIELD* ) &item;
|
field = ( LIB_FIELD* ) &item;
|
||||||
|
|
||||||
|
@ -1270,7 +1262,7 @@ 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 : drawingsMap[LIB_FIELD_T] )
|
for( LIB_ITEM& item : m_drawings[ LIB_FIELD_T ] )
|
||||||
{
|
{
|
||||||
LIB_FIELD* field = ( LIB_FIELD* ) &item;
|
LIB_FIELD* field = ( LIB_FIELD* ) &item;
|
||||||
|
|
||||||
|
@ -1284,7 +1276,7 @@ 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 : drawingsMap[LIB_FIELD_T] )
|
for( LIB_ITEM& item : m_drawings[ LIB_FIELD_T ] )
|
||||||
{
|
{
|
||||||
LIB_FIELD* field = ( LIB_FIELD* ) &item;
|
LIB_FIELD* field = ( LIB_FIELD* ) &item;
|
||||||
|
|
||||||
|
@ -1361,21 +1353,20 @@ 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 : m_drawings )
|
||||||
item.SetOffset( aOffset );
|
item.SetOffset( aOffset );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LIB_PART::RemoveDuplicateDrawItems()
|
void LIB_PART::RemoveDuplicateDrawItems()
|
||||||
{
|
{
|
||||||
for( auto& itemTypes : drawingsMap )
|
m_drawings.unique();
|
||||||
itemTypes.second.unique();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool LIB_PART::HasConversion() const
|
bool LIB_PART::HasConversion() const
|
||||||
{
|
{
|
||||||
for( const LIB_ITEM& item : drawings )
|
for( const LIB_ITEM& item : m_drawings )
|
||||||
{
|
{
|
||||||
if( item.m_Convert > 1 )
|
if( item.m_Convert > 1 )
|
||||||
return true;
|
return true;
|
||||||
|
@ -1387,7 +1378,7 @@ bool LIB_PART::HasConversion() const
|
||||||
|
|
||||||
void LIB_PART::ClearStatus()
|
void LIB_PART::ClearStatus()
|
||||||
{
|
{
|
||||||
for( LIB_ITEM& item : drawings )
|
for( LIB_ITEM& item : m_drawings )
|
||||||
{
|
{
|
||||||
item.m_Flags = 0;
|
item.m_Flags = 0;
|
||||||
}
|
}
|
||||||
|
@ -1398,7 +1389,7 @@ int LIB_PART::SelectItems( EDA_RECT& aRect, int aUnit, int aConvert, bool aEditP
|
||||||
{
|
{
|
||||||
int itemCount = 0;
|
int itemCount = 0;
|
||||||
|
|
||||||
for( LIB_ITEM& item : drawings )
|
for( LIB_ITEM& item : m_drawings )
|
||||||
{
|
{
|
||||||
item.ClearFlags( SELECTED );
|
item.ClearFlags( SELECTED );
|
||||||
|
|
||||||
|
@ -1427,7 +1418,7 @@ int LIB_PART::SelectItems( EDA_RECT& aRect, int aUnit, int aConvert, bool aEditP
|
||||||
|
|
||||||
void LIB_PART::MoveSelectedItems( const wxPoint& aOffset )
|
void LIB_PART::MoveSelectedItems( const wxPoint& aOffset )
|
||||||
{
|
{
|
||||||
for( LIB_ITEM& item : drawings )
|
for( LIB_ITEM& item : m_drawings )
|
||||||
{
|
{
|
||||||
if( !item.IsSelected() )
|
if( !item.IsSelected() )
|
||||||
continue;
|
continue;
|
||||||
|
@ -1440,7 +1431,7 @@ void LIB_PART::MoveSelectedItems( const wxPoint& aOffset )
|
||||||
|
|
||||||
void LIB_PART::ClearSelectedItems()
|
void LIB_PART::ClearSelectedItems()
|
||||||
{
|
{
|
||||||
for( LIB_ITEM& item : drawings )
|
for( LIB_ITEM& item : m_drawings )
|
||||||
{
|
{
|
||||||
item.m_Flags = 0;
|
item.m_Flags = 0;
|
||||||
}
|
}
|
||||||
|
@ -1449,14 +1440,14 @@ void LIB_PART::ClearSelectedItems()
|
||||||
|
|
||||||
void LIB_PART::DeleteSelectedItems()
|
void LIB_PART::DeleteSelectedItems()
|
||||||
{
|
{
|
||||||
LIB_ITEMS_LIST::ITERATOR item = drawings.begin();
|
LIB_ITEMS_CONTAINER::ITERATOR item = m_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.
|
||||||
// Skip also not visible items.
|
// Skip also not visible items.
|
||||||
// But I think fields must not be deleted by a block delete command or other global command
|
// But I think fields must not be deleted by a block delete command or other global command
|
||||||
// because they are not really graphic items
|
// because they are not really graphic items
|
||||||
while( item != drawings.end() )
|
while( item != m_drawings.end() )
|
||||||
{
|
{
|
||||||
if( item->Type() == LIB_FIELD_T )
|
if( item->Type() == LIB_FIELD_T )
|
||||||
{
|
{
|
||||||
|
@ -1472,25 +1463,17 @@ void LIB_PART::DeleteSelectedItems()
|
||||||
if( !item->IsSelected() )
|
if( !item->IsSelected() )
|
||||||
++item;
|
++item;
|
||||||
else
|
else
|
||||||
item = drawings.erase( item );
|
item = m_drawings.erase( item );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LIB_PART::CopySelectedItems( const wxPoint& aOffset )
|
void LIB_PART::CopySelectedItems( const wxPoint& aOffset )
|
||||||
{
|
{
|
||||||
/* *do not* use iterators here, because new items
|
|
||||||
* are added to drawings that is a boost::ptr_vector.
|
|
||||||
* When push_back elements in buffer,
|
|
||||||
* a memory reallocation can happen and will break pointers
|
|
||||||
*/
|
|
||||||
unsigned icnt = drawings.size();
|
|
||||||
std::vector< LIB_ITEM* > tmp;
|
std::vector< LIB_ITEM* > tmp;
|
||||||
|
|
||||||
for( unsigned ii = 0; ii < icnt; ii++ )
|
for( LIB_ITEM& item : m_drawings )
|
||||||
{
|
{
|
||||||
LIB_ITEM& item = drawings[ii];
|
|
||||||
|
|
||||||
// We *do not* copy fields because they are unique for the whole component
|
// We *do not* copy fields because they are unique for the whole component
|
||||||
// so skip them (do not duplicate) if they are flagged selected.
|
// so skip them (do not duplicate) if they are flagged selected.
|
||||||
if( item.Type() == LIB_FIELD_T )
|
if( item.Type() == LIB_FIELD_T )
|
||||||
|
@ -1502,11 +1485,15 @@ void LIB_PART::CopySelectedItems( const wxPoint& aOffset )
|
||||||
item.ClearFlags( SELECTED );
|
item.ClearFlags( SELECTED );
|
||||||
LIB_ITEM* newItem = (LIB_ITEM*) item.Clone();
|
LIB_ITEM* newItem = (LIB_ITEM*) item.Clone();
|
||||||
newItem->SetFlags( SELECTED );
|
newItem->SetFlags( SELECTED );
|
||||||
|
|
||||||
|
// When push_back elements in buffer, a memory reallocation can happen
|
||||||
|
// and will break pointers.
|
||||||
|
// So, push_back later.
|
||||||
tmp.push_back( newItem );
|
tmp.push_back( newItem );
|
||||||
}
|
}
|
||||||
|
|
||||||
for( unsigned ii = 0; ii < tmp.size(); ii++ )
|
for( auto item : tmp)
|
||||||
drawings.push_back( tmp[ii] );
|
m_drawings.push_back( item );
|
||||||
|
|
||||||
MoveSelectedItems( aOffset );
|
MoveSelectedItems( aOffset );
|
||||||
}
|
}
|
||||||
|
@ -1514,7 +1501,7 @@ void LIB_PART::CopySelectedItems( const wxPoint& aOffset )
|
||||||
|
|
||||||
void LIB_PART::MirrorSelectedItemsH( const wxPoint& aCenter )
|
void LIB_PART::MirrorSelectedItemsH( const wxPoint& aCenter )
|
||||||
{
|
{
|
||||||
for( LIB_ITEM& item : drawings )
|
for( LIB_ITEM& item : m_drawings )
|
||||||
{
|
{
|
||||||
if( !item.IsSelected() )
|
if( !item.IsSelected() )
|
||||||
continue;
|
continue;
|
||||||
|
@ -1527,7 +1514,7 @@ void LIB_PART::MirrorSelectedItemsH( const wxPoint& aCenter )
|
||||||
|
|
||||||
void LIB_PART::MirrorSelectedItemsV( const wxPoint& aCenter )
|
void LIB_PART::MirrorSelectedItemsV( const wxPoint& aCenter )
|
||||||
{
|
{
|
||||||
for( LIB_ITEM& item : drawings )
|
for( LIB_ITEM& item : m_drawings )
|
||||||
{
|
{
|
||||||
if( !item.IsSelected() )
|
if( !item.IsSelected() )
|
||||||
continue;
|
continue;
|
||||||
|
@ -1540,7 +1527,7 @@ void LIB_PART::MirrorSelectedItemsV( const wxPoint& aCenter )
|
||||||
|
|
||||||
void LIB_PART::RotateSelectedItems( const wxPoint& aCenter )
|
void LIB_PART::RotateSelectedItems( const wxPoint& aCenter )
|
||||||
{
|
{
|
||||||
for( LIB_ITEM& item : drawings )
|
for( LIB_ITEM& item : m_drawings )
|
||||||
{
|
{
|
||||||
if( !item.IsSelected() )
|
if( !item.IsSelected() )
|
||||||
continue;
|
continue;
|
||||||
|
@ -1554,7 +1541,7 @@ void LIB_PART::RotateSelectedItems( const wxPoint& aCenter )
|
||||||
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 )
|
||||||
{
|
{
|
||||||
for( LIB_ITEM& item : drawings )
|
for( LIB_ITEM& item : m_drawings )
|
||||||
{
|
{
|
||||||
if( ( aUnit && item.m_Unit && ( aUnit != item.m_Unit) )
|
if( ( aUnit && item.m_Unit && ( aUnit != item.m_Unit) )
|
||||||
|| ( aConvert && item.m_Convert && ( aConvert != item.m_Convert ) )
|
|| ( aConvert && item.m_Convert && ( aConvert != item.m_Convert ) )
|
||||||
|
@ -1597,12 +1584,12 @@ void LIB_PART::SetUnitCount( int aCount )
|
||||||
|
|
||||||
if( aCount < m_unitCount )
|
if( aCount < m_unitCount )
|
||||||
{
|
{
|
||||||
LIB_ITEMS_LIST::ITERATOR i = drawings.begin();
|
LIB_ITEMS_CONTAINER::ITERATOR i = m_drawings.begin();
|
||||||
|
|
||||||
while( i != drawings.end() )
|
while( i != m_drawings.end() )
|
||||||
{
|
{
|
||||||
if( i->m_Unit > aCount )
|
if( i->m_Unit > aCount )
|
||||||
i = drawings.erase( i );
|
i = m_drawings.erase( i );
|
||||||
else
|
else
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
@ -1611,23 +1598,25 @@ void LIB_PART::SetUnitCount( int aCount )
|
||||||
{
|
{
|
||||||
int prevCount = m_unitCount;
|
int prevCount = m_unitCount;
|
||||||
|
|
||||||
// We cannot use an iterator here, because when adding items in vector
|
std::vector< LIB_ITEM* > tmp;
|
||||||
// the buffer can be reallocated, that change the previous value of
|
for( LIB_ITEM& item : m_drawings )
|
||||||
// .begin() and .end() iterators and invalidate others iterators
|
|
||||||
unsigned imax = drawings.size();
|
|
||||||
|
|
||||||
for( unsigned ii = 0; ii < imax; ii++ )
|
|
||||||
{
|
{
|
||||||
if( drawings[ii].m_Unit != 1 )
|
if( item.m_Unit != 1 )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for( int j = prevCount + 1; j <= aCount; j++ )
|
for( int j = prevCount + 1; j <= aCount; j++ )
|
||||||
{
|
{
|
||||||
LIB_ITEM* newItem = (LIB_ITEM*) drawings[ii].Clone();
|
LIB_ITEM* newItem = (LIB_ITEM*) item.Clone();
|
||||||
newItem->m_Unit = j;
|
newItem->m_Unit = j;
|
||||||
drawings.push_back( newItem );
|
|
||||||
|
// We cannot use push_back here, because when adding items in vector
|
||||||
|
// the buffer can be reallocated, that change the previous value of
|
||||||
|
// .begin() and .end() iterators and invalidate others iterators
|
||||||
|
tmp.push_back( newItem );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for( auto item : tmp )
|
||||||
|
m_drawings.push_back( item );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_unitCount = aCount;
|
m_unitCount = aCount;
|
||||||
|
@ -1644,7 +1633,7 @@ void LIB_PART::SetConversion( bool aSetConvert )
|
||||||
{
|
{
|
||||||
std::vector< LIB_ITEM* > tmp; // Temporarily store the duplicated pins here.
|
std::vector< LIB_ITEM* > tmp; // Temporarily store the duplicated pins here.
|
||||||
|
|
||||||
for( LIB_ITEM& item : drawings )
|
for( LIB_ITEM& item : m_drawings )
|
||||||
{
|
{
|
||||||
// Only pins are duplicated.
|
// Only pins are duplicated.
|
||||||
if( item.Type() != LIB_PIN_T )
|
if( item.Type() != LIB_PIN_T )
|
||||||
|
@ -1660,18 +1649,18 @@ void LIB_PART::SetConversion( bool aSetConvert )
|
||||||
|
|
||||||
// Transfer the new pins to the LIB_PART.
|
// Transfer the new pins to the LIB_PART.
|
||||||
for( unsigned i = 0; i < tmp.size(); i++ )
|
for( unsigned i = 0; i < tmp.size(); i++ )
|
||||||
drawings.push_back( tmp[i] );
|
m_drawings.push_back( tmp[i] );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Delete converted shape items because the converted shape does
|
// Delete converted shape items because the converted shape does
|
||||||
// not exist
|
// not exist
|
||||||
LIB_ITEMS_LIST::ITERATOR i = drawings.begin();
|
LIB_ITEMS_CONTAINER::ITERATOR i = m_drawings.begin();
|
||||||
|
|
||||||
while( i != drawings.end() )
|
while( i != m_drawings.end() )
|
||||||
{
|
{
|
||||||
if( i->m_Convert > 1 )
|
if( i->m_Convert > 1 )
|
||||||
i = drawings.erase( i );
|
i = m_drawings.erase( i );
|
||||||
else
|
else
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,8 +236,7 @@ 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_MAP drawingsMap; ///< How to draw this part.
|
LIB_ITEMS_CONTAINER m_drawings; ///< Drawing items of 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
|
||||||
|
@ -683,19 +682,11 @@ public:
|
||||||
/**
|
/**
|
||||||
* Return a reference to the draw item list.
|
* Return a reference to the draw item list.
|
||||||
*
|
*
|
||||||
* @return LIB_ITEMS_LIST& - Reference to the draw item object list.
|
* @return LIB_ITEMS_CONTAINER& - Reference to the draw item object container.
|
||||||
*/
|
*/
|
||||||
LIB_ITEMS_LIST& GetDrawItemList()
|
LIB_ITEMS_CONTAINER& GetDrawItems()
|
||||||
{
|
{
|
||||||
return drawings;
|
return m_drawings;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a reference to the draw item map that stores items per their type.
|
|
||||||
*/
|
|
||||||
LIB_ITEMS_MAP& GetDrawItemMap()
|
|
||||||
{
|
|
||||||
return drawingsMap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -111,7 +111,7 @@ SEARCH_RESULT LIB_COLLECTOR::Inspect( EDA_ITEM* aItem, void* testData )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LIB_COLLECTOR::Collect( LIB_ITEMS_LIST& aItems, const KICAD_T aFilterList[],
|
void LIB_COLLECTOR::Collect( LIB_ITEMS_CONTAINER& 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
|
||||||
|
@ -124,9 +124,7 @@ void LIB_COLLECTOR::Collect( LIB_ITEMS_LIST& aItems, const KICAD_T aFilterList[]
|
||||||
m_data.m_unit = aUnit;
|
m_data.m_unit = aUnit;
|
||||||
m_data.m_convert = aConvert;
|
m_data.m_convert = aConvert;
|
||||||
|
|
||||||
for( size_t i = 0; i < aItems.size(); i++ )
|
for( LIB_ITEM& item : aItems )
|
||||||
{
|
if( SEARCH_QUIT == item.Visit( m_inspector, NULL, m_ScanTypes ) )
|
||||||
if( SEARCH_QUIT == aItems[i].Visit( m_inspector, NULL, m_ScanTypes ) )
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#include <lib_draw_item.h>
|
#include <lib_draw_item.h>
|
||||||
|
|
||||||
|
|
||||||
class LIB_ITEMS_LIST;
|
class LIB_ITEMS_CONTAINER;
|
||||||
class LIB_COLLECTOR;
|
class LIB_COLLECTOR;
|
||||||
|
|
||||||
|
|
||||||
|
@ -128,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_LIST& aItem, const KICAD_T aFilterList[], const wxPoint& aPosition,
|
void Collect( LIB_ITEMS_CONTAINER& aItem, const KICAD_T aFilterList[], const wxPoint& aPosition,
|
||||||
int aUnit = 0, int aConvert = 0 );
|
int aUnit = 0, int aConvert = 0 );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright 2017 CERN
|
* Copyright 2017 CERN
|
||||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||||
|
* @author Bernhard Stegmaier <stegmaier@sw-systems.de>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -28,194 +29,169 @@
|
||||||
#include <wx/debug.h>
|
#include <wx/debug.h>
|
||||||
|
|
||||||
|
|
||||||
LIB_ITEMS_LIST::ITERATOR::ITERATOR( LIB_ITEMS_MAP& aItems, int aType )
|
void LIB_ITEMS_CONTAINER::push_back( LIB_ITEM *aItem )
|
||||||
: m_parent( &aItems )
|
|
||||||
{
|
{
|
||||||
m_filter = ( aType != TYPE_NOT_INIT );
|
operator[]( aItem->Type() ).push_back( aItem );
|
||||||
m_type = m_filter ? aType : FIRST_TYPE;
|
|
||||||
m_it = (*m_parent)[m_type].begin();
|
|
||||||
|
|
||||||
// be sure the enum order is correct for the type
|
|
||||||
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_CONTAINER::ITERATOR LIB_ITEMS_CONTAINER::erase(const LIB_ITEMS_CONTAINER::ITERATOR &aIterator)
|
||||||
LIB_ITEMS_LIST::ITERATOR LIB_ITEMS_LIST::begin( int aType ) const
|
|
||||||
{
|
{
|
||||||
LIB_ITEMS_LIST::ITERATOR it( m_data, aType );
|
LIB_ITEMS_CONTAINER::ITERATOR it( aIterator );
|
||||||
|
it.m_it = (*aIterator.m_parent)[ aIterator.m_curType ].erase( aIterator.m_it );
|
||||||
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, starting from the last type
|
|
||||||
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 );
|
|
||||||
it.validate();
|
it.validate();
|
||||||
|
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LIB_ITEMS_CONTAINER::ITERATOR LIB_ITEMS_CONTAINER::begin( int aType )
|
||||||
size_t LIB_ITEMS_LIST::size() const
|
|
||||||
{
|
{
|
||||||
size_t counter = 0;
|
size_t bucket = ( aType != TYPE_NOT_INIT ) ? aType : first();
|
||||||
|
return ITERATOR( this, operator[]( bucket ).begin(), bucket, aType );
|
||||||
for( auto& type : m_data )
|
|
||||||
counter += type.second.size();
|
|
||||||
|
|
||||||
return counter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LIB_ITEMS_CONTAINER::ITERATOR LIB_ITEMS_CONTAINER::end(int aType)
|
||||||
bool LIB_ITEMS_LIST::empty() const
|
|
||||||
{
|
{
|
||||||
for( auto& type : m_data )
|
size_t bucket = ( aType != TYPE_NOT_INIT ) ? aType : last();
|
||||||
|
return ITERATOR( this, operator[]( bucket ).end(), bucket, aType );
|
||||||
|
}
|
||||||
|
|
||||||
|
LIB_ITEMS_CONTAINER::CONST_ITERATOR LIB_ITEMS_CONTAINER::begin( int aType ) const
|
||||||
|
{
|
||||||
|
size_t bucket = ( aType != TYPE_NOT_INIT ) ? aType : first();
|
||||||
|
return CONST_ITERATOR( this, operator[]( bucket ).begin(), bucket, aType );
|
||||||
|
}
|
||||||
|
|
||||||
|
LIB_ITEMS_CONTAINER::CONST_ITERATOR LIB_ITEMS_CONTAINER::end( int aType ) const
|
||||||
|
{
|
||||||
|
size_t bucket = ( aType != TYPE_NOT_INIT ) ? aType : last();
|
||||||
|
return CONST_ITERATOR( this, operator[]( bucket ).end(), bucket, aType );
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t LIB_ITEMS_CONTAINER::size( int aType ) const
|
||||||
|
{
|
||||||
|
if( aType != TYPE_NOT_INIT )
|
||||||
{
|
{
|
||||||
if( !type.second.empty() )
|
return operator[]( aType ).size();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
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() )
|
size_t cnt = 0;
|
||||||
return type.second[aIdx - counter];
|
for( int i = 0; i < TYPES_COUNT; ++i)
|
||||||
else
|
cnt += m_data[ i ].size();
|
||||||
counter += type.second.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
throw std::out_of_range( "LIB_ITEMS_LIST out of range" );
|
return cnt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LIB_ITEMS_CONTAINER::empty( int aType ) const
|
||||||
const LIB_ITEM& LIB_ITEMS_LIST::operator[]( unsigned int aIdx ) const
|
|
||||||
{
|
{
|
||||||
int counter = 0;
|
return ( size( aType ) == 0 );
|
||||||
|
|
||||||
for( const 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" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LIB_ITEMS_CONTAINER::sort()
|
||||||
LIB_ITEMS_LIST::ITERATOR& LIB_ITEMS_LIST::ITERATOR::operator++()
|
|
||||||
{
|
{
|
||||||
if( m_it != (*m_parent)[m_type].end() )
|
for( int i = 0; i < TYPES_COUNT; ++i )
|
||||||
|
m_data[ i ].sort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LIB_ITEMS_CONTAINER::unique()
|
||||||
|
{
|
||||||
|
for( int i = 0; i < TYPES_COUNT; ++i )
|
||||||
|
m_data[ i ].unique();
|
||||||
|
}
|
||||||
|
|
||||||
|
LIB_ITEMS &LIB_ITEMS_CONTAINER::operator[]( int aType )
|
||||||
|
{
|
||||||
|
if( ( aType < FIRST_TYPE ) || ( aType > LAST_TYPE ) )
|
||||||
|
throw std::out_of_range( "LIB_ITEMS_CONTAINER out of range" );
|
||||||
|
|
||||||
|
return m_data[ aType - FIRST_TYPE ];
|
||||||
|
}
|
||||||
|
|
||||||
|
const LIB_ITEMS &LIB_ITEMS_CONTAINER::operator[]( int aType ) const
|
||||||
|
{
|
||||||
|
if( ( aType < FIRST_TYPE ) || ( aType > LAST_TYPE ) )
|
||||||
|
throw std::out_of_range( "LIB_ITEMS_CONTAINER out of range" );
|
||||||
|
|
||||||
|
return m_data[ aType - FIRST_TYPE ];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t LIB_ITEMS_CONTAINER::first() const
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while( ( i < TYPES_COUNT ) && ( m_data[ i ].empty() ) )
|
||||||
|
++i;
|
||||||
|
|
||||||
|
return ( i == TYPES_COUNT ) ? FIRST_TYPE : FIRST_TYPE + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t LIB_ITEMS_CONTAINER::last() const
|
||||||
|
{
|
||||||
|
int i = TYPES_COUNT - 1;
|
||||||
|
while( ( i >= 0 ) && ( m_data[ i ].empty() ) )
|
||||||
|
--i;
|
||||||
|
|
||||||
|
return ( i < 0 ) ? FIRST_TYPE : FIRST_TYPE + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename ITEM_TYPE >
|
||||||
|
LIB_ITEMS_CONTAINER::ITERATOR_BASE<ITEM_TYPE>& LIB_ITEMS_CONTAINER::ITERATOR_BASE<ITEM_TYPE>::operator++()
|
||||||
|
{
|
||||||
|
if( m_it != (*m_parent)[ m_curType ].end() )
|
||||||
++m_it;
|
++m_it;
|
||||||
|
|
||||||
validate();
|
validate();
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template< typename ITEM_TYPE >
|
||||||
bool LIB_ITEMS_LIST::ITERATOR::operator!=( const LIB_ITEMS_LIST::ITERATOR& aOther ) const
|
bool LIB_ITEMS_CONTAINER::ITERATOR_BASE<ITEM_TYPE>::operator!=(const LIB_ITEMS_CONTAINER::ITERATOR_BASE<ITEM_TYPE> &aOther) const
|
||||||
{
|
{
|
||||||
wxASSERT( aOther.m_parent == m_parent );
|
if( aOther.m_parent != m_parent )
|
||||||
wxASSERT( aOther.m_filter == m_filter );
|
return true;
|
||||||
wxASSERT( !m_filter || aOther.m_type == m_type );
|
if( aOther.m_filter != m_filter )
|
||||||
|
return true;
|
||||||
|
if( aOther.m_curType != m_curType )
|
||||||
|
return true;
|
||||||
return aOther.m_it != m_it;
|
return aOther.m_it != m_it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template< typename ITEM_TYPE >
|
||||||
|
LIB_ITEMS_CONTAINER::ITERATOR_BASE<ITEM_TYPE>::ITERATOR_BASE( typename LIB_ITEMS_CONTAINER::ITERATOR_ADAPTER< ITEM_TYPE >::CONTAINER* aItems,
|
||||||
|
typename LIB_ITEMS_CONTAINER::ITERATOR_ADAPTER< ITEM_TYPE >::ITERATOR aIt,
|
||||||
|
int aBucket, int aType )
|
||||||
|
: m_parent( aItems )
|
||||||
|
, m_it( aIt )
|
||||||
|
, m_curType( aBucket )
|
||||||
|
{
|
||||||
|
m_filter = ( aType != TYPE_NOT_INIT );
|
||||||
|
}
|
||||||
|
|
||||||
void LIB_ITEMS_LIST::ITERATOR::validate()
|
template< typename ITEM_TYPE >
|
||||||
|
void LIB_ITEMS_CONTAINER::ITERATOR_BASE<ITEM_TYPE>::validate()
|
||||||
{
|
{
|
||||||
// for all-items iterators (unfiltered): check if this is the end of the
|
// for all-items iterators (unfiltered): check if this is the end of the
|
||||||
// current type container, if so switch to the next non-empty container
|
// current type container, if so switch to the next non-empty container
|
||||||
if( m_it == (*m_parent)[m_type].end() && !m_filter )
|
if( !m_filter && m_it == (*m_parent)[ m_curType ].end() )
|
||||||
{
|
{
|
||||||
auto typeIt = m_parent->find( m_type );
|
|
||||||
wxASSERT( typeIt != m_parent->end() );
|
|
||||||
|
|
||||||
// switch to the next type (look for a not empty container)
|
// switch to the next type (look for a not empty container)
|
||||||
|
int nextType = m_curType;
|
||||||
do
|
do
|
||||||
++typeIt;
|
++nextType;
|
||||||
while( typeIt != m_parent->end() && typeIt->second.empty() );
|
while( ( nextType <= LAST_TYPE ) && (*m_parent)[ nextType ].empty() );
|
||||||
|
|
||||||
// there is another not empty container, so make the iterator point to it,
|
// there is another not empty container, so make the iterator point to it,
|
||||||
// otherwise it means the iterator points to the last item
|
// otherwise it means the iterator points to the last item
|
||||||
if( typeIt != m_parent->end() )
|
if( nextType <= LAST_TYPE )
|
||||||
{
|
{
|
||||||
m_it = typeIt->second.begin();
|
m_curType = nextType;
|
||||||
m_type = typeIt->first;
|
m_it = (*m_parent)[ m_curType ].begin();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Template instantiation for const/non-const iterator
|
||||||
|
*/
|
||||||
|
template class LIB_ITEMS_CONTAINER::ITERATOR_BASE< LIB_ITEM >;
|
||||||
|
template class LIB_ITEMS_CONTAINER::ITERATOR_BASE< const LIB_ITEM >;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright 2017 CERN
|
* Copyright 2017 CERN
|
||||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||||
|
* @author Bernhard Stegmaier <stegmaier@sw-systems.de>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -31,7 +32,6 @@
|
||||||
|
|
||||||
#include <core/typeinfo.h>
|
#include <core/typeinfo.h>
|
||||||
#include <boost/ptr_container/ptr_vector.hpp>
|
#include <boost/ptr_container/ptr_vector.hpp>
|
||||||
#include <map>
|
|
||||||
|
|
||||||
class LIB_ITEM;
|
class LIB_ITEM;
|
||||||
|
|
||||||
|
@ -43,89 +43,131 @@ class LIB_ITEM;
|
||||||
*/
|
*/
|
||||||
typedef boost::ptr_vector<LIB_ITEM> LIB_ITEMS;
|
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
|
* LIB_ITEM container class. Provides both access as a flat list as well as
|
||||||
* stored in the map (@see LIB_ITEMS_MAP).
|
* access by type of item.
|
||||||
*/
|
*/
|
||||||
class LIB_ITEMS_LIST
|
class LIB_ITEMS_CONTAINER
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
class ITERATOR
|
/**
|
||||||
|
* Compile-time helper class to define some types depending on const/non-const iterator.
|
||||||
|
*/
|
||||||
|
template< typename ITEM_TYPE > struct ITERATOR_ADAPTER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic implementation of a flat const/non-const iterator over contained items.
|
||||||
|
*/
|
||||||
|
template< typename ITEM_TYPE > class ITERATOR_BASE
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ITERATOR& operator++();
|
ITERATOR_BASE& operator++();
|
||||||
|
|
||||||
LIB_ITEM& operator*()
|
ITEM_TYPE& operator*()
|
||||||
{
|
{
|
||||||
return *m_it;
|
return *m_it;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIB_ITEM* operator->()
|
ITEM_TYPE* operator->()
|
||||||
{
|
{
|
||||||
return &(*m_it);
|
return &( *m_it );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=( const ITERATOR& aOther ) const;
|
bool operator!=( const ITERATOR_BASE& aOther ) const;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
* @param aItems is the container to wrap.
|
* @param aItems is the container to wrap.
|
||||||
|
* @param aIt is the iterator to initialize this iterator (usually some begin() or end()
|
||||||
|
* iterator).
|
||||||
|
* @param aBucket is the type ID of the given iterator.
|
||||||
* @param aType enables item type filtering. When aType is TYPE_NOT_INIT, there is no
|
* @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.
|
* filtering and all item types are accessible by the iterator.
|
||||||
*/
|
*/
|
||||||
ITERATOR( LIB_ITEMS_MAP& aItems, int aType = TYPE_NOT_INIT );
|
ITERATOR_BASE( typename ITERATOR_ADAPTER<ITEM_TYPE>::CONTAINER* aItems,
|
||||||
|
typename ITERATOR_ADAPTER<ITEM_TYPE>::ITERATOR aIt,
|
||||||
|
int aBucket, int aType = TYPE_NOT_INIT );
|
||||||
|
|
||||||
///> Assures the iterator is in a valid state.
|
///> Assures the iterator is in a valid state.
|
||||||
void validate();
|
void validate();
|
||||||
|
|
||||||
///> Wrapped container
|
///> Wrapped container
|
||||||
LIB_ITEMS_MAP* m_parent;
|
typename ITERATOR_ADAPTER<ITEM_TYPE>::CONTAINER* m_parent;
|
||||||
|
|
||||||
|
///> Iterator for one of the LIB_ITEMS containers stored in the map
|
||||||
|
typename ITERATOR_ADAPTER<ITEM_TYPE>::ITERATOR m_it;
|
||||||
|
|
||||||
///> Flag indicating whether type filtering is enabled
|
///> Flag indicating whether type filtering is enabled
|
||||||
bool m_filter;
|
bool m_filter;
|
||||||
|
|
||||||
///> Type of the currently iterated items (@see KICAD_T)
|
///> Type of the currently iterated items (@see KICAD_T)
|
||||||
int m_type;
|
int m_curType;
|
||||||
|
|
||||||
///> Iterator for one of the LIB_ITEMS containers stored in the map
|
friend class LIB_ITEMS_CONTAINER;
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///> The non-const iterator
|
||||||
|
typedef ITERATOR_BASE< LIB_ITEM > ITERATOR;
|
||||||
|
///> The const iterator
|
||||||
|
typedef ITERATOR_BASE< const LIB_ITEM > CONST_ITERATOR;
|
||||||
|
|
||||||
LIB_ITEMS_LIST( LIB_ITEMS_MAP& aData )
|
|
||||||
: m_data( aData )
|
LIB_ITEMS_CONTAINER()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ITERATOR begin( int aType = TYPE_NOT_INIT ) const;
|
|
||||||
ITERATOR end( int aType = TYPE_NOT_INIT ) const;
|
|
||||||
|
|
||||||
void push_back( LIB_ITEM* aItem );
|
void push_back( LIB_ITEM* aItem );
|
||||||
ITERATOR erase( const ITERATOR& aIterator );
|
ITERATOR erase( const ITERATOR& aIterator );
|
||||||
|
|
||||||
size_t size() const;
|
ITERATOR begin( int aType = TYPE_NOT_INIT );
|
||||||
bool empty() const;
|
ITERATOR end( int aType = TYPE_NOT_INIT );
|
||||||
void sort();
|
CONST_ITERATOR begin( int aType = TYPE_NOT_INIT ) const;
|
||||||
|
CONST_ITERATOR end( int aType = TYPE_NOT_INIT ) const;
|
||||||
|
|
||||||
LIB_ITEM& operator[]( unsigned int aIdx );
|
size_t size( int aType = TYPE_NOT_INIT ) const;
|
||||||
const LIB_ITEM& operator[]( unsigned int aIdx ) const;
|
bool empty( int aType = TYPE_NOT_INIT ) const;
|
||||||
|
void sort();
|
||||||
|
void unique();
|
||||||
|
|
||||||
|
LIB_ITEMS& operator[]( int aType );
|
||||||
|
const LIB_ITEMS& operator[]( int aType ) const;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
static constexpr size_t TYPES_COUNT = LAST_TYPE - FIRST_TYPE + 1;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
///> Wrapped container
|
///> Get first non-empty type or first type if all are empty.
|
||||||
LIB_ITEMS_MAP& m_data;
|
size_t first() const;
|
||||||
|
|
||||||
|
///> Get last non-empty type or first type if all are empty.
|
||||||
|
size_t last() const;
|
||||||
|
|
||||||
|
///> Contained items by type
|
||||||
|
LIB_ITEMS m_data[ TYPES_COUNT ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definitions for non-const iterator
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
struct LIB_ITEMS_CONTAINER::ITERATOR_ADAPTER< LIB_ITEM >
|
||||||
|
{
|
||||||
|
typedef LIB_ITEMS::iterator ITERATOR;
|
||||||
|
typedef LIB_ITEMS_CONTAINER CONTAINER;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definitions for const iterator
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
struct LIB_ITEMS_CONTAINER::ITERATOR_ADAPTER< const LIB_ITEM >
|
||||||
|
{
|
||||||
|
typedef LIB_ITEMS::const_iterator ITERATOR;
|
||||||
|
typedef const LIB_ITEMS_CONTAINER CONTAINER;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* LIB_ITEMS_H */
|
#endif /* LIB_ITEMS_H */
|
||||||
|
|
|
@ -1315,7 +1315,7 @@ LIB_ITEM* LIB_EDIT_FRAME::locateItem( const wxPoint& aPosition, const KICAD_T aF
|
||||||
|
|
||||||
LIB_ITEM* item = NULL;
|
LIB_ITEM* item = NULL;
|
||||||
|
|
||||||
m_collectedItems.Collect( part->GetDrawItemList(), aFilterList, aPosition,
|
m_collectedItems.Collect( part->GetDrawItems(), aFilterList, aPosition,
|
||||||
m_unit, m_convert );
|
m_unit, m_convert );
|
||||||
|
|
||||||
if( m_collectedItems.GetCount() == 0 )
|
if( m_collectedItems.GetCount() == 0 )
|
||||||
|
|
|
@ -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_LIST& drawList = first->GetDrawItemList();
|
LIB_ITEMS_CONTAINER& drawList = first->GetDrawItems();
|
||||||
|
|
||||||
for( LIB_ITEM& item : drawList )
|
for( LIB_ITEM& item : drawList )
|
||||||
{
|
{
|
||||||
|
@ -146,7 +146,7 @@ void LIB_EDIT_FRAME::SaveOneSymbol()
|
||||||
SEARCH_STACK* search = prj.SchSearchS();
|
SEARCH_STACK* search = prj.SchSearchS();
|
||||||
LIB_PART* part = GetCurPart();
|
LIB_PART* part = GetCurPart();
|
||||||
|
|
||||||
if( !part || part->GetDrawItemList().empty() )
|
if( !part || part->GetDrawItems().empty() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wxString default_path = prj.GetRString( PROJECT::SCH_LIB_PATH );
|
wxString default_path = prj.GetRString( PROJECT::SCH_LIB_PATH );
|
||||||
|
@ -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_LIST& drawList = part->GetDrawItemList();
|
LIB_ITEMS_CONTAINER& drawList = part->GetDrawItems();
|
||||||
|
|
||||||
for( LIB_ITEM& item : drawList )
|
for( LIB_ITEM& item : drawList )
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue