diff --git a/common/view/view.cpp b/common/view/view.cpp index c58193b5b5..6bf4f983d5 100644 --- a/common/view/view.cpp +++ b/common/view/view.cpp @@ -672,16 +672,12 @@ void VIEW::draw( VIEW_ITEM* aItem, bool aImmediate ) } } - void VIEW::draw( VIEW_GROUP* aGroup, bool aImmediate ) { - std::set::const_iterator it; - - for( it = aGroup->Begin(); it != aGroup->End(); ++it ) - draw( *it, aImmediate ); + for ( int i = 0; i < aGroup->GetSize(); i++) + draw( aGroup->GetItem(i), aImmediate ); } - struct VIEW::unlinkItem { bool operator()( VIEW_ITEM* aItem ) diff --git a/common/view/view_group.cpp b/common/view/view_group.cpp index 94123f1b28..e41d1b7027 100644 --- a/common/view/view_group.cpp +++ b/common/view/view_group.cpp @@ -49,35 +49,48 @@ VIEW_GROUP::VIEW_GROUP( VIEW* aView ) : VIEW_GROUP::~VIEW_GROUP() { + } void VIEW_GROUP::Add( VIEW_ITEM* aItem ) { - m_items.insert( aItem ); + m_groupItems.push_back( aItem ); ViewUpdate(); } void VIEW_GROUP::Remove( VIEW_ITEM* aItem ) { - m_items.erase( aItem ); + for ( auto iter = m_groupItems.begin(); iter != m_groupItems.end(); ++iter) + { + if ( aItem == *iter ) + { + m_groupItems.erase( iter); + break; + } + } + ViewUpdate(); } void VIEW_GROUP::Clear() { - m_items.clear(); + m_groupItems.clear(); ViewUpdate(); } unsigned int VIEW_GROUP::GetSize() const { - return m_items.size(); + return m_groupItems.size(); } +VIEW_ITEM *VIEW_GROUP::GetItem(unsigned int idx) const +{ + return m_groupItems[idx]; +} const BOX2I VIEW_GROUP::ViewBBox() const { @@ -92,8 +105,10 @@ void VIEW_GROUP::ViewDraw( int aLayer, GAL* aGal ) const { PAINTER* painter = m_view->GetPainter(); + const auto drawList = updateDrawList(); + // Draw all items immediately (without caching) - for( VIEW_ITEM* item : m_items ) + for ( auto item : drawList ) { aGal->PushDepth(); @@ -127,31 +142,32 @@ void VIEW_GROUP::ViewGetLayers( int aLayers[], int& aCount ) const void VIEW_GROUP::FreeItems() { - for( VIEW_ITEM* item : m_items ) + for (unsigned int i = 0 ; i < GetSize(); i++) { + VIEW_ITEM *item = GetItem(i); delete item; } Clear(); } - -void VIEW_GROUP::ItemsSetVisibility( bool aVisible ) +const VIEW_GROUP::ITEMS VIEW_GROUP::updateDrawList() const { - std::set::const_iterator it, it_end; + return m_groupItems; +} - for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it ) - (*it)->ViewSetVisible( aVisible ); +/*void VIEW_GROUP::ItemsSetVisibility( bool aVisible ) +{ + for (unsigned int i = 0 ; i < GetSize(); i++) + GetItem(i)->ViewSetVisible( aVisible ); } void VIEW_GROUP::ItemsViewUpdate( VIEW_ITEM::VIEW_UPDATE_FLAGS aFlags ) { - std::set::const_iterator it, it_end; - - for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it ) - (*it)->ViewUpdate( aFlags ); -} + for (unsigned int i = 0 ; i < GetSize(); i++) + GetItem(i)->ViewUpdate( aFlags ); +}*/ void VIEW_GROUP::updateBbox() diff --git a/include/commit.h b/include/commit.h index 646e991a4b..9c3ef0fed4 100644 --- a/include/commit.h +++ b/include/commit.h @@ -109,6 +109,15 @@ public: ///> before the modification. COMMIT& Modified( EDA_ITEM* aItem, EDA_ITEM* aCopy ); + template + COMMIT& StageItems( const Range& aRange, CHANGE_TYPE aChangeType ) + { + for ( const auto& item : aRange ) + Stage ( item, aChangeType ); + return *this; + } + + ///> Adds a change of the item aItem of type aChangeType to the change list. COMMIT& Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType ); @@ -117,7 +126,7 @@ public: COMMIT& Stage( const PICKED_ITEMS_LIST& aItems, UNDO_REDO_T aModFlag = UR_UNSPECIFIED ); ///> Executes the changes. - virtual void Push( const wxString& aMessage ) = 0; + virtual void Push( const wxString& aMessage = wxT("A commit"), bool aCreateUndoEntry = true) = 0; ///> Revertes the commit by restoring the modifed items state. virtual void Revert() = 0; diff --git a/include/view/view_group.h b/include/view/view_group.h index 57c972ec2f..9082505198 100644 --- a/include/view/view_group.h +++ b/include/view/view_group.h @@ -40,15 +40,22 @@ namespace KIGFX { class VIEW_GROUP : public VIEW_ITEM { +protected: + typedef std::vector ITEMS; + public: VIEW_GROUP( VIEW* aView = NULL ); virtual ~VIEW_GROUP(); - /// Helper typedefs - typedef std::set::const_iterator const_iter; - typedef std::set::iterator iter; - /** + * Function GetSize() + * Returns the number of stored items. + * + * @return Number of stored items. + */ + virtual unsigned int GetSize() const; + + /** * Function Add() * Adds an item to the group. * @@ -70,31 +77,8 @@ public: */ virtual void Clear(); - /** - * Function Begin() - * Returns iterator to beginning. - */ - inline const_iter Begin() const - { - return m_items.begin(); - } - /** - * Function End() - * Returns iterator to end. - */ - inline const_iter End() const - { - return m_items.end(); - } - - /** - * Function GetSize() - * Returns the number of stored items. - * - * @return Number of stored items. - */ - virtual unsigned int GetSize() const; + virtual VIEW_ITEM *GetItem(unsigned int idx) const; /** * Function ViewBBox() @@ -157,7 +141,7 @@ public: * * @param aVisible decides if items should be visible or not. */ - virtual void ItemsSetVisibility( bool aVisible ); + //virtual void ItemsSetVisibility( bool aVisible ); /** * Function ItemsViewUpdate() @@ -165,9 +149,12 @@ public: * * @param aFlags determines the way in which items will be updated. */ - virtual void ItemsViewUpdate( VIEW_ITEM::VIEW_UPDATE_FLAGS aFlags ); + //virtual void ItemsViewUpdate( VIEW_ITEM::VIEW_UPDATE_FLAGS aFlags ); protected: + + virtual const ITEMS updateDrawList() const; + /// These functions cannot be used with VIEW_GROUP as they are intended only to work with /// singular VIEW_ITEMs (there is only one-to-one relation between item/layer combination and /// its group). @@ -195,12 +182,15 @@ protected: /// Layer on which the group is drawn int m_layer; +protected: + /// Container for storing VIEW_ITEMs + ITEMS m_groupItems; + private: void updateBbox(); - /// Container for storing VIEW_ITEMs - std::set m_items; }; + } // namespace KIGFX #endif // VIEW_GROUP_H_ diff --git a/pcbnew/board_commit.cpp b/pcbnew/board_commit.cpp index b5b23b9cae..09c5442b41 100644 --- a/pcbnew/board_commit.cpp +++ b/pcbnew/board_commit.cpp @@ -53,7 +53,7 @@ BOARD_COMMIT::~BOARD_COMMIT() } -void BOARD_COMMIT::Push( const wxString& aMessage ) +void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry) { // Objects potentially interested in changes: PICKED_ITEMS_LIST undoList; @@ -70,7 +70,6 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) { int changeType = ent.m_type & CHT_TYPE; int changeFlags = ent.m_type & CHT_FLAGS; - bool done = changeFlags & CHT_DONE; BOARD_ITEM* boardItem = static_cast( ent.m_item ); // Module items need to be saved in the undo buffer before modification @@ -92,10 +91,13 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) assert( ent.m_item->Type() == PCB_MODULE_T ); assert( ent.m_copy->Type() == PCB_MODULE_T ); - ITEM_PICKER itemWrapper( ent.m_item, UR_CHANGED ); - itemWrapper.SetLink( ent.m_copy ); - undoList.PushItem( itemWrapper ); - frame->SaveCopyInUndoList( undoList, UR_CHANGED ); + if ( aCreateUndoEntry ) + { + ITEM_PICKER itemWrapper( ent.m_item, UR_CHANGED ); + itemWrapper.SetLink( ent.m_copy ); + undoList.PushItem( itemWrapper ); + frame->SaveCopyInUndoList( undoList, UR_CHANGED ); + } savedModules.insert( ent.m_item ); static_cast( ent.m_item )->SetLastEditTime(); @@ -108,9 +110,10 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) { if( !m_editModules ) { + if ( aCreateUndoEntry ) undoList.PushItem( ITEM_PICKER( boardItem, UR_NEW ) ); - if( !done ) + if( !( changeFlags & CHT_DONE ) ) board->Add( boardItem ); //ratsnest->Add( boardItem ); // TODO currently done by BOARD::Add() @@ -126,7 +129,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) // modules inside modules are not supported yet assert( boardItem->Type() != PCB_MODULE_T ); - if( !done ) + if( !( changeFlags & CHT_DONE ) ) board->m_Modules->Add( boardItem ); } @@ -136,8 +139,10 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) case CHT_REMOVE: { - if( !m_editModules ) + if( !m_editModules && aCreateUndoEntry ) + { undoList.PushItem( ITEM_PICKER( boardItem, UR_DELETED ) ); + } switch( boardItem->Type() ) { @@ -181,7 +186,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) { view->Remove( boardItem ); - if( !done ) + if( !( changeFlags & CHT_DONE ) ) { MODULE* module = static_cast( boardItem->GetParent() ); assert( module && module->Type() == PCB_MODULE_T ); @@ -206,7 +211,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) case PCB_ZONE_AREA_T: view->Remove( boardItem ); - if( !done ) + if( !( changeFlags & CHT_DONE ) ) board->Remove( boardItem ); //ratsnest->Remove( boardItem ); // currently done by BOARD::Remove() @@ -223,7 +228,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) view->Remove( module ); - if( !done ) + if( !( changeFlags & CHT_DONE ) ) board->Remove( module ); // Clear flags to indicate, that the ratsnest, list of nets & pads are not valid anymore @@ -240,7 +245,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) case CHT_MODIFY: { - if( !m_editModules ) + if( !m_editModules && aCreateUndoEntry ) { ITEM_PICKER itemWrapper( boardItem, UR_CHANGED ); assert( ent.m_copy ); @@ -259,7 +264,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) } } - if( !m_editModules ) + if( !m_editModules && aCreateUndoEntry ) frame->SaveCopyInUndoList( undoList, UR_UNSPECIFIED ); if( TOOL_MANAGER* toolMgr = frame->GetToolManager() ) diff --git a/pcbnew/board_commit.h b/pcbnew/board_commit.h index 2dbcddf5a0..e1d73cb8c6 100644 --- a/pcbnew/board_commit.h +++ b/pcbnew/board_commit.h @@ -40,7 +40,7 @@ public: BOARD_COMMIT( PCB_BASE_FRAME* aFrame ); virtual ~BOARD_COMMIT(); - virtual void Push( const wxString& aMessage ) override; + virtual void Push( const wxString& aMessage = wxT("A commit"), bool aCreateUndoEntry = true) override; virtual void Revert() override; private: diff --git a/pcbnew/dialogs/dialog_track_via_properties.cpp b/pcbnew/dialogs/dialog_track_via_properties.cpp index 78ca781e44..cd712f8408 100644 --- a/pcbnew/dialogs/dialog_track_via_properties.cpp +++ b/pcbnew/dialogs/dialog_track_via_properties.cpp @@ -54,10 +54,8 @@ DIALOG_TRACK_VIA_PROPERTIES::DIALOG_TRACK_VIA_PROPERTIES( PCB_BASE_FRAME* aParen // Look for values that are common for every item that is selected - for( int i = 0; i < m_items.Size(); ++i ) + for ( auto& item : m_items ) { - const BOARD_ITEM* item = m_items.Item( i ); - switch( item->Type() ) { case PCB_TRACE_T: @@ -212,10 +210,8 @@ bool DIALOG_TRACK_VIA_PROPERTIES::Apply( COMMIT& aCommit ) bool changeLock = m_lockedCbox->Get3StateValue() != wxCHK_UNDETERMINED; bool setLock = m_lockedCbox->Get3StateValue() == wxCHK_CHECKED; - - for( int i = 0; i < m_items.Size(); ++i ) + for ( auto item : m_items ) { - BOARD_ITEM* item = m_items.Item( i ); aCommit.Modify( item ); switch( item->Type() ) diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp index b9a9fdac4f..ba271d4ae7 100644 --- a/pcbnew/tools/drawing_tool.cpp +++ b/pcbnew/tools/drawing_tool.cpp @@ -50,6 +50,8 @@ #include #include +#include + DRAWING_TOOL::DRAWING_TOOL() : PCB_TOOL( "pcbnew.InteractiveDrawing" ), m_view( NULL ), m_controls( NULL ), m_board( NULL ), m_frame( NULL ), m_lineWidth( 1 ) @@ -163,7 +165,7 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent ) BOARD_COMMIT commit( m_frame ); // Add a VIEW_GROUP that serves as a preview for the new item - KIGFX::VIEW_GROUP preview( m_view ); + SELECTION preview( m_view ); m_view->Add( &preview ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); @@ -326,7 +328,7 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent ) int maxThickness; // Add a VIEW_GROUP that serves as a preview for the new item - KIGFX::VIEW_GROUP preview( m_view ); + SELECTION preview( m_view ); m_view->Add( &preview ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); @@ -527,23 +529,22 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent ) return 0; VECTOR2I cursorPos = m_controls->GetCursorPosition(); - VECTOR2I delta = cursorPos - (*list.begin())->GetPosition(); + VECTOR2I delta = cursorPos - list.front()->GetPosition(); // Add a VIEW_GROUP that serves as a preview for the new item - KIGFX::VIEW_GROUP preview( m_view ); + SELECTION preview( m_view ); BOARD_COMMIT commit( m_frame ); // Build the undo list & add items to the current view - for( auto it = list.begin(), itEnd = list.end(); it != itEnd; ++it ) + for ( auto item : list ) { - KICAD_T type = (*it)->Type(); + KICAD_T type = item->Type(); assert( type == PCB_LINE_T || type == PCB_TEXT_T ); - if( type == PCB_LINE_T || type == PCB_TEXT_T ) - preview.Add( *it ); + preview.Add( item ); } - BOARD_ITEM* firstItem = static_cast( *preview.Begin() ); + BOARD_ITEM* firstItem = preview.Front(); m_view->Add( &preview ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); @@ -561,8 +562,8 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent ) { delta = cursorPos - firstItem->GetPosition(); - for( KIGFX::VIEW_GROUP::const_iter it = preview.Begin(), end = preview.End(); it != end; ++it ) - static_cast( *it )->Move( wxPoint( delta.x, delta.y ) ); + for ( auto item : preview ) + item->Move( wxPoint( delta.x, delta.y ) ); preview.ViewUpdate(); } @@ -572,16 +573,16 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent ) // TODO it should be handled by EDIT_TOOL, so add items and select? if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) { - for( KIGFX::VIEW_GROUP::const_iter it = preview.Begin(), end = preview.End(); it != end; ++it ) - static_cast( *it )->Rotate( wxPoint( cursorPos.x, cursorPos.y ), - m_frame->GetRotationAngle() ); + for ( auto item : preview ) + item->Rotate( wxPoint( cursorPos.x, cursorPos.y ), + m_frame->GetRotationAngle() ); preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); } else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) { - for( KIGFX::VIEW_GROUP::const_iter it = preview.Begin(), end = preview.End(); it != end; ++it ) - static_cast( *it )->Flip( wxPoint( cursorPos.x, cursorPos.y ) ); + for ( auto item : preview ) + item->Flip( wxPoint( cursorPos.x, cursorPos.y ) ); preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); } @@ -595,13 +596,10 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent ) else if( evt->IsClick( BUT_LEFT ) ) { // Place the drawing - PICKED_ITEMS_LIST picklist; BOARD_ITEM_CONTAINER* parent = m_frame->GetModel(); - for( KIGFX::VIEW_GROUP::const_iter it = preview.Begin(); it != preview.End(); ++it ) + for ( auto item : preview ) { - BOARD_ITEM* item = static_cast( *it ); - if( m_editModules ) { // Modules use different types for the same things, @@ -745,7 +743,7 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic, DRAWSEGMENT line45; // Add a VIEW_GROUP that serves as a preview for the new item - KIGFX::VIEW_GROUP preview( m_view ); + SELECTION preview( m_view ); m_view->Add( &preview ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); @@ -928,7 +926,7 @@ bool DRAWING_TOOL::drawArc( DRAWSEGMENT*& aGraphic ) helperLine.SetWidth( 1 ); // Add a VIEW_GROUP that serves as a preview for the new item - KIGFX::VIEW_GROUP preview( m_view ); + SELECTION preview( m_view ); m_view->Add( &preview ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); @@ -1105,7 +1103,7 @@ int DRAWING_TOOL::drawZone( bool aKeepout ) BOARD_COMMIT commit( m_frame ); // Add a VIEW_GROUP that serves as a preview for the new item - KIGFX::VIEW_GROUP preview( m_view ); + SELECTION preview( m_view ); m_view->Add( &preview ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index f6b552f9fa..3c27faba39 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -137,7 +137,7 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) PCB_BASE_EDIT_FRAME* editFrame = getEditFrame(); VECTOR2I originalCursorPos = controls->GetCursorPosition(); - const SELECTION& selection = m_selectionTool->GetSelection(); + SELECTION& selection = m_selectionTool->GetSelection(); // Shall the selection be cleared at the end? bool unselect = selection.Empty(); @@ -182,7 +182,7 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) else if( evt->IsAction( &COMMON_ACTIONS::editActivate ) || evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) { - BOARD_ITEM* item = selection.Item( 0 ); + BOARD_ITEM* item = selection.Front(); if( m_dragging && evt->Category() == TC_MOUSE ) { @@ -193,8 +193,8 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) totalMovement += movement; // Drag items to the current cursor position - for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) - selection.Item( i )->Move( movement + m_offset ); + for ( auto item : selection ) + item->Move( movement + m_offset ); updateRatsnest( true ); } @@ -216,10 +216,8 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) lockOverride = true; // Save items, so changes can be undone - selection.ForAll( [&](BOARD_ITEM* brd_item) - { - m_commit->Modify( brd_item ); - } ); + for ( auto item : selection ) + m_commit->Modify( item ); m_cursor = controls->GetCursorPosition(); @@ -247,7 +245,7 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) } } - selection.group->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + selection.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); m_toolMgr->RunAction( COMMON_ACTIONS::editModifiedSelection, true ); } @@ -287,9 +285,8 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) //editFrame->RestoreCopyFromUndoList( dummy ); // // So, instead, reset the position manually - for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) + for( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); item->SetPosition( item->GetPosition() - totalMovement ); // And what about flipping and rotation? @@ -307,8 +304,8 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) if( m_dragging ) { // Update dragging offset (distance between cursor and the first dragged item) - m_offset = selection.Item( 0 )->GetPosition() - modPoint; - selection.group->ViewUpdate( KIGFX::VIEW_ITEM::ALL ); + m_offset = selection.Front()->GetPosition() - modPoint; + selection.ViewUpdate( KIGFX::VIEW_ITEM::ALL ); updateRatsnest( true ); } } @@ -343,7 +340,7 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) int EDIT_TOOL::Properties( const TOOL_EVENT& aEvent ) { - const SELECTION& selection = m_selectionTool->GetSelection(); + SELECTION& selection = m_selectionTool->GetSelection(); PCB_BASE_EDIT_FRAME* editFrame = getEditFrame(); // Shall the selection be cleared at the end? @@ -366,7 +363,7 @@ int EDIT_TOOL::Properties( const TOOL_EVENT& aEvent ) else if( selection.Size() == 1 ) // Properties are displayed when there is only one item selected { // Display properties dialog - BOARD_ITEM* item = selection.Item( 0 ); + BOARD_ITEM* item = selection.Front(); // Some of properties dialogs alter pointers, so we should deselect them m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); @@ -403,9 +400,8 @@ int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent ) wxPoint rotatePoint = getModificationPoint( selection ); - for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) + for ( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); m_commit->Modify( item ); item->Rotate( rotatePoint, editFrame->GetRotationAngle() ); } @@ -435,9 +431,8 @@ int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent ) wxPoint flipPoint = getModificationPoint( selection ); - for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) + for( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); m_commit->Modify( item ); item->Flip( flipPoint ); } @@ -465,9 +460,8 @@ int EDIT_TOOL::Remove( const TOOL_EVENT& aEvent ) // As we are about to remove items, they have to be removed from the selection first m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); - for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) + for( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); m_commit->Remove( item ); } @@ -500,9 +494,8 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent ) VECTOR2I rp = selection.GetCenter(); wxPoint rotPoint( rp.x, rp.y ); - for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) + for( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); m_commit->Modify( item ); item->Move( translation ); @@ -532,7 +525,7 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent ) // first, check if we have a selection, or try to get one SELECTION_TOOL* selTool = m_toolMgr->GetTool(); - const SELECTION& selection = selTool->GetSelection(); + SELECTION& selection = selTool->GetSelection(); // Be sure that there is at least one item that we can modify if( !hoverSelection() ) @@ -543,10 +536,8 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent ) std::vector old_items; - for( int i = 0; i < selection.Size(); ++i ) + for ( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); - if( item ) old_items.push_back( item ); } @@ -621,7 +612,7 @@ private: BOARD_ITEM* getNthItemToArray( int n ) const override { - return m_selection.Item( n ); + return m_selection[n]; } BOARD* getBoard() const override @@ -648,11 +639,11 @@ private: true, new_item ); } - void postPushAction( BOARD_ITEM* new_item ) override + void postPushAction( BOARD_ITEM* new_item ) //override { } - void finalise() override + void finalise() // override { } @@ -665,7 +656,7 @@ int EDIT_TOOL::CreateArray( const TOOL_EVENT& aEvent ) { // first, check if we have a selection, or try to get one SELECTION_TOOL* selTool = m_toolMgr->GetTool(); - const SELECTION& selection = selTool->GetSelection(); + SELECTION& selection = selTool->GetSelection(); // pick up items under the cursor if needed if( !hoverSelection() ) @@ -697,15 +688,13 @@ void EDIT_TOOL::SetTransitions() void EDIT_TOOL::updateRatsnest( bool aRedraw ) { - const SELECTION& selection = m_selectionTool->GetSelection(); + SELECTION& selection = m_selectionTool->GetSelection(); RN_DATA* ratsnest = getModel()->GetRatsnest(); ratsnest->ClearSimple(); - for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) + for( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); - ratsnest->Update( item ); if( aRedraw ) @@ -718,7 +707,7 @@ wxPoint EDIT_TOOL::getModificationPoint( const SELECTION& aSelection ) { if( aSelection.Size() == 1 ) { - return aSelection.Item( 0 )->GetPosition() - m_offset; + return aSelection.Front()->GetPosition() - m_offset; } else { @@ -759,7 +748,7 @@ bool EDIT_TOOL::hoverSelection( bool aSanitize ) int EDIT_TOOL::editFootprintInFpEditor( const TOOL_EVENT& aEvent ) { - const SELECTION& selection = m_selectionTool->GetSelection(); + SELECTION& selection = m_selectionTool->GetSelection(); bool unselect = selection.Empty(); if( !hoverSelection() ) diff --git a/pcbnew/tools/edit_tool.h b/pcbnew/tools/edit_tool.h index 0a4ca6e442..1fb13a23ae 100644 --- a/pcbnew/tools/edit_tool.h +++ b/pcbnew/tools/edit_tool.h @@ -28,17 +28,11 @@ #include #include -#include class BOARD_COMMIT; class BOARD_ITEM; class SELECTION_TOOL; -namespace KIGFX -{ -class VIEW_GROUP; -} - /** * Class EDIT_TOOL * @@ -164,10 +158,10 @@ private: { const SELECTION& selection = m_selectionTool->GetSelection(); - if( selection.items.GetCount() != 1 ) - return NULL; + if( selection.Size() != 1 ) + return nullptr; - BOARD_ITEM* item = selection.Item( 0 ); + auto item = selection[0]; return dyn_cast( item ); } diff --git a/pcbnew/tools/module_tools.cpp b/pcbnew/tools/module_tools.cpp index d41f6e55f8..740de2c41d 100644 --- a/pcbnew/tools/module_tools.cpp +++ b/pcbnew/tools/module_tools.cpp @@ -370,9 +370,9 @@ int MODULE_TOOLS::CopyItems( const TOOL_EVENT& aEvent ) // Create a temporary module that contains selected items to ease serialization MODULE module( m_board ); - for( int i = 0; i < selection.Size(); ++i ) + for ( auto item : selection ) { - BOARD_ITEM* clone = static_cast( selection.Item( i )->Clone() ); + auto clone = static_cast ( item->Clone() ); // Do not add reference/value - convert them to the common type if( TEXTE_MODULE* text = dyn_cast( clone ) ) @@ -426,7 +426,7 @@ int MODULE_TOOLS::PasteItems( const TOOL_EVENT& aEvent ) KIGFX::VIEW_GROUP preview( m_view ); pastedModule->SetParent( m_board ); pastedModule->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); - pastedModule->RunOnChildren( std::bind( &KIGFX::VIEW_GROUP::Add, + pastedModule->RunOnChildren( std::bind( &KIGFX::VIEW_GROUP::Add, std::ref( preview ), _1 ) ); preview.Add( pastedModule ); m_view->Add( &preview ); diff --git a/pcbnew/tools/pcb_editor_control.cpp b/pcbnew/tools/pcb_editor_control.cpp index 8c94e0b40a..4d5d15afb7 100644 --- a/pcbnew/tools/pcb_editor_control.cpp +++ b/pcbnew/tools/pcb_editor_control.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -365,9 +366,8 @@ int PCB_EDITOR_CONTROL::modifyLockSelected( MODIFY_MODE aMode ) bool modified = false; - for( int i = 0; i < selection.Size(); ++i ) + for ( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); bool prevState = item->IsLocked(); switch( aMode ) @@ -484,15 +484,15 @@ int PCB_EDITOR_CONTROL::PlaceTarget( const TOOL_EVENT& aEvent ) // Zone actions int PCB_EDITOR_CONTROL::ZoneFill( const TOOL_EVENT& aEvent ) { - SELECTION_TOOL* selTool = m_toolMgr->GetTool(); - const SELECTION& selection = selTool->GetSelection(); + auto selTool = m_toolMgr->GetTool(); + const auto& selection = selTool->GetSelection(); RN_DATA* ratsnest = getModel()->GetRatsnest(); - for( int i = 0; i < selection.Size(); ++i ) + for ( auto item : selection ) { - assert( selection.Item( i )->Type() == PCB_ZONE_AREA_T ); + assert( item->Type() == PCB_ZONE_AREA_T ); - ZONE_CONTAINER* zone = selection.Item( i ); + ZONE_CONTAINER* zone = static_cast ( item ); m_frame->Fill_Zone( zone ); zone->SetIsFilled( true ); ratsnest->Update( zone ); @@ -527,15 +527,16 @@ int PCB_EDITOR_CONTROL::ZoneFillAll( const TOOL_EVENT& aEvent ) int PCB_EDITOR_CONTROL::ZoneUnfill( const TOOL_EVENT& aEvent ) { - SELECTION_TOOL* selTool = m_toolMgr->GetTool(); - const SELECTION& selection = selTool->GetSelection(); + auto selTool = m_toolMgr->GetTool(); + const auto& selection = selTool->GetSelection(); RN_DATA* ratsnest = getModel()->GetRatsnest(); - for( int i = 0; i < selection.Size(); ++i ) + for ( auto item : selection ) { - assert( selection.Item( i )->Type() == PCB_ZONE_AREA_T ); + assert( item->Type() == PCB_ZONE_AREA_T ); + + ZONE_CONTAINER* zone = static_cast ( item ); - ZONE_CONTAINER* zone = selection.Item( i ); zone->SetIsFilled( false ); zone->ClearFilledPolysList(); ratsnest->Update( zone ); @@ -567,102 +568,105 @@ int PCB_EDITOR_CONTROL::ZoneUnfillAll( const TOOL_EVENT& aEvent ) return 0; } +static bool mergeZones ( BOARD_COMMIT& aCommit, std::vector& aOriginZones, std::vector& aMergedZones ) +{ + SHAPE_POLY_SET mergedOutlines = ConvertPolyListToPolySet( aOriginZones[0]->Outline()->m_CornersList ); + + for ( unsigned int i = 1; i < aOriginZones.size(); i++ ) + { + SHAPE_POLY_SET areaToMergePoly = ConvertPolyListToPolySet( aOriginZones[i]->Outline()->m_CornersList ); + + mergedOutlines.BooleanAdd( areaToMergePoly, SHAPE_POLY_SET::PM_FAST ); + } + + mergedOutlines.Simplify( SHAPE_POLY_SET::PM_FAST ); + + // We should have one polygon with hole + // We can have 2 polygons with hole, if the 2 initial polygons have only one common corner + // and therefore cannot be merged (they are dectected as intersecting) + // but we should never have more than 2 polys + if( mergedOutlines.OutlineCount() > 1 ) + { + wxLogMessage(wxT("BOARD::CombineAreas error: more than 2 polys after merging") ); + return false; + } + + for ( unsigned int i = 1; i < aOriginZones.size(); i++ ) + { + aCommit.Remove( aOriginZones[i] ); + } + + aCommit.Modify ( aOriginZones[0] ); + aMergedZones.push_back( aOriginZones[0] ); + + aOriginZones[0]->Outline()->m_CornersList = ConvertPolySetToPolyList( mergedOutlines ); + aOriginZones[0]->SetLocalFlags( 1 ); + aOriginZones[0]->Outline()->Hatch(); + + return true; +} int PCB_EDITOR_CONTROL::ZoneMerge( const TOOL_EVENT& aEvent ) { - SELECTION selection = m_toolMgr->GetTool()->GetSelection(); + SELECTION& selection = m_toolMgr->GetTool()->GetSelection(); BOARD* board = getModel(); - RN_DATA* ratsnest = board->GetRatsnest(); - KIGFX::VIEW* view = getView(); BOARD_COMMIT commit( m_frame ); if( selection.Size() < 2 ) return 0; - PICKED_ITEMS_LIST changes; int netcode = -1; - // Loop through all combinations - for( int ia1 = 0; ia1 < selection.Size() - 1; ++ia1 ) + ZONE_CONTAINER *firstZone = nullptr; + std::vector toMerge, merged; + + + for ( auto item : selection ) { - ZONE_CONTAINER* curr_area = dynamic_cast( selection.Item( ia1 ) ); + auto curr_area = dynamic_cast( item ); if( !curr_area ) continue; + if( !firstZone ) + firstZone = curr_area; + netcode = curr_area->GetNetCode(); - EDA_RECT b1 = curr_area->Outline()->GetBoundingBox(); - bool mod_ia1 = false; - - for( int ia2 = selection.Size() - 1; ia2 > ia1; --ia2 ) + if ( firstZone ) { - ZONE_CONTAINER* area2 = dynamic_cast( selection.Item( ia2 ) ); - - if( !area2 ) + if( firstZone->GetNetCode() != netcode ) continue; - if( area2->GetNetCode() != netcode ) + if( curr_area->GetPriority() != firstZone->GetPriority() ) continue; - if( curr_area->GetPriority() != area2->GetPriority() ) + if( curr_area->GetIsKeepout() != firstZone->GetIsKeepout() ) continue; - if( curr_area->GetIsKeepout() != area2->GetIsKeepout() ) + if( curr_area->GetLayer() != firstZone->GetLayer() ) continue; - if( curr_area->GetLayer() != area2->GetLayer() ) + if (! board->TestAreaIntersection( curr_area, firstZone ) ) continue; - EDA_RECT b2 = area2->Outline()->GetBoundingBox(); - - if( b1.Intersects( b2 ) ) - { - EDA_ITEM* backup = curr_area->Clone(); - bool ret = board->TestAreaIntersection( curr_area, area2 ); - - if( ret && board->CombineAreas( &changes, curr_area, area2 ) ) - { - mod_ia1 = true; - selection.items.RemovePicker( ia2 ); - - ITEM_PICKER picker( curr_area, UR_CHANGED ); - picker.SetLink( backup ); - changes.PushItem( picker ); - } - else - { - delete backup; - } - } + toMerge.push_back(curr_area); + } + else + { + toMerge.push_back(curr_area); } - - if( mod_ia1 ) - --ia1; // if modified, we need to check it again } m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); - commit.Stage( changes ); - - for( unsigned i = 0; i < changes.GetCount(); ++i ) + if ( mergeZones( commit, toMerge, merged ) ) { - ITEM_PICKER picker = changes.GetItemWrapper( i ); - BOARD_ITEM* item = static_cast( picker.GetItem() ); - - if( picker.GetStatus() == UR_DELETED ) - { - view->Remove( item ); - ratsnest->Remove( item ); - } - else if( picker.GetStatus() == UR_CHANGED ) - { + commit.Push( _( "Merge zones" ) ); + for ( auto item : merged ) m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, item ); - } } - commit.Push( _( "Merge zones" ) ); - return 0; } @@ -679,7 +683,7 @@ int PCB_EDITOR_CONTROL::CrossProbePcbToSch( const TOOL_EVENT& aEvent ) const SELECTION& selection = selTool->GetSelection(); if( selection.Size() == 1 ) - m_frame->SendMessageToEESCHEMA( selection.Item( 0 ) ); + m_frame->SendMessageToEESCHEMA( selection.Front() ); return 0; } diff --git a/pcbnew/tools/pcb_tool.h b/pcbnew/tools/pcb_tool.h index f235945512..accc8f0d32 100644 --- a/pcbnew/tools/pcb_tool.h +++ b/pcbnew/tools/pcb_tool.h @@ -31,6 +31,7 @@ #include #include #include +#include /** * Class PCB_TOOL diff --git a/pcbnew/tools/pcbnew_control.cpp b/pcbnew/tools/pcbnew_control.cpp index 823dc617a1..f517d29772 100644 --- a/pcbnew/tools/pcbnew_control.cpp +++ b/pcbnew/tools/pcbnew_control.cpp @@ -740,7 +740,7 @@ static bool deleteItem( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition ) if( selection.Empty() ) return true; - bool canBeRemoved = ( selection.Item( 0 )->Type() != PCB_MODULE_T ); + bool canBeRemoved = ( selection.Front()->Type() != PCB_MODULE_T ); if( canBeRemoved || IsOK( aToolMgr->GetEditFrame(), _( "Are you sure you want to delete item?" ) ) ) aToolMgr->RunAction( COMMON_ACTIONS::remove, true ); @@ -897,7 +897,7 @@ int PCBNEW_CONTROL::AppendBoard( const TOOL_EVENT& aEvent ) // Start dragging the appended board SELECTION_TOOL* selectionTool = m_toolMgr->GetTool(); const SELECTION& selection = selectionTool->GetSelection(); - VECTOR2D v( selection.Item( 0 )->GetPosition() ); + VECTOR2D v( selection.Front()->GetPosition() ); getViewControls()->WarpCursor( v, true, true ); m_toolMgr->InvokeTool( "pcbnew.InteractiveEdit" ); diff --git a/pcbnew/tools/placement_tool.cpp b/pcbnew/tools/placement_tool.cpp index c5c6a5d723..841f02de12 100644 --- a/pcbnew/tools/placement_tool.cpp +++ b/pcbnew/tools/placement_tool.cpp @@ -80,23 +80,22 @@ int PLACEMENT_TOOL::AlignTop( const TOOL_EVENT& aEvent ) return 0; BOARD_COMMIT commit( getEditFrame() ); - commit.Stage( selection.items, UR_CHANGED ); + commit.StageItems( selection, CHT_MODIFY ); // Compute the highest point of selection - it will be the edge of alignment - int top = selection.Item( 0 )->GetBoundingBox().GetY(); + int top = selection.Front()->GetBoundingBox().GetY(); for( int i = 1; i < selection.Size(); ++i ) { - int currentTop = selection.Item( i )->GetBoundingBox().GetY(); + int currentTop = selection[i]->GetBoundingBox().GetY(); if( top > currentTop ) // Y decreases when going up top = currentTop; } // Move the selected items - for( int i = 0; i < selection.Size(); ++i ) + for ( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); int difference = top - item->GetBoundingBox().GetY(); item->Move( wxPoint( 0, difference ) ); @@ -116,23 +115,22 @@ int PLACEMENT_TOOL::AlignBottom( const TOOL_EVENT& aEvent ) return 0; BOARD_COMMIT commit( getEditFrame() ); - commit.Stage( selection.items, UR_CHANGED ); + commit.StageItems( selection, CHT_MODIFY ); // Compute the lowest point of selection - it will be the edge of alignment - int bottom = selection.Item( 0 )->GetBoundingBox().GetBottom(); + int bottom = selection.Front()->GetBoundingBox().GetBottom(); for( int i = 1; i < selection.Size(); ++i ) { - int currentBottom = selection.Item( i )->GetBoundingBox().GetBottom(); + int currentBottom = selection[i]->GetBoundingBox().GetBottom(); if( bottom < currentBottom ) // Y increases when going down bottom = currentBottom; } // Move the selected items - for( int i = 0; i < selection.Size(); ++i ) + for ( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); int difference = bottom - item->GetBoundingBox().GetBottom(); item->Move( wxPoint( 0, difference ) ); @@ -152,23 +150,22 @@ int PLACEMENT_TOOL::AlignLeft( const TOOL_EVENT& aEvent ) return 0; BOARD_COMMIT commit( getEditFrame() ); - commit.Stage( selection.items, UR_CHANGED ); + commit.StageItems( selection, CHT_MODIFY ); // Compute the leftmost point of selection - it will be the edge of alignment - int left = selection.Item( 0 )->GetBoundingBox().GetX(); + int left = selection.Front()->GetBoundingBox().GetX(); for( int i = 1; i < selection.Size(); ++i ) { - int currentLeft = selection.Item( i )->GetBoundingBox().GetX(); + int currentLeft = selection[i]->GetBoundingBox().GetX(); if( left > currentLeft ) // X decreases when going left left = currentLeft; } // Move the selected items - for( int i = 0; i < selection.Size(); ++i ) + for ( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); int difference = left - item->GetBoundingBox().GetX(); item->Move( wxPoint( difference, 0 ) ); @@ -188,23 +185,22 @@ int PLACEMENT_TOOL::AlignRight( const TOOL_EVENT& aEvent ) return 0; BOARD_COMMIT commit( getEditFrame() ); - commit.Stage( selection.items, UR_CHANGED ); + commit.StageItems( selection, CHT_MODIFY ); // Compute the rightmost point of selection - it will be the edge of alignment - int right = selection.Item( 0 )->GetBoundingBox().GetRight(); + int right = selection.Front()->GetBoundingBox().GetRight(); for( int i = 1; i < selection.Size(); ++i ) { - int currentRight = selection.Item( i )->GetBoundingBox().GetRight(); + int currentRight = selection[i]->GetBoundingBox().GetRight(); if( right < currentRight ) // X increases when going right right = currentRight; } // Move the selected items - for( int i = 0; i < selection.Size(); ++i ) + for ( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); int difference = right - item->GetBoundingBox().GetRight(); item->Move( wxPoint( difference, 0 ) ); @@ -236,26 +232,26 @@ int PLACEMENT_TOOL::DistributeHorizontally( const TOOL_EVENT& aEvent ) return 0; BOARD_COMMIT commit( getEditFrame() ); - commit.Stage( selection.items, UR_CHANGED ); + commit.StageItems( selection, CHT_MODIFY ); // Prepare a list, so the items can be sorted by their X coordinate - std::list itemsList; - for( int i = 0; i < selection.Size(); ++i ) - itemsList.push_back( selection.Item( i ) ); + std::vector itemsList; + for ( auto item : selection ) + itemsList.push_back( item ); // Sort items by X coordinate - itemsList.sort( compareX ); + std::sort(itemsList.begin(), itemsList.end(), compareX ); // Expected X coordinate for the next item (=minX) - int position = (*itemsList.begin())->GetBoundingBox().Centre().x; + int position = itemsList.front()->GetBoundingBox().Centre().x; // X coordinate for the last item - const int maxX = (*itemsList.rbegin())->GetBoundingBox().Centre().x; + const int maxX = itemsList.back()->GetBoundingBox().Centre().x; // Distance between items const int distance = ( maxX - position ) / ( itemsList.size() - 1 ); - for( BOARD_ITEM* item : itemsList ) + for( auto item : itemsList ) { int difference = position - item->GetBoundingBox().Centre().x; @@ -278,15 +274,15 @@ int PLACEMENT_TOOL::DistributeVertically( const TOOL_EVENT& aEvent ) return 0; BOARD_COMMIT commit( getEditFrame() ); - commit.Stage( selection.items, UR_CHANGED ); + commit.StageItems( selection, CHT_MODIFY ); // Prepare a list, so the items can be sorted by their Y coordinate - std::list itemsList; - for( int i = 0; i < selection.Size(); ++i ) - itemsList.push_back( selection.Item( i ) ); + std::vector itemsList; + for ( auto item : selection ) + itemsList.push_back( item ); // Sort items by Y coordinate - itemsList.sort( compareY ); + std::sort(itemsList.begin(), itemsList.end(), compareY ); // Expected Y coordinate for the next item (=minY) int position = (*itemsList.begin())->GetBoundingBox().Centre().y; @@ -297,7 +293,7 @@ int PLACEMENT_TOOL::DistributeVertically( const TOOL_EVENT& aEvent ) // Distance between items const int distance = ( maxY - position ) / ( itemsList.size() - 1 ); - for( BOARD_ITEM* item : itemsList ) + for( auto item : itemsList ) { int difference = position - item->GetBoundingBox().Centre().y; diff --git a/pcbnew/tools/point_editor.cpp b/pcbnew/tools/point_editor.cpp index 025d531b41..508e6ff608 100644 --- a/pcbnew/tools/point_editor.cpp +++ b/pcbnew/tools/point_editor.cpp @@ -249,7 +249,7 @@ int POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent ) KIGFX::VIEW_CONTROLS* controls = getViewControls(); KIGFX::VIEW* view = getView(); PCB_BASE_EDIT_FRAME* editFrame = getEditFrame(); - EDA_ITEM* item = selection.items.GetPickedItem( 0 ); + auto item = selection.Front(); m_editPoints = EDIT_POINTS_FACTORY::Make( item, getView()->GetGAL() ); @@ -295,7 +295,7 @@ int POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent ) { if( !modified ) { - commit.Stage( selection.items, UR_CHANGED ); + commit.StageItems( selection, CHT_MODIFY ); controls->ForceCursorPosition( false ); m_original = *m_editedPoint; // Save the original position @@ -851,7 +851,7 @@ bool POINT_EDITOR::addCornerCondition( const SELECTION& aSelection ) if( aSelection.Size() != 1 ) return false; - BOARD_ITEM* item = aSelection.Item( 0 ); + auto item = aSelection.Front(); // Works only for zones and line segments return item->Type() == PCB_ZONE_AREA_T || diff --git a/pcbnew/tools/selection_conditions.cpp b/pcbnew/tools/selection_conditions.cpp index c9b58b7d6f..3f2efcfb40 100644 --- a/pcbnew/tools/selection_conditions.cpp +++ b/pcbnew/tools/selection_conditions.cpp @@ -41,9 +41,9 @@ bool SELECTION_CONDITIONS::OnlyConnectedItems( const SELECTION& aSelection ) if( aSelection.Empty() ) return false; - for( int i = 0; i < aSelection.Size(); ++i ) + for ( const auto &item : aSelection ) { - KICAD_T type = aSelection.Item( i )->Type(); + auto type = item->Type(); if( type != PCB_PAD_T && type != PCB_VIA_T && type != PCB_TRACE_T && type != PCB_ZONE_T ) return false; @@ -114,12 +114,12 @@ bool SELECTION_CONDITIONS::sameNetFunc( const SELECTION& aSelection, bool aAllow int netcode = -1; // -1 stands for 'net code is not yet determined' - for( int i = 0; i < aSelection.Size(); ++i ) + for ( const auto& aitem : aSelection ) { int current_netcode = -1; const BOARD_CONNECTED_ITEM* item = - dynamic_cast( aSelection.Item( i ) ); + dynamic_cast( aitem ); if( item ) { @@ -161,13 +161,8 @@ bool SELECTION_CONDITIONS::sameLayerFunc( const SELECTION& aSelection ) LSET layerSet; layerSet.set(); - for( int i = 0; i < aSelection.Size(); ++i ) + for ( const auto& item : aSelection ) { - const BOARD_ITEM* item = dynamic_cast( aSelection.Item( i ) ); - - if( !item ) - return false; - layerSet &= item->GetLayerSet(); if( !layerSet.any() ) // there are no common layers left @@ -180,9 +175,9 @@ bool SELECTION_CONDITIONS::sameLayerFunc( const SELECTION& aSelection ) bool SELECTION_CONDITIONS::hasTypeFunc( const SELECTION& aSelection, KICAD_T aType ) { - for( int i = 0; i < aSelection.Size(); ++i ) + for ( const auto& item : aSelection ) { - if( aSelection.Item( i )->Type() == aType ) + if( item->Type() == aType ) return true; } @@ -195,9 +190,9 @@ bool SELECTION_CONDITIONS::onlyTypeFunc( const SELECTION& aSelection, KICAD_T aT if( aSelection.Empty() ) return false; - for( int i = 0; i < aSelection.Size(); ++i ) + for ( const auto& item : aSelection ) { - if( aSelection.Item( i )->Type() != aType ) + if( item->Type() != aType ) return false; } @@ -210,13 +205,13 @@ bool SELECTION_CONDITIONS::onlyTypesFunc( const SELECTION& aSelection, const std if( aSelection.Empty() ) return false; - for( int i = 0; i < aSelection.Size(); ++i ) + for ( const auto& item : aSelection ) { bool valid = false; for( std::vector::const_iterator it = aTypes.begin(); it != aTypes.end(); ++it ) { - if( aSelection.Item( i )->Type() == *it ) + if( item->Type() == *it ) { valid = true; break; @@ -236,14 +231,14 @@ bool SELECTION_CONDITIONS::onlyTypesFuncArr( const SELECTION& aSelection, const if( aSelection.Empty() ) return false; - for( int i = 0; i < aSelection.Size(); ++i ) + for ( const auto& item : aSelection ) { bool valid = false; const KICAD_T* type = aTypes; while( *type != EOT ) { - if( aSelection.Item( i )->Type() == *type ) + if( item->Type() == *type ) { valid = true; break; diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp index ba0b3585a0..c703ceeee3 100644 --- a/pcbnew/tools/selection_tool.cpp +++ b/pcbnew/tools/selection_tool.cpp @@ -80,7 +80,6 @@ SELECTION_TOOL::SELECTION_TOOL() : SELECTION_TOOL::~SELECTION_TOOL() { - delete m_selection.group; delete m_contextMenu; delete m_selectMenu; delete m_zoomMenu; @@ -90,8 +89,6 @@ SELECTION_TOOL::~SELECTION_TOOL() bool SELECTION_TOOL::Init() { - m_selection.group = new KIGFX::VIEW_GROUP; - m_selectMenu = new SELECT_MENU; m_selectMenu->SetTool( this ); @@ -129,7 +126,7 @@ void SELECTION_TOOL::Reset( RESET_REASON aReason ) // Remove pointers to the selected items from containers // without changing their properties (as they are already deleted // while a new board is loaded) - m_selection.clear(); + m_selection.Clear(); getView()->GetPainter()->GetSettings()->SetHighlight( false ); } else @@ -137,8 +134,8 @@ void SELECTION_TOOL::Reset( RESET_REASON aReason ) clearSelection(); // Reinsert the VIEW_GROUP, in case it was removed from the VIEW - getView()->Remove( m_selection.group ); - getView()->Add( m_selection.group ); + getView()->Remove( &m_selection ); + getView()->Add( &m_selection ); } @@ -301,24 +298,19 @@ int SELECTION_TOOL::Main( const TOOL_EVENT& aEvent ) } -const SELECTION& SELECTION_TOOL::GetSelection() +SELECTION& SELECTION_TOOL::GetSelection() { // The selected items list has been requested, so it is no longer preliminary m_preliminary = false; - // Filter out not modifiable items - for( int i = 0; i < m_selection.Size(); ) - { - BOARD_ITEM* item = m_selection.Item( i ); + auto items = m_selection.GetItems(); + // Filter out not modifiable items + for ( auto item : items ) + { if( !modifiable( item ) ) { - m_selection.items.RemovePicker( i ); - m_selection.group->Remove( item ); - } - else - { - ++i; + m_selection.Remove( item ); } } @@ -360,7 +352,7 @@ bool SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag ) GENERAL_COLLECTORS_GUIDE guide = m_frame->GetCollectorsGuide(); GENERAL_COLLECTOR collector; - collector.Collect( getModel(), + collector.Collect( board(), m_editModules ? GENERAL_COLLECTOR::ModuleItems : GENERAL_COLLECTOR::AllBoardItems, wxPoint( aWhere.x, aWhere.y ), guide ); @@ -485,7 +477,7 @@ bool SELECTION_TOOL::selectMultiple() } if( m_selection.Size() == 1 ) - m_frame->SetCurItem( m_selection.Item( 0 ) ); + m_frame->SetCurItem( m_selection.Front() ); else m_frame->SetCurItem( NULL ); @@ -530,10 +522,8 @@ SELECTION_LOCK_FLAGS SELECTION_TOOL::CheckLock() bool containsLocked = false; // Check if the selection contains locked items - for( int i = 0; i < m_selection.Size(); ++i ) + for ( const auto& item : m_selection ) { - BOARD_ITEM* item = m_selection.Item( i ); - switch( item->Type() ) { case PCB_MODULE_T: @@ -624,14 +614,14 @@ int SELECTION_TOOL::selectConnection( const TOOL_EVENT& aEvent ) if( !selectCursor( true ) ) return 0; - BOARD_CONNECTED_ITEM* item = m_selection.Item( 0 ); + auto item = m_selection.Front(); clearSelection(); if( item->Type() != PCB_TRACE_T && item->Type() != PCB_VIA_T ) return 0; int segmentCount; - TRACK* trackList = getModel()->MarkTrace( static_cast( item ), &segmentCount, + TRACK* trackList = board()->MarkTrace( static_cast( item ), &segmentCount, NULL, NULL, true ); if( segmentCount == 0 ) @@ -655,7 +645,7 @@ int SELECTION_TOOL::selectCopper( const TOOL_EVENT& aEvent ) if( !selectCursor( true ) ) return 0; - BOARD_CONNECTED_ITEM* item = m_selection.Item( 0 ); + auto item = static_cast ( m_selection.Front() ); clearSelection(); if( item->Type() != PCB_TRACE_T && item->Type() != PCB_VIA_T ) @@ -682,7 +672,10 @@ int SELECTION_TOOL::selectNet( const TOOL_EVENT& aEvent ) if( !selectCursor( true ) ) return 0; - BOARD_CONNECTED_ITEM* item = m_selection.Item( 0 ); + auto item = dynamic_cast ( m_selection.Front() ); + + if( !item ) + return 0; std::list itemsList; RN_DATA* ratsnest = getModel()->GetRatsnest(); @@ -752,19 +745,10 @@ void SELECTION_TOOL::clearSelection() if( m_selection.Empty() ) return; - KIGFX::VIEW_GROUP::const_iter it, it_end; + for ( auto item : m_selection ) + unselectVisually( item ); - // Restore the initial properties - for( it = m_selection.group->Begin(), it_end = m_selection.group->End(); it != it_end; ++it ) - { - BOARD_ITEM* item = static_cast( *it ); - - item->ViewHide( false ); - item->ClearSelected(); - item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ) ; - } - - m_selection.clear(); + m_selection.Clear(); m_frame->SetCurItem( NULL ); m_locked = true; @@ -904,8 +888,6 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const return false; } - BOARD* board = getModel(); - switch( aItem->Type() ) { case PCB_VIA_T: @@ -915,15 +897,15 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const static_cast( aItem )->LayerPair( &top, &bottom ); - return board->IsLayerVisible( top ) || board->IsLayerVisible( bottom ); + return board()->IsLayerVisible( top ) || board()->IsLayerVisible( bottom ); } break; case PCB_MODULE_T: - if( aItem->IsOnLayer( F_Cu ) && board->IsElementVisible( MOD_FR_VISIBLE ) ) + if( aItem->IsOnLayer( F_Cu ) && board()->IsElementVisible( MOD_FR_VISIBLE ) ) return !m_editModules; - if( aItem->IsOnLayer( B_Cu ) && board->IsElementVisible( MOD_BK_VISIBLE ) ) + if( aItem->IsOnLayer( B_Cu ) && board()->IsElementVisible( MOD_BK_VISIBLE ) ) return !m_editModules; return false; @@ -934,7 +916,7 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const if( m_multiple && !m_editModules ) return false; - return aItem->ViewIsVisible() && board->IsLayerVisible( aItem->GetLayer() ); + return aItem->ViewIsVisible() && board()->IsLayerVisible( aItem->GetLayer() ); case PCB_MODULE_EDGE_T: case PCB_PAD_T: @@ -959,7 +941,7 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const } // All other items are selected only if the layer on which they exist is visible - return board->IsLayerVisible( aItem->GetLayer() ); + return board()->IsLayerVisible( aItem->GetLayer() ); } @@ -975,27 +957,20 @@ bool SELECTION_TOOL::modifiable( const BOARD_ITEM* aItem ) const void SELECTION_TOOL::select( BOARD_ITEM* aItem ) { if( aItem->IsSelected() ) - return; - - // Modules are treated in a special way - when they are selected, we have to mark - // all the parts that make the module as selected - if( aItem->Type() == PCB_MODULE_T ) { - MODULE* module = static_cast( aItem ); - module->RunOnChildren( std::bind( &SELECTION_TOOL::selectVisually, this, _1 ) ); + return; } if( aItem->Type() == PCB_PAD_T ) { MODULE* module = static_cast( aItem->GetParent() ); - if( m_selection.items.FindItem( module ) >= 0 ) + if( m_selection.Contains( module ) ) return; } selectVisually( aItem ); - ITEM_PICKER picker( aItem ); - m_selection.items.PushItem( picker ); + m_selection.Add ( aItem ); if( m_selection.Size() == 1 ) { @@ -1015,19 +990,8 @@ void SELECTION_TOOL::unselect( BOARD_ITEM* aItem ) if( !aItem->IsSelected() ) return; - // Modules are treated in a special way - when they are selected, we have to - // unselect all the parts that make the module, not the module itself - if( aItem->Type() == PCB_MODULE_T ) - { - MODULE* module = static_cast( aItem ); - module->RunOnChildren( std::bind( &SELECTION_TOOL::unselectVisually, this, _1 ) ); - } - unselectVisually( aItem ); - - int itemIdx = m_selection.items.FindItem( aItem ); - if( itemIdx >= 0 ) - m_selection.items.RemovePicker( itemIdx ); + m_selection.Remove( aItem ); if( m_selection.Empty() ) { @@ -1039,22 +1003,41 @@ void SELECTION_TOOL::unselect( BOARD_ITEM* aItem ) void SELECTION_TOOL::selectVisually( BOARD_ITEM* aItem ) const { - m_selection.group->Add( aItem ); - // Hide the original item, so it is shown only on overlay aItem->ViewHide( true ); aItem->SetSelected(); + + // Modules are treated in a special way - when they are selected, we have to + // unselect all the parts that make the module, not the module itself + + if( aItem->Type() == PCB_MODULE_T ) + { + static_cast( aItem )->RunOnChildren( [] ( BOARD_ITEM *item ) { + item->ViewHide( true ); + item->SetSelected(); + }); + } } void SELECTION_TOOL::unselectVisually( BOARD_ITEM* aItem ) const { - m_selection.group->Remove( aItem ); - // Restore original item visibility aItem->ViewHide( false ); aItem->ClearSelected(); aItem->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + + // Modules are treated in a special way - when they are selected, we have to + // unselect all the parts that make the module, not the module itself + + if( aItem->Type() == PCB_MODULE_T ) + { + static_cast( aItem )->RunOnChildren( [] ( BOARD_ITEM *item ) { + item->ViewHide( false ); + item->ClearSelected(); + item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + }); + } } @@ -1064,9 +1047,8 @@ bool SELECTION_TOOL::selectionContains( const VECTOR2I& aPoint ) const VECTOR2D margin = getView()->ToWorld( VECTOR2D( GRIP_MARGIN, GRIP_MARGIN ), false ); // Check if the point is located within any of the currently selected items bounding boxes - for( unsigned int i = 0; i < m_selection.items.GetCount(); ++i ) + for( auto item : m_selection ) { - BOARD_ITEM* item = m_selection.Item( i ); BOX2I itemBox = item->ViewBBox(); itemBox.Inflate( margin.x, margin.y ); // Give some margin for gripping an item @@ -1382,10 +1364,8 @@ bool SELECTION_TOOL::SanitizeSelection() if( !m_editModules ) { - for( unsigned int i = 0; i < m_selection.items.GetCount(); ++i ) + for( auto item : m_selection ) { - BOARD_ITEM* item = m_selection.Item( i ); - if( item->Type() == PCB_PAD_T ) { MODULE* mod = static_cast( item->GetParent() ); @@ -1400,7 +1380,7 @@ bool SELECTION_TOOL::SanitizeSelection() } // case 2: multi-item selection contains both the module and its pads - remove the pads - if( mod && m_selection.items.FindItem( mod ) >= 0 ) + if( mod && m_selection.Contains( mod ) ) rejected.insert( item ); } } @@ -1430,8 +1410,7 @@ bool SELECTION_TOOL::SanitizeSelection() void SELECTION::clear() { - items.ClearItemsList(); - group->Clear(); + m_items.clear(); } @@ -1441,15 +1420,17 @@ VECTOR2I SELECTION::GetCenter() const if( Size() == 1 ) { - centre = Item( 0 )->GetCenter(); + centre = Front()->GetCenter(); } else { - EDA_RECT bbox = Item( 0 )->GetBoundingBox(); - for( unsigned int i = 1; i < items.GetCount(); ++i ) + EDA_RECT bbox = Front()->GetBoundingBox(); + auto i = m_items.begin(); + ++i; + + for( ; i != m_items.end(); ++i ) { - BOARD_ITEM* item = Item( i ); - bbox.Merge( item->GetBoundingBox() ); + bbox.Merge( (*i)->GetBoundingBox() ); } centre = bbox.Centre(); @@ -1462,3 +1443,25 @@ VECTOR2I SELECTION::GetCenter() const const TOOL_EVENT SELECTION_TOOL::SelectedEvent( TC_MESSAGE, TA_ACTION, "pcbnew.InteractiveSelection.selected" ); const TOOL_EVENT SELECTION_TOOL::UnselectedEvent( TC_MESSAGE, TA_ACTION, "pcbnew.InteractiveSelection.unselected" ); const TOOL_EVENT SELECTION_TOOL::ClearedEvent( TC_MESSAGE, TA_ACTION, "pcbnew.InteractiveSelection.cleared" ); + +SELECTION::SELECTION( KIGFX::VIEW *aView ) : + KIGFX::VIEW_GROUP ( aView ) +{} + +const KIGFX::VIEW_GROUP::ITEMS SELECTION::updateDrawList() const +{ + std::vector items; + + items.clear(); + for ( auto item : m_items ) + { + items.push_back( item ); + if( item->Type() == PCB_MODULE_T ) + { + MODULE* module = static_cast( item ); + module->RunOnChildren( [&] ( BOARD_ITEM *bitem ) { items.push_back(bitem); }); + } + } + + return items; +} diff --git a/pcbnew/tools/selection_tool.h b/pcbnew/tools/selection_tool.h index da3b9c61c1..da2a4bb51c 100644 --- a/pcbnew/tools/selection_tool.h +++ b/pcbnew/tools/selection_tool.h @@ -26,10 +26,11 @@ #ifndef __SELECTION_TOOL_H #define __SELECTION_TOOL_H +#include + #include #include #include -#include #include "selection_conditions.h" #include "conditional_menu.h" @@ -44,53 +45,109 @@ class GRID_MENU; namespace KIGFX { -class VIEW_GROUP; + class GAL; } -struct SELECTION +struct SELECTION : public KIGFX::VIEW_GROUP { +private: /// Set of selected items - PICKED_ITEMS_LIST items; + std::set m_items; - /// VIEW_GROUP that holds currently selected items - KIGFX::VIEW_GROUP* group; +public: + using ITER = std::set::iterator; + using CITER = std::set::const_iterator; + + SELECTION( KIGFX::VIEW *aView = nullptr ); + + ITER begin() { return m_items.begin(); } + ITER end() { return m_items.end(); } + CITER begin() const { return m_items.cbegin(); } + CITER end() const { return m_items.cend(); } + + virtual void Add( BOARD_ITEM *aItem ) + { + m_items.insert (aItem); + } + + virtual void Remove( BOARD_ITEM *aItem ) + { + m_items.erase (aItem); + } + + virtual void Clear() override + { + m_items.clear(); + } + + virtual unsigned int GetSize() const override + { + return m_items.size(); + } + + virtual KIGFX::VIEW_ITEM *GetItem( unsigned int idx ) const override + { + auto iter = m_items.begin(); + while(idx--) + ++iter; + + return *iter; + } + + bool Contains( BOARD_ITEM *aItem ) const + { + return m_items.find (aItem) != m_items.end(); + } /// Checks if there is anything selected bool Empty() const { - return ( items.GetCount() == 0 ); + return ( m_items.size() == 0 ); } /// Returns the number of selected parts int Size() const { - return items.GetCount(); + return m_items.size(); } - /// Alias to make code shorter and clearer - template - T* Item( unsigned int aIndex ) const + const std::set GetItems() const { - return static_cast( items.GetPickedItem( aIndex ) ); + return m_items; } /// Returns the center point of the selection area bounding box. VECTOR2I GetCenter() const; - /// Runs a function on all selected items. - template - void ForAll( std::function aFunction ) const + BOARD_ITEM *operator[] ( const int index ) const { - for( unsigned int i = 0; i < items.GetCount(); ++i ) - aFunction( Item( i ) ); + if ( index < 0 || (unsigned int) index >= m_items.size() ) + return nullptr; + + return (* m_items.begin() + index ); } + BOARD_ITEM *Front() const + { + if ( !m_items.size() ) + return nullptr; + + return *m_items.begin(); + } + + std::set& Items() + { + return m_items; + } + + virtual const VIEW_GROUP::ITEMS updateDrawList() const override; + private: + + /// Clears both the VIEW_GROUP and set of selected items. Please note that it does not /// change properties of selected items (e.g. selection flag). void clear(); - - friend class SELECTION_TOOL; }; enum SELECTION_LOCK_FLAGS @@ -135,7 +192,7 @@ public: * * Returns the set of currently selected items. */ - const SELECTION& GetSelection(); + SELECTION& GetSelection(); inline CONDITIONAL_MENU& GetMenu() { 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 f975c6a553..e5f39cd6c1 100644 --- a/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp +++ b/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp @@ -504,7 +504,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList_NG( BOARD* aPcb ) if( g_DumpZonesWhenFilling ) dumper->Write ( &th_fractured, "th_fractured" ); - m_FilledPolysList = th_fractured; + m_FilledPolysList = th_fractured; if( GetNetCode() > 0 ) TestForCopperIslandAndRemoveInsulatedIslands( aPcb );