Implement SCH_SELECTION_TOOL (but still with legacy semantics).

This commit is contained in:
Jeff Young 2019-04-22 00:45:34 +01:00
parent e885d739a4
commit 1a007c3e4b
40 changed files with 1365 additions and 592 deletions

View File

@ -139,3 +139,16 @@ TOOL_ACTION ACTIONS::gridResetOrigin( "common.Control.gridResetOrigin",
TOOL_ACTION ACTIONS::gridPreset( "common.Control.gridPreset",
AS_GLOBAL, 0,
"", "" );
// System-wide selection Events
///> Event sent after an item is selected.
const TOOL_EVENT EVENTS::SelectedEvent( TC_MESSAGE, TA_ACTION, "common.Interactive.selected" );
///> Event sent after an item is unselected.
const TOOL_EVENT EVENTS::UnselectedEvent( TC_MESSAGE, TA_ACTION, "common.Interactive.unselected" );
///> Event sent after selection is cleared.
const TOOL_EVENT EVENTS::ClearedEvent( TC_MESSAGE, TA_ACTION, "common.Interactive.cleared" );

View File

@ -164,7 +164,6 @@ set( EESCHEMA_SRCS
generate_alias_info.cpp
getpart.cpp
hierarch.cpp
tools/sch_editor_control.cpp
hotkeys.cpp
lib_arc.cpp
lib_bezier.cpp
@ -244,6 +243,8 @@ set( EESCHEMA_SRCS
tools/sch_actions.cpp
tools/sch_drawing_tool.cpp
tools/sch_edit_tool.cpp
tools/sch_editor_control.cpp
tools/sch_picker_tool.cpp
tools/sch_selection_tool.cpp
tools/selection.cpp

View File

@ -63,6 +63,8 @@
#include <kiface_i.h>
#include <vector>
#include <algorithm>
#include <tool/tool_manager.h>
#include <tools/sch_selection_tool.h>
#define FIELD_PADDING 10 // arbitrarily chosen for aesthetics
#define FIELD_PADDING_ALIGNED 18 // aligns 50 mil text to a 100 mil grid
@ -683,6 +685,7 @@ const AUTOPLACER::SIDE AUTOPLACER::SIDE_RIGHT( 1, 0 );
void SCH_EDIT_FRAME::OnAutoplaceFields( wxCommandEvent& aEvent )
{
SCH_SELECTION_TOOL* selTool = GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
SCH_SCREEN* screen = GetScreen();
SCH_ITEM* item = screen->GetCurItem();
@ -692,9 +695,8 @@ void SCH_EDIT_FRAME::OnAutoplaceFields( wxCommandEvent& aEvent )
if( aEvent.GetInt() == 0 )
return;
EDA_HOTKEY_CLIENT_DATA& data = dynamic_cast<EDA_HOTKEY_CLIENT_DATA&>(
*aEvent.GetClientObject() );
item = LocateItem( data.GetPosition(), SCH_COLLECTOR::MovableItems, aEvent.GetInt() );
auto& data = dynamic_cast<EDA_HOTKEY_CLIENT_DATA&>( *aEvent.GetClientObject() );
item = selTool->SelectPoint( data.GetPosition(), SCH_COLLECTOR::MovableItems );
screen->SetCurItem( NULL );
if( !item || item->GetEditFlags() )

View File

@ -23,224 +23,16 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* eeschema/controle.cpp
*/
#include <fctsys.h>
#include <gr_basic.h>
#include <sch_draw_panel.h>
#include <eda_dde.h>
#include <sch_edit_frame.h>
#include <menus_helpers.h>
#include <msgpanel.h>
#include <bitmaps.h>
#include <eeschema_id.h>
#include <general.h>
#include <hotkeys.h>
#include <lib_edit_frame.h>
#include <viewlib_frame.h>
#include <lib_draw_item.h>
#include <lib_pin.h>
#include <sch_sheet.h>
#include <sch_sheet_path.h>
#include <sch_marker.h>
#include <sch_component.h>
#include <sch_view.h>
SCH_ITEM* SCH_EDIT_FRAME::LocateAndShowItem( const wxPoint& aPosition, const KICAD_T aFilterList[],
int aHotKeyCommandId,
bool* aClarificationMenuCancelled )
{
SCH_ITEM* item;
LIB_PIN* Pin = NULL;
SCH_COMPONENT* component = NULL;
wxPoint gridPosition = GetNearestGridPosition( aPosition );
// Check the on grid position first. There is more likely to be multiple items on
// grid than off grid.
m_canvas->SetAbortRequest( false ); // be sure a old abort request in not pending
item = LocateItem( gridPosition, aFilterList, aHotKeyCommandId );
// If the user aborted the clarification context menu, don't show it again at the
// off grid position.
if( !item && m_canvas->GetAbortRequest() )
{
if( aClarificationMenuCancelled )
*aClarificationMenuCancelled = true;
m_canvas->SetAbortRequest( false );
return NULL;
}
if( !item && (aPosition != gridPosition) )
item = LocateItem( aPosition, aFilterList, aHotKeyCommandId );
if( !item )
{
if( aClarificationMenuCancelled )
*aClarificationMenuCancelled = m_canvas->GetAbortRequest();
m_canvas->SetAbortRequest( false ); // Just in case the user aborted the context menu.
return NULL;
}
// Cross probing to Pcbnew if a pin or a component is found
switch( item->Type() )
{
case SCH_FIELD_T:
case LIB_FIELD_T:
component = (SCH_COMPONENT*) item->GetParent();
SendMessageToPCBNEW( item, component );
break;
case SCH_COMPONENT_T:
component = (SCH_COMPONENT*) item;
SendMessageToPCBNEW( item, component );
break;
case LIB_PIN_T:
Pin = (LIB_PIN*) item;
component = (SCH_COMPONENT*) LocateItem( aPosition, SCH_COLLECTOR::ComponentsOnly );
break;
/* case SCH_SHEET_T: */
/* // This may lag on larger projects */
/* SendMessageToPCBNEW( item, nullptr ); */
/* break; */
default:
;
}
if( Pin )
{
// Force display pin information (the previous display could be a component info)
MSG_PANEL_ITEMS items;
Pin->GetMsgPanelInfo( m_UserUnits, items, component );
SetMsgPanel( items );
// Cross probing:2 - pin found, and send a locate pin command to Pcbnew (highlight net)
SendMessageToPCBNEW( Pin, component );
}
return item;
}
SCH_ITEM* SCH_EDIT_FRAME::LocateItem( const wxPoint& aPosition, const KICAD_T aFilterList[],
int aHotKeyCommandId )
{
SCH_ITEM* item = NULL;
m_collectedItems.Collect( GetScreen()->GetDrawItems(), aFilterList, aPosition );
if( m_collectedItems.GetCount() == 0 )
{
ClearMsgPanel();
}
else if( m_collectedItems.GetCount() == 1 )
{
item = m_collectedItems[0];
}
else
{
// There are certain parent/child and enclosure combinations that can be handled
// automatically. Since schematics are meant to be human-readable we don't have
// all the various overlap and coverage issues that we do in Pcbnew.
if( m_collectedItems.GetCount() == 2 )
{
SCH_ITEM* a = m_collectedItems[ 0 ];
SCH_ITEM* b = m_collectedItems[ 1 ];
if( a->GetParent() == b )
item = a;
else if( a == b->GetParent() )
item = b;
else if( a->Type() == SCH_SHEET_T && b->Type() != SCH_SHEET_T )
item = b;
else if( b->Type() == SCH_SHEET_T && a->Type() != SCH_SHEET_T )
item = a;
}
// There are certain combinations of items that do not need clarification such as
// a corner were two lines meet or all the items form a junction.
if( aHotKeyCommandId )
{
switch( aHotKeyCommandId )
{
case HK_DRAG:
if( m_collectedItems.IsCorner() || m_collectedItems.IsNode( false )
|| m_collectedItems.IsDraggableJunction() )
{
item = m_collectedItems[0];
}
break;
case HK_MOVE_COMPONENT_OR_ITEM:
if( m_collectedItems.GetCount() == 2 &&
dynamic_cast< SCH_SHEET_PIN * >( m_collectedItems[0] ) &&
dynamic_cast< SCH_SHEET * >( m_collectedItems[1] ) )
{
item = m_collectedItems[0];
}
break;
default:
;
}
}
if( item == NULL )
{
wxASSERT_MSG( m_collectedItems.GetCount() <= MAX_SELECT_ITEM_IDS,
wxT( "Select item clarification context menu size limit exceeded." ) );
wxMenu selectMenu;
AddMenuItem( &selectMenu, wxID_NONE, _( "Clarify Selection" ), KiBitmap( info_xpm ) );
selectMenu.AppendSeparator();
for( int i = 0; i < m_collectedItems.GetCount() && i < MAX_SELECT_ITEM_IDS; i++ )
{
wxString text = m_collectedItems[i]->GetSelectMenuText( m_UserUnits );
BITMAP_DEF xpm = m_collectedItems[i]->GetMenuImage();
AddMenuItem( &selectMenu, ID_SELECT_ITEM_START + i, text, KiBitmap( xpm ) );
}
// Set to NULL in case the user aborts the clarification context menu.
GetScreen()->SetCurItem( NULL );
m_canvas->SetAbortRequest( true ); // Changed to false if an item is selected
PopupMenu( &selectMenu );
if( !m_canvas->GetAbortRequest() )
{
m_canvas->MoveCursorToCrossHair();
item = GetScreen()->GetCurItem();
}
}
}
GetScreen()->SetCurItem( item );
if( item )
{
MSG_PANEL_ITEMS items;
item->GetMsgPanelInfo( m_UserUnits, items );
SetMsgPanel( items );
}
else
{
ClearMsgPanel();
}
return item;
}
bool SCH_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, EDA_KEY aHotKey )
{
// Filter out the 'fake' mouse motion after a keyboard movement

View File

@ -143,22 +143,29 @@ void SCH_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline )
}
std::string FormatProbeItem( EDA_ITEM* aItem, SCH_COMPONENT* aPart )
std::string FormatProbeItem( EDA_ITEM* aItem, SCH_COMPONENT* aComp )
{
// This is a keyword followed by a quoted string.
// Cross probing to Pcbnew if a pin or a component is found
switch( aItem->Type() )
{
case SCH_FIELD_T:
case LIB_PIN_T:
wxFAIL_MSG( "What are we doing with LIB_* items here?" );
break;
case LIB_FIELD_T:
if( aPart )
return StrPrintf( "$PART: \"%s\"", TO_UTF8( aPart->GetField( REFERENCE )->GetText() ) );
wxFAIL_MSG( "What are we doing with LIB_* items here?" );
// fall through to SCH_FIELD_T:
case SCH_FIELD_T:
if( aComp )
return StrPrintf( "$PART: \"%s\"", TO_UTF8( aComp->GetField( REFERENCE )->GetText() ) );
break;
case SCH_COMPONENT_T:
aPart = (SCH_COMPONENT*) aItem;
return StrPrintf( "$PART: \"%s\"", TO_UTF8( aPart->GetField( REFERENCE )->GetText() ) );
aComp = (SCH_COMPONENT*) aItem;
return StrPrintf( "$PART: \"%s\"", TO_UTF8( aComp->GetField( REFERENCE )->GetText() ) );
case SCH_SHEET_T:
{
@ -166,24 +173,23 @@ std::string FormatProbeItem( EDA_ITEM* aItem, SCH_COMPONENT* aPart )
return StrPrintf( "$SHEET: \"%8.8lX\"", (unsigned long) sheet->GetTimeStamp() );
}
case LIB_PIN_T:
case SCH_PIN_T:
{
if( !aPart )
break;
LIB_PIN* pin = (LIB_PIN*) aItem;
SCH_PIN* pin = (SCH_PIN*) aItem;
aComp = pin->GetParentComponent();
if( !pin->GetNumber().IsEmpty() )
{
return StrPrintf( "$PIN: \"%s\" $PART: \"%s\"", TO_UTF8( pin->GetNumber() ),
TO_UTF8( aPart->GetField( REFERENCE )->GetText() ) );
return StrPrintf( "$PIN: \"%s\" $PART: \"%s\"",
TO_UTF8( pin->GetNumber() ),
TO_UTF8( aComp->GetField( REFERENCE )->GetText() ) );
}
else
{
return StrPrintf( "$PART: \"%s\"", TO_UTF8( aPart->GetField( REFERENCE )->GetText() ) );
return StrPrintf( "$PART: \"%s\"",
TO_UTF8( aComp->GetField( REFERENCE )->GetText() ) );
}
}
break;
default:
break;

View File

@ -39,6 +39,8 @@
#include <sch_sheet.h>
#include <dialogs/dialog_schematic_find.h>
#include <tool/tool_manager.h>
#include <tools/sch_selection_tool.h>
// Remark: the hotkey message info is used as keyword in hotkey config files and
// as comments in help windows, therefore translated only when displayed
@ -610,7 +612,8 @@ bool SCH_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition,
if( aItem == NULL )
{
aItem = LocateAndShowItem( aPosition, SCH_COLLECTOR::CopyableItems );
SCH_SELECTION_TOOL* selTool = GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
aItem = selTool->SelectPoint( aPosition, SCH_COLLECTOR::CopyableItems );
if( aItem == NULL )
break;

View File

@ -99,7 +99,7 @@ public:
* @param aIndex The index into the list.
* @return LIB_ITEM* at \a aIndex or NULL.
*/
LIB_ITEM* operator[]( int aIndex ) const
LIB_ITEM* operator[]( int aIndex ) const override
{
if( (unsigned)aIndex < (unsigned)GetCount() )
return (LIB_ITEM*) m_List[ aIndex ];

View File

@ -34,10 +34,13 @@
#include <sch_bitmap.h>
#include <netlist_object.h>
#include <sch_view.h>
#include <tool/tool_manager.h>
#include <tools/sch_selection_tool.h>
void SCH_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition )
{
SCH_ITEM* item = GetScreen()->GetCurItem();
SCH_SELECTION_TOOL* selTool = GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
if( GetToolId() == ID_NO_TOOL_SELECTED )
{
@ -76,7 +79,7 @@ void SCH_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition )
}
else
{
item = LocateAndShowItem( aPosition );
item = selTool->SelectPoint( aPosition );
}
}
@ -96,7 +99,7 @@ void SCH_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition )
SCH_COMPONENT_T,
SCH_SHEET_PIN_T,
EOT };
item = LocateAndShowItem( aPosition, wiresAndComponents );
item = selTool->SelectPoint( aPosition, wiresAndComponents );
if( !item )
break;
@ -121,7 +124,7 @@ void SCH_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition )
case ID_SIM_TUNE:
{
constexpr KICAD_T fieldsAndComponents[] = { SCH_COMPONENT_T, SCH_FIELD_T, EOT };
item = LocateAndShowItem( aPosition, fieldsAndComponents );
item = selTool->SelectPoint( aPosition, fieldsAndComponents );
if( !item )
return;
@ -159,13 +162,14 @@ void SCH_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition )
void SCH_EDIT_FRAME::OnLeftDClick( wxDC* aDC, const wxPoint& aPosition )
{
SCH_SELECTION_TOOL* selTool = GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
EDA_ITEM* item = GetScreen()->GetCurItem();
switch( GetToolId() )
{
case ID_NO_TOOL_SELECTED:
if( item == NULL || item->GetEditFlags() == 0 )
item = LocateAndShowItem( aPosition, SCH_COLLECTOR::DoubleClickItems );
item = selTool->SelectPoint( aPosition, SCH_COLLECTOR::DoubleClickItems );
if( item == NULL || item->GetEditFlags() != 0 )
break;

View File

@ -54,7 +54,9 @@
#include <sch_view.h>
#include <iostream>
#include <tool/tool_manager.h>
#include <tools/sch_actions.h>
#include <tools/sch_selection_tool.h>
static void AddMenusForBlock( wxMenu* PopMenu, SCH_EDIT_FRAME* frame );
static void AddMenusForWire( wxMenu* PopMenu, SCH_LINE* Wire, SCH_EDIT_FRAME* frame );
@ -77,6 +79,7 @@ static void AddMenusForBusEntry( wxMenu* aPopMenu, SCH_BUS_ENTRY_BASE * aBusEntr
bool SCH_EDIT_FRAME::OnRightClick( const wxPoint& aPosition, wxMenu* PopMenu )
{
SCH_SELECTION_TOOL* selTool = GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
SCH_ITEM* item = GetScreen()->GetCurItem();
bool blockActive = GetScreen()->IsBlockActive();
wxString msg;
@ -147,7 +150,7 @@ bool SCH_EDIT_FRAME::OnRightClick( const wxPoint& aPosition, wxMenu* PopMenu )
if( item == NULL || item->GetEditFlags() == 0 )
{
bool actionCancelled = false;
item = LocateAndShowItem( aPosition, SCH_COLLECTOR::AllItemsButPins, 0, &actionCancelled );
item = selTool->SelectPoint( aPosition, SCH_COLLECTOR::AllItemsButPins, &actionCancelled );
// If the clarify item selection context menu is aborted, don't show the context menu.
if( item == NULL && actionCancelled )
@ -744,6 +747,7 @@ void AddMenusForWire( wxMenu* PopMenu, SCH_LINE* Wire, SCH_EDIT_FRAME* frame )
void AddMenusForBus( wxMenu* PopMenu, SCH_LINE* Bus, SCH_EDIT_FRAME* frame )
{
SCH_SELECTION_TOOL* selTool = frame->GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
wxPoint pos = frame->GetCrossHairPosition();
wxString msg;
@ -773,8 +777,8 @@ void AddMenusForBus( wxMenu* PopMenu, SCH_LINE* Bus, SCH_EDIT_FRAME* frame )
// Have to pick up the pointer again because it may have been changed by SchematicCleanUp
bool actionCancelled = false;
Bus = dynamic_cast<SCH_LINE*>( frame->LocateAndShowItem( pos, SCH_COLLECTOR::AllItemsButPins,
0, &actionCancelled ) );
Bus = dynamic_cast<SCH_LINE*>( selTool->SelectPoint( pos, SCH_COLLECTOR::AllItemsButPins,
&actionCancelled ) );
wxASSERT( Bus );
}

View File

@ -110,6 +110,11 @@ public:
KIGFX::SCH_RENDER_SETTINGS* GetRenderSettings();
/**
* Allow some frames to show/hide hidden pins. The default impl shows all pins.
*/
virtual bool GetShowAllPins() const { return true; }
/**
* switches currently used canvas ( Cairo / OpenGL).
*/

View File

@ -51,7 +51,7 @@ const KICAD_T SCH_COLLECTOR::AllItems[] = {
SCH_HIER_LABEL_T,
SCH_FIELD_T,
SCH_COMPONENT_T,
LIB_PIN_T,
SCH_PIN_T,
SCH_SHEET_PIN_T,
SCH_SHEET_T,
EOT
@ -238,43 +238,21 @@ const KICAD_T SCH_COLLECTOR::DoubleClickItems[] = {
SEARCH_RESULT SCH_COLLECTOR::Inspect( EDA_ITEM* aItem, void* aTestData )
{
if( aItem->Type() != LIB_PIN_T && !aItem->HitTest( m_RefPos ) )
return SEARCH_CONTINUE;
// Pins have special hit testing requirements that are relative to their parent
// SCH_COMPONENT item.
if( aItem->Type() == LIB_PIN_T )
{
wxCHECK_MSG( aTestData && ( (EDA_ITEM*) aTestData )->Type() == SCH_COMPONENT_T,
SEARCH_CONTINUE, wxT( "Cannot inspect invalid data. Bad programmer!" ) );
// Pin hit testing is relative to the components position and orientation in the
// schematic. The hit test position must be converted to library coordinates.
SCH_COMPONENT* component = (SCH_COMPONENT*) aTestData;
TRANSFORM transform = component->GetTransform().InverseTransform();
wxPoint position = transform.TransformCoordinate( m_RefPos - component->GetPosition() );
position.y *= -1; // Y axis polarity in schematic is inverted from library.
if( !aItem->HitTest( position ) )
return SEARCH_CONTINUE;
}
if( aItem->HitTest( m_RefPos ) )
Append( aItem );
return SEARCH_CONTINUE;
}
void SCH_COLLECTOR::Collect( SCH_ITEM* aItem, const KICAD_T aFilterList[],
const wxPoint& aPosition )
void SCH_COLLECTOR::Collect( SCH_ITEM* aItem, const KICAD_T aFilterList[], const wxPoint& aPos )
{
Empty(); // empty the collection just in case
SetScanTypes( aFilterList );
// remember where the snapshot was taken from and pass refPos to the Inspect() function.
SetRefPos( aPosition );
SetRefPos( aPos );
EDA_ITEM::IterateForward( aItem, m_inspector, NULL, m_ScanTypes );
}
@ -319,7 +297,7 @@ bool SCH_COLLECTOR::IsNode( bool aIncludePins ) const
continue;
}
if( type == LIB_PIN_T )
if( type == SCH_PIN_T )
{
if( !aIncludePins )
return false;
@ -559,7 +537,7 @@ SEARCH_RESULT SCH_FIND_COLLECTOR::Inspect( EDA_ITEM* aItem, void* aTestData )
if( aItem->Matches( m_findReplaceData, m_currentSheetPath, &position ) )
{
if( aItem->Type() == LIB_PIN_T )
if( aItem->Type() == SCH_PIN_T )
{
wxCHECK_MSG( aTestData && ( (EDA_ITEM*) aTestData )->Type() == SCH_COMPONENT_T,
SEARCH_CONTINUE, wxT( "Cannot inspect invalid data. Bad programmer!" ) );

View File

@ -142,7 +142,7 @@ public:
* @param aIndex The index into the list.
* @return SCH_ITEM* at \a aIndex or NULL.
*/
SCH_ITEM* operator[]( int aIndex ) const
SCH_ITEM* operator[]( int aIndex ) const override
{
if( (unsigned)aIndex < (unsigned)GetCount() )
return (SCH_ITEM*) m_List[ aIndex ];
@ -159,9 +159,9 @@ public:
* @param aFilterList A list of #KICAD_T types with a terminating #EOT, that determines
* what is to be collected and the priority order of the resulting
* collection.
* @param aPosition A wxPoint to use in hit-testing.
* @param aPos A wxPoint to use in hit-testing.
*/
void Collect( SCH_ITEM* aItem, const KICAD_T aFilterList[], const wxPoint& aPosition );
void Collect( SCH_ITEM* aItem, const KICAD_T aFilterList[], const wxPoint& aPos );
/**
* Function IsCorner
@ -289,7 +289,7 @@ public:
}
SCH_ITEM* GetItem( int ndx ) const;
SCH_ITEM* operator[]( int ndx ) const;
SCH_ITEM* operator[]( int ndx ) const override;
void SetForceSearch( bool doSearch = true ) { m_forceSearch = doSearch; }
@ -405,8 +405,7 @@ class SCH_TYPE_COLLECTOR : public SCH_COLLECTOR
public:
/**
* Function Inspect
* is the examining function within the INSPECTOR which is passed to the
* Iterate function.
* is the examining function within the INSPECTOR which is passed to the Iterate function.
*
* @param testItem An EDA_ITEM to examine.
* @param testData is not used in this class.
@ -417,12 +416,11 @@ public:
/**
* Function Collect
* scans a BOARD_ITEM using this class's Inspector method, which does
* the collection.
* @param aBoard The BOARD_ITEM to scan.
* scans a DLIST using this class's Inspector method, which does the collection.
* @param aItem The head of a DLIST to scan.
* @param aScanList The KICAD_Ts to gather up.
*/
void Collect( SCH_ITEM* aBoard, const KICAD_T aScanList[] );
void Collect( SCH_ITEM* aItem, const KICAD_T aScanList[] );
};

View File

@ -1612,19 +1612,12 @@ SEARCH_RESULT SCH_COMPONENT::Visit( INSPECTOR aInspector, void* aTestData,
return SEARCH_QUIT;
break;
case LIB_PIN_T:
if( PART_SPTR part = m_part.lock() )
case SCH_PIN_T:
for( SCH_PIN& pin : m_pins )
{
LIB_PINS pins;
part->GetPins( pins, m_unit, m_convert );
for( size_t i = 0; i < pins.size(); i++ )
{
if( SEARCH_QUIT == aInspector( pins[ i ], (void*) this ) )
if( SEARCH_QUIT == aInspector( &pin, (void*) this ) )
return SEARCH_QUIT;
}
}
break;
default:
@ -1728,7 +1721,7 @@ bool SCH_COMPONENT::operator!=( const SCH_COMPONENT& aComponent ) const
}
SCH_ITEM& SCH_COMPONENT::operator=( const SCH_ITEM& aItem )
SCH_COMPONENT& SCH_COMPONENT::operator=( const SCH_ITEM& aItem )
{
wxCHECK_MSG( Type() == aItem.Type(), *this,
wxT( "Cannot assign object type " ) + aItem.GetClass() + wxT( " to type " ) +

View File

@ -606,7 +606,7 @@ public:
bool operator==( const SCH_COMPONENT& aComponent) const;
bool operator!=( const SCH_COMPONENT& aComponent) const;
SCH_ITEM& operator=( const SCH_ITEM& aItem );
SCH_COMPONENT& operator=( const SCH_ITEM& aItem );
bool IsReplaceable() const override { return true; }

View File

@ -62,6 +62,7 @@
#include <view/view.h>
#include <tool/tool_manager.h>
#include <tools/sch_actions.h>
#include <tools/sch_selection_tool.h>
#include <wx/display.h>
#include <build_version.h>
@ -1107,6 +1108,7 @@ void SCH_EDIT_FRAME::OnOpenCvpcb( wxCommandEvent& event )
void SCH_EDIT_FRAME::OnOpenLibraryEditor( wxCommandEvent& event )
{
SCH_SELECTION_TOOL* selTool = GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
SCH_COMPONENT* component = NULL;
if( event.GetId() == ID_POPUP_SCH_CALL_LIBEDIT_AND_LOAD_CMP )
@ -1127,7 +1129,7 @@ void SCH_EDIT_FRAME::OnOpenLibraryEditor( wxCommandEvent& event )
// Set the locat filter, according to the edit command
const KICAD_T* filterList = SCH_COLLECTOR::ComponentsOnly;
item = LocateAndShowItem( data->GetPosition(), filterList, event.GetInt() );
item = selTool->SelectPoint( data->GetPosition(), filterList );
// Exit if no item found at the current location or the item is already being edited.
if( item == NULL || item->GetEditFlags() != 0 )

View File

@ -225,7 +225,7 @@ public:
bool GetForceHVLines() const { return m_forceHVLines; }
void SetForceHVLines( bool aForceHVdirection ) { m_forceHVLines = aForceHVdirection; }
bool GetShowAllPins() const { return m_showAllPins; }
bool GetShowAllPins() const override { return m_showAllPins; }
void SetShowAllPins( bool aEnable ) { m_showAllPins = aEnable; }
bool GetShowFootprintPreviews() const { return m_footprintPreview; }
@ -383,48 +383,6 @@ public:
*/
void AddItemToScreen( SCH_ITEM* aItem );
/**
* Check the schematic at \a aPosition in logical (drawing) units for a item
* matching the types in \a aFilterList.
* <p>
* The search is first performed at the nearest grid position to \a aPosition. If no
* item if found on grid, then \a aPosition is tested for any items. If the item found
* can be cross probed, a message is send to Pcbnew and the selected item is highlighted
* in PCB editor.
* </p>
*
* @param aPosition The wxPoint on the schematic to search.
* @param aFilterList A list of #KICAD_T types to to filter.
* @param aHotKeyCommandId A hot key command ID for performing additional tests when
* multiple items are found at \a aPosition.
* @param aClarifySelectionMenuCancelled is a pointer to a bool to handle a cancel command
* from user when the user cancels the locate menu disambiguation (selection between located items)
* @return A SCH_ITEM pointer of the item found or NULL if no item found
*/
SCH_ITEM* LocateAndShowItem( const wxPoint& aPosition,
const KICAD_T aFilterList[] = SCH_COLLECTOR::AllItems,
int aHotKeyCommandId = 0,
bool* aClarifySelectionMenuCancelled = nullptr );
/**
* Check for items at \a aPosition matching the types in \a aFilterList.
* <p>
* If multiple items are located at \a aPosition, a context menu is displayed to clarify
* which item the user intended to select. If the user aborts the context menu, NULL is
* returned and the abort request flag will be set to true. Make sure to clear this flag
* before attempting to display any other context menus.
* </p>
*
* @param aPosition The wxPoint location where to search.
* @param aFilterList A list of #KICAD_T types to to filter.
* @param aHotKeyCommandId A hot key command ID for performing additional tests when
* multiple items are found at \a aPosition.
* @return The SCH_ITEM pointer of the item found or NULL if no item found.
*/
SCH_ITEM* LocateItem( const wxPoint& aPosition,
const KICAD_T aFilterList[] = SCH_COLLECTOR::AllItems,
int aHotKeyCommandId = 0 );
/**
* Delete the item found under the cross hair. If multiple items are found at the
* cross hair position, a context menu is displayed to clarify which item to delete.

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
* Copyright (C) 2004-2017 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2004-2019 KiCad Developers, see change_log.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
@ -171,6 +171,17 @@ public:
wxPoint& GetStoredPos() { return m_storedPos; }
void SetStoredPos( wxPoint aPos ) { m_storedPos = aPos; }
/**
* Function IsLocked
* @return bool - true if the object is locked, else false
*/
virtual bool IsLocked() const { return false; }
/**
* Function SetLocked
* modifies 'lock' status for of the item.
*/
virtual void SetLocked( bool aLocked ) {}
/**
* Function GetLayer

View File

@ -46,6 +46,7 @@
#include <simulation_cursors.h>
#include <tool/tool_manager.h>
#include <tools/sch_actions.h>
#include <tools/sch_selection_tool.h>
void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
{
@ -364,6 +365,7 @@ void SCH_EDIT_FRAME::OnDuplicateItem( wxCommandEvent& event )
void SCH_EDIT_FRAME::OnMoveItem( wxCommandEvent& aEvent )
{
SCH_SELECTION_TOOL* selTool = GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
SCH_SCREEN* screen = GetScreen();
SCH_ITEM* item = screen->GetCurItem();
@ -381,8 +383,7 @@ void SCH_EDIT_FRAME::OnMoveItem( wxCommandEvent& aEvent )
wxCHECK_RET( data != NULL, wxT( "Invalid hot key client object." ) );
item = LocateAndShowItem( data->GetPosition(), SCH_COLLECTOR::MovableItems,
aEvent.GetInt() );
item = selTool->SelectPoint( data->GetPosition(), SCH_COLLECTOR::MovableItems );
// Exit if no item found at the current location or the item is already being edited.
if( item == NULL || item->GetEditFlags() != 0 )
@ -526,8 +527,10 @@ void SCH_EDIT_FRAME::DeleteConnection( bool aFullConnection )
bool SCH_EDIT_FRAME::DeleteItemAtCrossHair()
{
SCH_SELECTION_TOOL* selTool = GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
SCH_SCREEN* screen = GetScreen();
SCH_ITEM* item = LocateItem( GetCrossHairPosition(), SCH_COLLECTOR::ParentItems );
SCH_ITEM* item = selTool->SelectPoint( GetCrossHairPosition(), SCH_COLLECTOR::ParentItems );
if( item )
{
@ -693,12 +696,13 @@ void SCH_EDIT_FRAME::PrepareMoveItem( SCH_ITEM* aItem )
void SCH_EDIT_FRAME::SelectAllFromSheet( wxCommandEvent& aEvent )
{
SCH_SELECTION_TOOL* selTool = GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
SCH_SCREEN* screen = GetScreen();
SCH_ITEM* item = screen->GetCurItem();
if( item != NULL )
{
item = LocateAndShowItem( item->GetPosition() );
item = selTool->SelectPoint( item->GetPosition() );
SendMessageToPCBNEW( item, NULL );
}
else
@ -711,7 +715,7 @@ void SCH_EDIT_FRAME::SelectAllFromSheet( wxCommandEvent& aEvent )
wxCHECK_RET( data != NULL, wxT( "Invalid hot key client object." ) );
item = LocateAndShowItem( data->GetPosition() );
item = selTool->SelectPoint( data->GetPosition() );
SendMessageToPCBNEW( item, NULL );
}
}
@ -719,6 +723,7 @@ void SCH_EDIT_FRAME::SelectAllFromSheet( wxCommandEvent& aEvent )
void SCH_EDIT_FRAME::OnRotate( wxCommandEvent& aEvent )
{
SCH_SELECTION_TOOL* selTool = GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
SCH_SCREEN* screen = GetScreen();
SCH_ITEM* item = screen->GetCurItem();
BLOCK_SELECTOR& block = screen->m_BlockLocate;
@ -752,8 +757,7 @@ void SCH_EDIT_FRAME::OnRotate( wxCommandEvent& aEvent )
wxCHECK_RET( data != NULL, wxT( "Invalid hot key client object." ) );
item = LocateAndShowItem( data->GetPosition(), SCH_COLLECTOR::RotatableItems,
aEvent.GetInt() );
item = selTool->SelectPoint( data->GetPosition(), SCH_COLLECTOR::RotatableItems );
// Exit if no item found at the current location or the item is already being edited.
if( item == NULL || item->GetEditFlags() != 0 )
@ -852,6 +856,7 @@ void SCH_EDIT_FRAME::OnRotate( wxCommandEvent& aEvent )
void SCH_EDIT_FRAME::OnEditItem( wxCommandEvent& aEvent )
{
SCH_SELECTION_TOOL* selTool = GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
SCH_SCREEN* screen = GetScreen();
SCH_ITEM* item = screen->GetCurItem();
@ -894,11 +899,11 @@ void SCH_EDIT_FRAME::OnEditItem( wxCommandEvent& aEvent )
break;
}
item = LocateAndShowItem( data->GetPosition(), filterList, aEvent.GetInt() );
item = selTool->SelectPoint( data->GetPosition(), filterList );
// If no item found, and if an auxiliary filter exists, try to use it
if( !item && filterListAux )
item = LocateAndShowItem( data->GetPosition(), filterListAux, aEvent.GetInt() );
item = selTool->SelectPoint( data->GetPosition(), filterListAux );
// Exit if no item found at the current location or the item is already being edited.
if( item == NULL || item->GetEditFlags() != 0 )
@ -1014,6 +1019,7 @@ void SCH_EDIT_FRAME::OnEditItem( wxCommandEvent& aEvent )
void SCH_EDIT_FRAME::OnDragItem( wxCommandEvent& aEvent )
{
SCH_SELECTION_TOOL* selTool = GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
SCH_SCREEN* screen = GetScreen();
SCH_ITEM* item = screen->GetCurItem();
@ -1036,8 +1042,7 @@ void SCH_EDIT_FRAME::OnDragItem( wxCommandEvent& aEvent )
wxCHECK_RET( data != NULL, wxT( "Invalid hot key client object." ) );
item = LocateAndShowItem( data->GetPosition(), SCH_COLLECTOR::DraggableItems,
aEvent.GetInt() );
item = selTool->SelectPoint( data->GetPosition(), SCH_COLLECTOR::DraggableItems );
// Exit if no item found at the current location or the item is already being edited.
if( item == NULL || item->GetEditFlags() != 0 )
@ -1086,6 +1091,7 @@ void SCH_EDIT_FRAME::OnDragItem( wxCommandEvent& aEvent )
void SCH_EDIT_FRAME::OnOrient( wxCommandEvent& aEvent )
{
SCH_SELECTION_TOOL* selTool = GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
SCH_SCREEN* screen = GetScreen();
SCH_ITEM* item = screen->GetCurItem();
BLOCK_SELECTOR& block = screen->m_BlockLocate;
@ -1149,8 +1155,7 @@ void SCH_EDIT_FRAME::OnOrient( wxCommandEvent& aEvent )
wxCHECK_RET( data != NULL, wxT( "Invalid hot key client object." ) );
item = LocateAndShowItem( data->GetPosition(), SCH_COLLECTOR::OrientableItems,
aEvent.GetInt() );
item = selTool->SelectPoint( data->GetPosition(), SCH_COLLECTOR::OrientableItems );
// Exit if no item found at the current location or the item is already being edited.
if( item == NULL || item->GetEditFlags() != 0 )
@ -1231,8 +1236,9 @@ void SCH_EDIT_FRAME::OnOrient( wxCommandEvent& aEvent )
void SCH_EDIT_FRAME::OnUnfoldBusHotkey( wxCommandEvent& aEvent )
{
auto data = (EDA_HOTKEY_CLIENT_DATA*) aEvent.GetClientObject();
auto item = GetScreen()->GetCurItem();
SCH_SELECTION_TOOL* selTool = GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
EDA_HOTKEY_CLIENT_DATA* data = (EDA_HOTKEY_CLIENT_DATA*) aEvent.GetClientObject();
SCH_ITEM* item = GetScreen()->GetCurItem();
wxCHECK_RET( data != NULL, wxT( "Invalid hot key client object." ) );
@ -1242,8 +1248,7 @@ void SCH_EDIT_FRAME::OnUnfoldBusHotkey( wxCommandEvent& aEvent )
if( aEvent.GetInt() == 0 )
return;
item = LocateAndShowItem( data->GetPosition(), SCH_COLLECTOR::EditableItems,
aEvent.GetInt() );
item = selTool->SelectPoint( data->GetPosition(), SCH_COLLECTOR::EditableItems );
// Exit if no item found at the current location or the item is already being edited.
if( item == NULL || item->GetEditFlags() != 0 )

View File

@ -28,8 +28,8 @@
#include <tools/sch_editor_control.h>
#include <tools/sch_picker_tool.h>
#include <tools/sch_drawing_tool.h>
#include <sch_actions.h>
#include <tools/sch_selection_tool.h>
#include <tools/sch_actions.h>
#include <tool/zoom_tool.h>
OPT<TOOL_EVENT> SCH_ACTIONS::TranslateLegacyId( int aId )
@ -180,6 +180,7 @@ void SCH_ACTIONS::RegisterAllTools( TOOL_MANAGER* aToolManager )
{
aToolManager->RegisterTool( new COMMON_TOOLS );
aToolManager->RegisterTool( new ZOOM_TOOL );
aToolManager->RegisterTool( new SCH_SELECTION_TOOL );
aToolManager->RegisterTool( new SCH_EDITOR_CONTROL );
aToolManager->RegisterTool( new SCH_PICKER_TOOL );
aToolManager->RegisterTool( new SCH_DRAWING_TOOL );

View File

@ -112,6 +112,10 @@ public:
static TOOL_ACTION finishDrawing;
// Editing
static TOOL_ACTION editActivate;
static TOOL_ACTION move;
static TOOL_ACTION duplicate;
static TOOL_ACTION rotate;
static TOOL_ACTION properties;
static TOOL_ACTION addJunction;
static TOOL_ACTION addLabel;
@ -131,6 +135,7 @@ public:
// Net highlighting
static TOOL_ACTION highlightNet;
static TOOL_ACTION clearHighlight;
static TOOL_ACTION highlightNetSelection;
static TOOL_ACTION highlightNetCursor;

View File

@ -22,6 +22,7 @@
*/
#include "sch_drawing_tool.h"
#include "sch_selection_tool.h"
#include <sch_actions.h>
#include <sch_edit_frame.h>
@ -513,6 +514,7 @@ int SCH_DRAWING_TOOL::PlaceImage( const TOOL_EVENT& aEvent )
int SCH_DRAWING_TOOL::doTwoClickPlace( KICAD_T aType )
{
SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
VECTOR2I cursorPos = m_controls->GetCursorPosition();
SCH_ITEM* item = nullptr;
@ -569,8 +571,7 @@ int SCH_DRAWING_TOOL::doTwoClickPlace( KICAD_T aType )
item = m_frame->CreateNewImage();
break;
case SCH_SHEET_PIN_T:
item = m_frame->LocateAndShowItem( (wxPoint)cursorPos,
SCH_COLLECTOR::SheetsAndSheetLabels );
item = selTool->SelectPoint( cursorPos, SCH_COLLECTOR::SheetsAndSheetLabels );
if( item )
{
if( m_frame->GetToolId() == ID_IMPORT_HLABEL_BUTT )

View File

@ -0,0 +1,50 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 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 Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "sch_edit_tool.h"
#include <sch_actions.h>
#include <hotkeys.h>
#include <bitmaps.h>
TOOL_ACTION SCH_ACTIONS::editActivate( "eeschema.InteractiveEdit",
AS_GLOBAL, 0,
_( "Edit Activate" ), "", move_xpm, AF_ACTIVATE );
TOOL_ACTION SCH_ACTIONS::move( "eeschema.InteractiveEdit.move",
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_MOVE_COMPONENT_OR_ITEM ),
_( "Move" ), _( "Moves the selected item(s)" ), move_xpm, AF_ACTIVATE );
TOOL_ACTION SCH_ACTIONS::duplicate( "eeschema.InteractiveEdit.duplicate",
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_DUPLICATE_ITEM ),
_( "Duplicate" ), _( "Duplicates the selected item(s)" ), duplicate_xpm );
TOOL_ACTION SCH_ACTIONS::rotate( "eeschema.InteractiveEdit.rotate",
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_ROTATE ),
_( "Rotate" ), _( "Rotates selected item(s)" ),
rotate_ccw_xpm, AF_NONE );
TOOL_ACTION SCH_ACTIONS::properties( "eeschema.InteractiveEdit.properties",
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_EDIT ),
_( "Properties..." ), _( "Displays item properties dialog" ), config_xpm );

View File

@ -0,0 +1,34 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 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 Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef KICAD_SCH_EDIT_TOOL_H
#define KICAD_SCH_EDIT_TOOL_H
#include <tool/tool_interactive.h>
class SCH_EDIT_TOOL : public TOOL_INTERACTIVE
{
};
#endif //KICAD_SCH_EDIT_TOOL_H

View File

@ -34,8 +34,9 @@
#include <tool/tool_manager.h>
#include <tools/sch_actions.h>
#include <tools/sch_picker_tool.h>
#include <project.h>
#include <tools/sch_editor_control.h>
#include <tools/sch_selection_tool.h>
#include <project.h>
#include <hotkeys.h>
#include <advanced_config.h>
@ -45,6 +46,9 @@ TOOL_ACTION SCH_ACTIONS::refreshPreview( "eeschema.EditorControl.refreshPreview"
TOOL_ACTION SCH_ACTIONS::highlightNet( "eeschema.EditorControl.highlightNet",
AS_GLOBAL, 0, "", "" );
TOOL_ACTION SCH_ACTIONS::clearHighlight( "eeschema.EditorControl.clearHighlight",
AS_GLOBAL, 0, "", "" );
TOOL_ACTION SCH_ACTIONS::highlightNetSelection( "eeschema.EditorControl.highlightNetSelection",
AS_GLOBAL, 0, "", "" );
@ -115,6 +119,59 @@ bool SCH_EDITOR_CONTROL::Init()
}
int SCH_EDITOR_CONTROL::CrossProbeSchToPcb( const TOOL_EVENT& aEvent )
{
// Don't get in an infinite loop SCH -> PCB -> SCH -> PCB -> SCH -> ...
if( m_probingSchToPcb )
{
m_probingSchToPcb = false;
return 0;
}
SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
const SELECTION& selection = selTool->GetSelection();
if( selection.Size() == 1 )
{
SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.Front() );
SCH_COMPONENT* component;
switch( item->Type() )
{
case SCH_FIELD_T:
case LIB_FIELD_T:
component = (SCH_COMPONENT*) item->GetParent();
m_frame->SendMessageToPCBNEW( item, component );
break;
case SCH_COMPONENT_T:
component = (SCH_COMPONENT*) item;
m_frame->SendMessageToPCBNEW( item, component );
break;
case SCH_PIN_T:
component = (SCH_COMPONENT*) item->GetParent();
m_frame->SendMessageToPCBNEW( static_cast<SCH_PIN*>( item ), component );
break;
#if 0 // This is too slow on larger projects
case SCH_SHEET_T:
SendMessageToPCBNEW( item, nullptr );
break;
#endif
default:
;
}
}
return 0;
}
// A magic cookie token for clearing the highlight
static VECTOR2D CLEAR;
// TODO(JE) Probably use netcode rather than connection name here eventually
static bool highlightNet( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition )
{
@ -123,7 +180,7 @@ static bool highlightNet( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition )
EDA_ITEMS nodeList;
bool retVal = true;
if( editFrame->GetScreen()->GetNode( wxPoint( aPosition.x, aPosition.y ), nodeList ) )
if( aPosition != CLEAR && editFrame->GetScreen()->GetNode( (wxPoint) aPosition, nodeList ) )
{
if( TestDuplicateSheetNames( false ) > 0 )
{
@ -156,7 +213,7 @@ static bool highlightNet( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition )
int SCH_EDITOR_CONTROL::HighlightNet( const TOOL_EVENT& aEvent )
{
KIGFX::VIEW_CONTROLS* controls = getViewControls();
VECTOR2I gridPosition = controls->GetCursorPosition( true );
VECTOR2D gridPosition = controls->GetCursorPosition( true );
highlightNet( m_toolMgr, gridPosition );
@ -164,6 +221,14 @@ int SCH_EDITOR_CONTROL::HighlightNet( const TOOL_EVENT& aEvent )
}
int SCH_EDITOR_CONTROL::ClearHighlight( const TOOL_EVENT& aEvent )
{
highlightNet( m_toolMgr, CLEAR );
return 0;
}
int SCH_EDITOR_CONTROL::HighlightNetSelection( const TOOL_EVENT& aEvent )
{
SCH_SCREEN* screen = g_CurrentSheet->LastScreen();
@ -269,14 +334,15 @@ void SCH_EDITOR_CONTROL::setTransitions()
Go( &SCH_EDITOR_CONTROL::UnlockSelected, SCH_ACTIONS::unlock.MakeEvent() );
*/
Go( &SCH_EDITOR_CONTROL::CrossProbeSchToPcb, EVENTS::SelectedEvent );
Go( &SCH_EDITOR_CONTROL::CrossProbeSchToPcb, EVENTS::UnselectedEvent );
Go( &SCH_EDITOR_CONTROL::CrossProbeSchToPcb, EVENTS::ClearedEvent );
/*
Go( &SCH_EDITOR_CONTROL::CrossProbeSchToPcb, SELECTION_TOOL::SelectedEvent );
Go( &SCH_EDITOR_CONTROL::CrossProbeSchToPcb, SELECTION_TOOL::UnselectedEvent );
Go( &SCH_EDITOR_CONTROL::CrossProbeSchToPcb, SELECTION_TOOL::ClearedEvent );
Go( &SCH_EDITOR_CONTROL::CrossProbePcbToSch, SCH_ACTIONS::crossProbeSchToPcb.MakeEvent() );
*/
Go( &SCH_EDITOR_CONTROL::HighlightNet, SCH_ACTIONS::highlightNet.MakeEvent() );
Go( &SCH_EDITOR_CONTROL::ClearHighlight, SCH_ACTIONS::clearHighlight.MakeEvent() );
Go( &SCH_EDITOR_CONTROL::HighlightNetCursor, SCH_ACTIONS::highlightNetCursor.MakeEvent() );
Go( &SCH_EDITOR_CONTROL::HighlightNetSelection, SCH_ACTIONS::highlightNetSelection.MakeEvent() );
}

View File

@ -62,6 +62,9 @@ public:
///> Highlights net under the cursor.
int HighlightNet( const TOOL_EVENT& aEvent );
///> Removes any net highlighting
int ClearHighlight( const TOOL_EVENT& aEvent );
///> Highlights frame's SelectedNetName.
int HighlightNetSelection( const TOOL_EVENT& aEvent );
@ -73,8 +76,9 @@ private:
///> Sets up handlers for various events.
void setTransitions() override;
///> Pointer to the currently used edit frame.
SCH_EDIT_FRAME* m_frame;
SCH_EDIT_FRAME* m_frame; ///> Pointer to the currently used edit frame
bool m_probingSchToPcb; ///> Recursion guard when cross-probing to PCBNew
/// Menu model displayed by the tool.
TOOL_MENU m_menu;

View File

@ -23,34 +23,706 @@
#include <sch_actions.h>
#include <core/typeinfo.h>
#include <sch_selection_tool.h>
#include <sch_base_frame.h>
#include <sch_edit_frame.h>
#include <sch_component.h>
#include <sch_sheet.h>
#include <view/view.h>
#include <view/view_controls.h>
#include <view/view_group.h>
#include <tool/tool_event.h>
#include <tool/tool_manager.h>
#include <sch_actions.h>
#include <sch_collectors.h>
#include <painter.h>
#include <eeschema_id.h>
// Selection tool actions
TOOL_ACTION SCH_ACTIONS::selectionActivate( "eeschema.InteractiveSelection",
AS_GLOBAL, 0,
"", "", NULL, AF_ACTIVATE ); // No description, it is not supposed to be shown anywhere
AS_GLOBAL, 0, "", "", NULL, AF_ACTIVATE ); // No description, not shown anywhere
TOOL_ACTION SCH_ACTIONS::selectionCursor( "eeschema.InteractiveSelection.Cursor",
AS_GLOBAL, 0,
"", "" ); // No description, it is not supposed to be shown anywhere
AS_GLOBAL, 0, "", "" ); // No description, it is not supposed to be shown anywhere
TOOL_ACTION SCH_ACTIONS::selectionMenu( "eeschema.InteractiveSelection.SelectionMenu",
AS_GLOBAL, 0, "", "" ); // No description, it is not supposed to be shown anywhere
TOOL_ACTION SCH_ACTIONS::selectItem( "eeschema.InteractiveSelection.SelectItem",
AS_GLOBAL, 0,
"", "" ); // No description, it is not supposed to be shown anywhere
AS_GLOBAL, 0, "", "" ); // No description, it is not supposed to be shown anywhere
TOOL_ACTION SCH_ACTIONS::selectItems( "eeschema.InteractiveSelection.SelectItems",
AS_GLOBAL, 0,
"", "" ); // No description, it is not supposed to be shown anywhere
AS_GLOBAL, 0, "", "" ); // No description, it is not supposed to be shown anywhere
TOOL_ACTION SCH_ACTIONS::unselectItem( "eeschema.InteractiveSelection.UnselectItem",
AS_GLOBAL, 0,
"", "" ); // No description, it is not supposed to be shown anywhere
AS_GLOBAL, 0, "", "" ); // No description, it is not supposed to be shown anywhere
TOOL_ACTION SCH_ACTIONS::unselectItems( "eeschema.InteractiveSelection.UnselectItems",
AS_GLOBAL, 0,
"", "" ); // No description, it is not supposed to be shown anywhere
AS_GLOBAL, 0, "", "" ); // No description, it is not supposed to be shown anywhere
TOOL_ACTION SCH_ACTIONS::selectionClear( "eeschema.InteractiveSelection.Clear",
AS_GLOBAL, 0,
"", "" ); // No description, it is not supposed to be shown anywhere
AS_GLOBAL, 0, "", "" ); // No description, it is not supposed to be shown anywhere
SCH_SELECTION_TOOL::SCH_SELECTION_TOOL() :
TOOL_INTERACTIVE( "eeschema.InteractiveSelection" ),
m_frame( NULL ),
m_additive( false ),
m_subtractive( false ),
m_multiple( false ),
m_skip_heuristics( false ),
m_locked( true ),
m_menu( *this )
{
}
SCH_SELECTION_TOOL::~SCH_SELECTION_TOOL()
{
getView()->Remove( &m_selection );
}
bool SCH_SELECTION_TOOL::Init()
{
auto frame = getEditFrame<SCH_BASE_FRAME>();
if( frame )
m_menu.AddStandardSubMenus( *frame );
return true;
}
void SCH_SELECTION_TOOL::Reset( RESET_REASON aReason )
{
m_frame = getEditFrame<SCH_BASE_FRAME>();
m_locked = true;
if( aReason == TOOL_BASE::MODEL_RELOAD )
{
// Remove pointers to the selected items from containers without changing their
// properties (as they are already deleted while a new sheet is loaded)
m_selection.Clear();
getView()->GetPainter()->GetSettings()->SetHighlight( false );
}
else
// Restore previous properties of selected items and remove them from containers
clearSelection();
// Reinsert the VIEW_GROUP, in case it was removed from the VIEW
getView()->Remove( &m_selection );
getView()->Add( &m_selection );
}
int SCH_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
{
// Main loop: keep receiving events
while( OPT_TOOL_EVENT evt = Wait() )
{
// Should selected items be added to the current selection or
// become the new selection (discarding previously selected items)
m_additive = evt->Modifier( MD_SHIFT );
// Should selected items be REMOVED from the current selection?
// This will be ignored if the SHIFT modifier is pressed
m_subtractive = !m_additive && evt->Modifier( MD_CTRL );
// Is the user requesting that the selection list include all possible
// items without removing less likely selection candidates
m_skip_heuristics = !!evt->Modifier( MD_ALT );
// Single click? Select single object
if( evt->IsClick( BUT_LEFT ) )
{
if( evt->Modifier( MD_CTRL ) && dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
{
m_toolMgr->RunAction( SCH_ACTIONS::highlightNet, true );
}
else
{
// If no modifier keys are pressed, clear the selection
if( !m_additive )
clearSelection();
SelectPoint( evt->Position());
}
}
// right click? if there is any object - show the context menu
else if( evt->IsClick( BUT_RIGHT ) )
{
bool selectionCancelled = false;
if( m_selection.Empty() )
{
SelectPoint( evt->Position(), SCH_COLLECTOR::AllItems, &selectionCancelled );
m_selection.SetIsHover( true );
}
if( !selectionCancelled )
m_menu.ShowContextMenu( m_selection );
}
// double click? Display the properties window
else if( evt->IsDblClick( BUT_LEFT ) )
{
if( m_selection.Empty() )
SelectPoint( evt->Position());
m_toolMgr->RunAction( SCH_ACTIONS::properties );
}
// drag with LMB? Select multiple objects (or at least draw a selection box) or drag them
else if( evt->IsDrag( BUT_LEFT ) )
{
if( m_additive || m_subtractive || m_selection.Empty() )
{
// JEY TODO: move block selection to SCH_SELECTION_TOOL
//selectMultiple();
}
else
{
// Check if dragging has started within any of selected items bounding box
if( selectionContains( evt->Position() ) )
{
// Yes -> run the move tool and wait till it finishes
m_toolMgr->InvokeTool( "eeschema.InteractiveEdit" );
}
else
{
// No -> clear the selection list
clearSelection();
}
}
}
else if( evt->IsCancel() || evt->Action() == TA_UNDO_REDO_PRE )
{
clearSelection();
if( evt->IsCancel() && dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
m_toolMgr->RunAction( SCH_ACTIONS::clearHighlight, true );
}
else if( evt->Action() == TA_CONTEXT_MENU_CLOSED )
{
m_menu.CloseContextMenu( evt );
}
}
// This tool is supposed to be active forever
assert( false );
return 0;
}
SELECTION& SCH_SELECTION_TOOL::GetSelection()
{
return m_selection;
}
SCH_ITEM* SCH_SELECTION_TOOL::SelectPoint( const VECTOR2I& aWhere, const KICAD_T* aFilterList,
bool* aSelectionCancelledFlag, bool aCheckLocked )
{
SCH_COLLECTOR collector;
collector.Collect( m_frame->GetScreen()->GetDrawItems(), aFilterList, (wxPoint) aWhere );
bool anyCollected = collector.GetCount() != 0;
// Remove unselectable items
for( int i = collector.GetCount() - 1; i >= 0; --i )
{
if( !selectable( collector[ i ] ) )
collector.Remove( i );
if( aCheckLocked && collector[ i ]->IsLocked() )
collector.Remove( i );
}
m_selection.ClearReferencePoint();
// 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 )
{
if( !doSelectionMenu( &collector, _( "Clarify Selection" ) ) )
{
if( aSelectionCancelledFlag )
*aSelectionCancelledFlag = true;
m_frame->GetScreen()->SetCurItem( nullptr );
return nullptr;
}
}
if( collector.GetCount() == 1 )
{
SCH_ITEM* item = collector[ 0 ];
toggleSelection( item );
MSG_PANEL_ITEMS msgItems;
item->GetMsgPanelInfo( m_frame->GetUserUnits(), msgItems );
m_frame->SetMsgPanel( msgItems );
return item;
}
if( !m_additive && anyCollected )
clearSelection();
m_frame->ClearMsgPanel();
return nullptr;
}
void SCH_SELECTION_TOOL::guessSelectionCandidates( SCH_COLLECTOR& collector,
const VECTOR2I& aWhere )
{
// There are certain parent/child and enclosure combinations that can be handled
// automatically. Since schematics are meant to be human-readable we don't have
// all the various overlap and coverage issues that we do in Pcbnew.
if( collector.GetCount() == 2 )
{
SCH_ITEM* a = collector[ 0 ];
SCH_ITEM* b = collector[ 1 ];
if( a->GetParent() == b )
collector.Remove( b );
else if( a == b->GetParent() )
collector.Remove( a );
else if( a->Type() == SCH_SHEET_T && b->Type() != SCH_SHEET_T )
collector.Remove( a );
else if( b->Type() == SCH_SHEET_T && a->Type() != SCH_SHEET_T )
collector.Remove( b );
}
}
bool SCH_SELECTION_TOOL::selectCursor( const KICAD_T aFilterList[], bool aForceSelect )
{
if( aForceSelect || m_selection.Empty() )
{
VECTOR2D cursorPos = getViewControls()->GetCursorPosition( false );
clearSelection();
SelectPoint( cursorPos, aFilterList );
}
return !m_selection.Empty();
}
int SCH_SELECTION_TOOL::SelectItems( const TOOL_EVENT& aEvent )
{
std::vector<SCH_ITEM*>* items = aEvent.Parameter<std::vector<SCH_ITEM*>*>();
if( items )
{
// Perform individual selection of each item before processing the event.
for( auto item : *items )
select( item );
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
}
return 0;
}
int SCH_SELECTION_TOOL::SelectItem( const TOOL_EVENT& aEvent )
{
// Check if there is an item to be selected
SCH_ITEM* item = aEvent.Parameter<SCH_ITEM*>();
if( item )
{
select( item );
// Inform other potentially interested tools
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
}
return 0;
}
int SCH_SELECTION_TOOL::UnselectItems( const TOOL_EVENT& aEvent )
{
std::vector<SCH_ITEM*>* items = aEvent.Parameter<std::vector<SCH_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 SCH_SELECTION_TOOL::UnselectItem( const TOOL_EVENT& aEvent )
{
// Check if there is an item to be selected
SCH_ITEM* item = aEvent.Parameter<SCH_ITEM*>();
if( item )
{
unselect( item );
// Inform other potentially interested tools
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
}
return 0;
}
int SCH_SELECTION_TOOL::ClearSelection( const TOOL_EVENT& aEvent )
{
clearSelection();
return 0;
}
int SCH_SELECTION_TOOL::SelectionMenu( const TOOL_EVENT& aEvent )
{
SCH_COLLECTOR* collector = aEvent.Parameter<SCH_COLLECTOR*>();
doSelectionMenu( collector, wxEmptyString );
return 0;
}
bool SCH_SELECTION_TOOL::doSelectionMenu( SCH_COLLECTOR* aCollector, const wxString& aTitle )
{
SCH_ITEM* current = nullptr;
CONTEXT_MENU menu;
int limit = std::min( MAX_SELECT_ITEM_IDS, aCollector->GetCount() );
for( int i = 0; i < limit; ++i )
{
wxString text;
SCH_ITEM* item = ( *aCollector )[i];
text = item->GetSelectMenuText( m_frame->GetUserUnits() );
wxString menuText = wxString::Format("&%d. %s", i + 1, text );
menu.Add( menuText, i + 1, item->GetMenuImage() );
}
if( aTitle.Length() )
menu.SetTitle( aTitle );
menu.SetIcon( info_xpm );
menu.DisplayTitle( true );
SetContextMenu( &menu, CMENU_NOW );
while( OPT_TOOL_EVENT evt = Wait() )
{
if( evt->Action() == TA_CONTEXT_MENU_UPDATE )
{
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 = NULL;
}
}
else if( evt->Action() == TA_CONTEXT_MENU_CHOICE )
{
if( current )
unhighlight( current, BRIGHTENED );
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 = NULL;
break;
}
}
if( current )
{
unhighlight( current, BRIGHTENED );
toggleSelection( current );
aCollector->Empty();
aCollector->Append( current );
return true;
}
return false;
}
bool SCH_SELECTION_TOOL::selectable( const SCH_ITEM* aItem, bool checkVisibilityOnly ) const
{
// NOTE: in the future this is where eeschema layer/itemtype visibility will be handled
switch( aItem->Type() )
{
case SCH_PIN_T:
if( !static_cast<const SCH_PIN*>( aItem )->IsVisible() && !m_frame->GetShowAllPins() )
return false;
break;
case LIB_PART_T: // In libedit we do not want to select the symbol itself.
return false;
case SCH_MARKER_T: // Always selectable
return true;
default: // Suppress warnings
break;
}
return true;
}
void SCH_SELECTION_TOOL::clearSelection()
{
if( m_selection.Empty() )
return;
while( m_selection.GetSize() )
unhighlight( static_cast<SCH_ITEM*>( m_selection.Front() ), SELECTED, &m_selection );
getView()->Update( &m_selection );
m_selection.SetIsHover( false );
m_selection.ClearReferencePoint();
if( m_frame )
m_frame->GetScreen()->SetCurItem( nullptr );
m_locked = true;
// Inform other potentially interested tools
m_toolMgr->ProcessEvent( EVENTS::ClearedEvent );
}
void SCH_SELECTION_TOOL::toggleSelection( SCH_ITEM* aItem, bool aForce )
{
if( aItem->IsSelected() )
{
unselect( aItem );
// Inform other potentially interested tools
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
}
else
{
if( !m_additive )
clearSelection();
// Prevent selection of invisible or inactive items
if( aForce || selectable( aItem ) )
{
select( aItem );
// Inform other potentially interested tools
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
}
}
if( m_frame )
m_frame->GetGalCanvas()->ForceRefresh();
}
void SCH_SELECTION_TOOL::select( SCH_ITEM* aItem )
{
if( aItem->IsSelected() )
return;
highlight( aItem, SELECTED, &m_selection );
getView()->Update( &m_selection );
if( m_frame )
{
if( m_selection.Size() == 1 )
{
// Set as the current item, so the information about selection is displayed
m_frame->GetScreen()->SetCurItem( aItem );
}
else if( m_selection.Size() == 2 ) // Check only for 2, so it will not be
{ // called for every next selected item
// If multiple items are selected, do not show the information about the selected item
m_frame->GetScreen()->SetCurItem( nullptr );
}
}
}
void SCH_SELECTION_TOOL::unselect( SCH_ITEM* aItem )
{
unhighlight( aItem, SELECTED, &m_selection );
getView()->Update( &m_selection );
if( m_frame && m_frame->GetScreen()->GetCurItem() == aItem )
m_frame->GetScreen()->SetCurItem( nullptr );
if( m_selection.Empty() )
m_locked = true;
}
void SCH_SELECTION_TOOL::highlight( SCH_ITEM* aItem, int aMode, SELECTION* aGroup )
{
if( aMode == SELECTED )
aItem->SetSelected();
else if( aMode == BRIGHTENED )
aItem->SetBrightened();
if( aGroup )
aGroup->Add( aItem );
// Highlight pins and fields. (All the other component children are currently only
// represented in the LIB_PART.)
if( aItem->Type() == SCH_COMPONENT_T )
{
SCH_PINS pins = static_cast<SCH_COMPONENT*>( aItem )->GetPins();
for( SCH_PIN& pin : pins )
{
if( aMode == SELECTED )
pin.SetSelected();
else if( aMode == BRIGHTENED )
pin.SetBrightened();
}
std::vector<SCH_FIELD*> fields;
static_cast<SCH_COMPONENT*>( aItem )->GetFields( fields, false );
for( auto field : fields )
{
if( aMode == SELECTED )
field->SetSelected();
else if( aMode == BRIGHTENED )
field->SetBrightened();
// JEY TODO: do these need hiding from view and adding to aGroup?
}
}
// JEY TODO: Sheets and sheet pins?
// Many selections are very temporal and updating the display each time just
// creates noise.
if( aMode == BRIGHTENED )
getView()->MarkTargetDirty( KIGFX::TARGET_OVERLAY );
}
void SCH_SELECTION_TOOL::unhighlight( SCH_ITEM* aItem, int aMode, SELECTION* aGroup )
{
if( aMode == SELECTED )
aItem->ClearSelected();
else if( aMode == BRIGHTENED )
aItem->ClearBrightened();
if( aGroup )
aGroup->Remove( aItem );
// Unhighlight pins and fields. (All the other component children are currently only
// represented in the LIB_PART.)
if( aItem->Type() == SCH_COMPONENT_T )
{
SCH_PINS pins = static_cast<SCH_COMPONENT*>( aItem )->GetPins();
for( SCH_PIN& pin : pins )
{
if( aMode == SELECTED )
pin.ClearSelected();
else if( aMode == BRIGHTENED )
pin.ClearBrightened();
}
std::vector<SCH_FIELD*> fields;
static_cast<SCH_COMPONENT*>( aItem )->GetFields( fields, false );
for( auto field : fields )
{
if( aMode == SELECTED )
field->ClearSelected();
else if( aMode == BRIGHTENED )
field->ClearBrightened();
// JEY TODO: do these need showing and updating?
}
}
// JEY TODO: Sheets and sheet pins?
// Many selections are very temporal and updating the display each time just
// creates noise.
if( aMode == BRIGHTENED )
getView()->MarkTargetDirty( KIGFX::TARGET_OVERLAY );
}
bool SCH_SELECTION_TOOL::selectionContains( const VECTOR2I& aPoint ) const
{
const unsigned GRIP_MARGIN = 20;
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 )
{
BOX2I itemBox = item->ViewBBox();
itemBox.Inflate( margin.x, margin.y ); // Give some margin for gripping an item
if( itemBox.Contains( aPoint ) )
return true;
}
return false;
}
void SCH_SELECTION_TOOL::setTransitions()
{
Go( &SCH_SELECTION_TOOL::Main, SCH_ACTIONS::selectionActivate.MakeEvent() );
Go( &SCH_SELECTION_TOOL::ClearSelection, SCH_ACTIONS::selectionClear.MakeEvent() );
Go( &SCH_SELECTION_TOOL::SelectItem, SCH_ACTIONS::selectItem.MakeEvent() );
Go( &SCH_SELECTION_TOOL::SelectItems, SCH_ACTIONS::selectItems.MakeEvent() );
Go( &SCH_SELECTION_TOOL::UnselectItem, SCH_ACTIONS::unselectItem.MakeEvent() );
Go( &SCH_SELECTION_TOOL::UnselectItems, SCH_ACTIONS::unselectItems.MakeEvent() );
Go( &SCH_SELECTION_TOOL::SelectionMenu, SCH_ACTIONS::selectionMenu.MakeEvent() );
}

View File

@ -0,0 +1,212 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 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 Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef KICAD_SCH_SELECTION_TOOL_H
#define KICAD_SCH_SELECTION_TOOL_H
#include <tool/tool_interactive.h>
#include <tool/context_menu.h>
#include <tool/selection.h>
#include <tool/tool_menu.h>
#include <sch_collectors.h>
class SCH_BASE_FRAME;
class SCH_ITEM;
class SCH_COLLECTOR;
namespace KIGFX
{
class GAL;
}
class SCH_SELECTION_TOOL : public TOOL_INTERACTIVE
{
public:
SCH_SELECTION_TOOL();
~SCH_SELECTION_TOOL();
/// @copydoc TOOL_BASE::Init()
bool Init() override;
/// @copydoc TOOL_BASE::Reset()
void Reset( RESET_REASON aReason ) override;
/**
* Function Main()
*
* The main loop.
*/
int Main( const TOOL_EVENT& aEvent );
/**
* Function GetSelection()
*
* Returns the set of currently selected items.
*/
SELECTION& GetSelection();
/**
* Function selectPoint()
* Selects 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 aSelectionCancelledFlag allows the function to inform its caller that a selection
* was cancelled (for instance, by clicking outside of the disambiguation menu).
* @param aCheckLocked indicates if locked items should be excluded
*/
SCH_ITEM* SelectPoint( const VECTOR2I& aWhere,
const KICAD_T* aFilterList = SCH_COLLECTOR::AllItems,
bool* aSelectionCancelledFlag = NULL, bool aCheckLocked = false );
///> Item selection event handler.
int SelectItem( 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 );
///> Multiple item unselection event handler
int UnselectItems( const TOOL_EVENT& aEvent );
///> Clear current selection event handler.
int ClearSelection( const TOOL_EVENT& aEvent );
/**
* Function SelectionMenu()
* Allows the selection of a single item from a list of items via a popup menu. The
* list is passed as aEvent's parameter.
*/
int SelectionMenu( const TOOL_EVENT& aEvent );
private:
/**
* Function selectCursor()
* Selects an item under the cursor unless there is something already selected or aForceSelect
* is true.
* @param aForceSelect forces to select an item even if there is an item already selected.
* @param aClientFilter allows the client to perform tool- or action-specific filtering.
* @return true if eventually there is an item selected, false otherwise.
*/
bool selectCursor( const KICAD_T aFilterList[], bool aForceSelect = false );
/**
* Apply heuristics to try and determine a single object when multiple are found under the
* cursor.
*/
void guessSelectionCandidates( SCH_COLLECTOR& collector, const VECTOR2I& aWhere );
/**
* Allows 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.
* @param aTitle (optional) Allows the menu to be titled (ie: "Clarify Selection").
* @return true if an item was picked
*/
bool doSelectionMenu( SCH_COLLECTOR* aItems, const wxString& aTitle );
/**
* Function clearSelection()
* Clears the current selection.
*/
void clearSelection();
/**
* Function toggleSelection()
* Changes selection status of a given item.
*
* @param aItem is the item to have selection status changed.
* @param aForce causes the toggle to happen without checking selectability
*/
void toggleSelection( SCH_ITEM* aItem, bool aForce = false );
/**
* Function selectable()
* Checks conditions for an item to be selected.
*
* @return True if the item fulfills conditions to be selected.
*/
bool selectable( const SCH_ITEM* aItem, bool checkVisibilityOnly = false ) const;
/**
* Function select()
* Takes necessary action mark an item as selected.
*
* @param aItem is an item to be selected.
*/
void select( SCH_ITEM* aItem );
/**
* Function unselect()
* Takes necessary action mark an item as unselected.
*
* @param aItem is an item to be unselected.
*/
void unselect( SCH_ITEM* aItem );
/**
* Function highlight()
* Highlights 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( SCH_ITEM* aItem, int aHighlightMode, SELECTION* aGroup = nullptr );
/**
* Function unhighlight()
* Unhighlights 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( SCH_ITEM* aItem, int aHighlightMode, SELECTION* aGroup = nullptr );
/**
* Function selectionContains()
* Checks if the given point is placed within any of selected items' bounding box.
*
* @return True if the given point is contained in any of selected items' bouding box.
*/
bool selectionContains( const VECTOR2I& aPoint ) const;
///> Sets up handlers for various events.
void setTransitions() override;
private:
SCH_BASE_FRAME* m_frame; // Pointer to the parent frame
SELECTION m_selection; // Current state of selection
bool m_additive; // Items should be added to selection (instead of replacing)
bool m_subtractive; // Items should be removed from selection
bool m_multiple; // Multiple selection mode is active
bool m_skip_heuristics; // Heuristics are not allowed when choosing item under cursor
bool m_locked; // Other tools are not allowed to modify locked items
TOOL_MENU m_menu;
};
#endif //KICAD_SCH_SELECTION_TOOL_H

View File

@ -92,7 +92,7 @@ public:
* @param ndx The index into the list.
* @return EDA_ITEM* - or something derived from it, or NULL.
*/
EDA_ITEM* operator[]( int ndx ) const
EDA_ITEM* operator[]( int ndx ) const override
{
if( (unsigned)ndx < (unsigned)GetCount() )
return (EDA_ITEM*) m_List[ ndx ];

View File

@ -267,7 +267,7 @@ void GERBVIEW_SELECTION_TOOL::toggleSelection( EDA_ITEM* aItem )
unselect( aItem );
// Inform other potentially interested tools
m_toolMgr->ProcessEvent( UnselectedEvent );
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
}
else
{
@ -280,7 +280,7 @@ void GERBVIEW_SELECTION_TOOL::toggleSelection( EDA_ITEM* aItem )
select( aItem );
// Inform other potentially interested tools
m_toolMgr->ProcessEvent( SelectedEvent );
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
}
}
@ -455,7 +455,7 @@ bool GERBVIEW_SELECTION_TOOL::selectMultiple()
// Inform other potentially interested tools
if( !m_selection.Empty() )
m_toolMgr->ProcessEvent( SelectedEvent );
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
break; // Stop waiting for events
}
@ -516,7 +516,7 @@ int GERBVIEW_SELECTION_TOOL::SelectItems( const TOOL_EVENT& aEvent )
select( item );
}
m_toolMgr->ProcessEvent( SelectedEvent );
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
}
return 0;
@ -533,7 +533,7 @@ int GERBVIEW_SELECTION_TOOL::SelectItem( const TOOL_EVENT& aEvent )
select( item );
// Inform other potentially interested tools
m_toolMgr->ProcessEvent( SelectedEvent );
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
}
return 0;
@ -553,7 +553,7 @@ int GERBVIEW_SELECTION_TOOL::UnselectItems( const TOOL_EVENT& aEvent )
unselect( item );
}
m_toolMgr->ProcessEvent( UnselectedEvent );
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
}
return 0;
@ -570,7 +570,7 @@ int GERBVIEW_SELECTION_TOOL::UnselectItem( const TOOL_EVENT& aEvent )
unselect( item );
// Inform other potentially interested tools
m_toolMgr->ProcessEvent( UnselectedEvent );
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
}
return 0;
@ -590,7 +590,7 @@ void GERBVIEW_SELECTION_TOOL::clearSelection()
m_frame->SetCurItem( NULL );
// Inform other potentially interested tools
m_toolMgr->ProcessEvent( ClearedEvent );
m_toolMgr->ProcessEvent( EVENTS::ClearedEvent );
}
@ -950,9 +950,3 @@ const KIGFX::VIEW_GROUP::ITEMS SELECTION::updateDrawList() const
return items;
}
const TOOL_EVENT GERBVIEW_SELECTION_TOOL::SelectedEvent( TC_MESSAGE, TA_ACTION, "gerbview.InteractiveSelection.selected" );
const TOOL_EVENT GERBVIEW_SELECTION_TOOL::UnselectedEvent( TC_MESSAGE, TA_ACTION, "gerbview.InteractiveSelection.unselected" );
const TOOL_EVENT GERBVIEW_SELECTION_TOOL::ClearedEvent( TC_MESSAGE, TA_ACTION, "gerbview.InteractiveSelection.cleared" );

View File

@ -98,15 +98,6 @@ public:
///> Launches a tool to measure between points
int MeasureTool( const TOOL_EVENT& aEvent );
///> Event sent after an item is selected.
static const TOOL_EVENT SelectedEvent;
///> Event sent after an item is unselected.
static const TOOL_EVENT UnselectedEvent;
///> Event sent after selection is cleared.
static const TOOL_EVENT ClearedEvent;
///> Sets up handlers for various events.
void setTransitions() override;

View File

@ -168,7 +168,7 @@ public:
* @param aIndex The index into the list.
* @return EDA_ITEM* - or something derived from it, or NULL.
*/
EDA_ITEM* operator[]( int aIndex ) const
virtual EDA_ITEM* operator[]( int aIndex ) const
{
if( (unsigned)aIndex < (unsigned)GetCount() ) // (unsigned) excludes aIndex<0 also
return m_List[ aIndex ];

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013-2016 CERN
* Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2016-2019 KiCad Developers, see AUTHORS.txt for contributors.
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
@ -108,4 +108,20 @@ public:
enum class REMOVE_FLAGS { NORMAL = 0x00, ALT = 0x01, CUT = 0x02 };
};
#endif
/**
* Class EVENTS
*
* Gathers all the events that are shared by tools.
*/
class EVENTS
{
public:
const static TOOL_EVENT SelectedEvent;
const static TOOL_EVENT UnselectedEvent;
const static TOOL_EVENT ClearedEvent;
};
#endif // __ACTIONS_H

View File

@ -286,7 +286,7 @@ public:
return (BOARD_ITEM*) &myItems[aIndex];
}
BOARD_ITEM* operator[]( int aIndex ) const
BOARD_ITEM* operator[]( int aIndex ) const override
{
return At( aIndex );
}

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2007-2008 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2004-2018 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2004-2019 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
@ -22,10 +22,6 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file collectors.h
*/
#ifndef COLLECTORS_H
#define COLLECTORS_H
@ -38,10 +34,9 @@
#include <collector.h>
#include <layers_id_colors_and_visibility.h> // LAYER_COUNT, layer defs
#include <view/view.h>
#include <class_board_item.h>
class BOARD_ITEM;
/**
* An abstract base class whose derivatives may be passed to a GENERAL_COLLECTOR,
@ -223,7 +218,7 @@ public:
* @param ndx The index into the list.
* @return BOARD_ITEM* - or something derived from it, or NULL.
*/
BOARD_ITEM* operator[]( int ndx ) const
BOARD_ITEM* operator[]( int ndx ) const override
{
if( (unsigned)ndx < (unsigned)GetCount() )
return (BOARD_ITEM*) m_List[ ndx ];

View File

@ -25,10 +25,11 @@
#include <cstdint>
#include <thread>
#include <mutex>
#include <functional>
#include "pcb_editor_control.h"
#include "pcb_actions.h"
#include <tool/tool_manager.h>
#include <tools/tool_event_utils.h>
#include <wx/progdlg.h>
#include "edit_tool.h"
@ -57,12 +58,8 @@
#include <view/view_controls.h>
#include <origin_viewitem.h>
#include <profile.h>
#include <widgets/progress_reporter.h>
#include <tools/tool_event_utils.h>
#include <functional>
using namespace std::placeholders;
@ -836,6 +833,7 @@ int PCB_EDITOR_CONTROL::ZoneDuplicate( const TOOL_EVENT& aEvent )
int PCB_EDITOR_CONTROL::CrossProbePcbToSch( const TOOL_EVENT& aEvent )
{
// Don't get in an infinite loop PCB -> SCH -> PCB -> SCH -> ...
if( m_probingSchToPcb )
{
m_probingSchToPcb = false;
@ -1287,9 +1285,9 @@ void PCB_EDITOR_CONTROL::setTransitions()
Go( &PCB_EDITOR_CONTROL::ToggleLockSelected, PCB_ACTIONS::toggleLock.MakeEvent() );
Go( &PCB_EDITOR_CONTROL::LockSelected, PCB_ACTIONS::lock.MakeEvent() );
Go( &PCB_EDITOR_CONTROL::UnlockSelected, PCB_ACTIONS::unlock.MakeEvent() );
Go( &PCB_EDITOR_CONTROL::CrossProbePcbToSch, SELECTION_TOOL::SelectedEvent );
Go( &PCB_EDITOR_CONTROL::CrossProbePcbToSch, SELECTION_TOOL::UnselectedEvent );
Go( &PCB_EDITOR_CONTROL::CrossProbePcbToSch, SELECTION_TOOL::ClearedEvent );
Go( &PCB_EDITOR_CONTROL::CrossProbePcbToSch, EVENTS::SelectedEvent );
Go( &PCB_EDITOR_CONTROL::CrossProbePcbToSch, EVENTS::UnselectedEvent );
Go( &PCB_EDITOR_CONTROL::CrossProbePcbToSch, EVENTS::ClearedEvent );
Go( &PCB_EDITOR_CONTROL::CrossProbeSchToPcb, PCB_ACTIONS::crossProbeSchToPcb.MakeEvent() );
Go( &PCB_EDITOR_CONTROL::DrillOrigin, PCB_ACTIONS::drillOrigin.MakeEvent() );
Go( &PCB_EDITOR_CONTROL::HighlightNet, PCB_ACTIONS::highlightNet.MakeEvent() );

View File

@ -135,17 +135,11 @@ private:
/// Menu model displayed by the tool.
TOOL_MENU m_menu;
///> Place & drill origin marker.
std::unique_ptr<KIGFX::ORIGIN_VIEWITEM> m_placeOrigin;
std::unique_ptr<KIGFX::ORIGIN_VIEWITEM> m_placeOrigin; ///> Place & drill origin marker
///> Flag to ignore a single crossprobe message from eeschema.
bool m_probingSchToPcb;
///> Flag to indicate whether the current selection ratsnest is slow to calculate.
bool m_slowRatsnest;
///> Timer that start ratsnest calculation when it is slow to compute.
wxTimer m_ratsnestTimer;
bool m_probingSchToPcb; ///> Recursion guard when cross-probing to EESchema
bool m_slowRatsnest; ///> Indicates current selection ratsnest will be slow to calculate
wxTimer m_ratsnestTimer; ///> Timer to initiate lazy ratsnest calculation (ie: when slow)
///> How to modify a property for selected items.
enum MODIFY_MODE { ON, OFF, TOGGLE };

View File

@ -899,7 +899,7 @@ int PCBNEW_CONTROL::placeBoardItems( std::vector<BOARD_ITEM*>& aItems, bool aIsN
selection.SetReferencePoint( VECTOR2I( 0, 0 ) );
m_toolMgr->ProcessEvent( SELECTION_TOOL::SelectedEvent );
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
m_toolMgr->RunAction( PCB_ACTIONS::move, true );
return 0;

View File

@ -345,9 +345,9 @@ int POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
controls->SetSnapping( !evt->Modifier( MD_ALT ) );
if( !m_editPoints ||
evt->Matches( m_selectionTool->ClearedEvent ) ||
evt->Matches( m_selectionTool->UnselectedEvent ) ||
evt->Matches( m_selectionTool->SelectedEvent ) )
evt->Matches( EVENTS::ClearedEvent ) ||
evt->Matches( EVENTS::UnselectedEvent ) ||
evt->Matches( EVENTS::SelectedEvent ) )
{
break;
}
@ -905,8 +905,8 @@ void POINT_EDITOR::setTransitions()
Go( &POINT_EDITOR::addCorner, PCB_ACTIONS::pointEditorAddCorner.MakeEvent() );
Go( &POINT_EDITOR::removeCorner, PCB_ACTIONS::pointEditorRemoveCorner.MakeEvent() );
Go( &POINT_EDITOR::modifiedSelection, PCB_ACTIONS::selectionModified.MakeEvent() );
Go( &POINT_EDITOR::OnSelectionChange, SELECTION_TOOL::SelectedEvent );
Go( &POINT_EDITOR::OnSelectionChange, SELECTION_TOOL::UnselectedEvent );
Go( &POINT_EDITOR::OnSelectionChange, EVENTS::SelectedEvent );
Go( &POINT_EDITOR::OnSelectionChange, EVENTS::UnselectedEvent );
}

View File

@ -65,44 +65,40 @@ using namespace std::placeholders;
// Selection tool actions
TOOL_ACTION PCB_ACTIONS::selectionActivate( "pcbnew.InteractiveSelection",
AS_GLOBAL, 0,
"", "", NULL, AF_ACTIVATE ); // No description, it is not supposed to be shown anywhere
AS_GLOBAL, 0, "", "", NULL, AF_ACTIVATE ); // No description, not shown anywhere
TOOL_ACTION PCB_ACTIONS::selectionCursor( "pcbnew.InteractiveSelection.Cursor",
AS_GLOBAL, 0,
"", "" ); // No description, it is not supposed to be shown anywhere
AS_GLOBAL, 0, "", "" ); // No description, it is not supposed to be shown anywhere
TOOL_ACTION PCB_ACTIONS::selectItem( "pcbnew.InteractiveSelection.SelectItem",
AS_GLOBAL, 0,
"", "" ); // No description, it is not supposed to be shown anywhere
AS_GLOBAL, 0, "", "" ); // No description, it is not supposed to be shown anywhere
TOOL_ACTION PCB_ACTIONS::selectItems( "pcbnew.InteractiveSelection.SelectItems",
AS_GLOBAL, 0,
"", "" ); // No description, it is not supposed to be shown anywhere
AS_GLOBAL, 0, "", "" ); // No description, it is not supposed to be shown anywhere
TOOL_ACTION PCB_ACTIONS::unselectItem( "pcbnew.InteractiveSelection.UnselectItem",
AS_GLOBAL, 0,
"", "" ); // No description, it is not supposed to be shown anywhere
AS_GLOBAL, 0, "", "" ); // No description, it is not supposed to be shown anywhere
TOOL_ACTION PCB_ACTIONS::unselectItems( "pcbnew.InteractiveSelection.UnselectItems",
AS_GLOBAL, 0,
"", "" ); // No description, it is not supposed to be shown anywhere
AS_GLOBAL, 0, "", "" ); // No description, it is not supposed to be shown anywhere
TOOL_ACTION PCB_ACTIONS::selectionClear( "pcbnew.InteractiveSelection.Clear",
AS_GLOBAL, 0,
"", "" ); // No description, it is not supposed to be shown anywhere
AS_GLOBAL, 0, "", "" ); // No description, it is not supposed to be shown anywhere
TOOL_ACTION PCB_ACTIONS::selectionMenu( "pcbnew.InteractiveSelection.SelectionMenu",
AS_GLOBAL, 0,
"", "" ); // No description, it is not supposed to be shown anywhere
AS_GLOBAL, 0, "", "" ); // No description, it is not supposed to be shown anywhere
TOOL_ACTION PCB_ACTIONS::selectConnection( "pcbnew.InteractiveSelection.SelectConnection",
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_SEL_TRIVIAL_CONNECTION ),
_( "Single Track" ), _( "Selects all track segments & vias between two junctions." ), add_tracks_xpm );
_( "Single Track" ),
_( "Selects all track segments & vias between two junctions." ),
add_tracks_xpm );
TOOL_ACTION PCB_ACTIONS::selectCopper( "pcbnew.InteractiveSelection.SelectCopper",
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_SEL_COPPER_CONNECTION ),
_( "Connected Tracks" ), _( "Selects all connected tracks & vias." ), net_highlight_xpm );
_( "Connected Tracks" ),
_( "Selects all connected tracks & vias." ),
net_highlight_xpm );
TOOL_ACTION PCB_ACTIONS::expandSelectedConnection( "pcbnew.InteractiveSelection.ExpandConnection",
AS_GLOBAL, 0,
@ -111,20 +107,27 @@ TOOL_ACTION PCB_ACTIONS::expandSelectedConnection( "pcbnew.InteractiveSelection.
TOOL_ACTION PCB_ACTIONS::selectNet( "pcbnew.InteractiveSelection.SelectNet",
AS_GLOBAL, 0,
_( "All Tracks in Net" ), _( "Selects all tracks & vias belonging to the same net." ), mode_track_xpm );
_( "All Tracks in Net" ),
_( "Selects all tracks & vias belonging to the same net." ),
mode_track_xpm );
TOOL_ACTION PCB_ACTIONS::selectOnSheetFromEeschema( "pcbnew.InteractiveSelection.SelectOnSheet",
AS_GLOBAL, 0,
_( "Sheet" ), _( "Selects all modules and tracks in the schematic sheet" ), select_same_sheet_xpm );
_( "Sheet" ),
_( "Selects all modules and tracks in the schematic sheet" ),
select_same_sheet_xpm );
TOOL_ACTION PCB_ACTIONS::selectSameSheet( "pcbnew.InteractiveSelection.SelectSameSheet",
AS_GLOBAL, 0,
_( "Items in Same Hierarchical Sheet" ),
_( "Selects all modules and tracks in the same schematic sheet" ), select_same_sheet_xpm );
_( "Selects all modules and tracks in the same schematic sheet" ),
select_same_sheet_xpm );
TOOL_ACTION PCB_ACTIONS::find( "pcbnew.InteractiveSelection.Find",
AS_GLOBAL, 0, //TOOL_ACTION::LegacyHotKey( HK_FIND_ITEM ), // handled by wxWidgets
_( "Find Item..." ),_( "Searches the document for an item" ), find_xpm );
_( "Find Item..." ),
_( "Searches the document for an item" ),
find_xpm );
TOOL_ACTION PCB_ACTIONS::findMove( "pcbnew.InteractiveSelection.FindMove",
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_GET_AND_MOVE_FOOTPRINT ),
@ -466,7 +469,7 @@ void SELECTION_TOOL::toggleSelection( BOARD_ITEM* aItem, bool aForce )
unselect( aItem );
// Inform other potentially interested tools
m_toolMgr->ProcessEvent( UnselectedEvent );
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
}
else
{
@ -479,7 +482,7 @@ void SELECTION_TOOL::toggleSelection( BOARD_ITEM* aItem, bool aForce )
select( aItem );
// Inform other potentially interested tools
m_toolMgr->ProcessEvent( SelectedEvent );
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
}
}
@ -542,60 +545,47 @@ bool SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag,
if( aClientFilter )
aClientFilter( aWhere, collector );
if( collector.GetCount() == 0 )
{
if( !m_additive && anyCollected )
{
clearSelection();
}
return false;
}
if( collector.GetCount() == 1 )
{
toggleSelection( collector[0] );
return true;
}
// Apply some ugly heuristics to avoid disambiguation menus whenever possible
if( !m_skip_heuristics )
if( collector.GetCount() > 1 && !m_skip_heuristics )
{
guessSelectionCandidates( collector, aWhere );
}
if( collector.GetCount() == 1 )
// If still more than one item we're going to have to ask the user.
if( collector.GetCount() > 1 )
{
toggleSelection( collector[0] );
return true;
}
}
// Still more than one item. We're going to have to ask the user.
if( aOnDrag )
{
Wait( TOOL_EVENT( TC_ANY, TA_MOUSE_UP, BUT_LEFT ) );
}
BOARD_ITEM* item = doSelectionMenu( &collector, _( "Clarify Selection" ) );
if( item )
{
return true;
}
else
if( !doSelectionMenu( &collector, _( "Clarify Selection" ) ) )
{
if( aSelectionCancelledFlag )
*aSelectionCancelledFlag = true;
return false;
}
}
if( collector.GetCount() == 1 )
{
BOARD_ITEM* item = collector[ 0 ];
toggleSelection( item );
return true;
}
if( !m_additive && anyCollected )
clearSelection();
return false;
}
bool SELECTION_TOOL::selectCursor( bool aSelectAlways, CLIENT_SELECTION_FILTER aClientFilter )
bool SELECTION_TOOL::selectCursor( bool aForceSelect, CLIENT_SELECTION_FILTER aClientFilter )
{
if( aSelectAlways || m_selection.Empty() )
if( aForceSelect || m_selection.Empty() )
{
clearSelection();
selectPoint( getViewControls()->GetCursorPosition( false ), false, NULL, aClientFilter );
@ -710,7 +700,7 @@ bool SELECTION_TOOL::selectMultiple()
// Inform other potentially interested tools
if( !m_selection.Empty() )
m_toolMgr->ProcessEvent( SelectedEvent );
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
break; // Stop waiting for events
}
@ -819,14 +809,11 @@ int SELECTION_TOOL::SelectItems( const TOOL_EVENT& aEvent )
if( items )
{
// Perform individual selection of each item
// before processing the event.
// Perform individual selection of each item before processing the event.
for( auto item : *items )
{
select( item );
}
m_toolMgr->ProcessEvent( SelectedEvent );
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
}
return 0;
@ -843,7 +830,7 @@ int SELECTION_TOOL::SelectItem( const TOOL_EVENT& aEvent )
select( item );
// Inform other potentially interested tools
m_toolMgr->ProcessEvent( SelectedEvent );
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
}
return 0;
@ -856,14 +843,11 @@ int SELECTION_TOOL::UnselectItems( const TOOL_EVENT& aEvent )
if( items )
{
// Perform individual unselection of each item
// before processing the event
// Perform individual unselection of each item before processing the event
for( auto item : *items )
{
unselect( item );
}
m_toolMgr->ProcessEvent( UnselectedEvent );
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
}
return 0;
@ -880,7 +864,7 @@ int SELECTION_TOOL::UnselectItem( const TOOL_EVENT& aEvent )
unselect( item );
// Inform other potentially interested tools
m_toolMgr->ProcessEvent( UnselectedEvent );
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
}
return 0;
@ -935,7 +919,7 @@ int SELECTION_TOOL::expandSelectedConnection( const TOOL_EVENT& aEvent )
// Inform other potentially interested tools
if( m_selection.Size() > 0 )
m_toolMgr->ProcessEvent( SelectedEvent );
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
return 0;
}
@ -987,7 +971,7 @@ int SELECTION_TOOL::selectCopper( const TOOL_EVENT& aEvent )
// Inform other potentially interested tools
if( m_selection.Size() > 0 )
m_toolMgr->ProcessEvent( SelectedEvent );
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
return 0;
}
@ -1056,7 +1040,7 @@ int SELECTION_TOOL::selectNet( const TOOL_EVENT& aEvent )
// Inform other potentially interested tools
if( m_selection.Size() > 0 )
m_toolMgr->ProcessEvent( SelectedEvent );
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
return 0;
}
@ -1201,7 +1185,7 @@ int SELECTION_TOOL::selectOnSheetFromEeschema( const TOOL_EVENT& aEvent )
zoomFitSelection();
if( m_selection.Size() > 0 )
m_toolMgr->ProcessEvent( SelectedEvent );
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
return 0;
}
@ -1235,7 +1219,7 @@ int SELECTION_TOOL::selectSameSheet( const TOOL_EVENT& aEvent )
// Inform other potentially interested tools
if( m_selection.Size() > 0 )
m_toolMgr->ProcessEvent( SelectedEvent );
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
return 0;
}
@ -1251,7 +1235,7 @@ void SELECTION_TOOL::findCallback( BOARD_ITEM* aItem )
getView()->SetCenter( aItem->GetPosition() );
// Inform other potentially interested tools
m_toolMgr->ProcessEvent( SelectedEvent );
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
}
m_frame->GetGalCanvas()->ForceRefresh();
@ -1430,14 +1414,12 @@ void SELECTION_TOOL::clearSelection()
m_selection.ClearReferencePoint();
if( m_frame )
{
m_frame->SetCurItem( NULL );
}
m_locked = true;
// Inform other potentially interested tools
m_toolMgr->ProcessEvent( ClearedEvent );
m_toolMgr->ProcessEvent( EVENTS::ClearedEvent );
m_toolMgr->RunAction( PCB_ACTIONS::hideLocalRatsnest, true );
}
@ -1451,10 +1433,9 @@ int SELECTION_TOOL::SelectionMenu( const TOOL_EVENT& aEvent )
}
BOARD_ITEM* SELECTION_TOOL::doSelectionMenu( GENERAL_COLLECTOR* aCollector,
const wxString& aTitle )
bool SELECTION_TOOL::doSelectionMenu( GENERAL_COLLECTOR* aCollector, const wxString& aTitle )
{
BOARD_ITEM* current = NULL;
BOARD_ITEM* current = nullptr;
SELECTION highlightGroup;
CONTEXT_MENU menu;
@ -1475,6 +1456,7 @@ BOARD_ITEM* SELECTION_TOOL::doSelectionMenu( GENERAL_COLLECTOR* aCollector,
if( aTitle.Length() )
menu.SetTitle( aTitle );
menu.SetIcon( info_xpm );
menu.DisplayTitle( true );
SetContextMenu( &menu, CMENU_NOW );
@ -1518,9 +1500,14 @@ BOARD_ITEM* SELECTION_TOOL::doSelectionMenu( GENERAL_COLLECTOR* aCollector,
getView()->Remove( &highlightGroup );
if( current )
{
toggleSelection( current );
aCollector->Empty();
aCollector->Append( current );
return true;
}
return current;
return false;
}
@ -1849,8 +1836,8 @@ void SELECTION_TOOL::highlight( BOARD_ITEM* aItem, int aMode, SELECTION& aGroup
aGroup.Add( aItem );
// 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
// Modules are treated in a special way - when they are highlighted, we have to
// highlight all the parts that make the module, not the module itself
if( aItem->Type() == PCB_MODULE_T )
{
static_cast<MODULE*>( aItem )->RunOnChildren( [&] ( BOARD_ITEM* item )
@ -1886,8 +1873,8 @@ void SELECTION_TOOL::unhighlight( BOARD_ITEM* aItem, int aMode, SELECTION& aGrou
view()->Hide( aItem, false );
view()->Update( aItem );
// 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
// Modules are treated in a special way - when they are highlighted, we have to
// highlight all the parts that make the module, not the module itself
if( aItem->Type() == PCB_MODULE_T )
{
static_cast<MODULE*>( aItem )->RunOnChildren( [&] ( BOARD_ITEM* item )
@ -2301,6 +2288,3 @@ int SELECTION_TOOL::updateSelection( const TOOL_EVENT& aEvent )
}
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" );

View File

@ -4,7 +4,7 @@
* Copyright (C) 2013-2017 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Maciej Suminski <maciej.suminski@cern.ch>
* Copyright (C) 2017 KiCad Developers, see CHANGELOG.TXT for contributors.
* Copyright (C) 2017-2019 KiCad Developers, see CHANGELOG.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
@ -132,15 +132,6 @@ public:
*/
int SelectionMenu( const TOOL_EVENT& aEvent );
///> Event sent after an item is selected.
static const TOOL_EVENT SelectedEvent;
///> Event sent after an item is unselected.
static const TOOL_EVENT UnselectedEvent;
///> Event sent after selection is cleared.
static const TOOL_EVENT ClearedEvent;
///> Sets up handlers for various events.
void setTransitions() override;
@ -168,11 +159,11 @@ private:
* Function selectCursor()
* Selects an item under the cursor unless there is something already selected or aSelectAlways
* is true.
* @param aSelectAlways forces to select an item even if there is an item already selected.
* @param aForceSelect forces to select an item even if there is an item already selected.
* @param aClientFilter allows the client to perform tool- or action-specific filtering.
* @return true if eventually there is an item selected, false otherwise.
*/
bool selectCursor( bool aSelectAlways = false,
bool selectCursor( bool aForceSelect = false,
CLIENT_SELECTION_FILTER aClientFilter = NULL );
/**
@ -186,10 +177,12 @@ private:
/**
* Allows 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.
* highlighted on the canvas when hovered in the menu. The collector is trimmed to
* the picked item.
* @param aTitle (optional) Allows the menu to be titled (ie: "Clarify Selection").
* @return true if an item was picked
*/
BOARD_ITEM* doSelectionMenu( GENERAL_COLLECTOR* aItems, const wxString& aTitle );
bool doSelectionMenu( GENERAL_COLLECTOR* aItems, const wxString& aTitle );
///> Selects a trivial connection (between two junctions) of items in selection
int selectConnection( const TOOL_EVENT& aEvent );
@ -295,7 +288,7 @@ private:
void unselect( BOARD_ITEM* aItem );
/**
* Function selectVisually()
* Function highlight()
* Highlights the item visually.
* @param aItem is an item to be be highlighted.
* @param aHighlightMode should be either SELECTED or BRIGHTENED
@ -304,7 +297,7 @@ private:
void highlight( BOARD_ITEM* aItem, int aHighlightMode, SELECTION& aGroup );
/**
* Function unselectVisually()
* Function unhighlight()
* Unhighlights the item visually.
* @param aItem is an item to be be highlighted.
* @param aHighlightMode should be either SELECTED or BRIGHTENED
@ -336,28 +329,16 @@ private:
const GENERAL_COLLECTORS_GUIDE getCollectorsGuide() const;
/// Pointer to the parent frame.
PCB_BASE_FRAME* m_frame;
private:
PCB_BASE_FRAME* m_frame; // Pointer to the parent frame
SELECTION m_selection; // Current state of selection
/// Current state of selection.
SELECTION m_selection;
bool m_additive; // Items should be added to selection (instead of replacing)
bool m_subtractive; // Items should be removed from selection
bool m_multiple; // Multiple selection mode is active
bool m_skip_heuristics; // Heuristics are not allowed when choosing item under cursor
bool m_locked; // Other tools are not allowed to modify locked items
/// Flag saying if items should be added to the current selection or rather replace it.
bool m_additive;
/// Flag saying if items should be removed from the current selection
bool m_subtractive;
/// Flag saying if multiple selection mode is active.
bool m_multiple;
/// Flag saying that heuristics should be skipped while choosing selection
bool m_skip_heuristics;
/// Can other tools modify locked items.
bool m_locked;
/// Menu model displayed by the tool.
TOOL_MENU m_menu;
/// Private state (opaque pointer/compilation firewall)