Allow selectConnection/Copper/Net on multiple items

The previous behaviour was to act on only the first item in the
selection. The new behaviour is to act on every eligible item (in this
case, tracks and vias).
This commit is contained in:
John Beard 2017-02-04 14:44:17 +08:00 committed by Maciej Suminski
parent 112c10fbd9
commit 0cd121049f
2 changed files with 97 additions and 47 deletions

View File

@ -92,8 +92,9 @@ bool SELECTION_TOOL::Init()
{
using S_C = SELECTION_CONDITIONS;
auto showSelectMenuFunctor = ( S_C::OnlyType( PCB_VIA_T ) || S_C::OnlyType( PCB_TRACE_T ) )
&& S_C::Count( 1 );
// can show the select menu as long as there is something the
// subitems can be run on
auto showSelectMenuFunctor = ( S_C::HasType( PCB_VIA_T ) || S_C::HasType( PCB_TRACE_T ) );
auto selectMenu = std::make_shared<SELECT_MENU>();
selectMenu->SetTool( this );
@ -571,29 +572,24 @@ int SELECTION_TOOL::UnselectItem( const TOOL_EVENT& aEvent )
int SELECTION_TOOL::selectConnection( const TOOL_EVENT& aEvent )
{
if( !selectCursor( true ) )
if( !selectCursor() )
return 0;
auto item = m_selection.Front();
clearSelection();
// copy the selection, since we're going to iterate and modify
auto selection = m_selection.GetItems();
if( item->Type() != PCB_TRACE_T && item->Type() != PCB_VIA_T )
return 0;
int segmentCount;
TRACK* trackList = board()->MarkTrace( static_cast<TRACK*>( item ), &segmentCount,
NULL, NULL, true );
if( segmentCount == 0 )
return 0;
for( int i = 0; i < segmentCount; ++i )
for( auto item : selection )
{
select( trackList );
trackList = trackList->Next();
// only TRACK items can be checked for trivial connections
if( item->Type() == PCB_TRACE_T || item->Type() == PCB_VIA_T )
{
TRACK& trackItem = static_cast<TRACK&>( *item );
selectAllItemsConnectedToTrack( trackItem );
}
}
// Inform other potentially interested tools
if( m_selection.Size() > 0 )
m_toolMgr->ProcessEvent( SelectedEvent );
return 0;
@ -602,53 +598,89 @@ int SELECTION_TOOL::selectConnection( const TOOL_EVENT& aEvent )
int SELECTION_TOOL::selectCopper( const TOOL_EVENT& aEvent )
{
if( !selectCursor( true ) )
if( !selectCursor( ) )
return 0;
auto item = static_cast<BOARD_CONNECTED_ITEM*> ( m_selection.Front() );
clearSelection();
// copy the selection, since we're going to iterate and modify
auto selection = m_selection.GetItems();
if( item->Type() != PCB_TRACE_T && item->Type() != PCB_VIA_T )
return 0;
for( auto item : selection )
{
// only connected items can be traversed in the ratsnest
if ( item->IsConnected() )
{
auto& connItem = static_cast<BOARD_CONNECTED_ITEM&>( *item );
std::list<BOARD_CONNECTED_ITEM*> itemsList;
RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest();
ratsnest->GetConnectedItems( item, itemsList, (RN_ITEM_TYPE)( RN_TRACKS | RN_VIAS ) );
for( BOARD_CONNECTED_ITEM* i : itemsList )
select( i );
selectAllItemsConnectedToItem( connItem );
}
}
// Inform other potentially interested tools
if( itemsList.size() > 0 )
if( m_selection.Size() > 0 )
m_toolMgr->ProcessEvent( SelectedEvent );
return 0;
}
int SELECTION_TOOL::selectNet( const TOOL_EVENT& aEvent )
void SELECTION_TOOL::selectAllItemsConnectedToTrack( TRACK& aSourceTrack )
{
if( !selectCursor( true ) )
return 0;
int segmentCount;
TRACK* trackList = board()->MarkTrace( &aSourceTrack, &segmentCount,
nullptr, nullptr, true );
auto item = dynamic_cast<BOARD_CONNECTED_ITEM*> ( m_selection.Front() );
for( int i = 0; i < segmentCount; ++i )
{
select( trackList );
trackList = trackList->Next();
}
}
if( !item )
return 0;
std::list<BOARD_CONNECTED_ITEM*> itemsList;
void SELECTION_TOOL::selectAllItemsConnectedToItem( BOARD_CONNECTED_ITEM& aSourceItem )
{
RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest();
int netCode = item->GetNetCode();
clearSelection();
ratsnest->GetNetItems( netCode, itemsList, (RN_ITEM_TYPE)( RN_TRACKS | RN_VIAS ) );
std::list<BOARD_CONNECTED_ITEM*> itemsList;
ratsnest->GetConnectedItems( &aSourceItem, itemsList, (RN_ITEM_TYPE)( RN_TRACKS | RN_VIAS ) );
for( BOARD_CONNECTED_ITEM* i : itemsList )
select( i );
}
void SELECTION_TOOL::selectAllItemsOnNet( int aNetCode )
{
RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest();
std::list<BOARD_CONNECTED_ITEM*> itemsList;
ratsnest->GetNetItems( aNetCode, itemsList, (RN_ITEM_TYPE)( RN_TRACKS | RN_VIAS ) );
for( BOARD_CONNECTED_ITEM* i : itemsList )
select( i );
}
int SELECTION_TOOL::selectNet( const TOOL_EVENT& aEvent )
{
if( !selectCursor() )
return 0;
// copy the selection, since we're going to iterate and modify
auto selection = m_selection.GetItems();
for( auto item : selection )
{
// only connected items get a net code
if( item->IsConnected() )
{
auto& connItem = static_cast<BOARD_CONNECTED_ITEM&>( *item );
selectAllItemsOnNet( connItem.GetNetCode() );
}
}
// Inform other potentially interested tools
if( itemsList.size() > 0 )
if( m_selection.Size() > 0 )
m_toolMgr->ProcessEvent( SelectedEvent );
return 0;

View File

@ -254,15 +254,33 @@ private:
*/
bool selectMultiple();
///> Selects a trivial connection (between two junctions).
///> Selects a trivial connection (between two junctions) of items in selection
int selectConnection( const TOOL_EVENT& aEvent );
///> Selects a continuous copper connection.
///> Selects items with a continuous copper connection to items in selection
int selectCopper( const TOOL_EVENT& aEvent );
///> Selects all copper connections belonging to a single net.
/**
* Selects all copper connections belonging to the same net(s) as the
* items in the selection
*/
int selectNet( const TOOL_EVENT& aEvent );
/**
* Selects all items connected by copper tracks to the given TRACK
*/
void selectAllItemsConnectedToTrack( TRACK& aSourceTrack );
/**
* Selects all items connected (by copper) to the given item
*/
void selectAllItemsConnectedToItem( BOARD_CONNECTED_ITEM& aSourceItem );
/**
* Selects all items with the given net code
*/
void selectAllItemsOnNet( int aNetCode );
///> Find dialog callback.
void findCallback( BOARD_ITEM* aItem );