diff --git a/include/collector.h b/include/collector.h index 8eaee8ef66..690f96ae6c 100644 --- a/include/collector.h +++ b/include/collector.h @@ -62,7 +62,7 @@ public: virtual ~COLLECTOR() {} - virtual INSPECT_RESULT Inspect( EDA_ITEM* aItem, void* aTestData ) + virtual INSPECT_RESULT Inspect( EDA_ITEM* aTestItem, void* aTestData ) { return INSPECT_RESULT::QUIT; }; diff --git a/pcbnew/array_creator.cpp b/pcbnew/array_creator.cpp index 83177f4036..2dc8a419b9 100644 --- a/pcbnew/array_creator.cpp +++ b/pcbnew/array_creator.cpp @@ -82,7 +82,10 @@ void ARRAY_CREATOR::Invoke() for ( int i = 0; i < m_selection.Size(); ++i ) { - BOARD_ITEM* item = static_cast( m_selection[ i ] ); + BOARD_ITEM* item = dynamic_cast( m_selection[ i ] ); + + if( !item ) + continue; if( item->Type() == PCB_PAD_T && !m_isFootprintEditor ) { diff --git a/pcbnew/board.cpp b/pcbnew/board.cpp index ae38d61f58..03be3a7e4e 100644 --- a/pcbnew/board.cpp +++ b/pcbnew/board.cpp @@ -426,13 +426,13 @@ void BOARD::Move( const VECTOR2I& aMoveVector ) // overload INSPECTOR_FUNC inspector = [&] ( EDA_ITEM* item, void* testData ) { - BOARD_ITEM* brdItem = static_cast( item ); - - // aMoveVector was snapshotted, don't need "data". - // Only move the top level group - if( brdItem->GetParentGroup() == nullptr - && brdItem->GetParentFootprint() == nullptr ) - brdItem->Move( aMoveVector ); + if( BOARD_ITEM* board_item = dynamic_cast( item ) ) + { + // aMoveVector was snapshotted, don't need "data". + // Only move the top level group + if( !board_item->GetParentGroup() && !board_item->GetParentFootprint() ) + board_item->Move( aMoveVector ); + } return INSPECT_RESULT::CONTINUE; }; @@ -2257,11 +2257,14 @@ BOARD::GroupLegalOpsField BOARD::GroupLegalOps( const PCB_SELECTION& selection ) for( EDA_ITEM* item : selection ) { - if( item->Type() == PCB_GROUP_T ) - hasGroup = true; + if( BOARD_ITEM* board_item = dynamic_cast( item ) ) + { + if( board_item->Type() == PCB_GROUP_T ) + hasGroup = true; - if( static_cast( item )->GetParentGroup() ) - hasMember = true; + if( board_item->GetParentGroup() ) + hasMember = true; + } } GroupLegalOpsField legalOps; diff --git a/pcbnew/board_commit.cpp b/pcbnew/board_commit.cpp index b103f25536..56472954fe 100644 --- a/pcbnew/board_commit.cpp +++ b/pcbnew/board_commit.cpp @@ -269,7 +269,6 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags ) { int changeType = ent.m_type & CHT_TYPE; int changeFlags = ent.m_type & CHT_FLAGS; - BOARD_ITEM* boardItem = static_cast( ent.m_item ); wxASSERT( ent.m_item ); @@ -307,7 +306,10 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags ) } } - if( m_isBoardEditor ) + BOARD_ITEM* boardItem = dynamic_cast( ent.m_item ); + wxCHECK2( boardItem, continue ); + + if( m_isBoardEditor && boardItem ) { if( boardItem->Type() == PCB_VIA_T || boardItem->Type() == PCB_FOOTPRINT_T || boardItem->IsOnLayer( F_Mask ) || boardItem->IsOnLayer( B_Mask ) ) @@ -519,26 +521,28 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags ) case CHT_MODIFY: { + BOARD_ITEM* boardItemCopy = dynamic_cast( ent.m_copy ); + if( !m_isFootprintEditor && !( aCommitFlags & SKIP_UNDO ) ) { ITEM_PICKER itemWrapper( nullptr, boardItem, UNDO_REDO::CHANGED ); - wxASSERT( ent.m_copy ); - itemWrapper.SetLink( ent.m_copy ); + wxASSERT( boardItemCopy ); + itemWrapper.SetLink( boardItemCopy ); undoList.PushItem( itemWrapper ); } if( !( aCommitFlags & SKIP_CONNECTIVITY ) ) { - if( ent.m_copy ) - connectivity->MarkItemNetAsDirty( static_cast( ent.m_copy ) ); + if( boardItemCopy ) + connectivity->MarkItemNetAsDirty( boardItemCopy ); connectivity->Update( boardItem ); } if( autofillZones ) { - dirtyIntersectingZones( static_cast( ent.m_copy ), changeType ); // before - dirtyIntersectingZones( boardItem, changeType ); // after + dirtyIntersectingZones( boardItemCopy, changeType ); // before + dirtyIntersectingZones( boardItem, changeType ); // after } if( view ) @@ -565,7 +569,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags ) } default: - wxASSERT( false ); + UNIMPLEMENTED_FOR( boardItem->GetClass() ); break; } @@ -616,12 +620,16 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags ) for( size_t i = num_changes; i < m_changes.size(); ++i ) { COMMIT_LINE& ent = m_changes[i]; - BOARD_ITEM* boardItem = static_cast( ent.m_item ); + BOARD_ITEM* boardItem = dynamic_cast( ent.m_item ); + BOARD_ITEM* boardItemCopy = dynamic_cast( ent.m_copy ); + + wxCHECK2( boardItem, continue ); if( !( aCommitFlags & SKIP_UNDO ) ) { ITEM_PICKER itemWrapper( nullptr, boardItem, convert( ent.m_type & CHT_TYPE ) ); - itemWrapper.SetLink( ent.m_copy ); + wxASSERT( boardItemCopy ); + itemWrapper.SetLink( boardItemCopy ); undoList.PushItem( itemWrapper ); } else @@ -686,9 +694,11 @@ EDA_ITEM* BOARD_COMMIT::parentObject( EDA_ITEM* aItem ) const EDA_ITEM* BOARD_COMMIT::makeImage( EDA_ITEM* aItem ) const { - BOARD_ITEM* clone = static_cast( aItem->Clone() ); + EDA_ITEM* clone = aItem->Clone(); + + if( BOARD_ITEM* board_item = dynamic_cast( clone ) ) + board_item->SetParentGroup( nullptr ); - clone->SetParentGroup( nullptr ); return clone; } @@ -709,10 +719,11 @@ void BOARD_COMMIT::Revert() for( auto it = m_changes.rbegin(); it != m_changes.rend(); ++it ) { COMMIT_LINE& ent = *it; - BOARD_ITEM* item = static_cast( ent.m_item ); - BOARD_ITEM* copy = static_cast( ent.m_copy ); - int changeType = ent.m_type & CHT_TYPE; - int changeFlags = ent.m_type & CHT_FLAGS; + BOARD_ITEM* boardItem = dynamic_cast( ent.m_item ); + int changeType = ent.m_type & CHT_TYPE; + int changeFlags = ent.m_type & CHT_FLAGS; + + wxCHECK2( boardItem, continue ); switch( changeType ) { @@ -720,32 +731,34 @@ void BOARD_COMMIT::Revert() if( !( changeFlags & CHT_DONE ) ) break; - view->Remove( item ); - connectivity->Remove( item ); - board->Remove( item, REMOVE_MODE::BULK ); - bulkRemovedItems.push_back( item ); + view->Remove( boardItem ); + connectivity->Remove( boardItem ); + board->Remove( boardItem, REMOVE_MODE::BULK ); + bulkRemovedItems.push_back( boardItem ); break; case CHT_REMOVE: if( !( changeFlags & CHT_DONE ) ) break; - view->Add( item ); - connectivity->Add( item ); - board->Add( item, ADD_MODE::INSERT ); - bulkAddedItems.push_back( item ); + view->Add( boardItem ); + connectivity->Add( boardItem ); + board->Add( boardItem, ADD_MODE::INSERT ); + bulkAddedItems.push_back( boardItem ); break; case CHT_MODIFY: { - view->Remove( item ); - connectivity->Remove( item ); + view->Remove( boardItem ); + connectivity->Remove( boardItem ); - item->SwapItemData( copy ); + BOARD_ITEM* boardItemCopy = dynamic_cast( ent.m_copy ); + wxASSERT( boardItemCopy ); + boardItem->SwapItemData( boardItemCopy ); - if( item->Type() == PCB_GROUP_T ) + if( boardItem->Type() == PCB_GROUP_T ) { - PCB_GROUP* group = static_cast( item ); + PCB_GROUP* group = static_cast( boardItem ); group->RunOnChildren( [&]( BOARD_ITEM* child ) { @@ -753,21 +766,21 @@ void BOARD_COMMIT::Revert() } ); } - view->Add( item ); - connectivity->Add( item ); - board->OnItemChanged( item ); - itemsChanged.push_back( item ); + view->Add( boardItem ); + connectivity->Add( boardItem ); + board->OnItemChanged( boardItem ); + itemsChanged.push_back( boardItem ); - delete copy; + delete ent.m_copy; break; } default: - wxASSERT( false ); + UNIMPLEMENTED_FOR( boardItem->GetClass() ); break; } - item->ClearEditFlags(); + boardItem->ClearEditFlags(); } if( bulkAddedItems.size() > 0 ) diff --git a/pcbnew/board_item.cpp b/pcbnew/board_item.cpp index e5847355b2..2dfcd75959 100644 --- a/pcbnew/board_item.cpp +++ b/pcbnew/board_item.cpp @@ -190,7 +190,7 @@ BOARD_ITEM* BOARD_ITEM::Duplicate() const if( dupe->GetParentGroup() ) dupe->GetParentGroup()->AddItem( dupe ); - return static_cast( dupe ); + return dupe; } diff --git a/pcbnew/collectors.cpp b/pcbnew/collectors.cpp index 4fa7f2c5ed..d263304cd3 100644 --- a/pcbnew/collectors.cpp +++ b/pcbnew/collectors.cpp @@ -136,26 +136,16 @@ const std::vector GENERAL_COLLECTOR::DraggableItems = { }; -INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) +INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* aTestItem, void* aTestData ) { - BOARD_ITEM* item = static_cast( testItem ); - FOOTPRINT* footprint = item->GetParentFootprint(); - PCB_GROUP* group = nullptr; - PAD* pad = nullptr; - bool pad_through = false; - PCB_VIA* via = nullptr; - PCB_MARKER* marker = nullptr; - ZONE* zone = nullptr; - PCB_DIMENSION_BASE* dimension = nullptr; - -#if 0 // debugging +#if 1 // debugging static int breakhere = 0; - switch( item->Type() ) + switch( aTestItem->Type() ) { case PCB_PAD_T: { - FOOTPRINT* footprint = (FOOTPRINT*) item->GetParent(); + FOOTPRINT* footprint = (FOOTPRINT*) aTestItem->GetParent(); if( footprint->GetReference() == wxT( "Y2" ) ) breakhere++; @@ -190,7 +180,7 @@ INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) case PCB_FOOTPRINT_T: { - FOOTPRINT* footprint = (FOOTPRINT*) item; + FOOTPRINT* footprint = (FOOTPRINT*) aTestItem; if( footprint->GetReference() == wxT( "C98" ) ) breakhere++; @@ -208,7 +198,19 @@ INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) #endif - switch( item->Type() ) + BOARD_ITEM* boardItem = nullptr; + FOOTPRINT* footprint = nullptr; + PCB_GROUP* group = nullptr; + PAD* pad = nullptr; + bool pad_through = false; + PCB_VIA* via = nullptr; + PCB_MARKER* marker = nullptr; + ZONE* zone = nullptr; + PCB_FIELD* field = nullptr; + PCB_TEXT* text = nullptr; + PCB_DIMENSION_BASE* dimension = nullptr; + + switch( aTestItem->Type() ) { case PCB_PAD_T: // there are pad specific visibility controls. @@ -217,7 +219,8 @@ INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) // board side must be visible // if pad is a thru hole, then it can be visible when its parent footprint is not. // for through pads: pads on Front or Back board sides must be visible - pad = static_cast( item ); + pad = static_cast( aTestItem ); + boardItem = pad; if( ( pad->GetAttribute() != PAD_ATTRIB::SMD ) && ( pad->GetAttribute() != PAD_ATTRIB::CONN ) ) // a hole is present, so multiple layers @@ -230,7 +233,8 @@ INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) break; case PCB_VIA_T: // vias are on many layers, so layer test is specific - via = static_cast( item ); + via = static_cast( aTestItem ); + boardItem = via; break; case PCB_TRACE_T: @@ -238,14 +242,17 @@ INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) if( m_Guide->IgnoreTracks() ) return INSPECT_RESULT::CONTINUE; + boardItem = static_cast( aTestItem ); break; case PCB_ZONE_T: - zone = static_cast( item ); + zone = static_cast( aTestItem ); + boardItem = zone; break; case PCB_TEXTBOX_T: case PCB_SHAPE_T: + boardItem = static_cast( aTestItem ); break; case PCB_DIM_ALIGNED_T: @@ -253,29 +260,32 @@ INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) case PCB_DIM_RADIAL_T: case PCB_DIM_ORTHOGONAL_T: case PCB_DIM_LEADER_T: - dimension = static_cast( item ); + dimension = static_cast( aTestItem ); + boardItem = dimension; break; case PCB_TARGET_T: + boardItem = static_cast( aTestItem ); break; case PCB_FIELD_T: - { - PCB_FIELD* field = static_cast( item ); + field = static_cast( aTestItem ); if( field->IsReference() && m_Guide->IgnoreFPReferences() ) return INSPECT_RESULT::CONTINUE; if( field->IsValue() && m_Guide->IgnoreFPValues() ) return INSPECT_RESULT::CONTINUE; - } KI_FALLTHROUGH; + case PCB_TEXT_T: - if( item->GetParentFootprint() ) + text = static_cast( aTestItem ); + boardItem = text; + + if( text->GetParentFootprint() ) { - PCB_TEXT* text = static_cast( item ); - PCB_LAYER_ID layer = item->GetLayer(); + PCB_LAYER_ID layer = text->GetLayer(); if( m_Guide->IgnoreHiddenFPText() ) { @@ -293,21 +303,28 @@ INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) break; case PCB_FOOTPRINT_T: - footprint = static_cast( item ); + footprint = static_cast( aTestItem ); + boardItem = footprint; break; case PCB_GROUP_T: - group = static_cast( item ); + group = static_cast( aTestItem ); + boardItem = group; break; case PCB_MARKER_T: - marker = static_cast( item ); + marker = static_cast( aTestItem ); + boardItem = marker; break; default: + boardItem = dynamic_cast( aTestItem ); break; } + if( boardItem && !footprint ) + footprint = boardItem->GetParentFootprint(); + // common tests: if( footprint ) @@ -341,7 +358,7 @@ INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) { // Markers are not sensitive to the layer if( marker->HitTest( m_refPos ) ) - Append( item ); + Append( aTestItem ); return INSPECT_RESULT::CONTINUE; } @@ -350,7 +367,7 @@ INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) { // Groups are not sensitive to the layer ... ? if( group->HitTest( m_refPos ) ) - Append( item ); + Append( aTestItem ); return INSPECT_RESULT::CONTINUE; } @@ -367,8 +384,9 @@ INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) } } - if( ( item->IsOnLayer( m_Guide->GetPreferredLayer() ) ) - && ( !item->IsLocked() || !m_Guide->IgnoreLockedItems() ) ) + if( boardItem + && ( boardItem->IsOnLayer( m_Guide->GetPreferredLayer() ) ) + && ( !boardItem->IsLocked() || !m_Guide->IgnoreLockedItems() ) ) { // footprints and their subcomponents: reference, value and pads are not sensitive // to the layer visibility controls. They all have their own separate visibility @@ -382,7 +400,7 @@ INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) if( zone->HitTestForCorner( m_refPos, accuracy * 2 ) || zone->HitTestForEdge( m_refPos, accuracy ) ) { - Append( item ); + Append( aTestItem ); return INSPECT_RESULT::CONTINUE; } else if( !m_Guide->IgnoreZoneFills() ) @@ -392,32 +410,32 @@ INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) if( m_Guide->IsLayerVisible( layer ) && zone->HitTestFilledArea( layer, m_refPos ) ) { - Append( item ); + Append( aTestItem ); return INSPECT_RESULT::CONTINUE; } } } } - else if( item == footprint ) + else if( aTestItem == footprint ) { if( footprint->HitTest( m_refPos, accuracy ) && footprint->HitTestAccurate( m_refPos, accuracy ) ) { - Append( item ); + Append( aTestItem ); return INSPECT_RESULT::CONTINUE; } } else if( pad || via ) { - if( item->HitTest( m_refPos, accuracy ) ) + if( aTestItem->HitTest( m_refPos, accuracy ) ) { - Append( item ); + Append( aTestItem ); return INSPECT_RESULT::CONTINUE; } } else { - PCB_LAYER_ID layer = item->GetLayer(); + PCB_LAYER_ID layer = boardItem->GetLayer(); if( m_Guide->IsLayerVisible( layer ) ) { @@ -428,16 +446,17 @@ INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) accuracy = KiROUND( accuracy * 1.5 ); } - if( item->HitTest( m_refPos, accuracy ) ) + if( aTestItem->HitTest( m_refPos, accuracy ) ) { - Append( item ); + Append( aTestItem ); return INSPECT_RESULT::CONTINUE; } } } } - if( m_Guide->IncludeSecondary() && ( !item->IsLocked() || !m_Guide->IgnoreLockedItems() ) ) + if( m_Guide->IncludeSecondary() + && ( !boardItem || !boardItem->IsLocked() || !m_Guide->IgnoreLockedItems() ) ) { // for now, "secondary" means "tolerate any visible layer". It has no effect on other // criteria, since there is a separate "ignore" control for those in the COLLECTORS_GUIDE @@ -454,7 +473,7 @@ INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) if( zone->HitTestForCorner( m_refPos, accuracy * 2 ) || zone->HitTestForEdge( m_refPos, accuracy ) ) { - Append2nd( item ); + Append2nd( aTestItem ); return INSPECT_RESULT::CONTINUE; } else if( !m_Guide->IgnoreZoneFills() ) @@ -464,47 +483,42 @@ INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) if( m_Guide->IsLayerVisible( layer ) && zone->HitTestFilledArea( layer, m_refPos ) ) { - Append2nd( item ); + Append2nd( aTestItem ); return INSPECT_RESULT::CONTINUE; } } } } - else if( item->Type() == PCB_FOOTPRINT_T ) + else if( aTestItem->Type() == PCB_FOOTPRINT_T ) { if( footprint->HitTest( m_refPos, accuracy ) && footprint->HitTestAccurate( m_refPos, accuracy ) ) { - Append2nd( item ); + Append2nd( aTestItem ); return INSPECT_RESULT::CONTINUE; } } else if( pad || via ) { - if( item->HitTest( m_refPos, accuracy ) ) + if( aTestItem->HitTest( m_refPos, accuracy ) ) { - Append2nd( item ); + Append2nd( aTestItem ); return INSPECT_RESULT::CONTINUE; } } - else + else if( boardItem && m_Guide->IsLayerVisible( boardItem->GetLayer() ) ) { - PCB_LAYER_ID layer = item->GetLayer(); - - if( m_Guide->IsLayerVisible( layer ) ) + if( dimension ) { - if( dimension ) - { - // Dimensions feel particularly hard to select, probably due to their - // noisy shape making it feel like they should have a larger boundary. - accuracy = KiROUND( accuracy * 1.5 ); - } + // Dimensions feel particularly hard to select, probably due to their + // noisy shape making it feel like they should have a larger boundary. + accuracy = KiROUND( accuracy * 1.5 ); + } - if( item->HitTest( m_refPos, accuracy ) ) - { - Append2nd( item ); - return INSPECT_RESULT::CONTINUE; - } + if( aTestItem->HitTest( m_refPos, accuracy ) ) + { + Append2nd( aTestItem ); + return INSPECT_RESULT::CONTINUE; } } } diff --git a/pcbnew/collectors.h b/pcbnew/collectors.h index 886a882d04..49d3f72a32 100644 --- a/pcbnew/collectors.h +++ b/pcbnew/collectors.h @@ -209,7 +209,7 @@ protected: * "2nd" choice, which will be appended to the end of COLLECTOR's prime * "list" at the end of the search. */ - std::vector m_List2nd; + std::vector m_List2nd; /** * Determine which items are to be collected by Inspect(). @@ -275,7 +275,7 @@ public: m_List2nd.clear(); } - void Append2nd( BOARD_ITEM* item ) + void Append2nd( EDA_ITEM* item ) { m_List2nd.push_back( item ); } @@ -294,10 +294,10 @@ public: * Search and collect all the objects which match the test data. * * @param testItem An EDA_ITEM to examine. - * @param testData is not used in this class. + * @param aTestData is not used in this class. * @return SEARCH_QUIT if the Iterator is to stop the scan, else SCAN_CONTINUE */ - INSPECT_RESULT Inspect( EDA_ITEM* testItem, void* testData ) override; + INSPECT_RESULT Inspect( EDA_ITEM* aTestItem, void* aTestData ) override; /** * Scan a BOARD_ITEM using this class's Inspector method, which does the collection. diff --git a/pcbnew/kicad_clipboard.cpp b/pcbnew/kicad_clipboard.cpp index 70f5b2722d..abf793f29c 100644 --- a/pcbnew/kicad_clipboard.cpp +++ b/pcbnew/kicad_clipboard.cpp @@ -109,8 +109,11 @@ void CLIPBOARD_IO::SaveSelection( const PCB_SELECTION& aSelected, bool isFootpri for( const EDA_ITEM* item : aSelected ) { - const PCB_GROUP* group = dynamic_cast( item ); - BOARD_ITEM* clone; + const BOARD_ITEM* boardItem = dynamic_cast( item ); + const PCB_GROUP* group = dynamic_cast( item ); + BOARD_ITEM* clone = nullptr; + + wxCHECK2( boardItem, continue ); if( const PCB_FIELD* field = dynamic_cast( item ) ) { @@ -121,7 +124,7 @@ void CLIPBOARD_IO::SaveSelection( const PCB_SELECTION& aSelected, bool isFootpri if( group ) clone = static_cast( group->DeepClone() ); else - clone = static_cast( item->Clone() ); + clone = static_cast( boardItem->Clone() ); // If it is only a footprint, clear the nets from the pads if( PAD* pad = dynamic_cast( clone ) ) @@ -198,39 +201,41 @@ void CLIPBOARD_IO::SaveSelection( const PCB_SELECTION& aSelected, bool isFootpri m_formatter.Print( 0, "\n" ); - for( EDA_ITEM* i : aSelected ) + for( EDA_ITEM* item : aSelected ) { - BOARD_ITEM* item = static_cast( i ); + BOARD_ITEM* boardItem = dynamic_cast( item ); BOARD_ITEM* copy = nullptr; - if( item->Type() == PCB_FIELD_T || item->Type() == PCB_TEXT_T ) + wxCHECK2( boardItem, continue ); + + if( boardItem->Type() == PCB_FIELD_T || boardItem->Type() == PCB_TEXT_T ) { - copy = static_cast( item->Clone() ); + copy = static_cast( boardItem->Clone() ); PCB_TEXT* textItem = static_cast( copy ); if( textItem->GetText() == wxT( "${VALUE}" ) ) - textItem->SetText( item->GetParentFootprint()->GetValue() ); + textItem->SetText( boardItem->GetParentFootprint()->GetValue() ); else if( textItem->GetText() == wxT( "${REFERENCE}" ) ) - textItem->SetText( item->GetParentFootprint()->GetReference() ); + textItem->SetText( boardItem->GetParentFootprint()->GetReference() ); } - else if( item->Type() == PCB_PAD_T ) + else if( boardItem->Type() == PCB_PAD_T ) { // Create a parent to own the copied pad FOOTPRINT* footprint = new FOOTPRINT( m_board ); - PAD* pad = (PAD*) item->Clone(); + PAD* pad = (PAD*) boardItem->Clone(); footprint->SetPosition( pad->GetPosition() ); footprint->Add( pad ); copy = footprint; } - else if( item->Type() == PCB_GROUP_T ) + else if( boardItem->Type() == PCB_GROUP_T ) { - copy = static_cast( item )->DeepClone(); + copy = static_cast( boardItem )->DeepClone(); } else { - copy = static_cast( item->Clone() ); + copy = static_cast( boardItem->Clone() ); } auto prepItem = [&]( BOARD_ITEM* aItem ) diff --git a/pcbnew/tools/board_editor_control.cpp b/pcbnew/tools/board_editor_control.cpp index 2b0bd81195..e9a6e9781e 100644 --- a/pcbnew/tools/board_editor_control.cpp +++ b/pcbnew/tools/board_editor_control.cpp @@ -1212,9 +1212,9 @@ int BOARD_EDITOR_CONTROL::modifyLockSelected( MODIFY_MODE aMode ) for( EDA_ITEM* item : selection ) { - BOARD_ITEM* board_item = static_cast( item ); + BOARD_ITEM* board_item = dynamic_cast( item ); - if( board_item->IsLocked() ) + if( board_item && board_item->IsLocked() ) { aMode = OFF; break; @@ -1226,7 +1226,9 @@ int BOARD_EDITOR_CONTROL::modifyLockSelected( MODIFY_MODE aMode ) for( EDA_ITEM* item : selection ) { - BOARD_ITEM* board_item = static_cast( item ); + BOARD_ITEM* board_item = dynamic_cast( item ); + + wxCHECK2( board_item, continue ); commit.Modify( board_item ); diff --git a/pcbnew/tools/board_inspection_tool.cpp b/pcbnew/tools/board_inspection_tool.cpp index 8beab64032..622b713acf 100644 --- a/pcbnew/tools/board_inspection_tool.cpp +++ b/pcbnew/tools/board_inspection_tool.cpp @@ -581,8 +581,8 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent ) return 0; } - BOARD_ITEM* a = static_cast( selection.GetItem( 0 ) ); - BOARD_ITEM* b = static_cast( selection.GetItem( 1 ) ); + BOARD_ITEM* a = dynamic_cast( selection.GetItem( 0 ) ); + BOARD_ITEM* b = dynamic_cast( selection.GetItem( 1 ) ); wxCHECK( a && b, 0 ); @@ -1210,12 +1210,14 @@ int BOARD_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent ) dialog->DeleteAllPages(); - BOARD_ITEM* item = static_cast( selection.GetItem( 0 ) ); + BOARD_ITEM* item = dynamic_cast( selection.GetItem( 0 ) ); bool compileError = false; bool courtyardError = false; DRC_ENGINE drcEngine = makeDRCEngine( &compileError, &courtyardError ); DRC_CONSTRAINT constraint; + wxCHECK( item, 0 ); + WX_HTML_REPORT_BOX* r = nullptr; if( item->Type() == PCB_TRACE_T ) @@ -1898,7 +1900,9 @@ void BOARD_INSPECTION_TOOL::calculateSelectionRatsnest( const VECTOR2I& aDelta ) for( std::size_t i = 0; i < queued_items.size(); ++i ) { - BOARD_ITEM* item = static_cast( queued_items[i] ); + BOARD_ITEM* item = dynamic_cast( queued_items[i] ); + + wxCHECK2( item, continue ); if( item->Type() == PCB_FOOTPRINT_T ) { diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp index c730341bc3..b271d8ab9b 100644 --- a/pcbnew/tools/drawing_tool.cpp +++ b/pcbnew/tools/drawing_tool.cpp @@ -1524,7 +1524,9 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent ) for( std::unique_ptr& ptr : list ) { - BOARD_ITEM* item = static_cast( ptr.get() ); + BOARD_ITEM* item = dynamic_cast( ptr.get() ); + + wxCHECK2( item, continue ); newItems.push_back( item ); diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index 6fffdd60ab..1c50f18076 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -1348,13 +1348,14 @@ int EDIT_TOOL::Properties( const TOOL_EVENT& aEvent ) else if( selection.Size() == 1 ) { // Display properties dialog - BOARD_ITEM* item = static_cast( selection.Front() ); + if( BOARD_ITEM* item = dynamic_cast( selection.Front() ) ) + { + // Do not handle undo buffer, it is done by the properties dialogs + editFrame->OnEditItemRequest( item ); - // Do not handle undo buffer, it is done by the properties dialogs - editFrame->OnEditItemRequest( item ); - - // Notify other tools of the changes - m_toolMgr->ProcessEvent( EVENTS::SelectedItemsModified ); + // Notify other tools of the changes + m_toolMgr->ProcessEvent( EVENTS::SelectedItemsModified ); + } } else if( selection.Size() == 0 && getView()->IsLayerVisible( LAYER_DRAWINGSHEET ) ) { @@ -1380,10 +1381,11 @@ int EDIT_TOOL::Properties( const TOOL_EVENT& aEvent ) for( EDA_ITEM* eda_item : selCopy ) { - BOARD_ITEM* item = static_cast( eda_item ); - - if( !( item->GetLayerSet() & visible ).any() ) - m_selectionTool->RemoveItemFromSel( item ); + if( BOARD_ITEM* item = dynamic_cast( eda_item ) ) + { + if( !( item->GetLayerSet() & visible ).any() ) + m_selectionTool->RemoveItemFromSel( item ); + } } } @@ -1490,7 +1492,8 @@ int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent ) } } - static_cast( item )->Rotate( refPt, rotateAngle ); + if( BOARD_ITEM* board_item = dynamic_cast( item ) ) + board_item->Rotate( refPt, rotateAngle ); } if( !localCommit.Empty() ) @@ -1752,28 +1755,33 @@ int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent ) { if( m_dragging && selection.HasReferencePoint() ) refPt = selection.GetReferencePoint(); - else - refPt = static_cast( selection.GetItem( 0 ) )->GetPosition(); + else if( BOARD_ITEM* boardItem = dynamic_cast( selection.Front() ) ) + refPt = boardItem->GetPosition(); } bool leftRight = frame()->GetPcbNewSettings()->m_FlipLeftRight; for( EDA_ITEM* item : selection ) { - if( !item->IsNew() && !item->IsMoving() && ( !IsFootprintEditor() || commit->Empty() ) ) + if( BOARD_ITEM* boardItem = dynamic_cast( item ) ) { - commit->Modify( item ); - - if( item->Type() == PCB_GROUP_T ) + if( !boardItem->IsNew() && !boardItem->IsMoving() + && ( !IsFootprintEditor() || commit->Empty() ) ) { - static_cast( item )->RunOnDescendants( [&]( BOARD_ITEM* bItem ) - { - commit->Modify( bItem ); - }); - } - } + commit->Modify( boardItem ); - static_cast( item )->Flip( refPt, leftRight ); + if( boardItem->Type() == PCB_GROUP_T ) + { + static_cast( boardItem )->RunOnDescendants( + [&]( BOARD_ITEM* descendant ) + { + commit->Modify( descendant ); + }); + } + } + + boardItem->Flip( refPt, leftRight ); + } } if( !localCommit.Empty() ) @@ -1807,9 +1815,12 @@ void EDIT_TOOL::DeleteItems( const PCB_SELECTION& aItems, bool aIsCut ) for( EDA_ITEM* item : aItems ) { - BOARD_ITEM* board_item = static_cast( item ); - FOOTPRINT* parentFP = board_item->GetParentFootprint(); - PCB_GROUP* parentGroup = board_item->GetParentGroup(); + BOARD_ITEM* board_item = dynamic_cast( item ); + + wxCHECK2( board_item, continue ); + + FOOTPRINT* parentFP = board_item->GetParentFootprint(); + PCB_GROUP* parentGroup = board_item->GetParentGroup(); if( parentGroup ) { @@ -2090,46 +2101,47 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent ) if( IsFootprintEditor() ) commit.Modify( selection.Front() ); - for( EDA_ITEM* selItem : selection ) + for( EDA_ITEM* item : selection ) { - BOARD_ITEM* item = static_cast( selItem ); + BOARD_ITEM* boardItem = dynamic_cast( item ); - if( !item->IsNew() && !IsFootprintEditor() ) + wxCHECK2( boardItem, continue ); + + if( !boardItem->IsNew() && !IsFootprintEditor() ) { - commit.Modify( item ); + commit.Modify( boardItem ); - if( item->Type() == PCB_GROUP_T ) + if( boardItem->Type() == PCB_GROUP_T ) { - PCB_GROUP* group = static_cast( item ); + PCB_GROUP* group = static_cast( boardItem ); - group->RunOnDescendants( [&]( BOARD_ITEM* bItem ) + group->RunOnDescendants( [&]( BOARD_ITEM* descendant ) { - commit.Modify( bItem ); + commit.Modify( descendant ); }); } } - if( !item->GetParent() || !item->GetParent()->IsSelected() ) - item->Move( translation ); + if( !boardItem->GetParent() || !boardItem->GetParent()->IsSelected() ) + boardItem->Move( translation ); switch( rotationAnchor ) { case ROTATE_AROUND_ITEM_ANCHOR: - item->Rotate( item->GetPosition(), angle ); + boardItem->Rotate( boardItem->GetPosition(), angle ); break; - case ROTATE_AROUND_SEL_CENTER: - item->Rotate( selCenter, angle ); + case ROTATE_AROUND_SEL_CENTER: boardItem->Rotate( selCenter, angle ); break; case ROTATE_AROUND_USER_ORIGIN: - item->Rotate( frame()->GetScreen()->m_LocalOrigin, angle ); + boardItem->Rotate( frame()->GetScreen()->m_LocalOrigin, angle ); break; case ROTATE_AROUND_AUX_ORIGIN: - item->Rotate( board()->GetDesignSettings().GetAuxOrigin(), angle ); + boardItem->Rotate( board()->GetDesignSettings().GetAuxOrigin(), angle ); break; } if( !m_dragging ) - getView()->Update( item ); + getView()->Update( boardItem ); } commit.Push( _( "Move exact" ) ); @@ -2183,7 +2195,9 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent ) for( EDA_ITEM* item : selection ) { BOARD_ITEM* dupe_item = nullptr; - BOARD_ITEM* orig_item = static_cast( item ); + BOARD_ITEM* orig_item = dynamic_cast( item ); + + wxCHECK2( orig_item, continue ); if( m_isFootprintEditor ) { @@ -2324,9 +2338,7 @@ void EDIT_TOOL::PadFilter( const VECTOR2I&, GENERAL_COLLECTOR& aCollector, { for( int i = aCollector.GetCount() - 1; i >= 0; i-- ) { - BOARD_ITEM* item = static_cast( aCollector[i] ); - - if( item->Type() != PCB_PAD_T ) + if( aCollector[i]->Type() != PCB_PAD_T ) aCollector.Remove( i ); } } @@ -2337,9 +2349,7 @@ void EDIT_TOOL::FootprintFilter( const VECTOR2I&, GENERAL_COLLECTOR& aCollector, { for( int i = aCollector.GetCount() - 1; i >= 0; i-- ) { - BOARD_ITEM* item = static_cast( aCollector[i] ); - - if( item->Type() != PCB_FOOTPRINT_T ) + if( aCollector[i]->Type() != PCB_FOOTPRINT_T ) aCollector.Remove( i ); } } @@ -2357,9 +2367,8 @@ bool EDIT_TOOL::updateModificationPoint( PCB_SELECTION& aSelection ) // When there is only one item selected, the reference point is its position... if( aSelection.Size() == 1 ) { - auto item = static_cast( aSelection.Front() ); - auto pos = item->GetPosition(); - aSelection.SetReferencePoint( VECTOR2I( pos.x, pos.y ) ); + if( BOARD_ITEM* item = dynamic_cast( aSelection.Front() ) ) + aSelection.SetReferencePoint( item->GetPosition() ); } // ...otherwise modify items with regard to the grid-snapped center position else @@ -2491,7 +2500,10 @@ int EDIT_TOOL::copyToClipboard( const TOOL_EVENT& aEvent ) std::vector items; for( EDA_ITEM* item : selection ) - items.push_back( static_cast( item ) ); + { + if( BOARD_ITEM* boardItem = dynamic_cast( item ) ) + items.push_back( boardItem ); + } VECTOR2I refPoint; diff --git a/pcbnew/tools/edit_tool_move_fct.cpp b/pcbnew/tools/edit_tool_move_fct.cpp index 637c141b3e..0b6798980c 100644 --- a/pcbnew/tools/edit_tool_move_fct.cpp +++ b/pcbnew/tools/edit_tool_move_fct.cpp @@ -95,9 +95,9 @@ int EDIT_TOOL::Swap( const TOOL_EVENT& aEvent ) if( item->Type() == PCB_GROUP_T ) { PCB_GROUP* group = static_cast( item ); - group->RunOnDescendants( [&]( BOARD_ITEM* bItem ) + group->RunOnDescendants( [&]( BOARD_ITEM* descendant ) { - commit->Modify( bItem ); + commit->Modify( descendant ); }); } } @@ -105,8 +105,10 @@ int EDIT_TOOL::Swap( const TOOL_EVENT& aEvent ) for( size_t i = 0; i < sorted.size() - 1; i++ ) { - BOARD_ITEM* a = static_cast( sorted[i] ); - BOARD_ITEM* b = static_cast( sorted[( i + 1 ) % sorted.size()] ); + BOARD_ITEM* a = dynamic_cast( sorted[i] ); + BOARD_ITEM* b = dynamic_cast( sorted[( i + 1 ) % sorted.size()] ); + + wxCHECK2( a && b, continue ); // Swap X,Y position VECTOR2I aPos = a->GetPosition(), bPos = b->GetPosition(); @@ -404,7 +406,10 @@ bool EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, BOARD_COMMIT* aCommit orig_items.clear(); for( EDA_ITEM* item : selection.GetItemsSortedBySelectionOrder() ) - orig_items.push_back( static_cast( item ) ); + { + if( BOARD_ITEM* boardItem = dynamic_cast( item ) ) + orig_items.push_back( boardItem ); + } updateStatusPopup( orig_items[ itemIdx ], itemIdx + 1, orig_items.size() ); statusPopup.Popup(); diff --git a/pcbnew/tools/placement_tool.cpp b/pcbnew/tools/placement_tool.cpp index 3a42b2a71f..c6f72f0f7e 100644 --- a/pcbnew/tools/placement_tool.cpp +++ b/pcbnew/tools/placement_tool.cpp @@ -91,7 +91,9 @@ std::vector> GetBoundingBoxes( const T& aItems ) for( EDA_ITEM* item : aItems ) { - BOARD_ITEM* boardItem = static_cast( item ); + BOARD_ITEM* boardItem = dynamic_cast( item ); + + wxCHECK2( boardItem, continue ); if( item->Type() == PCB_FOOTPRINT_T ) { @@ -163,7 +165,9 @@ size_t ALIGN_DISTRIBUTE_TOOL::GetSelections( std::vector( item ); + BOARD_ITEM* boardItem = dynamic_cast( item ); + + wxCHECK2( boardItem, continue ); // We do not lock items in the footprint editor if( boardItem->IsLocked() && m_frame->IsType( FRAME_PCB_EDITOR ) ) diff --git a/pcbnew/tools/position_relative_tool.cpp b/pcbnew/tools/position_relative_tool.cpp index 9f3bf89813..9ccbf4b116 100644 --- a/pcbnew/tools/position_relative_tool.cpp +++ b/pcbnew/tools/position_relative_tool.cpp @@ -127,27 +127,30 @@ int POSITION_RELATIVE_TOOL::RelativeItemSelectionMove( const VECTOR2I& aPosAncho for( EDA_ITEM* item : m_selection ) { - // Don't move a pad by itself unless editing the footprint - if( item->Type() == PCB_PAD_T - && !frame()->GetPcbNewSettings()->m_AllowFreePads - && frame()->IsType( FRAME_PCB_EDITOR ) ) + if( BOARD_ITEM* boardItem = dynamic_cast( item ) ) { - item = item->GetParent(); + // Don't move a pad by itself unless editing the footprint + if( boardItem->Type() == PCB_PAD_T + && !frame()->GetPcbNewSettings()->m_AllowFreePads + && frame()->IsType( FRAME_PCB_EDITOR ) ) + { + boardItem = boardItem->GetParent(); + } + + m_commit->Modify( boardItem ); + + // If moving a group, record position of all the descendants for undo + if( boardItem->Type() == PCB_GROUP_T ) + { + PCB_GROUP* group = static_cast( boardItem ); + group->RunOnDescendants( [&]( BOARD_ITEM* descendant ) + { + m_commit->Modify( descendant ); + }); + } + + boardItem->Move( aggregateTranslation ); } - - m_commit->Modify( item ); - - // If moving a group, record position of all the descendants for undo - if( item->Type() == PCB_GROUP_T ) - { - PCB_GROUP* group = static_cast( item ); - group->RunOnDescendants( [&]( BOARD_ITEM* bItem ) - { - m_commit->Modify( bItem ); - }); - } - - static_cast( item )->Move( aggregateTranslation ); } m_commit->Push( _( "Position Relative" ) ); diff --git a/pcbnew/undo_redo.cpp b/pcbnew/undo_redo.cpp index edc87e55cd..37972111d7 100644 --- a/pcbnew/undo_redo.cpp +++ b/pcbnew/undo_redo.cpp @@ -112,39 +112,37 @@ static bool TestForExistingItem( BOARD* aPcb, BOARD_ITEM* aItem ) { for( PCB_TRACK* item : aPcb->Tracks() ) { - if( aItem == static_cast( item ) ) + if( aItem == item) return true; } for( FOOTPRINT* item : aPcb->Footprints() ) { - if( aItem == static_cast( item ) ) + if( aItem == item ) return true; } for( BOARD_ITEM* item : aPcb->Drawings() ) { - if( aItem == static_cast( item ) ) + if( aItem == item ) return true; } for( ZONE* item : aPcb->Zones() ) { - if( aItem == static_cast( item ) ) + if( aItem == item ) return true; } - NETINFO_LIST& netInfo = aPcb->GetNetInfo(); - - for( NETINFO_LIST::iterator i = netInfo.begin(); i != netInfo.end(); ++i ) + for( const NETINFO_ITEM* item : aPcb->GetNetInfo() ) { - if( aItem == static_cast( *i ) ) + if( aItem == item ) return true; } for( PCB_GROUP* item : aPcb->Groups() ) { - if( aItem == static_cast( item ) ) + if( aItem == item ) return true; } @@ -536,14 +534,20 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList ) case UNDO_REDO::REGROUP: aList->SetPickedItemStatus( UNDO_REDO::UNGROUP, ii ); - static_cast( eda_item )->SetParentGroup( nullptr ); + + if( BOARD_ITEM* boardItem = dynamic_cast( eda_item ) ) + boardItem->SetParentGroup( nullptr ); + break; case UNDO_REDO::UNGROUP: aList->SetPickedItemStatus( UNDO_REDO::REGROUP, ii ); - if( group ) - group->AddItem( static_cast( eda_item ) ); + if( BOARD_ITEM* boardItem = dynamic_cast( eda_item ) ) + { + if( group ) + group->AddItem( boardItem ); + } break; @@ -626,11 +630,14 @@ void PCB_BASE_EDIT_FRAME::ClearUndoORRedoList( UNDO_REDO_LIST whichList, int aIt void PCB_BASE_EDIT_FRAME::ClearListAndDeleteItems( PICKED_ITEMS_LIST* aList ) { - aList->ClearListAndDeleteItems( []( EDA_ITEM* item ) - { - static_cast( item )->SetParentGroup( nullptr ); - delete item; - } ); + aList->ClearListAndDeleteItems( + []( EDA_ITEM* item ) + { + if( BOARD_ITEM* boardItem = dynamic_cast( item ) ) + boardItem->SetParentGroup( nullptr ); + + delete item; + } ); }