Share more code between selection tools.

This commit is contained in:
Jeff Young 2022-07-11 19:03:45 -06:00
parent c243c7e1b8
commit 57acce9e55
12 changed files with 567 additions and 1312 deletions

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2021 KiCad Developers, see AUTHORS.TXT for contributors.
* Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.TXT for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -21,10 +21,18 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <bitmaps.h>
#include <widgets/ui_common.h>
#include <collector.h>
#include <tool/tool_manager.h>
#include <tool/actions.h>
#include <tool/selection_tool.h>
#include <view/view.h>
#include <eda_draw_frame.h>
SELECTION_TOOL::SELECTION_TOOL() :
SELECTION_TOOL::SELECTION_TOOL( const std::string& aName ) :
TOOL_INTERACTIVE( aName ),
m_additive( false ),
m_subtractive( false ),
m_exclusive_or( false ),
@ -73,3 +81,325 @@ void SELECTION_TOOL::setModifiersState( bool aShiftState, bool aCtrlState, bool
#endif
}
int SELECTION_TOOL::UpdateMenu( const TOOL_EVENT& aEvent )
{
ACTION_MENU* actionMenu = aEvent.Parameter<ACTION_MENU*>();
CONDITIONAL_MENU* conditionalMenu = dynamic_cast<CONDITIONAL_MENU*>( actionMenu );
if( conditionalMenu )
conditionalMenu->Evaluate( selection() );
if( actionMenu )
actionMenu->UpdateAll();
return 0;
}
int SELECTION_TOOL::AddItemToSel( const TOOL_EVENT& aEvent )
{
AddItemToSel( aEvent.Parameter<EDA_ITEM*>() );
selection().SetIsHover( false );
return 0;
}
void SELECTION_TOOL::AddItemToSel( EDA_ITEM* aItem, bool aQuietMode )
{
if( aItem )
{
select( aItem );
// Inform other potentially interested tools
if( !aQuietMode )
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
}
}
int SELECTION_TOOL::AddItemsToSel( const TOOL_EVENT& aEvent )
{
AddItemsToSel( aEvent.Parameter<EDA_ITEMS*>(), false );
selection().SetIsHover( false );
return 0;
}
void SELECTION_TOOL::AddItemsToSel( EDA_ITEMS* aList, bool aQuietMode )
{
if( aList )
{
for( EDA_ITEM* item : *aList )
select( item );
// Inform other potentially interested tools
if( !aQuietMode )
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
}
}
int SELECTION_TOOL::RemoveItemFromSel( const TOOL_EVENT& aEvent )
{
RemoveItemFromSel( aEvent.Parameter<EDA_ITEM*>() );
selection().SetIsHover( false );
return 0;
}
void SELECTION_TOOL::RemoveItemFromSel( EDA_ITEM* aItem, bool aQuietMode )
{
if( aItem )
{
unselect( aItem );
// Inform other potentially interested tools
if( !aQuietMode )
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
}
}
int SELECTION_TOOL::RemoveItemsFromSel( const TOOL_EVENT& aEvent )
{
RemoveItemsFromSel( aEvent.Parameter<EDA_ITEMS*>(), false );
selection().SetIsHover( false );
return 0;
}
void SELECTION_TOOL::RemoveItemsFromSel( EDA_ITEMS* aList, bool aQuietMode )
{
if( aList )
{
for( EDA_ITEM* item : *aList )
unselect( item );
// Inform other potentially interested tools
if( !aQuietMode )
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
}
}
void SELECTION_TOOL::RemoveItemsFromSel( std::vector<KIID>* aList, bool aQuietMode )
{
EDA_ITEMS removeItems;
for( EDA_ITEM* item : selection() )
{
if( alg::contains( *aList, item->m_Uuid ) )
removeItems.push_back( item );
}
RemoveItemsFromSel( &removeItems, aQuietMode );
}
void SELECTION_TOOL::BrightenItem( EDA_ITEM* aItem )
{
highlight( aItem, BRIGHTENED );
}
void SELECTION_TOOL::UnbrightenItem( EDA_ITEM* aItem )
{
unhighlight( aItem, BRIGHTENED );
}
void SELECTION_TOOL::onDisambiguationExpire( wxTimerEvent& aEvent )
{
// If there is a multiple selection then it's more likely that we're seeing a paused drag
// than a long-click.
if( selection().GetSize() >= 2 )
return;
m_toolMgr->ProcessEvent( EVENTS::DisambiguatePoint );
}
int SELECTION_TOOL::SelectionMenu( const TOOL_EVENT& aEvent )
{
COLLECTOR* collector = aEvent.Parameter<COLLECTOR*>();
if( !doSelectionMenu( collector ) )
collector->m_MenuCancelled = true;
return 0;
}
bool SELECTION_TOOL::doSelectionMenu( COLLECTOR* aCollector )
{
EDA_UNITS userUnits = getEditFrame<EDA_DRAW_FRAME>()->GetUserUnits();
EDA_ITEM* current = nullptr;
SELECTION highlightGroup;
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( 100, aCollector->GetCount() );
ACTION_MENU menu( true );
for( int i = 0; i < limit; ++i )
{
EDA_ITEM* item = ( *aCollector )[i];
wxString menuText;
if( i < 9 )
{
#ifdef __WXMAC__
menuText = wxString::Format( "%s\t%d",
item->GetSelectMenuText( userUnits ),
i + 1 );
#else
menuText = wxString::Format( "&%d %s\t%d",
i + 1,
item->GetSelectMenuText( userUnits ),
i + 1 );
#endif
}
else
{
menuText = item->GetSelectMenuText( userUnits );
}
menu.Add( menuText, i + 1, item->GetMenuImage() );
}
menu.AppendSeparator();
menu.Add( _( "Select &All\tA" ), limit + 1, BITMAPS::INVALID_BITMAP );
if( !expandSelection && aCollector->HasAdditionalItems() )
menu.Add( _( "&Expand Selection\tE" ), limit + 2, BITMAPS::INVALID_BITMAP );
if( aCollector->m_MenuTitle.Length() )
{
menu.SetTitle( aCollector->m_MenuTitle );
menu.SetIcon( BITMAPS::info );
menu.DisplayTitle( true );
}
else
{
menu.DisplayTitle( false );
}
SetContextMenu( &menu, CMENU_NOW );
while( TOOL_EVENT* evt = Wait() )
{
if( evt->Action() == TA_CHOICE_MENU_UPDATE )
{
if( selectAll )
{
for( int i = 0; i < aCollector->GetCount(); ++i )
unhighlight( ( *aCollector )[i], BRIGHTENED, &highlightGroup );
}
else if( current )
{
unhighlight( current, BRIGHTENED, &highlightGroup );
}
int id = *evt->GetCommandId();
// User has pointed an item, so show it in a different way
if( id > 0 && id <= limit )
{
current = ( *aCollector )[id - 1];
highlight( current, BRIGHTENED, &highlightGroup );
}
else
{
current = nullptr;
}
// User has pointed on the "Select All" option
if( id == limit + 1 )
{
for( int i = 0; i < aCollector->GetCount(); ++i )
highlight( ( *aCollector )[i], BRIGHTENED, &highlightGroup );
selectAll = true;
}
else
{
selectAll = false;
}
}
else if( evt->Action() == TA_CHOICE_MENU_CHOICE )
{
if( selectAll )
{
for( int i = 0; i < aCollector->GetCount(); ++i )
unhighlight( ( *aCollector )[i], BRIGHTENED, &highlightGroup );
}
else if( current )
{
unhighlight( current, BRIGHTENED, &highlightGroup );
}
OPT<int> id = evt->GetCommandId();
// User has selected the "Select All" option
if( id == limit + 1 )
{
selectAll = true;
current = nullptr;
}
// User has selected the "Expand Selection" option
else if( id == limit + 2 )
{
selectAll = false;
current = nullptr;
expandSelection = true;
}
// User has selected an item, so this one will be returned
else if( id && ( *id > 0 ) && ( *id <= limit ) )
{
selectAll = false;
current = ( *aCollector )[*id - 1];
}
// User has cancelled the menu (either by <esc> or clicking out of it)
else
{
selectAll = false;
current = nullptr;
}
}
else if( evt->Action() == TA_CHOICE_MENU_CLOSED )
{
break;
}
}
} while( expandSelection );
getView()->Remove( &highlightGroup );
if( selectAll )
{
return true;
}
else if( current )
{
aCollector->Empty();
aCollector->Append( current );
return true;
}
return false;
}

View File

@ -22,14 +22,13 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <bitmaps.h>
#include <core/typeinfo.h>
#include <core/kicad_algo.h>
#include <geometry/shape_compound.h>
#include <ee_actions.h>
#include <ee_collectors.h>
#include <ee_selection_tool.h>
#include <eeschema_id.h> // For MAX_SELECT_ITEM_IDS
#include <eeschema_id.h>
#include <symbol_edit_frame.h>
#include <lib_item.h>
#include <symbol_viewer_frame.h>
@ -62,6 +61,7 @@
#include <view/view_controls.h>
#include <wx/log.h>
SELECTION_CONDITION EE_CONDITIONS::SingleSymbol = []( const SELECTION& aSel )
{
if( aSel.GetSize() == 1 )
@ -123,7 +123,7 @@ SELECTION_CONDITION EE_CONDITIONS::SingleNonExcludedMarker = []( const SELECTION
EE_SELECTION_TOOL::EE_SELECTION_TOOL() :
TOOL_INTERACTIVE( "eeschema.InteractiveSelection" ),
SELECTION_TOOL( "eeschema.InteractiveSelection" ),
m_frame( nullptr ),
m_nonModifiedCursor( KICURSOR::ARROW ),
m_isSymbolEditor( false ),
@ -288,7 +288,9 @@ void EE_SELECTION_TOOL::Reset( RESET_REASON aReason )
m_convert = symbolEditFrame->GetConvert();
}
else
{
m_isSymbolViewer = symbolViewerFrame != nullptr;
}
}
else
{
@ -302,21 +304,6 @@ void EE_SELECTION_TOOL::Reset( RESET_REASON aReason )
}
int EE_SELECTION_TOOL::UpdateMenu( const TOOL_EVENT& aEvent )
{
ACTION_MENU* actionMenu = aEvent.Parameter<ACTION_MENU*>();
CONDITIONAL_MENU* conditionalMenu = dynamic_cast<CONDITIONAL_MENU*>( actionMenu );
if( conditionalMenu )
conditionalMenu->Evaluate( m_selection );
if( actionMenu )
actionMenu->UpdateAll();
return 0;
}
const KICAD_T movableSymbolItems[] =
{
LIB_SHAPE_T,
@ -768,13 +755,6 @@ int EE_SELECTION_TOOL::disambiguateCursor( const TOOL_EVENT& aEvent )
}
void EE_SELECTION_TOOL::onDisambiguationExpire( wxTimerEvent& aEvent )
{
if( m_selection.GetSize() < 2 )
m_toolMgr->ProcessEvent( EVENTS::DisambiguatePoint );
}
void EE_SELECTION_TOOL::OnIdle( wxIdleEvent& aEvent )
{
if( m_frame->ToolStackIsEmpty() && !m_multiple )
@ -847,9 +827,7 @@ void EE_SELECTION_TOOL::narrowSelection( EE_COLLECTOR& collector, const VECTOR2I
// Apply some ugly heuristics to avoid disambiguation menus whenever possible
if( collector.GetCount() > 1 && !m_skip_heuristics )
{
GuessSelectionCandidates( collector, aWhere );
}
}
@ -908,6 +886,7 @@ bool EE_SELECTION_TOOL::selectPoint( EE_COLLECTOR& aCollector, const VECTOR2I& a
if( aSubtract || ( aExclusiveOr && aCollector[i]->IsSelected() ) )
{
aCollector[i]->ClearFlags( flags );
if( !aCollector[i]->HasFlag( STARTPOINT ) && !aCollector[i]->HasFlag( ENDPOINT ) )
{
unselect( aCollector[i] );
@ -1325,6 +1304,7 @@ bool EE_SELECTION_TOOL::selectMultiple()
if( m_subtractive || ( m_exclusive_or && aItem->IsSelected() ) )
{
aItem->ClearFlags( flags );
if( !aItem->HasFlag( STARTPOINT ) && !aItem->HasFlag( ENDPOINT ) )
{
unselect( aItem );
@ -1487,118 +1467,6 @@ int EE_SELECTION_TOOL::SelectConnection( const TOOL_EVENT& aEvent )
}
int EE_SELECTION_TOOL::AddItemToSel( const TOOL_EVENT& aEvent )
{
AddItemToSel( aEvent.Parameter<EDA_ITEM*>() );
m_selection.SetIsHover( false );
return 0;
}
void EE_SELECTION_TOOL::AddItemToSel( EDA_ITEM* aItem, bool aQuietMode )
{
if( aItem )
{
select( aItem );
// Inform other potentially interested tools
if( !aQuietMode )
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
}
}
int EE_SELECTION_TOOL::AddItemsToSel( const TOOL_EVENT& aEvent )
{
AddItemsToSel( aEvent.Parameter<EDA_ITEMS*>(), false );
m_selection.SetIsHover( false );
return 0;
}
void EE_SELECTION_TOOL::AddItemsToSel( EDA_ITEMS* aList, bool aQuietMode )
{
if( aList )
{
for( EDA_ITEM* item : *aList )
select( item );
// Inform other potentially interested tools
if( !aQuietMode )
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
}
}
int EE_SELECTION_TOOL::RemoveItemFromSel( const TOOL_EVENT& aEvent )
{
RemoveItemFromSel( aEvent.Parameter<EDA_ITEM*>() );
m_selection.SetIsHover( false );
return 0;
}
void EE_SELECTION_TOOL::RemoveItemFromSel( EDA_ITEM* aItem, bool aQuietMode )
{
if( aItem )
{
unselect( aItem );
// Inform other potentially interested tools
if( !aQuietMode )
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
}
}
int EE_SELECTION_TOOL::RemoveItemsFromSel( const TOOL_EVENT& aEvent )
{
RemoveItemsFromSel( aEvent.Parameter<EDA_ITEMS*>(), false );
m_selection.SetIsHover( false );
return 0;
}
void EE_SELECTION_TOOL::RemoveItemsFromSel( EDA_ITEMS* aList, bool aQuietMode )
{
if( aList )
{
for( EDA_ITEM* item : *aList )
unselect( item );
// Inform other potentially interested tools
if( !aQuietMode )
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
}
}
void EE_SELECTION_TOOL::RemoveItemsFromSel( std::vector<KIID>* aList, bool aQuietMode )
{
EDA_ITEMS removeItems;
for( EDA_ITEM* item : m_selection )
{
if( alg::contains( *aList, item->m_Uuid ) )
removeItems.push_back( item );
}
RemoveItemsFromSel( &removeItems, aQuietMode );
}
void EE_SELECTION_TOOL::BrightenItem( EDA_ITEM* aItem )
{
highlight( aItem, BRIGHTENED );
}
void EE_SELECTION_TOOL::UnbrightenItem( EDA_ITEM* aItem )
{
unhighlight( aItem, BRIGHTENED );
}
int EE_SELECTION_TOOL::ClearSelection( const TOOL_EVENT& aEvent )
{
ClearSelection();
@ -1618,7 +1486,7 @@ void EE_SELECTION_TOOL::RebuildSelection()
for( LIB_ITEM& item : start->GetDrawItems() )
{
if( item.IsSelected() )
select( static_cast<EDA_ITEM*>( &item ) );
select( &item );
}
}
else
@ -1649,182 +1517,6 @@ void EE_SELECTION_TOOL::RebuildSelection()
}
int EE_SELECTION_TOOL::SelectionMenu( const TOOL_EVENT& aEvent )
{
EE_COLLECTOR* collector = aEvent.Parameter<EE_COLLECTOR*>();
if( !doSelectionMenu( collector ) )
collector->m_MenuCancelled = true;
return 0;
}
bool EE_SELECTION_TOOL::doSelectionMenu( EE_COLLECTOR* aCollector )
{
EDA_ITEM* current = nullptr;
bool selectAll = false;
bool expandSelection = false;
do
{
/// The user has requested the full, non-limited list of selection items
if( expandSelection )
aCollector->Combine();
expandSelection = false;
int limit = std::min( 100, aCollector->GetCount() );
ACTION_MENU menu( true );
for( int i = 0; i < limit; ++i )
{
EDA_ITEM* item = ( *aCollector )[i];
wxString text = item->GetSelectMenuText( m_frame->GetUserUnits() );
wxString menuText;
if( i < 9 )
{
#ifdef __WXMAC__
menuText = wxString::Format( "%s\t%d", text, i + 1 );
#else
menuText = wxString::Format( "&%d %s\t%d", i + 1, text, i + 1 );
#endif
}
else
{
menuText = text;
}
menu.Add( menuText, i + 1, item->GetMenuImage() );
}
menu.AppendSeparator();
menu.Add( _( "Select &All\tA" ), limit + 1, BITMAPS::INVALID_BITMAP );
if( !expandSelection && aCollector->HasAdditionalItems() )
menu.Add( _( "&Expand Selection\tE" ), limit + 2, BITMAPS::INVALID_BITMAP );
if( aCollector->m_MenuTitle.Length() )
{
menu.SetTitle( aCollector->m_MenuTitle );
menu.SetIcon( BITMAPS::info );
menu.DisplayTitle( true );
}
else
{
menu.DisplayTitle( false );
}
SetContextMenu( &menu, CMENU_NOW );
while( TOOL_EVENT* evt = Wait() )
{
if( evt->Action() == TA_CHOICE_MENU_UPDATE )
{
if( selectAll )
{
for( int i = 0; i < aCollector->GetCount(); ++i )
unhighlight( ( *aCollector )[i], BRIGHTENED );
}
else if( current )
{
unhighlight( current, BRIGHTENED );
}
int id = *evt->GetCommandId();
// User has pointed an item, so show it in a different way
if( id > 0 && id <= limit )
{
current = ( *aCollector )[id - 1];
highlight( current, BRIGHTENED );
}
else
{
current = nullptr;
}
// User has pointed on the "Select All" option
if( id == limit + 1 )
{
for( int i = 0; i < aCollector->GetCount(); ++i )
highlight( ( *aCollector )[i], BRIGHTENED );
selectAll = true;
}
else
{
selectAll = false;
}
}
else if( evt->Action() == TA_CHOICE_MENU_CHOICE )
{
if( selectAll )
{
for( int i = 0; i < aCollector->GetCount(); ++i )
unhighlight( ( *aCollector )[i], BRIGHTENED );
}
else if( current )
{
unhighlight( current, BRIGHTENED );
}
OPT<int> id = evt->GetCommandId();
// User has selected the "Select All" option
if( id == limit + 1 )
{
selectAll = true;
current = nullptr;
}
else if( id == limit + 2 )
{
selectAll = false;
current = nullptr;
expandSelection = true;
}
// User has selected an item, so this one will be returned
else if( id && ( *id > 0 ) && ( *id <= limit ) )
{
selectAll = false;
current = ( *aCollector )[*id - 1];
}
// User has cancelled the menu (either by <esc> or clicking out of it)
else
{
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;
else if( current )
{
unhighlight( current, BRIGHTENED );
getView()->UpdateItems();
m_frame->GetCanvas()->Refresh();
aCollector->Empty();
aCollector->Append( current );
return true;
}
return false;
}
bool EE_SELECTION_TOOL::Selectable( const EDA_ITEM* aItem, const VECTOR2I* aPos,
bool checkVisibilityOnly ) const
{
@ -1902,7 +1594,7 @@ void EE_SELECTION_TOOL::ClearSelection()
return;
while( m_selection.GetSize() )
unhighlight( (EDA_ITEM*) m_selection.Front(), SELECTED, &m_selection );
unhighlight( m_selection.Front(), SELECTED, &m_selection );
getView()->Update( &m_selection );
@ -1926,7 +1618,7 @@ void EE_SELECTION_TOOL::unselect( EDA_ITEM* aItem )
}
void EE_SELECTION_TOOL::highlight( EDA_ITEM* aItem, int aMode, EE_SELECTION* aGroup )
void EE_SELECTION_TOOL::highlight( EDA_ITEM* aItem, int aMode, SELECTION* aGroup )
{
KICAD_T itemType = aItem->Type();
@ -1959,7 +1651,7 @@ void EE_SELECTION_TOOL::highlight( EDA_ITEM* aItem, int aMode, EE_SELECTION* aGr
}
void EE_SELECTION_TOOL::unhighlight( EDA_ITEM* aItem, int aMode, EE_SELECTION* aGroup )
void EE_SELECTION_TOOL::unhighlight( EDA_ITEM* aItem, int aMode, SELECTION* aGroup )
{
KICAD_T itemType = aItem->Type();
@ -1981,13 +1673,13 @@ void EE_SELECTION_TOOL::unhighlight( EDA_ITEM* aItem, int aMode, EE_SELECTION* a
if( SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( aItem ) )
{
sch_item->RunOnChildren(
[&]( SCH_ITEM* aChild )
{
if( aMode == SELECTED )
aChild->ClearSelected();
else if( aMode == BRIGHTENED )
aChild->ClearBrightened();
} );
[&]( SCH_ITEM* aChild )
{
if( aMode == SELECTED )
aChild->ClearSelected();
else if( aMode == BRIGHTENED )
aChild->ClearBrightened();
} );
}
if( itemType == SCH_PIN_T || itemType == SCH_FIELD_T || itemType == SCH_SHEET_PIN_T )

View File

@ -54,7 +54,7 @@ public:
};
class EE_SELECTION_TOOL : public SELECTION_TOOL, public TOOL_INTERACTIVE
class EE_SELECTION_TOOL : public SELECTION_TOOL
{
public:
EE_SELECTION_TOOL();
@ -66,8 +66,6 @@ public:
/// @copydoc TOOL_BASE::Reset()
void Reset( RESET_REASON aReason ) override;
int UpdateMenu( const TOOL_EVENT& aEvent );
/**
* The main loop.
*/
@ -106,27 +104,6 @@ public:
bool aCheckLocked = false, bool aAdd = false, bool aSubtract = false,
bool aExclusiveOr = false );
int AddItemToSel( const TOOL_EVENT& aEvent );
void AddItemToSel( EDA_ITEM* aItem, bool aQuietMode = false );
int AddItemsToSel( const TOOL_EVENT& aEvent );
void AddItemsToSel( EDA_ITEMS* aList, bool aQuietMode = false );
int RemoveItemFromSel( const TOOL_EVENT& aEvent );
void RemoveItemFromSel( EDA_ITEM* aItem, bool aQuietMode = false );
int RemoveItemsFromSel( const TOOL_EVENT& aEvent );
void RemoveItemsFromSel( EDA_ITEMS* aList, bool aQuietMode = false );
/**
* A safer version of RemoveItemsFromSel( EDA_ITEMS ) which doesn't require the items to
* still exist.
*/
void RemoveItemsFromSel( std::vector<KIID>* aList, bool aQuietMode = false );
void BrightenItem( EDA_ITEM* aItem );
void UnbrightenItem( EDA_ITEM* aItem );
void SelectHighlightItem( EDA_ITEM* aItem ) { highlight( aItem, SELECTED ); }
///< Find (but don't select) node under cursor
EDA_ITEM* GetNode( VECTOR2I aPosition );
@ -158,14 +135,6 @@ public:
*/
void GuessSelectionCandidates( EE_COLLECTOR& collector, const VECTOR2I& aPos );
/**
* Show a popup menu to trim the COLLECTOR passed as aEvent's parameter down to a single
* item.
*
* @note This routine **does not** modify the selection.
*/
int SelectionMenu( const TOOL_EVENT& aEvent );
/**
* Rebuild the selection from the EDA_ITEMs' selection flags.
*
@ -187,6 +156,9 @@ public:
bool CollectHits( EE_COLLECTOR& aCollector, const VECTOR2I& aWhere,
const KICAD_T* aFilterList = EE_COLLECTOR::AllItems );
protected:
SELECTION& selection() override { return m_selection; }
private:
OPT_TOOL_EVENT autostartEvent( TOOL_EVENT* aEvent, EE_GRID_HELPER& aGrid, SCH_ITEM* aItem );
@ -227,22 +199,6 @@ private:
*/
bool selectMultiple();
/**
* Allow the selection of a single item from a list via pop-up menu. The items are
* highlighted on the canvas when hovered in the menu. The collector is trimmed to
* the picked item.
*
* @return true if an item was picked
*/
bool doSelectionMenu( EE_COLLECTOR* aItems );
/**
* Start the process to show our disambiguation menu once the user has kept
* the mouse down for the minimum time
* @param aEvent
*/
void onDisambiguationExpire( wxTimerEvent& aEvent );
/**
* Handle disambiguation actions including displaying the menu.
*/
@ -253,14 +209,14 @@ private:
*
* @param aItem is an item to be selected.
*/
void select( EDA_ITEM* aItem );
void select( EDA_ITEM* aItem ) override;
/**
* Take necessary action mark an item as unselected.
*
* @param aItem is an item to be unselected.
*/
void unselect( EDA_ITEM* aItem );
void unselect( EDA_ITEM* aItem ) override;
/**
* Highlight the item visually.
@ -269,7 +225,7 @@ private:
* @param aHighlightMode should be either SELECTED or BRIGHTENED
* @param aGroup is the group to add the item to in the BRIGHTENED mode.
*/
void highlight( EDA_ITEM* aItem, int aHighlightMode, EE_SELECTION* aGroup = nullptr );
void highlight( EDA_ITEM* aItem, int aHighlightMode, SELECTION* aGroup = nullptr ) override;
/**
* Unhighlight the item visually.
@ -278,7 +234,7 @@ private:
* @param aHighlightMode should be either SELECTED or BRIGHTENED
* @param aGroup is the group to remove the item from.
*/
void unhighlight( EDA_ITEM* aItem, int aHighlightMode, EE_SELECTION* aGroup = nullptr );
void unhighlight( EDA_ITEM* aItem, int aHighlightMode, SELECTION* aGroup = nullptr ) override;
/**
* Set the reference point to the anchor of the top-left item.

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017 Jon Evans <jon@craftyjon.com>
* Copyright (C) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2017-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@ -21,7 +21,6 @@
#include <limits>
#include <functional>
using namespace std::placeholders;
#include <bitmaps.h>
#include <eda_item.h>
#include <gerber_collectors.h>
@ -112,25 +111,9 @@ private:
GERBVIEW_SELECTION_TOOL::GERBVIEW_SELECTION_TOOL() :
TOOL_INTERACTIVE( "gerbview.InteractiveSelection" ),
SELECTION_TOOL( "gerbview.InteractiveSelection" ),
m_frame( nullptr )
{
m_preliminary = true;
}
int GERBVIEW_SELECTION_TOOL::UpdateMenu( const TOOL_EVENT& aEvent )
{
ACTION_MENU* actionMenu = aEvent.Parameter<ACTION_MENU*>();
CONDITIONAL_MENU* conditionalMenu = dynamic_cast<CONDITIONAL_MENU*>( actionMenu );
if( conditionalMenu )
conditionalMenu->Evaluate( m_selection );
if( actionMenu )
actionMenu->UpdateAll();
return 0;
}
@ -160,7 +143,6 @@ bool GERBVIEW_SELECTION_TOOL::Init()
void GERBVIEW_SELECTION_TOOL::Reset( RESET_REASON aReason )
{
m_frame = getEditFrame<GERBVIEW_FRAME>();
m_preliminary = true;
if( aReason == TOOL_BASE::MODEL_RELOAD )
{
@ -235,11 +217,11 @@ GERBVIEW_SELECTION& GERBVIEW_SELECTION_TOOL::GetSelection()
}
bool GERBVIEW_SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag )
bool GERBVIEW_SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere )
{
EDA_ITEM* item = nullptr;
EDA_ITEM* item = nullptr;
GERBER_COLLECTOR collector;
EDA_ITEM* model = getModel<EDA_ITEM>();
EDA_ITEM* model = getModel<EDA_ITEM>();
collector.Collect( model, GERBER_COLLECTOR::AllItems, wxPoint( aWhere.x, aWhere.y ) );
@ -252,16 +234,10 @@ bool GERBVIEW_SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag
if( collector.GetCount() > 1 )
{
if( aOnDrag )
Wait( TOOL_EVENT( TC_ANY, TA_MOUSE_UP, BUT_LEFT ) );
doSelectionMenu( &collector );
item = disambiguationMenu( &collector );
if( item )
{
collector.Empty();
collector.Append( item );
}
if( collector.m_MenuCancelled )
return false;
}
if( !m_additive && !m_subtractive && !m_exclusive_or )
@ -289,18 +265,6 @@ bool GERBVIEW_SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag
}
bool GERBVIEW_SELECTION_TOOL::selectCursor( bool aSelectAlways )
{
if( aSelectAlways || m_selection.Empty() )
{
clearSelection();
selectPoint( getViewControls()->GetCursorPosition( false ) );
}
return !m_selection.Empty();
}
void GERBVIEW_SELECTION_TOOL::setTransitions()
{
Go( &GERBVIEW_SELECTION_TOOL::UpdateMenu, ACTIONS::updateMenu.MakeEvent() );
@ -402,93 +366,6 @@ void GERBVIEW_SELECTION_TOOL::clearSelection()
}
EDA_ITEM* GERBVIEW_SELECTION_TOOL::disambiguationMenu( GERBER_COLLECTOR* aCollector )
{
EDA_ITEM* current = nullptr;
KIGFX::VIEW_GROUP highlightGroup;
ACTION_MENU menu( true );
highlightGroup.SetLayer( LAYER_SELECT_OVERLAY );
getView()->Add( &highlightGroup );
int limit = std::min( 10, aCollector->GetCount() );
for( int i = 0; i < limit; ++i )
{
wxString text;
EDA_ITEM* item = ( *aCollector )[i];
text = item->GetSelectMenuText( m_frame->GetUserUnits() );
menu.Add( text, i + 1, item->GetMenuImage() );
}
if( aCollector->m_MenuTitle.Length() )
{
menu.SetTitle( aCollector->m_MenuTitle );
menu.SetIcon( BITMAPS::info );
menu.DisplayTitle( true );
}
else
{
menu.DisplayTitle( false );
}
SetContextMenu( &menu, CMENU_NOW );
while( TOOL_EVENT* evt = Wait() )
{
if( evt->Action() == TA_CHOICE_MENU_UPDATE )
{
if( current )
{
current->ClearBrightened();
getView()->Hide( current, false );
highlightGroup.Remove( current );
getView()->MarkTargetDirty( KIGFX::TARGET_OVERLAY );
}
int id = *evt->GetCommandId();
// User has pointed an item, so show it in a different way
if( id > 0 && id <= limit )
{
current = ( *aCollector )[id - 1];
current->SetBrightened();
getView()->Hide( current, true );
highlightGroup.Add( current );
getView()->MarkTargetDirty( KIGFX::TARGET_OVERLAY );
}
else
{
current = nullptr;
}
}
else if( evt->Action() == TA_CHOICE_MENU_CHOICE )
{
OPT<int> id = evt->GetCommandId();
// User has selected an item, so this one will be returned
if( id && ( *id > 0 ) )
current = ( *aCollector )[*id - 1];
else
current = nullptr;
break;
}
}
if( current && current->IsBrightened() )
{
current->ClearBrightened();
getView()->Hide( current, false );
getView()->MarkTargetDirty( KIGFX::TARGET_OVERLAY );
}
getView()->Remove( &highlightGroup );
return current;
}
bool GERBVIEW_SELECTION_TOOL::selectable( const EDA_ITEM* aItem ) const
{
GERBVIEW_FRAME* frame = getEditFrame<GERBVIEW_FRAME>();

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017 Jon Evans <jon@craftyjon.com>
* Copyright (C) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2017-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@ -43,7 +43,7 @@ namespace KIGFX
/**
* Selection tool for GerbView, based on the one in Pcbnew
*/
class GERBVIEW_SELECTION_TOOL : public SELECTION_TOOL, public TOOL_INTERACTIVE
class GERBVIEW_SELECTION_TOOL : public SELECTION_TOOL
{
public:
GERBVIEW_SELECTION_TOOL();
@ -55,9 +55,6 @@ public:
/// @copydoc TOOL_BASE::Reset()
void Reset( RESET_REASON aReason ) override;
// called to rebuild a CONDITIONAL_MENU before opening it:
int UpdateMenu( const TOOL_EVENT& aEvent );
/**
* The main loop.
*/
@ -79,40 +76,24 @@ public:
///< Sets up handlers for various events.
void setTransitions() override;
protected:
SELECTION& selection() override { return m_selection; }
private:
/**
* Select an item pointed by the parameter aWhere. If there is more than one item at that
* place, there is a menu displayed that allows one to choose the item.
*
* @param aWhere is the place where the item should be selected.
* @param aAllowDisambiguation decides what to do in case of disambiguation. If true, then
* a menu is shown, otherwise function finishes without selecting anything.
* @return True if an item was selected, false otherwise.
*/
bool selectPoint( const VECTOR2I& aWhere, bool aOnDrag = false );
/**
* Select an item under the cursor unless there is something already selected or
* \a aSelectAlways is true.
*
* @param aSelectAlways forces to select an item even if there is an item already selected.
* @return true if eventually there is an item selected, false otherwise.
*/
bool selectCursor( bool aSelectAlways = false );
bool selectPoint( const VECTOR2I& aWhere );
/**
* Clear the current selection.
*/
void clearSelection();
/**
* Handle the menu that allows one to select one of many items in case
* there is more than one item at the selected point (@see selectCursor()).
*
* @param aItems contains list of items that are displayed to the user.
*/
EDA_ITEM* disambiguationMenu( GERBER_COLLECTOR* aItems );
/**
* Check conditions for an item to be selected.
*
@ -125,14 +106,14 @@ private:
*
* @param aItem is an item to be selected.
*/
void select( EDA_ITEM* aItem );
void select( EDA_ITEM* aItem ) override;
/**
* Take necessary action mark an item as unselected.
*
* @param aItem is an item to be unselected.
*/
void unselect( EDA_ITEM* aItem );
void unselect( EDA_ITEM* aItem ) override;
/**
* Mark item as selected, but does not add it to the #ITEMS_PICKED_LIST.
@ -148,10 +129,33 @@ private:
*/
void unselectVisually( EDA_ITEM* aItem );
GERBVIEW_FRAME* m_frame; // Pointer to the parent frame.
GERBVIEW_SELECTION m_selection; // Current state of selection.
/**
* Highlight the item visually.
*
* @param aItem is an item to be be highlighted.
* @param aHighlightMode should be either SELECTED or BRIGHTENED
* @param aGroup is the group to add the item to in the BRIGHTENED mode.
*/
void highlight( EDA_ITEM* aItem, int aHighlightMode, SELECTION* aGroup = nullptr ) override
{
// Currently not used in GerbView
};
bool m_preliminary; // Determines if the selection is preliminary or final.
/**
* Unhighlight the item visually.
*
* @param aItem is an item to be be highlighted.
* @param aHighlightMode should be either SELECTED or BRIGHTENED
* @param aGroup is the group to remove the item from.
*/
void unhighlight( EDA_ITEM* aItem, int aHighlightMode, SELECTION* aGroup = nullptr ) override
{
// Currently not used in GerbView
};
private:
GERBVIEW_FRAME* m_frame; // Pointer to the parent frame.
GERBVIEW_SELECTION m_selection; // Current state of selection.
};
#endif

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2021 KiCad Developers, see AUTHORS.TXT for contributors.
* Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.TXT for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -29,14 +29,87 @@
#include <tool/tool_interactive.h>
#include <wx/timer.h>
class SELECTION_TOOL : public wxEvtHandler
class COLLECTOR;
class SELECTION_TOOL : public TOOL_INTERACTIVE, public wxEvtHandler
{
public:
SELECTION_TOOL();
SELECTION_TOOL( const std::string& aName );
~SELECTION_TOOL(){};
/**
* Update a menu's state based on the current selection. The menu is passed in aEvent's
* parameter.
*/
int UpdateMenu( const TOOL_EVENT& aEvent );
int AddItemToSel( const TOOL_EVENT& aEvent );
void AddItemToSel( EDA_ITEM* aItem, bool aQuietMode = false );
int AddItemsToSel( const TOOL_EVENT& aEvent );
void AddItemsToSel( EDA_ITEMS* aList, bool aQuietMode = false );
int RemoveItemFromSel( const TOOL_EVENT& aEvent );
void RemoveItemFromSel( EDA_ITEM* aItem, bool aQuietMode = false );
int RemoveItemsFromSel( const TOOL_EVENT& aEvent );
void RemoveItemsFromSel( EDA_ITEMS* aList, bool aQuietMode = false );
/**
* A safer version of RemoveItemsFromSel( EDA_ITEMS ) which doesn't require the items to
* still exist.
*/
void RemoveItemsFromSel( std::vector<KIID>* aList, bool aQuietMode = false );
void BrightenItem( EDA_ITEM* aItem );
void UnbrightenItem( EDA_ITEM* aItem );
/**
* Show a popup menu to trim the COLLECTOR passed as aEvent's parameter down to a single
* item.
*
* @note This routine **does not** modify the selection.
*/
int SelectionMenu( const TOOL_EVENT& aEvent );
protected:
/**
* Return a reference to the selection.
*/
virtual SELECTION& selection() = 0;
/**
* Start the process to show our disambiguation menu once the user has kept the mouse down
* for the minimum time.
* @param aEvent
*/
void onDisambiguationExpire( wxTimerEvent& aEvent );
/**
* Take necessary action mark an item as selected.
*/
virtual void select( EDA_ITEM* aItem ) = 0;
/**
* Take necessary action mark an item as unselected.
*/
virtual void unselect( EDA_ITEM* aItem ) = 0;
/**
* Highlight the item visually.
*
* @param aHighlightMode should be either SELECTED or BRIGHTENED
* @param aGroup is the group to add the item to in the BRIGHTENED mode.
*/
virtual void highlight( EDA_ITEM* aItem, int aHighlightMode, SELECTION* aGroup = nullptr ) = 0;
/**
* Unhighlight the item visually.
*
* @param aHighlightMode should be either SELECTED or BRIGHTENED
* @param aGroup is the group to remove the item from.
*/
virtual void unhighlight( EDA_ITEM* aItem, int aHighlightMode, SELECTION* aGroup = nullptr ) = 0;
/**
* Set the configuration of m_additive, m_subtractive, m_exclusive_or, m_skip_heuristics
* from the state of modifier keys SHIFT, CTRL, ALT and depending on the OS
@ -48,6 +121,9 @@ protected:
*/
virtual bool ctrlClickHighlights() { return false; }
bool doSelectionMenu( COLLECTOR* aCollector );
protected:
bool m_additive; // Items should be added to sel (instead of replacing)
bool m_subtractive; // Items should be removed from sel
bool m_exclusive_or; // Items' selection state should be toggled

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 CERN
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -23,7 +23,6 @@
*/
#include <bitmaps.h>
#include <view/view.h>
#include <view/view_controls.h>
#include <preview_items/selection_area.h>
@ -41,16 +40,12 @@
#include "pl_editor_frame.h"
/**
* The maximum number of items in the clarify selection context menu. The current
* setting of 40 is arbitrary.
*/
#define MAX_SELECT_ITEM_IDS 40
#define HITTEST_THRESHOLD_PIXELS 3
PL_SELECTION_TOOL::PL_SELECTION_TOOL() :
TOOL_INTERACTIVE( "plEditor.InteractiveSelection" ),
SELECTION_TOOL( "plEditor.InteractiveSelection" ),
m_frame( nullptr )
{
}
@ -85,21 +80,6 @@ void PL_SELECTION_TOOL::Reset( RESET_REASON aReason )
}
int PL_SELECTION_TOOL::UpdateMenu( const TOOL_EVENT& aEvent )
{
ACTION_MENU* actionMenu = aEvent.Parameter<ACTION_MENU*>();
CONDITIONAL_MENU* conditionalMenu = dynamic_cast<CONDITIONAL_MENU*>( actionMenu );
if( conditionalMenu )
conditionalMenu->Evaluate( m_selection );
if( actionMenu )
actionMenu->UpdateAll();
return 0;
}
int PL_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
{
// Main loop: keep receiving events
@ -248,12 +228,6 @@ int PL_SELECTION_TOOL::disambiguateCursor( const TOOL_EVENT& aEvent )
}
void PL_SELECTION_TOOL::onDisambiguationExpire( wxTimerEvent& aEvent )
{
m_toolMgr->ProcessEvent( EVENTS::DisambiguatePoint );
}
PL_SELECTION& PL_SELECTION_TOOL::GetSelection()
{
return m_selection;
@ -280,9 +254,7 @@ void PL_SELECTION_TOOL::SelectPoint( const VECTOR2I& aWhere, bool* aSelectionCan
// Apply some ugly heuristics to avoid disambiguation menus whenever possible
if( collector.GetCount() > 1 && !m_skip_heuristics )
{
guessSelectionCandidates( collector, aWhere );
}
// If still more than one item we're going to have to ask the user.
if( collector.GetCount() > 1 )
@ -386,8 +358,8 @@ bool PL_SELECTION_TOOL::selectMultiple()
*/
bool windowSelection = width >= 0 ? true : false;
m_frame->GetCanvas()->SetCurrentCursor(
windowSelection ? KICURSOR::SELECT_WINDOW : KICURSOR::SELECT_LASSO );
m_frame->GetCanvas()->SetCurrentCursor( windowSelection ? KICURSOR::SELECT_WINDOW
: KICURSOR::SELECT_LASSO );
if( evt->IsCancelInteractive() || evt->IsActivate() )
{
@ -473,100 +445,6 @@ bool PL_SELECTION_TOOL::selectMultiple()
}
int PL_SELECTION_TOOL::AddItemToSel( const TOOL_EVENT& aEvent )
{
AddItemToSel( aEvent.Parameter<EDA_ITEM*>() );
return 0;
}
void PL_SELECTION_TOOL::AddItemToSel( EDA_ITEM* aItem, bool aQuietMode )
{
if( aItem )
{
select( aItem );
// Inform other potentially interested tools
if( !aQuietMode )
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
}
}
int PL_SELECTION_TOOL::AddItemsToSel( const TOOL_EVENT& aEvent )
{
AddItemsToSel( aEvent.Parameter<EDA_ITEMS*>(), false );
return 0;
}
void PL_SELECTION_TOOL::AddItemsToSel( EDA_ITEMS* aList, bool aQuietMode )
{
if( aList )
{
for( EDA_ITEM* item : *aList )
select( item );
// Inform other potentially interested tools
if( !aQuietMode )
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
}
}
int PL_SELECTION_TOOL::RemoveItemFromSel( const TOOL_EVENT& aEvent )
{
RemoveItemFromSel( aEvent.Parameter<EDA_ITEM*>() );
return 0;
}
void PL_SELECTION_TOOL::RemoveItemFromSel( EDA_ITEM* aItem, bool aQuietMode )
{
if( aItem )
{
unselect( aItem );
// Inform other potentially interested tools
if( !aQuietMode )
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
}
}
int PL_SELECTION_TOOL::RemoveItemsFromSel( const TOOL_EVENT& aEvent )
{
RemoveItemsFromSel( aEvent.Parameter<EDA_ITEMS*>(), false );
return 0;
}
void PL_SELECTION_TOOL::RemoveItemsFromSel( EDA_ITEMS* aList, bool aQuietMode )
{
if( aList )
{
for( EDA_ITEM* item : *aList )
unselect( item );
// Inform other potentially interested tools
if( !aQuietMode )
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
}
}
void PL_SELECTION_TOOL::BrightenItem( EDA_ITEM* aItem )
{
highlight( aItem, BRIGHTENED );
}
void PL_SELECTION_TOOL::UnbrightenItem( EDA_ITEM* aItem )
{
unhighlight( aItem, BRIGHTENED );
}
int PL_SELECTION_TOOL::ClearSelection( const TOOL_EVENT& aEvent )
{
ClearSelection();
@ -589,160 +467,13 @@ void PL_SELECTION_TOOL::RebuildSelection()
}
int PL_SELECTION_TOOL::SelectionMenu( const TOOL_EVENT& aEvent )
{
COLLECTOR* collector = aEvent.Parameter<COLLECTOR*>();
if( !doSelectionMenu( collector ) )
collector->m_MenuCancelled = true;
return 0;
}
bool PL_SELECTION_TOOL::doSelectionMenu( COLLECTOR* aCollector )
{
EDA_ITEM* current = nullptr;
ACTION_MENU menu( true );
// ID limit is `MAX_SELECT_ITEM_IDS+1` because the last item is "select all"
// and the first item has ID of 1.
int limit = std::min( MAX_SELECT_ITEM_IDS + 1, aCollector->GetCount() );
for( int i = 0; i < limit; ++i )
{
wxString text;
EDA_ITEM* item = ( *aCollector )[i];
text = item->GetSelectMenuText( m_frame->GetUserUnits() );
wxString menuText = wxString::Format( "&%d. %s\t%d", i + 1, text, i + 1 );
menu.Add( menuText, i + 1, item->GetMenuImage() );
}
menu.AppendSeparator();
menu.Add( _( "Select &All\tA" ), limit + 1, BITMAPS::INVALID_BITMAP );
if( aCollector->m_MenuTitle.Length() )
{
menu.SetTitle( aCollector->m_MenuTitle );
menu.SetIcon( BITMAPS::info );
menu.DisplayTitle( true );
}
else
{
menu.DisplayTitle( false );
}
SetContextMenu( &menu, CMENU_NOW );
bool selectAll = false;
while( TOOL_EVENT* evt = Wait() )
{
if( evt->Action() == TA_CHOICE_MENU_UPDATE )
{
if( selectAll )
{
for( int i = 0; i < aCollector->GetCount(); ++i )
unhighlight( ( *aCollector )[i], BRIGHTENED );
}
else if( current )
{
unhighlight( current, BRIGHTENED );
}
int id = *evt->GetCommandId();
// User has pointed an item, so show it in a different way
if( id > 0 && id <= limit )
{
current = ( *aCollector )[id - 1];
highlight( current, BRIGHTENED );
}
else
{
current = nullptr;
}
if( id == limit + 1 )
{
for( int i = 0; i < aCollector->GetCount(); ++i )
highlight( ( *aCollector )[i], BRIGHTENED );
selectAll = true;
}
else
{
selectAll = false;
}
}
else if( evt->Action() == TA_CHOICE_MENU_CHOICE )
{
if( selectAll )
{
for( int i = 0; i < aCollector->GetCount(); ++i )
unhighlight( ( *aCollector )[i], BRIGHTENED );
}
else if( current )
{
unhighlight( current, BRIGHTENED );
}
OPT<int> id = evt->GetCommandId();
// User has selected an item, so this one will be returned
if( id == limit + 1 )
{
selectAll = true;
current = nullptr;
}
else if( id && ( *id > 0 ) && ( *id <= limit ) )
{
selectAll = false;
current = ( *aCollector )[*id - 1];
}
else
{
selectAll = false;
current = nullptr;
}
}
else if( evt->Action() == TA_CHOICE_MENU_CLOSED )
{
break;
}
getView()->UpdateItems();
m_frame->GetCanvas()->Refresh();
}
if( selectAll )
{
return true;
}
else if( current )
{
unhighlight( current, BRIGHTENED );
getView()->UpdateItems();
m_frame->GetCanvas()->Refresh();
aCollector->Empty();
aCollector->Append( current );
return true;
}
return false;
}
void PL_SELECTION_TOOL::ClearSelection()
{
if( m_selection.Empty() )
return;
while( m_selection.GetSize() )
unhighlight( (EDA_ITEM*) m_selection.Front(), SELECTED, &m_selection );
unhighlight( m_selection.Front(), SELECTED, &m_selection );
getView()->Update( &m_selection );
@ -766,7 +497,7 @@ void PL_SELECTION_TOOL::unselect( EDA_ITEM* aItem )
}
void PL_SELECTION_TOOL::highlight( EDA_ITEM* aItem, int aMode, PL_SELECTION* aGroup )
void PL_SELECTION_TOOL::highlight( EDA_ITEM* aItem, int aMode, SELECTION* aGroup )
{
if( aMode == SELECTED )
aItem->SetSelected();
@ -780,7 +511,7 @@ void PL_SELECTION_TOOL::highlight( EDA_ITEM* aItem, int aMode, PL_SELECTION* aGr
}
void PL_SELECTION_TOOL::unhighlight( EDA_ITEM* aItem, int aMode, PL_SELECTION* aGroup )
void PL_SELECTION_TOOL::unhighlight( EDA_ITEM* aItem, int aMode, SELECTION* aGroup )
{
if( aMode == SELECTED )
aItem->ClearSelected();
@ -800,7 +531,7 @@ bool PL_SELECTION_TOOL::selectionContains( const VECTOR2I& aPoint ) const
VECTOR2I margin = getView()->ToWorld( VECTOR2I( GRIP_MARGIN, GRIP_MARGIN ), false );
// Check if the point is located within any of the currently selected items bounding boxes
for( auto item : m_selection )
for( EDA_ITEM* item : m_selection )
{
BOX2I itemBox = item->ViewBBox();
itemBox.Inflate( margin.x, margin.y ); // Give some margin for gripping an item

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 CERN
* Copyright (C) 2019-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -40,7 +40,7 @@ namespace KIGFX
}
class PL_SELECTION_TOOL : public SELECTION_TOOL, public TOOL_INTERACTIVE
class PL_SELECTION_TOOL : public SELECTION_TOOL
{
public:
PL_SELECTION_TOOL();
@ -52,8 +52,6 @@ public:
/// @copydoc TOOL_INTERACTIVE::Reset()
void Reset( RESET_REASON aReason ) override;
int UpdateMenu( const TOOL_EVENT& aEvent );
/**
* The main loop.
*/
@ -81,19 +79,6 @@ public:
*/
void SelectPoint( const VECTOR2I& aWhere, bool* aSelectionCancelledFlag = nullptr );
int AddItemToSel( const TOOL_EVENT& aEvent );
void AddItemToSel( EDA_ITEM* aItem, bool aQuietMode = false );
int AddItemsToSel( const TOOL_EVENT& aEvent );
void AddItemsToSel( EDA_ITEMS* aList, bool aQuietMode = false );
int RemoveItemFromSel( const TOOL_EVENT& aEvent );
void RemoveItemFromSel( EDA_ITEM* aItem, bool aQuietMode = false );
int RemoveItemsFromSel( const TOOL_EVENT& aEvent );
void RemoveItemsFromSel( EDA_ITEMS* aList, bool aQuietMode = false );
void BrightenItem( EDA_ITEM* aItem );
void UnbrightenItem( EDA_ITEM* aItem );
int ClearSelection( const TOOL_EVENT& aEvent );
void ClearSelection();
@ -103,13 +88,8 @@ public:
*/
void RebuildSelection();
/**
* Shows a popup menu to trim the COLLECTOR passed as aEvent's parameter down to a single
* item.
*
* @note This routine **does not** modify the selection.
*/
int SelectionMenu( const TOOL_EVENT& aEvent );
protected:
SELECTION& selection() override { return m_selection; }
private:
/**
@ -125,22 +105,6 @@ private:
*/
void guessSelectionCandidates( COLLECTOR& collector, const VECTOR2I& aWhere );
/**
* Allow the selection of a single item from a list via pop-up menu. The items are
* highlighted on the canvas when hovered in the menu. The collector is trimmed to
* the picked item.
*
* @return true if an item was picked.
*/
bool doSelectionMenu( COLLECTOR* aItems );
/**
* Start the process to show our disambiguation menu once the user has kept
* the mouse down for the minimum time
* @param aEvent
*/
void onDisambiguationExpire( wxTimerEvent& aEvent );
/**
* Handle disambiguation actions including displaying the menu.
*/
@ -151,14 +115,14 @@ private:
*
* @param aItem is an item to be selected.
*/
void select( EDA_ITEM* aItem );
void select( EDA_ITEM* aItem ) override;
/**
* Take necessary action mark an item as unselected.
*
* @param aItem is an item to be unselected.
*/
void unselect( EDA_ITEM* aItem );
void unselect( EDA_ITEM* aItem ) override;
/**
* Highlight the item visually.
@ -167,7 +131,7 @@ private:
* @param aHighlightMode should be either SELECTED or BRIGHTENED
* @param aGroup is the group to add the item to in the BRIGHTENED mode.
*/
void highlight( EDA_ITEM* aItem, int aHighlightMode, PL_SELECTION* aGroup = nullptr );
void highlight( EDA_ITEM* aItem, int aHighlightMode, SELECTION* aGroup = nullptr ) override;
/**
* Unhighlight the item visually.
@ -176,7 +140,7 @@ private:
* @param aHighlightMode should be either SELECTED or BRIGHTENED
* @param aGroup is the group to remove the item from.
*/
void unhighlight( EDA_ITEM* aItem, int aHighlightMode, PL_SELECTION* aGroup = nullptr );
void unhighlight( EDA_ITEM* aItem, int aHighlightMode, SELECTION* aGroup = nullptr ) override;
/**
* @return True if the given point is contained in any of selected items' bounding box.

View File

@ -57,12 +57,12 @@ private:
void update() override
{
PCB_SELECTION_TOOL* selTool = getToolManager()->GetTool<PCB_SELECTION_TOOL>();
BOARD* board = selTool->GetBoard();
BOARD* board = static_cast<BOARD*>( getToolManager()->GetModel() );
const auto& selection = selTool->GetSelection();
wxString check = board->GroupsSanityCheck();
wxCHECK_RET( check == wxEmptyString, _( "Group is in inconsistent state:" ) + wxS( " " )+ check );
wxCHECK_RET( check == wxEmptyString, _( "Group is in inconsistent state:" ) + wxS( " " ) + check );
BOARD::GroupLegalOpsField legalOps = board->GroupLegalOps( selection );

View File

@ -51,7 +51,6 @@ using namespace std::placeholders;
#include <preview_items/selection_area.h>
#include <painter.h>
#include <router/router_tool.h>
#include <bitmaps.h>
#include <pcbnew_settings.h>
#include <tool/tool_event.h>
#include <tool/tool_manager.h>
@ -61,7 +60,6 @@ using namespace std::placeholders;
#include <tools/pcb_actions.h>
#include <connectivity/connectivity_data.h>
#include <footprint_viewer_frame.h>
#include <id.h>
#include <wx/event.h>
#include <wx/timer.h>
#include <wx/log.h>
@ -107,8 +105,9 @@ public:
PCB_SELECTION_TOOL::PCB_SELECTION_TOOL() :
PCB_TOOL_BASE( "pcbnew.InteractiveSelection" ),
SELECTION_TOOL( "pcbnew.InteractiveSelection" ),
m_frame( nullptr ),
m_isFootprintEditor( false ),
m_nonModifiedCursor( KICURSOR::ARROW ),
m_enteredGroup( nullptr ),
m_priv( std::make_unique<PRIV>() )
@ -138,7 +137,7 @@ PCB_SELECTION_TOOL::~PCB_SELECTION_TOOL()
bool PCB_SELECTION_TOOL::Init()
{
auto frame = getEditFrame<PCB_BASE_FRAME>();
PCB_BASE_FRAME* frame = getEditFrame<PCB_BASE_FRAME>();
if( frame && ( frame->IsType( FRAME_FOOTPRINT_VIEWER )
|| frame->IsType( FRAME_FOOTPRINT_VIEWER_MODAL ) ) )
@ -199,6 +198,7 @@ bool PCB_SELECTION_TOOL::Init()
void PCB_SELECTION_TOOL::Reset( RESET_REASON aReason )
{
m_frame = getEditFrame<PCB_BASE_FRAME>();
m_isFootprintEditor = m_frame->IsType( FRAME_FOOTPRINT_EDITOR );
if( m_enteredGroup )
ExitGroup();
@ -228,12 +228,6 @@ void PCB_SELECTION_TOOL::Reset( RESET_REASON aReason )
}
void PCB_SELECTION_TOOL::onDisambiguationExpire( wxTimerEvent& aEvent )
{
m_toolMgr->ProcessEvent( EVENTS::DisambiguatePoint );
}
void PCB_SELECTION_TOOL::OnIdle( wxIdleEvent& aEvent )
{
if( m_frame->ToolStackIsEmpty() && !m_multiple )
@ -298,7 +292,9 @@ int PCB_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
// Single click? Select single object
if( m_highlight_modifier && brd_editor )
{
m_toolMgr->RunAction( PCB_ACTIONS::highlightNet, true );
}
else
{
m_frame->FocusOnItem( nullptr );
@ -392,9 +388,11 @@ int PCB_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
{
ZONE* zone = static_cast<ZONE*>( item );
if( !zone->HitTestForCorner( location, accuracy * 2 ) &&
!zone->HitTestForEdge( location, accuracy ) )
if( !zone->HitTestForCorner( location, accuracy * 2 )
&& !zone->HitTestForEdge( location, accuracy ) )
{
remove.insert( zone );
}
}
}
@ -561,7 +559,7 @@ PCB_SELECTION& PCB_SELECTION_TOOL::RequestSelection( CLIENT_SELECTION_FILTER aCl
for( std::pair<EDA_ITEM* const, DISPOSITION> itemDisposition : itemDispositions )
{
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( itemDisposition.first );
EDA_ITEM* item = itemDisposition.first;
DISPOSITION disposition = itemDisposition.second;
if( disposition == BEFORE )
@ -570,7 +568,7 @@ PCB_SELECTION& PCB_SELECTION_TOOL::RequestSelection( CLIENT_SELECTION_FILTER aCl
for( std::pair<EDA_ITEM* const, DISPOSITION> itemDisposition : itemDispositions )
{
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( itemDisposition.first );
EDA_ITEM* item = itemDisposition.first;
DISPOSITION disposition = itemDisposition.second;
// Note that we must re-highlight even previously-highlighted items
@ -975,30 +973,6 @@ int PCB_SELECTION_TOOL::ClearSelection( const TOOL_EVENT& aEvent )
}
int PCB_SELECTION_TOOL::SelectItems( const TOOL_EVENT& aEvent )
{
std::vector<BOARD_ITEM*>* items = aEvent.Parameter<std::vector<BOARD_ITEM*>*>();
if( items )
{
// Perform individual selection of each item before processing the event.
for( BOARD_ITEM* item : *items )
select( item );
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
}
return 0;
}
int PCB_SELECTION_TOOL::SelectItem( const TOOL_EVENT& aEvent )
{
AddItemToSel( aEvent.Parameter<BOARD_ITEM*>() );
return 0;
}
int PCB_SELECTION_TOOL::SelectAll( const TOOL_EVENT& aEvent )
{
KIGFX::VIEW* view = getView();
@ -1028,7 +1002,7 @@ int PCB_SELECTION_TOOL::SelectAll( const TOOL_EVENT& aEvent )
FilterCollectorForHierarchy( collection, true );
for( EDA_ITEM* item : collection )
select( static_cast<BOARD_ITEM*>( item ) );
select( item );
m_frame->GetCanvas()->ForceRefresh();
@ -1036,70 +1010,6 @@ int PCB_SELECTION_TOOL::SelectAll( const TOOL_EVENT& aEvent )
}
void PCB_SELECTION_TOOL::AddItemToSel( BOARD_ITEM* aItem, bool aQuietMode )
{
if( aItem )
{
select( aItem );
// Inform other potentially interested tools
if( !aQuietMode )
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
}
}
int PCB_SELECTION_TOOL::UnselectItems( const TOOL_EVENT& aEvent )
{
std::vector<BOARD_ITEM*>* items = aEvent.Parameter<std::vector<BOARD_ITEM*>*>();
if( items )
{
// Perform individual unselection of each item before processing the event
for( auto item : *items )
unselect( item );
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
}
return 0;
}
int PCB_SELECTION_TOOL::UnselectItem( const TOOL_EVENT& aEvent )
{
RemoveItemFromSel( aEvent.Parameter<BOARD_ITEM*>() );
return 0;
}
void PCB_SELECTION_TOOL::RemoveItemFromSel( BOARD_ITEM* aItem, bool aQuietMode )
{
if( aItem )
{
unselect( aItem );
if( !aQuietMode )
{
// Inform other potentially interested tools
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
}
}
}
void PCB_SELECTION_TOOL::BrightenItem( BOARD_ITEM* aItem )
{
highlight( aItem, BRIGHTENED );
}
void PCB_SELECTION_TOOL::UnbrightenItem( BOARD_ITEM* aItem )
{
unhighlight( aItem, BRIGHTENED );
}
void connectedItemFilter( const VECTOR2I&, GENERAL_COLLECTOR& aCollector,
PCB_SELECTION_TOOL* sTool )
{
@ -1110,6 +1020,7 @@ void connectedItemFilter( const VECTOR2I&, GENERAL_COLLECTOR& aCollector,
for( int i = aCollector.GetCount() - 1; i >= 0; i-- )
{
BOARD_CONNECTED_ITEM* item = dynamic_cast<BOARD_CONNECTED_ITEM*>( aCollector[i] );
if( !item )
aCollector.Remove( i );
else if ( representedNets.count( item->GetNetCode() ) )
@ -1151,9 +1062,7 @@ int PCB_SELECTION_TOOL::expandConnection( const TOOL_EVENT& aEvent )
FOOTPRINT* footprint = static_cast<FOOTPRINT*>( item );
for( PAD* pad : footprint->Pads() )
{
startItems.push_back( pad );
}
}
else if( BOARD_CONNECTED_ITEM::ClassOf( item ) )
{
@ -2139,7 +2048,7 @@ void PCB_SELECTION_TOOL::ClearSelection( bool aQuietMode )
return;
while( m_selection.GetSize() )
unhighlight( static_cast<BOARD_ITEM*>( m_selection.Front() ), SELECTED, &m_selection );
unhighlight( m_selection.Front(), SELECTED, &m_selection );
view()->Update( &m_selection );
@ -2172,7 +2081,7 @@ void PCB_SELECTION_TOOL::RebuildSelection()
if( parent && parent->IsSelected() )
return SEARCH_RESULT::CONTINUE;
highlight( (BOARD_ITEM*) item, SELECTED, &m_selection );
highlight( item, SELECTED, &m_selection );
}
if( item == m_enteredGroup )
@ -2199,167 +2108,6 @@ void PCB_SELECTION_TOOL::RebuildSelection()
}
int PCB_SELECTION_TOOL::SelectionMenu( const TOOL_EVENT& aEvent )
{
GENERAL_COLLECTOR* collector = aEvent.Parameter<GENERAL_COLLECTOR*>();
doSelectionMenu( collector );
return 0;
}
bool PCB_SELECTION_TOOL::doSelectionMenu( GENERAL_COLLECTOR* aCollector )
{
BOARD_ITEM* current = nullptr;
PCB_SELECTION highlightGroup;
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 )
{
wxString text;
BOARD_ITEM* item = ( *aCollector )[i];
text = item->GetSelectMenuText( m_frame->GetUserUnits() );
wxString menuText = wxString::Format( wxT( "&%d. %s\t%d" ), i + 1, text, i + 1 );
menu.Add( menuText, i + 1, item->GetMenuImage() );
}
menu.AppendSeparator();
menu.Add( _( "Select &All\tA" ), limit + 1, BITMAPS::INVALID_BITMAP );
if( !expandSelection && aCollector->HasAdditionalItems() )
menu.Add( _( "&Expand Selection\tE" ), limit + 2, BITMAPS::INVALID_BITMAP );
if( aCollector->m_MenuTitle.Length() )
{
menu.SetTitle( aCollector->m_MenuTitle );
menu.SetIcon( BITMAPS::info );
menu.DisplayTitle( true );
}
else
{
menu.DisplayTitle( false );
}
SetContextMenu( &menu, CMENU_NOW );
while( TOOL_EVENT* evt = Wait() )
{
if( evt->Action() == TA_CHOICE_MENU_UPDATE )
{
if( selectAll )
{
for( int i = 0; i < aCollector->GetCount(); ++i )
unhighlight( ( *aCollector )[i], BRIGHTENED, &highlightGroup );
}
else if( current )
{
unhighlight( current, BRIGHTENED, &highlightGroup );
}
int id = *evt->GetCommandId();
// User has pointed an item, so show it in a different way
if( id > 0 && id <= limit )
{
current = ( *aCollector )[id - 1];
highlight( current, BRIGHTENED, &highlightGroup );
}
else
{
current = nullptr;
}
// User has pointed on the "Select All" option
if( id == limit + 1 )
{
for( int i = 0; i < aCollector->GetCount(); ++i )
highlight( ( *aCollector )[i], BRIGHTENED, &highlightGroup );
selectAll = true;
}
else
{
selectAll = false;
}
}
else if( evt->Action() == TA_CHOICE_MENU_CHOICE )
{
if( selectAll )
{
for( int i = 0; i < aCollector->GetCount(); ++i )
unhighlight( ( *aCollector )[i], BRIGHTENED, &highlightGroup );
}
else if( current )
{
unhighlight( current, BRIGHTENED, &highlightGroup );
}
OPT<int> id = evt->GetCommandId();
// User has selected the "Select All" option
if( id == limit + 1 )
{
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 ) )
{
selectAll = false;
current = ( *aCollector )[*id - 1];
}
else
{
selectAll = false;
current = nullptr;
}
}
else if( evt->Action() == TA_CHOICE_MENU_CLOSED )
{
break;
}
}
} while( expandSelection );
getView()->Remove( &highlightGroup );
if( selectAll )
{
return true;
}
else if( current )
{
aCollector->Empty();
aCollector->Append( current );
return true;
}
return false;
}
bool PCB_SELECTION_TOOL::Selectable( const BOARD_ITEM* aItem, bool checkVisibilityOnly ) const
{
const RENDER_SETTINGS* settings = getView()->GetPainter()->GetSettings();
@ -2606,7 +2354,7 @@ bool PCB_SELECTION_TOOL::Selectable( const BOARD_ITEM* aItem, bool checkVisibili
}
void PCB_SELECTION_TOOL::select( BOARD_ITEM* aItem )
void PCB_SELECTION_TOOL::select( EDA_ITEM* aItem )
{
if( aItem->IsSelected() )
return;
@ -2623,13 +2371,13 @@ void PCB_SELECTION_TOOL::select( BOARD_ITEM* aItem )
}
void PCB_SELECTION_TOOL::unselect( BOARD_ITEM* aItem )
void PCB_SELECTION_TOOL::unselect( EDA_ITEM* aItem )
{
unhighlight( aItem, SELECTED, &m_selection );
}
void PCB_SELECTION_TOOL::highlight( BOARD_ITEM* aItem, int aMode, PCB_SELECTION* aGroup )
void PCB_SELECTION_TOOL::highlight( EDA_ITEM* aItem, int aMode, SELECTION* aGroup )
{
if( aGroup )
aGroup->Add( aItem );
@ -2644,7 +2392,7 @@ void PCB_SELECTION_TOOL::highlight( BOARD_ITEM* aItem, int aMode, PCB_SELECTION*
}
void PCB_SELECTION_TOOL::highlightInternal( BOARD_ITEM* aItem, int aMode, bool aUsingOverlay )
void PCB_SELECTION_TOOL::highlightInternal( EDA_ITEM* aItem, int aMode, bool aUsingOverlay )
{
if( aMode == SELECTED )
aItem->SetSelected();
@ -2673,7 +2421,7 @@ void PCB_SELECTION_TOOL::highlightInternal( BOARD_ITEM* aItem, int aMode, bool a
}
void PCB_SELECTION_TOOL::unhighlight( BOARD_ITEM* aItem, int aMode, PCB_SELECTION* aGroup )
void PCB_SELECTION_TOOL::unhighlight( EDA_ITEM* aItem, int aMode, SELECTION* aGroup )
{
if( aGroup )
aGroup->Remove( aItem );
@ -2687,7 +2435,7 @@ void PCB_SELECTION_TOOL::unhighlight( BOARD_ITEM* aItem, int aMode, PCB_SELECTIO
}
void PCB_SELECTION_TOOL::unhighlightInternal( BOARD_ITEM* aItem, int aMode, bool aUsingOverlay )
void PCB_SELECTION_TOOL::unhighlightInternal( EDA_ITEM* aItem, int aMode, bool aUsingOverlay )
{
if( aMode == SELECTED )
aItem->ClearSelected();
@ -3104,7 +2852,7 @@ void PCB_SELECTION_TOOL::FilterCollectorForFreePads( GENERAL_COLLECTOR& aCollect
{
BOARD_ITEM* item = aCollector[i];
if( !IsFootprintEditor() && item->Type() == PCB_PAD_T
if( !m_isFootprintEditor && item->Type() == PCB_PAD_T
&& !frame()->Settings().m_AllowFreePads )
{
if( !aCollector.HasItem( item->GetParent() ) )
@ -3141,21 +2889,6 @@ int PCB_SELECTION_TOOL::updateSelection( const TOOL_EVENT& aEvent )
}
int PCB_SELECTION_TOOL::UpdateMenu( const TOOL_EVENT& aEvent )
{
ACTION_MENU* actionMenu = aEvent.Parameter<ACTION_MENU*>();
CONDITIONAL_MENU* conditionalMenu = dynamic_cast<CONDITIONAL_MENU*>( actionMenu );
if( conditionalMenu )
conditionalMenu->Evaluate( m_selection );
if( actionMenu )
actionMenu->UpdateAll();
return 0;
}
void PCB_SELECTION_TOOL::setTransitions()
{
Go( &PCB_SELECTION_TOOL::UpdateMenu, ACTIONS::updateMenu.MakeEvent() );
@ -3164,10 +2897,10 @@ void PCB_SELECTION_TOOL::setTransitions()
Go( &PCB_SELECTION_TOOL::CursorSelection, PCB_ACTIONS::selectionCursor.MakeEvent() );
Go( &PCB_SELECTION_TOOL::ClearSelection, PCB_ACTIONS::selectionClear.MakeEvent() );
Go( &PCB_SELECTION_TOOL::SelectItem, PCB_ACTIONS::selectItem.MakeEvent() );
Go( &PCB_SELECTION_TOOL::SelectItems, PCB_ACTIONS::selectItems.MakeEvent() );
Go( &PCB_SELECTION_TOOL::UnselectItem, PCB_ACTIONS::unselectItem.MakeEvent() );
Go( &PCB_SELECTION_TOOL::UnselectItems, PCB_ACTIONS::unselectItems.MakeEvent() );
Go( &PCB_SELECTION_TOOL::AddItemToSel, PCB_ACTIONS::selectItem.MakeEvent() );
Go( &PCB_SELECTION_TOOL::AddItemsToSel, PCB_ACTIONS::selectItems.MakeEvent() );
Go( &PCB_SELECTION_TOOL::RemoveItemFromSel, PCB_ACTIONS::unselectItem.MakeEvent() );
Go( &PCB_SELECTION_TOOL::RemoveItemsFromSel, PCB_ACTIONS::unselectItems.MakeEvent() );
Go( &PCB_SELECTION_TOOL::SelectionMenu, PCB_ACTIONS::selectionMenu.MakeEvent() );
Go( &PCB_SELECTION_TOOL::filterSelection, PCB_ACTIONS::filterSelection.MakeEvent() );

View File

@ -61,7 +61,7 @@ typedef void (*CLIENT_SELECTION_FILTER)( const VECTOR2I&, GENERAL_COLLECTOR&, PC
* - takes into account high-contrast & layer visibility settings
* - invokes InteractiveEdit tool when user starts to drag selected items
*/
class PCB_SELECTION_TOOL : public SELECTION_TOOL, public PCB_TOOL_BASE
class PCB_SELECTION_TOOL : public SELECTION_TOOL
{
public:
PCB_SELECTION_TOOL();
@ -75,6 +75,11 @@ public:
void OnIdle( wxIdleEvent& aEvent );
bool IsFootprintEditor()
{
return m_isFootprintEditor;
}
/**
* The main loop.
*/
@ -103,26 +108,9 @@ public:
int ClearSelection( const TOOL_EVENT& aEvent );
void ClearSelection( bool aQuietMode = false );
///< Item selection event handler.
int SelectItem( const TOOL_EVENT& aEvent );
void AddItemToSel( BOARD_ITEM* aItem, bool aQuietMode = false );
///< Select all items on the board
int SelectAll( const TOOL_EVENT& aEvent );
///< Multiple item selection event handler
int SelectItems( const TOOL_EVENT& aEvent );
///< Item unselection event handler.
int UnselectItem( const TOOL_EVENT& aEvent );
void RemoveItemFromSel( BOARD_ITEM* aItem, bool aQuietMode = false );
///< Multiple item unselection event handler
int UnselectItems( const TOOL_EVENT& aEvent );
void BrightenItem( BOARD_ITEM* aItem );
void UnbrightenItem( BOARD_ITEM* aItem );
/**
* Handle finding an item. Does not do the actual searching, is called
* by the find dialog.
@ -136,7 +124,7 @@ public:
*
* @param aItem is an item to be selected.
*/
void select( BOARD_ITEM* aItem );
void select( EDA_ITEM* aItem ) override;
/**
* Check conditions for an item to be selected.
@ -154,14 +142,6 @@ public:
*/
void GuessSelectionCandidates( GENERAL_COLLECTOR& aCollector, const VECTOR2I& aWhere ) const;
/**
* Show a popup menu to trim the COLLECTOR passed as aEvent's parameter down to a single
* item.
*
* @note This routine **does not** modify the selection.
*/
int SelectionMenu( const TOOL_EVENT& aEvent );
/**
* Rebuild the selection from the EDA_ITEMs' selection flags.
*
@ -184,11 +164,6 @@ public:
///< Zoom the screen to fit the bounding box for cross probing/selection sync.
void zoomFitCrossProbeBBox( EDA_RECT bbox );
BOARD* GetBoard() const
{
return board();
}
void EnterGroup();
/**
@ -218,8 +193,35 @@ public:
void FilterCollectedItems( GENERAL_COLLECTOR& aCollector, bool aMultiSelect );
protected:
KIGFX::PCB_VIEW* view() const
{
return static_cast<KIGFX::PCB_VIEW*>( getView() );
}
KIGFX::VIEW_CONTROLS* controls() const
{
return getViewControls();
}
PCB_BASE_EDIT_FRAME* frame() const
{
return getEditFrame<PCB_BASE_EDIT_FRAME>();
}
BOARD* board() const
{
return getModel<BOARD>();
}
PCB_DRAW_PANEL_GAL* canvas() const
{
return static_cast<PCB_DRAW_PANEL_GAL*>( frame()->GetCanvas() );
}
virtual bool ctrlClickHighlights() override;
SELECTION& selection() override { return m_selection; }
private:
/**
@ -258,23 +260,6 @@ private:
*/
bool selectMultiple();
/**
* Allow the selection of a single item from a list via pop-up menu.
*
* The items are highlighted on the canvas when hovered in the menu. The collector is
* trimmed to the picked item.
*
* @return true if an item was picked
*/
bool doSelectionMenu( GENERAL_COLLECTOR* aItems );
/**
* Start the process to show our disambiguation menu once the user has kept
* the mouse down for the minimum time
* @param aEvent
*/
void onDisambiguationExpire( wxTimerEvent& aEvent );
/**
* Handle disambiguation actions including displaying the menu.
*/
@ -357,7 +342,7 @@ private:
*
* @param aItem is an item to be unselected.
*/
void unselect( BOARD_ITEM* aItem );
void unselect( EDA_ITEM* aItem ) override;
/**
* Highlight the item visually.
@ -366,7 +351,7 @@ private:
* @param aHighlightMode should be either SELECTED or BRIGHTENED
* @param aGroup is the group to add the item to in the BRIGHTENED mode.
*/
void highlight( BOARD_ITEM* aItem, int aHighlightMode, PCB_SELECTION* aGroup = nullptr );
void highlight( EDA_ITEM* aItem, int aHighlightMode, SELECTION* aGroup = nullptr ) override;
/**
* Unhighlight the item visually.
@ -375,7 +360,7 @@ private:
* @param aHighlightMode should be either SELECTED or BRIGHTENED
* @param aGroup is the group to remove the item from.
*/
void unhighlight( BOARD_ITEM* aItem, int aHighlightMode, PCB_SELECTION* aGroup = nullptr );
void unhighlight( EDA_ITEM* aItem, int aHighlightMode, SELECTION* aGroup = nullptr ) override;
/**
* @return True if the given point is contained in any of selected items' bounding box.
@ -389,20 +374,17 @@ private:
*/
int updateSelection( const TOOL_EVENT& aEvent );
/**
* Pass the selection to a conditional menu for updating.
*/
int UpdateMenu( const TOOL_EVENT& aEvent );
const GENERAL_COLLECTORS_GUIDE getCollectorsGuide() const;
private:
void highlightInternal( BOARD_ITEM* aItem, int aHighlightMode, bool aUsingOverlay );
void highlightInternal( EDA_ITEM* aItem, int aHighlightMode, bool aUsingOverlay );
void unhighlightInternal( BOARD_ITEM* aItem, int aHighlightMode, bool aUsingOverlay );
void unhighlightInternal( EDA_ITEM* aItem, int aHighlightMode, bool aUsingOverlay );
private:
PCB_BASE_FRAME* m_frame; // Pointer to the parent frame
bool m_isFootprintEditor;
PCB_SELECTION m_selection; // Current state of selection
SELECTION_FILTER_OPTIONS m_filter;

View File

@ -191,7 +191,7 @@ public:
PCB_SELECTION_TOOL::PCB_SELECTION_TOOL() :
PCB_TOOL_BASE( "pcbnew.InteractiveSelection" ),
SELECTION_TOOL( "pcbnew.InteractiveSelection" ),
m_frame( NULL ),
m_enteredGroup( NULL ),
m_nonModifiedCursor( KICURSOR::ARROW ),
@ -283,56 +283,12 @@ int PCB_SELECTION_TOOL::ClearSelection( const TOOL_EVENT& aEvent )
}
int PCB_SELECTION_TOOL::SelectItems( const TOOL_EVENT& aEvent )
{
return 0;
}
int PCB_SELECTION_TOOL::SelectItem( const TOOL_EVENT& aEvent )
{
return 0;
}
int PCB_SELECTION_TOOL::SelectAll( const TOOL_EVENT& aEvent )
{
return 0;
}
void PCB_SELECTION_TOOL::AddItemToSel( BOARD_ITEM* aItem, bool aQuietMode )
{
}
int PCB_SELECTION_TOOL::UnselectItems( const TOOL_EVENT& aEvent )
{
return 0;
}
int PCB_SELECTION_TOOL::UnselectItem( const TOOL_EVENT& aEvent )
{
return 0;
}
void PCB_SELECTION_TOOL::RemoveItemFromSel( BOARD_ITEM* aItem, bool aQuietMode )
{
}
void PCB_SELECTION_TOOL::BrightenItem( BOARD_ITEM* aItem )
{
}
void PCB_SELECTION_TOOL::UnbrightenItem( BOARD_ITEM* aItem )
{
}
int PCB_SELECTION_TOOL::expandConnection( const TOOL_EVENT& aEvent )
{
return 0;
@ -425,52 +381,12 @@ void PCB_SELECTION_TOOL::RebuildSelection()
}
int PCB_SELECTION_TOOL::SelectionMenu( const TOOL_EVENT& aEvent )
{
return 0;
}
bool PCB_SELECTION_TOOL::doSelectionMenu( GENERAL_COLLECTOR* aCollector )
{
return false;
}
bool PCB_SELECTION_TOOL::Selectable( const BOARD_ITEM* aItem, bool checkVisibilityOnly ) const
{
return false;
}
void PCB_SELECTION_TOOL::select( BOARD_ITEM* aItem )
{
}
void PCB_SELECTION_TOOL::unselect( BOARD_ITEM* aItem )
{
}
void PCB_SELECTION_TOOL::highlight( BOARD_ITEM* aItem, int aMode, PCB_SELECTION* aGroup )
{
}
void PCB_SELECTION_TOOL::highlightInternal( BOARD_ITEM* aItem, int aMode, bool aUsingOverlay )
{
}
void PCB_SELECTION_TOOL::unhighlight( BOARD_ITEM* aItem, int aMode, PCB_SELECTION* aGroup )
{
}
void PCB_SELECTION_TOOL::unhighlightInternal( BOARD_ITEM* aItem, int aMode, bool aUsingOverlay )
{
}
bool PCB_SELECTION_TOOL::selectionContains( const VECTOR2I& aPoint ) const
{
return false;
@ -490,12 +406,6 @@ int PCB_SELECTION_TOOL::updateSelection( const TOOL_EVENT& aEvent )
}
int PCB_SELECTION_TOOL::UpdateMenu( const TOOL_EVENT& aEvent )
{
return 0;
}
void PCB_SELECTION_TOOL::setTransitions()
{
}