ADDED: Expand selection in context menu

Break out the context menu with heuristically limited choices being
appended to the main list rather than re-selecting

Fixes https://gitlab.com/kicad/code/kicad/issues/4799
This commit is contained in:
Seth Hillbrand 2020-07-06 21:51:12 -07:00
parent 84b02e51f1
commit 7cea4b23f1
5 changed files with 281 additions and 183 deletions

View File

@ -525,7 +525,7 @@ bool EE_SELECTION_TOOL::SelectPoint( const VECTOR2I& aWhere, const KICAD_T* aFil
// If still more than one item we're going to have to ask the user.
if( collector.GetCount() > 1 )
{
collector.m_MenuTitle = _( "Clarify Selection" );
collector.m_MenuTitle = wxEmptyString;
// Must call selectionMenu via RunAction() to avoid event-loop contention
m_toolMgr->RunAction( EE_ACTIONS::selectionMenu, true, &collector );
@ -603,7 +603,7 @@ void EE_SELECTION_TOOL::GuessSelectionCandidates( EE_COLLECTOR& collector, const
EDA_ITEM* item = collector[ i ];
if( !item->HitTest( (wxPoint) aPos, 0 ) )
collector.Remove( item );
collector.Transfer( item );
}
}
@ -614,7 +614,7 @@ void EE_SELECTION_TOOL::GuessSelectionCandidates( EE_COLLECTOR& collector, const
EDA_ITEM* other = collector[ ( i + 1 ) % 2 ];
if( item->Type() != SCH_SHEET_T && other->Type() == SCH_SHEET_T )
collector.Remove( other );
collector.Transfer( other );
}
// Prefer a symbol to a pin or the opposite, when both a symbol and a pin are selected
@ -631,9 +631,9 @@ void EE_SELECTION_TOOL::GuessSelectionCandidates( EE_COLLECTOR& collector, const
if( item->Type() == SCH_COMPONENT_T && other->Type() == SCH_PIN_T )
{
if( !m_isLibEdit && m_frame->eeconfig()->m_Selection.select_pin_selects_symbol )
collector.Remove( other );
collector.Transfer( other );
else
collector.Remove( item );
collector.Transfer( item );
}
}
@ -644,7 +644,7 @@ void EE_SELECTION_TOOL::GuessSelectionCandidates( EE_COLLECTOR& collector, const
EDA_ITEM* other = collector[ ( i + 1 ) % 2 ];
if( item->Type() == SCH_FIELD_T && other->Type() == SCH_COMPONENT_T )
collector.Remove( other );
collector.Transfer( other );
}
// No need for multiple wires at a single point; if there's a junction select that;
@ -665,9 +665,9 @@ void EE_SELECTION_TOOL::GuessSelectionCandidates( EE_COLLECTOR& collector, const
for( int j = collector.GetCount() - 1; j >= 0; --j )
{
if( junction && collector[ j ]->Type() != SCH_JUNCTION_T )
collector.Remove( j );
collector.Transfer( j );
else if( !junction && j > 0 )
collector.Remove( j );
collector.Transfer( j );
}
}
}
@ -1102,10 +1102,19 @@ int EE_SELECTION_TOOL::SelectionMenu( const TOOL_EVENT& aEvent )
bool EE_SELECTION_TOOL::doSelectionMenu( EE_COLLECTOR* aCollector )
{
EDA_ITEM* current = nullptr;
ACTION_MENU menu( true );
bool selectAll = false;
bool expandSelection = false;
int limit = std::min( MAX_SELECT_ITEM_IDS, aCollector->GetCount() );
do
{
/// The user has requested the full, non-limited list of selection items
if( expandSelection )
aCollector->Combine();
expandSelection = false;
int limit = std::min( 9, aCollector->GetCount() );
ACTION_MENU menu( true );
for( int i = 0; i < limit; ++i )
{
@ -1120,11 +1129,20 @@ bool EE_SELECTION_TOOL::doSelectionMenu( EE_COLLECTOR* aCollector )
menu.AppendSeparator();
menu.Add( _( "Select &All\tA" ), limit + 1, net_highlight_schematic_xpm );
if( aCollector->m_MenuTitle.Length() )
menu.SetTitle( aCollector->m_MenuTitle );
if( !expandSelection && aCollector->HasAdditionalItems() )
menu.Add( _( "&Expand Selection\tE" ), limit + 2, nullptr );
if( aCollector->m_MenuTitle.Length() )
{
menu.SetTitle( aCollector->m_MenuTitle );
menu.SetIcon( info_xpm );
menu.DisplayTitle( true );
}
else
{
menu.DisplayTitle( false );
}
SetContextMenu( &menu, CMENU_NOW );
while( TOOL_EVENT* evt = Wait() )
@ -1195,13 +1213,16 @@ bool EE_SELECTION_TOOL::doSelectionMenu( EE_COLLECTOR* aCollector )
selectAll = false;
current = nullptr;
}
}
else if( evt->Action() == TA_CHOICE_MENU_CLOSED )
{
break;
}
getView()->UpdateItems();
m_frame->GetCanvas()->Refresh();
}
} while( expandSelection );
if( selectAll )
return true;

View File

@ -55,7 +55,8 @@ class EDA_ITEM;
class COLLECTOR
{
protected:
std::vector<EDA_ITEM*> m_List;
std::vector<EDA_ITEM*> m_List; // Primary list of most likely items
std::vector<EDA_ITEM*> m_BackupList; // Secondary list with items removed by heuristics
const KICAD_T* m_ScanTypes;
INSPECTOR_FUNC m_inspector;
@ -148,6 +149,51 @@ public:
}
}
/**
* Test if the collector has heuristic backup items
* @return true if Combine() can run to bring secondary items into the list
*/
bool HasAdditionalItems()
{
return !m_BackupList.empty();
}
/**
* Re-combines the backup list into the main list of the collector
*/
void Combine()
{
std::copy( m_BackupList.begin(), m_BackupList.end(), std::back_inserter( m_List ) );
m_BackupList.clear();
}
/**
* Moves the item at \a aIndex (first position is 0) to the backup list
* @param aIndex The index into the list.
*/
void Transfer( int aIndex )
{
m_BackupList.push_back( m_List[aIndex] );
m_List.erase( m_List.begin() + aIndex );
}
/**
* Moves the item aItem (if exists in the collector) to the backup list
* @param aItem the item to be moved.
*/
void Transfer( EDA_ITEM* aItem )
{
for( size_t i = 0; i < m_List.size(); i++ )
{
if( m_List[i] == aItem )
{
m_List.erase( m_List.begin() + i );
m_BackupList.push_back( aItem );
return;
}
}
}
/**
* Function operator[int]
* is used for read only access and returns the object at \a aIndex.

View File

@ -210,6 +210,9 @@ protected:
///> Checks if any of submenus contains a TOOL_ACTION with a specific ID.
OPT_TOOL_EVENT findToolAction( int aId );
bool m_isForcedPosition;
wxPoint m_forcedPosition;
bool m_dirty; // Menu requires update before display
bool m_titleDisplayed;

View File

@ -280,7 +280,7 @@ void PL_SELECTION_TOOL::guessSelectionCandidates( COLLECTOR& collector, const VE
EDA_ITEM* other = collector[ ( i + 1 ) % 2 ];
if( item->HitTest( (wxPoint) aPos, 0 ) && !other->HitTest( (wxPoint) aPos, 0 ) )
collector.Remove( other );
collector.Transfer( other );
}
}
@ -585,7 +585,9 @@ bool PL_SELECTION_TOOL::doSelectionMenu( COLLECTOR* aCollector )
current = ( *aCollector )[*id - 1];
else
current = NULL;
}
else if( evt->Action() == TA_CHOICE_MENU_CLOSED )
{
break;
}

View File

@ -461,7 +461,7 @@ bool SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag,
if( aOnDrag )
Wait( TOOL_EVENT( TC_ANY, TA_MOUSE_UP, BUT_LEFT ) );
if( !doSelectionMenu( &collector, _( "Clarify Selection" ) ) )
if( !doSelectionMenu( &collector, wxEmptyString ) )
{
if( aSelectionCancelledFlag )
*aSelectionCancelledFlag = true;
@ -1487,13 +1487,22 @@ bool SELECTION_TOOL::doSelectionMenu( GENERAL_COLLECTOR* aCollector, const wxStr
{
BOARD_ITEM* current = nullptr;
PCBNEW_SELECTION highlightGroup;
ACTION_MENU menu( true );
bool selectAll = false;
bool expandSelection = false;
highlightGroup.SetLayer( LAYER_SELECT_OVERLAY );
getView()->Add( &highlightGroup );
do
{
/// The user has requested the full, non-limited list of selection items
if( expandSelection )
aCollector->Combine();
expandSelection = false;
int limit = std::min( 9, aCollector->GetCount() );
ACTION_MENU menu( true );
for( int i = 0; i < limit; ++i )
{
@ -1508,11 +1517,18 @@ bool SELECTION_TOOL::doSelectionMenu( GENERAL_COLLECTOR* aCollector, const wxStr
menu.AppendSeparator();
menu.Add( _( "Select &All\tA" ), limit + 1, net_highlight_xpm );
if( aTitle.Length() )
menu.SetTitle( aTitle );
if( !expandSelection && aCollector->HasAdditionalItems() )
menu.Add( _( "&Expand Selection\tE" ), limit + 2, nullptr );
if( aTitle.Length() )
{
menu.SetTitle( aTitle );
menu.SetIcon( info_xpm );
menu.DisplayTitle( true );
}
else
menu.DisplayTitle( false );
SetContextMenu( &menu, CMENU_NOW );
while( TOOL_EVENT* evt = Wait() )
@ -1566,6 +1582,12 @@ bool SELECTION_TOOL::doSelectionMenu( GENERAL_COLLECTOR* aCollector, const wxStr
selectAll = true;
current = nullptr;
}
else if( id == limit + 2 )
{
expandSelection = true;
selectAll = false;
current = nullptr;
}
// User has selected an item, so this one will be returned
else if( id && ( *id > 0 ) && ( *id <= limit ) )
{
@ -1577,10 +1599,14 @@ bool SELECTION_TOOL::doSelectionMenu( GENERAL_COLLECTOR* aCollector, const wxStr
selectAll = false;
current = nullptr;
}
}
else if( evt->Action() == TA_CHOICE_MENU_CLOSED )
{
break;
}
}
} while( expandSelection );
getView()->Remove( &highlightGroup );
if( selectAll )
@ -2420,7 +2446,7 @@ void SELECTION_TOOL::GuessSelectionCandidates( GENERAL_COLLECTOR& aCollector,
{
for( BOARD_ITEM* item : rejected )
{
aCollector.Remove( item );
aCollector.Transfer( item );
}
}
}