Hi, In the attachment you will find a patch that refactors data storage in LIB_PART. Instead of keeping all drawings in a boost::ptr_vector<LIB_ITEM>, the items are stored in an integer to LIB_ITEMS map. Thanks to that, it is no longer necessary to call LIB_ITEMS::sort() on every modification, so the result is ~33% library loading. I see some other places where the performance could be enhanced thanks to the refactor, so if this change works then I will try to improve other areas.
I would appreciate a bit of help from brave testers that could take the patch for a test drive and confirm whether it satisfies expectations. Regards, Orson
>From 97b150e113d3922e24913378cbcf4f341d25b1fe Mon Sep 17 00:00:00 2001 From: Maciej Suminski <[email protected]> Date: Mon, 14 Aug 2017 16:53:25 +0200 Subject: [PATCH] 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. --- eeschema/CMakeLists.txt | 1 + eeschema/class_libentry.cpp | 114 +++++++----------------- eeschema/class_libentry.h | 20 ++++- eeschema/lib_collectors.cpp | 3 +- eeschema/lib_collectors.h | 3 +- eeschema/lib_draw_item.h | 10 --- eeschema/lib_items.cpp | 211 ++++++++++++++++++++++++++++++++++++++++++++ eeschema/lib_items.h | 128 +++++++++++++++++++++++++++ eeschema/symbdraw.cpp | 3 - eeschema/symbedit.cpp | 4 +- 10 files changed, 396 insertions(+), 101 deletions(-) create mode 100644 eeschema/lib_items.cpp create mode 100644 eeschema/lib_items.h diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index dc7c0c050..b369a7ab4 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -138,6 +138,7 @@ set( EESCHEMA_SRCS lib_draw_item.cpp lib_export.cpp lib_field.cpp + lib_items.cpp lib_pin.cpp lib_polyline.cpp lib_rectangle.cpp diff --git a/eeschema/class_libentry.cpp b/eeschema/class_libentry.cpp index fd01fff55..7b2bbc886 100644 --- a/eeschema/class_libentry.cpp +++ b/eeschema/class_libentry.cpp @@ -178,7 +178,7 @@ struct null_deleter LIB_PART::LIB_PART( const wxString& aName, PART_LIB* aLibrary ) : EDA_ITEM( LIB_PART_T ), - m_me( this, null_deleter() ) + m_me( this, null_deleter() ), drawings( drawingsMap ) { m_name = aName; m_library = aLibrary; @@ -198,17 +198,17 @@ LIB_PART::LIB_PART( const wxString& aName, PART_LIB* aLibrary ) : // when the field editors are invoked. LIB_FIELD* value = new LIB_FIELD( this, VALUE ); value->SetText( aName ); - drawings.push_back( value ); + drawingsMap[LIB_FIELD_T].push_back( value ); - drawings.push_back( new LIB_FIELD( this, REFERENCE ) ); - drawings.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, REFERENCE ) ); + drawingsMap[LIB_FIELD_T].push_back( new LIB_FIELD( this, FOOTPRINT ) ); + drawingsMap[LIB_FIELD_T].push_back( new LIB_FIELD( this, DATASHEET ) ); } LIB_PART::LIB_PART( LIB_PART& aPart, PART_LIB* aLibrary ) : EDA_ITEM( aPart ), - m_me( this, null_deleter() ) + m_me( this, null_deleter() ), drawings( drawingsMap ) { LIB_ITEM* newItem; @@ -223,7 +223,7 @@ LIB_PART::LIB_PART( LIB_PART& aPart, PART_LIB* aLibrary ) : m_dateModified = aPart.m_dateModified; m_options = aPart.m_options; - for( LIB_ITEM& oldItem : aPart.GetDrawItemList() ) + for( LIB_ITEM& oldItem : aPart.drawings ) { if( oldItem.IsNew() ) continue; @@ -351,7 +351,7 @@ void LIB_PART::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDc, const wxPoint& aOffset, if( drawItem.Type() == LIB_FIELD_T ) continue; - if( drawItem.Type() == LIB_FIELD_T ) + if( drawItem.Type() == LIB_FIELD_T ) // TODO dead code? { drawItem.Draw( aPanel, aDc, aOffset, aOpts.color, 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.transform ); } - } // 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 ) { @@ -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, g_XorMode, NULL, DefaultTransform ); - drawings.erase( i ); + items.erase( i ); SetModified(); break; } @@ -576,7 +575,6 @@ void LIB_PART::AddDrawItem( LIB_ITEM* aItem ) wxASSERT( aItem != NULL ); 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 ) { + if( drawingsMap.count( LIB_PIN_T ) == 0 ) + return; + /* Notes: * when aUnit == 0: no unit filtering * when aConvert == 0: no convert (shape selection) filtering * when .m_Unit == 0, the body item is common to units * 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: if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) ) continue; @@ -994,7 +992,6 @@ bool LIB_PART::Load( LINE_READER& aLineReader, wxString& aErrorMsg ) ok: // If we are here, this part is O.k. - put it in: - drawings.sort(); return true; } @@ -1132,7 +1129,7 @@ bool LIB_PART::LoadField( LINE_READER& aLineReader, wxString& aErrorMsg ) } else { - drawings.push_back( field ); + drawingsMap[LIB_FIELD_T].push_back( field ); } return true; @@ -1169,10 +1166,8 @@ const EDA_RECT LIB_PART::GetUnitBoundingBox( int aUnit, int aConvert ) const EDA_RECT bBox; 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 ) && ( aUnit != item.m_Unit ) ) ) continue; @@ -1201,10 +1196,8 @@ const EDA_RECT LIB_PART::GetBodyBoundingBox( int aUnit, int aConvert ) const EDA_RECT bBox; 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 ) && ( aUnit != item.m_Unit ) ) ) continue; @@ -1230,19 +1223,7 @@ const EDA_RECT LIB_PART::GetBodyBoundingBox( int aUnit, int aConvert ) const void LIB_PART::deleteAllFields() { - LIB_ITEMS::iterator it; - - 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 ); - } + drawingsMap[LIB_FIELD_T].clear(); } @@ -1256,12 +1237,8 @@ void LIB_PART::SetFields( const std::vector <LIB_FIELD>& aFields ) LIB_FIELD* field = new LIB_FIELD( aFields[i] ); 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. - for( LIB_ITEM& item : drawings ) + for( LIB_ITEM& item : drawingsMap[LIB_FIELD_T] ) { - if( item.Type() != LIB_FIELD_T ) - continue; - field = ( LIB_FIELD* ) &item; if( (unsigned) field->GetId() < MANDATORY_FIELDS ) @@ -1302,11 +1276,8 @@ void LIB_PART::GetFields( LIB_FIELDS& aList ) 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; if( field->GetId() == aId ) @@ -1319,11 +1290,8 @@ LIB_FIELD* LIB_PART::GetField( int aId ) 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; if( field->GetName() == aFieldName ) @@ -1400,23 +1368,21 @@ bool LIB_PART::LoadDateAndTime( char* aLine ) void LIB_PART::SetOffset( const wxPoint& aOffset ) { for( LIB_ITEM& item : drawings ) - { item.SetOffset( aOffset ); - } } void LIB_PART::RemoveDuplicateDrawItems() { - drawings.unique(); + for( auto& itemTypes : drawingsMap ) + itemTypes.second.unique(); } 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 ) return true; } @@ -1475,8 +1441,6 @@ void LIB_PART::MoveSelectedItems( const wxPoint& aOffset ) item.SetOffset( aOffset ); item.m_Flags = 0; } - - drawings.sort(); } @@ -1491,7 +1455,7 @@ void LIB_PART::ClearSelectedItems() 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 // so skip them (do not remove) if they are flagged selected. @@ -1512,7 +1476,7 @@ void LIB_PART::DeleteSelectedItems() } if( !item->IsSelected() ) - item++; + ++item; else item = drawings.erase( item ); } @@ -1547,11 +1511,9 @@ void LIB_PART::CopySelectedItems( const wxPoint& aOffset ) } MoveSelectedItems( aOffset ); - drawings.sort(); } - void LIB_PART::MirrorSelectedItemsH( const wxPoint& aCenter ) { for( LIB_ITEM& item : drawings ) @@ -1562,10 +1524,9 @@ void LIB_PART::MirrorSelectedItemsH( const wxPoint& aCenter ) item.MirrorHorizontal( aCenter ); item.m_Flags = 0; } - - drawings.sort(); } + void LIB_PART::MirrorSelectedItemsV( const wxPoint& aCenter ) { for( LIB_ITEM& item : drawings ) @@ -1576,10 +1537,9 @@ void LIB_PART::MirrorSelectedItemsV( const wxPoint& aCenter ) item.MirrorVertical( aCenter ); item.m_Flags = 0; } - - drawings.sort(); } + void LIB_PART::RotateSelectedItems( const wxPoint& aCenter ) { for( LIB_ITEM& item : drawings ) @@ -1590,12 +1550,9 @@ void LIB_PART::RotateSelectedItems( const wxPoint& aCenter ) item.Rotate( aCenter ); item.m_Flags = 0; } - - drawings.sort(); } - LIB_ITEM* LIB_PART::LocateDrawItem( int aUnit, int aConvert, KICAD_T aType, const wxPoint& aPoint ) { @@ -1642,15 +1599,14 @@ void LIB_PART::SetUnitCount( int aCount ) if( aCount < m_unitCount ) { - LIB_ITEMS::iterator i; - i = drawings.begin(); + LIB_ITEMS_LIST::ITERATOR i = drawings.begin(); while( i != drawings.end() ) { if( i->m_Unit > aCount ) i = drawings.erase( i ); else - i++; + ++i; } } else @@ -1674,8 +1630,6 @@ void LIB_PART::SetUnitCount( int aCount ) drawings.push_back( newItem ); } } - - drawings.sort(); } m_unitCount = aCount; @@ -1714,14 +1668,14 @@ void LIB_PART::SetConversion( bool aSetConvert ) { // Delete converted shape items because the converted shape does // not exist - LIB_ITEMS::iterator i = drawings.begin(); + LIB_ITEMS_LIST::ITERATOR i = drawings.begin(); while( i != drawings.end() ) { if( i->m_Convert > 1 ) i = drawings.erase( i ); else - i++; + ++i; } } } diff --git a/eeschema/class_libentry.h b/eeschema/class_libentry.h index c22b3e3cc..7659ccd99 100644 --- a/eeschema/class_libentry.h +++ b/eeschema/class_libentry.h @@ -34,8 +34,8 @@ #include <lib_id.h> #include <lib_draw_item.h> #include <lib_field.h> +#include <lib_items.h> #include <vector> -#include <memory> class EDA_RECT; class LINE_READER; @@ -236,7 +236,8 @@ class LIB_PART : public EDA_ITEM long m_dateModified; ///< Date the part was last modified. LIBRENTRYOPTIONS m_options; ///< Special part features such as POWER or NORMAL.) 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 part (wild card names accepted). */ 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 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. diff --git a/eeschema/lib_collectors.cpp b/eeschema/lib_collectors.cpp index 60dd95c17..2190388ba 100644 --- a/eeschema/lib_collectors.cpp +++ b/eeschema/lib_collectors.cpp @@ -26,6 +26,7 @@ #include <general.h> #include <transform.h> #include <lib_collectors.h> +#include <lib_items.h> 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 ) { Empty(); // empty the collection just in case diff --git a/eeschema/lib_collectors.h b/eeschema/lib_collectors.h index 6f08341e2..c875c452d 100644 --- a/eeschema/lib_collectors.h +++ b/eeschema/lib_collectors.h @@ -30,6 +30,7 @@ #include <lib_draw_item.h> +class LIB_ITEMS_LIST; class LIB_COLLECTOR; @@ -127,7 +128,7 @@ public: * @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. */ - 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 ); }; diff --git a/eeschema/lib_draw_item.h b/eeschema/lib_draw_item.h index f1c0f8604..1e72a85dd 100644 --- a/eeschema/lib_draw_item.h +++ b/eeschema/lib_draw_item.h @@ -36,8 +36,6 @@ #include <transform.h> #include <gr_basic.h> -#include <boost/ptr_container/ptr_vector.hpp> - class LINE_READER; class OUTPUTFORMATTER; @@ -55,14 +53,6 @@ extern const int fill_tab[]; /** - * 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 * use a Boost pointer class so the object pointers do not accidentally get * deleted when the container is deleted. diff --git a/eeschema/lib_items.cpp b/eeschema/lib_items.cpp new file mode 100644 index 000000000..a49738bbe --- /dev/null +++ b/eeschema/lib_items.cpp @@ -0,0 +1,211 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright 2017 CERN + * @author Maciej Suminski <[email protected]> + * + * 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; +} diff --git a/eeschema/lib_items.h b/eeschema/lib_items.h new file mode 100644 index 000000000..a1c207ed6 --- /dev/null +++ b/eeschema/lib_items.h @@ -0,0 +1,128 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright 2017 CERN + * @author Maciej Suminski <[email protected]> + * + * 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 */ diff --git a/eeschema/symbdraw.cpp b/eeschema/symbdraw.cpp index 01f5775f9..ca1f2bb2c 100644 --- a/eeschema/symbdraw.cpp +++ b/eeschema/symbdraw.cpp @@ -113,9 +113,6 @@ void LIB_EDIT_FRAME::EditGraphicSymbol( wxDC* DC, LIB_ITEM* DrawItem ) DrawItem->SetWidth( m_drawLineWidth ); - if( component ) - component->GetDrawItemList().sort(); - OnModify( ); MSG_PANEL_ITEMS items; diff --git a/eeschema/symbedit.cpp b/eeschema/symbedit.cpp index 49139fbde..d02a618a6 100644 --- a/eeschema/symbedit.cpp +++ b/eeschema/symbedit.cpp @@ -110,7 +110,7 @@ void LIB_EDIT_FRAME::LoadOneSymbol() wxCHECK_RET( !aliasNames.IsEmpty(), "No aliases found in library " + filename ); LIB_PART* first = lib->FindAlias( aliasNames[0] )->GetPart(); - LIB_ITEMS& drawList = first->GetDrawItemList(); + LIB_ITEMS_LIST& drawList = first->GetDrawItemList(); for( LIB_ITEM& item : drawList ) { @@ -213,7 +213,7 @@ void LIB_EDIT_FRAME::SaveOneSymbol() part->GetValueField().Save( formatter ); formatter.Print( 0, "DRAW\n" ); - LIB_ITEMS& drawList = part->GetDrawItemList(); + LIB_ITEMS_LIST& drawList = part->GetDrawItemList(); for( LIB_ITEM& item : drawList ) { -- 2.13.1
_______________________________________________ Mailing list: https://launchpad.net/~kicad-developers Post to : [email protected] Unsubscribe : https://launchpad.net/~kicad-developers More help : https://help.launchpad.net/ListHelp

