diff --git a/include/core/iterators.h b/include/core/iterators.h new file mode 100644 index 0000000000..abd51bd2d7 --- /dev/null +++ b/include/core/iterators.h @@ -0,0 +1,66 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2016 CERN + * + * 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 __ITERATORS_H +#define __ITERATORS_H + +#include +#include + +template +class DLIST_ITERATOR: public std::iterator +{ +private: + T m_obj; + + using reference = typename DLIST_ITERATOR::reference ; +public: + explicit DLIST_ITERATOR( T obj ) : m_obj(obj) {} + + DLIST_ITERATOR& operator++() { m_obj = m_obj->Next(); return *this; } + DLIST_ITERATOR& operator--() { m_obj = m_obj->Prev(); return *this; } + + bool operator==(DLIST_ITERATOR other) const {return m_obj == other.m_obj;} + bool operator!=(DLIST_ITERATOR other) const {return !(*this == other);} + + reference operator*() {return m_obj;} +}; + +// helper object, used to convert a DLIST to an iterator +template class DLIST_ITERATOR_WRAPPER +{ + public: + explicit DLIST_ITERATOR_WRAPPER ( DLIST& list ) : m_list(list) {}; + + DLIST_ITERATOR begin() { return DLIST_ITERATOR ( m_list.GetFirst()); } + DLIST_ITERATOR end() { return DLIST_ITERATOR ( m_list.GetLast()); } + + unsigned int Size() const { + return m_list.GetCount(); + } + + private: + DLIST& m_list; +}; + +#endif diff --git a/pcbnew/append_board_to_current.cpp b/pcbnew/append_board_to_current.cpp index 48f4eb3346..8c52f67f45 100644 --- a/pcbnew/append_board_to_current.cpp +++ b/pcbnew/append_board_to_current.cpp @@ -58,7 +58,7 @@ bool PCB_EDIT_FRAME::AppendBoardFile( const wxString& aFullFileName, int aCtl ) // Other items are append to the item list, so keep trace to the // last existing item is enough MODULE* module = GetBoard()->m_Modules.GetLast(); - BOARD_ITEM* drawing = GetBoard()->m_Drawings.GetLast(); + BOARD_ITEM* drawing = GetBoard()->DrawingsList().GetLast(); int zonescount = GetBoard()->GetAreaCount(); // Keep also the count of copper layers, because we can happen boards @@ -152,7 +152,7 @@ bool PCB_EDIT_FRAME::AppendBoardFile( const wxString& aFullFileName, int aCtl ) if( drawing ) drawing = drawing->Next(); else - drawing = GetBoard()->m_Drawings; + drawing = GetBoard()->DrawingsList(); for( ; drawing; drawing = drawing->Next() ) { diff --git a/pcbnew/autorouter/auto_place_footprints.cpp b/pcbnew/autorouter/auto_place_footprints.cpp index 94ed5a43c5..331bc1b50b 100644 --- a/pcbnew/autorouter/auto_place_footprints.cpp +++ b/pcbnew/autorouter/auto_place_footprints.cpp @@ -501,9 +501,7 @@ int genPlacementRoutingMatrix( BOARD* aBrd, EDA_MSG_PANEL* messagePanel ) TmpSegm.SetNetCode( -1 ); TmpSegm.SetWidth( RoutingMatrix.m_GridRouting / 2 ); - EDA_ITEM* PtStruct = aBrd->m_Drawings; - - for( ; PtStruct != NULL; PtStruct = PtStruct->Next() ) + for( auto PtStruct : aBrd->Drawings() ) { DRAWSEGMENT* DrawSegm; diff --git a/pcbnew/autorouter/routing_matrix.cpp b/pcbnew/autorouter/routing_matrix.cpp index 470b3990e9..856dead922 100644 --- a/pcbnew/autorouter/routing_matrix.cpp +++ b/pcbnew/autorouter/routing_matrix.cpp @@ -251,7 +251,7 @@ void PlaceCells( BOARD* aPcb, int net_code, int flag ) } // Place board outlines and texts on copper layers: - for( BOARD_ITEM* item = aPcb->m_Drawings; item; item = item->Next() ) + for( auto item : aPcb->Drawings() ) { switch( item->Type() ) { diff --git a/pcbnew/block.cpp b/pcbnew/block.cpp index 9393a4b4e4..6b44d3b274 100644 --- a/pcbnew/block.cpp +++ b/pcbnew/block.cpp @@ -357,7 +357,7 @@ void PCB_EDIT_FRAME::Block_SelectItems() if( !blockOpts.includeBoardOutlineLayer ) layerMask.set( Edge_Cuts, false ); - for( BOARD_ITEM* PtStruct = m_Pcb->m_Drawings; PtStruct != NULL; PtStruct = PtStruct->Next() ) + for( auto PtStruct : m_Pcb->Drawings() ) { if( !m_Pcb->IsLayerVisible( PtStruct->GetLayer() ) && ! blockOpts.includeItemsOnInvisibleLayers) continue; diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h index 0b061c89d8..f8a0a5abfe 100644 --- a/pcbnew/class_board.h +++ b/pcbnew/class_board.h @@ -32,6 +32,7 @@ #include +#include #include // PAGE_INFO #include @@ -239,11 +240,23 @@ public: /// Flags used in ratsnest calculation and update. int m_Status_Pcb; + +private: DLIST m_Drawings; // linked list of lines & texts + +public: + DLIST m_Modules; // linked list of MODULEs DLIST m_Track; // linked list of TRACKs and VIAs DLIST m_Zone; // linked list of SEGZONEs + DLIST_ITERATOR_WRAPPER Tracks() { return DLIST_ITERATOR_WRAPPER(m_Track); } + DLIST_ITERATOR_WRAPPER Modules() { return DLIST_ITERATOR_WRAPPER(m_Modules); } + DLIST_ITERATOR_WRAPPER Drawings() { return DLIST_ITERATOR_WRAPPER(m_Drawings); } + + // will be deprecated as soon as append board functionality is fixed + DLIST& DrawingsList() { return m_Drawings; } + /// Ratsnest list for the BOARD std::vector m_FullRatsnest; diff --git a/pcbnew/drc.cpp b/pcbnew/drc.cpp index d4d0776747..034622f3d9 100644 --- a/pcbnew/drc.cpp +++ b/pcbnew/drc.cpp @@ -677,14 +677,13 @@ void DRC::testKeepoutAreas() } } - void DRC::testTexts() { std::vector textShape; // a buffer to store the text shape (set of segments) std::vector padList = m_pcb->GetPads(); // Test text areas for vias, tracks and pads inside text areas - for( BOARD_ITEM* item = m_pcb->m_Drawings; item; item = item->Next() ) + for( auto item : m_pcb->Drawings() ) { // Drc test only items on copper layers if( ! IsCopperLayer( item->GetLayer() ) ) diff --git a/pcbnew/editedge.cpp b/pcbnew/editedge.cpp index 4184c2b763..81b3d9d8aa 100644 --- a/pcbnew/editedge.cpp +++ b/pcbnew/editedge.cpp @@ -164,7 +164,7 @@ void PCB_EDIT_FRAME::Delete_Drawings_All_Layer( PCB_LAYER_ID aLayer ) ITEM_PICKER picker( NULL, UR_DELETED ); BOARD_ITEM* PtNext; - for( BOARD_ITEM* item = GetBoard()->m_Drawings; item; item = PtNext ) + for( auto item : GetBoard()->Drawings() ) { PtNext = item->Next(); diff --git a/pcbnew/exporters/export_gencad.cpp b/pcbnew/exporters/export_gencad.cpp index 67d1361886..ad344c310e 100644 --- a/pcbnew/exporters/export_gencad.cpp +++ b/pcbnew/exporters/export_gencad.cpp @@ -1029,8 +1029,7 @@ static void CreateBoardSection( FILE* aFile, BOARD* aPcb ) fputs( "$BOARD\n", aFile ); // Extract the board edges - for( EDA_ITEM* drawing = aPcb->m_Drawings; drawing != 0; - drawing = drawing->Next() ) + for( auto drawing : aPcb->Drawings() ) { if( drawing->Type() == PCB_LINE_T ) { diff --git a/pcbnew/exporters/export_idf.cpp b/pcbnew/exporters/export_idf.cpp index ae8b318364..5c3b6c8144 100644 --- a/pcbnew/exporters/export_idf.cpp +++ b/pcbnew/exporters/export_idf.cpp @@ -76,7 +76,7 @@ static void idf_export_outline( BOARD* aPcb, IDF3_BOARD& aIDFBoard ) aIDFBoard.GetUserOffset( offX, offY ); // Retrieve segments and arcs from the board - for( BOARD_ITEM* item = aPcb->m_Drawings; item; item = item->Next() ) + for( auto item : aPcb->Drawings() ) { if( item->Type() != PCB_LINE_T || item->GetLayer() != Edge_Cuts ) continue; diff --git a/pcbnew/exporters/export_vrml.cpp b/pcbnew/exporters/export_vrml.cpp index 4d8bcf4036..11a2fc932e 100644 --- a/pcbnew/exporters/export_vrml.cpp +++ b/pcbnew/exporters/export_vrml.cpp @@ -771,7 +771,7 @@ static void export_vrml_pcbtext( MODEL_VRML& aModel, TEXTE_PCB* text ) static void export_vrml_drawings( MODEL_VRML& aModel, BOARD* pcb ) { // draw graphic items - for( BOARD_ITEM* drawing = pcb->m_Drawings; drawing != 0; drawing = drawing->Next() ) + for( auto drawing : pcb->Drawings() ) { PCB_LAYER_ID layer = drawing->GetLayer(); diff --git a/pcbnew/exporters/gen_drill_report_files.cpp b/pcbnew/exporters/gen_drill_report_files.cpp index 76bcd96e61..0f94464824 100644 --- a/pcbnew/exporters/gen_drill_report_files.cpp +++ b/pcbnew/exporters/gen_drill_report_files.cpp @@ -176,7 +176,7 @@ bool GENDRILL_WRITER_BASE::genDrillMapFile( const wxString& aFullFileName, BRDITEMS_PLOTTER itemplotter( plotter, m_pcb, plot_opts ); itemplotter.SetLayerSet( Edge_Cuts ); - for( EDA_ITEM* PtStruct = m_pcb->m_Drawings; PtStruct != NULL; PtStruct = PtStruct->Next() ) + for( auto PtStruct : m_pcb->Drawings() ) { switch( PtStruct->Type() ) { diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp index 8fd3714040..50663b1f0c 100644 --- a/pcbnew/kicad_plugin.cpp +++ b/pcbnew/kicad_plugin.cpp @@ -542,7 +542,7 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const m_out->Print( aNestLevel+1, "(thickness %s)\n", FMTIU( dsnSettings.GetBoardThickness() ).c_str() ); - m_out->Print( aNestLevel+1, "(drawings %d)\n", aBoard->m_Drawings.GetCount() ); + m_out->Print( aNestLevel+1, "(drawings %d)\n", aBoard->Drawings().Size() ); m_out->Print( aNestLevel+1, "(tracks %d)\n", aBoard->GetNumSegmTrack() ); m_out->Print( aNestLevel+1, "(zones %d)\n", aBoard->GetNumSegmZone() ); m_out->Print( aNestLevel+1, "(modules %d)\n", aBoard->m_Modules.GetCount() ); @@ -756,10 +756,10 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const } // Save the graphical items on the board (not owned by a module) - for( BOARD_ITEM* item = aBoard->m_Drawings; item; item = item->Next() ) + for( auto item : aBoard->Drawings() ) Format( item, aNestLevel ); - if( aBoard->m_Drawings.GetCount() ) + if( aBoard->Drawings().Size() ) m_out->Print( 0, "\n" ); // Do not save MARKER_PCBs, they can be regenerated easily. diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp index 7555058b80..8a7b0c5bcd 100644 --- a/pcbnew/plot_brditems_plotter.cpp +++ b/pcbnew/plot_brditems_plotter.cpp @@ -266,7 +266,7 @@ bool BRDITEMS_PLOTTER::PlotAllTextsModule( MODULE* aModule ) // plot items like text and graphics, but not tracks and module void BRDITEMS_PLOTTER::PlotBoardGraphicItems() { - for( BOARD_ITEM* item = m_board->m_Drawings; item; item = item->Next() ) + for( auto item : m_board->Drawings() ) { switch( item->Type() ) { diff --git a/pcbnew/print_board_functions.cpp b/pcbnew/print_board_functions.cpp index ce8a611338..c7031c6de7 100644 --- a/pcbnew/print_board_functions.cpp +++ b/pcbnew/print_board_functions.cpp @@ -194,7 +194,7 @@ void PCB_EDIT_FRAME::PrintPage( wxDC* aDC, m_canvas->SetPrintMirrored( aPrintMirrorMode ); - for( BOARD_ITEM* item = Pcb->m_Drawings; item; item = item->Next() ) + for( auto item : Pcb->Drawings() ) { switch( item->Type() ) { diff --git a/pcbnew/swap_layers.cpp b/pcbnew/swap_layers.cpp index deb022d150..4b91f31f42 100644 --- a/pcbnew/swap_layers.cpp +++ b/pcbnew/swap_layers.cpp @@ -412,7 +412,7 @@ void PCB_EDIT_FRAME::Swap_Layers( wxCommandEvent& event ) } // Change other segments. - for( EDA_ITEM* item = GetBoard()->m_Drawings; item; item = item->Next() ) + for( auto item : GetBoard()->Drawings() ) { if( item->Type() == PCB_LINE_T ) { diff --git a/pcbnew/tools/pcbnew_control.cpp b/pcbnew/tools/pcbnew_control.cpp index 5479eee90d..9a00d90bfb 100644 --- a/pcbnew/tools/pcbnew_control.cpp +++ b/pcbnew/tools/pcbnew_control.cpp @@ -804,7 +804,7 @@ int PCBNEW_CONTROL::AppendBoard( const TOOL_EVENT& aEvent ) // Other items are appended to the item list, so keep trace to the last existing item is enough MODULE* module = board->m_Modules.GetLast(); - BOARD_ITEM* drawing = board->m_Drawings.GetLast(); + BOARD_ITEM* drawing = board->DrawingsList().GetLast(); int zonescount = board->GetAreaCount(); // Keep also the count of copper layers, to adjust if necessary @@ -868,7 +868,7 @@ int PCBNEW_CONTROL::AppendBoard( const TOOL_EVENT& aEvent ) selection.Add( module ); } - drawing = drawing ? drawing->Next() : board->m_Drawings; + drawing = drawing ? drawing->Next() : board->DrawingsList(); for( ; drawing; drawing = drawing->Next() ) { diff --git a/pcbnew/undo_redo.cpp b/pcbnew/undo_redo.cpp index bb4b4a65b6..ede5340917 100644 --- a/pcbnew/undo_redo.cpp +++ b/pcbnew/undo_redo.cpp @@ -142,7 +142,7 @@ static bool TestForExistingItem( BOARD* aPcb, BOARD_ITEM* aItem ) itemsList.push_back( item ); // Append drawings - for( item = aPcb->m_Drawings; item != NULL; item = item->Next() ) + for( auto item : aPcb->Drawings() ) itemsList.push_back( item ); // Append zones outlines diff --git a/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp b/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp index 4ae50562ee..cafe6f5606 100644 --- a/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp +++ b/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp @@ -269,7 +269,7 @@ void ZONE_CONTAINER::buildFeatureHoleList( BOARD* aPcb, SHAPE_POLY_SET& aFeature } // Add graphic items (copper texts) and board edges - for( BOARD_ITEM* item = aPcb->m_Drawings; item; item = item->Next() ) + for( auto item : aPcb->Drawings() ) { if( item->GetLayer() != GetLayer() && item->GetLayer() != Edge_Cuts ) continue;