Cross-probing/selection for multiple items (PCB -> SCH)
Fixes https://gitlab.com/kicad/code/kicad/issues/10469
This commit is contained in:
parent
8757b3f98a
commit
3a76d42630
|
@ -667,6 +667,7 @@ TOOL_ACTION ACTIONS::reportBug( "common.SuiteControl.reportBug",
|
||||||
|
|
||||||
// System-wide selection Events
|
// System-wide selection Events
|
||||||
|
|
||||||
|
const TOOL_EVENT EVENTS::PointSelectedEvent( TC_MESSAGE, TA_ACTION, "common.Interactive.pointSelected" );
|
||||||
const TOOL_EVENT EVENTS::SelectedEvent( TC_MESSAGE, TA_ACTION, "common.Interactive.selected" );
|
const TOOL_EVENT EVENTS::SelectedEvent( TC_MESSAGE, TA_ACTION, "common.Interactive.selected" );
|
||||||
const TOOL_EVENT EVENTS::UnselectedEvent( TC_MESSAGE, TA_ACTION, "common.Interactive.unselected" );
|
const TOOL_EVENT EVENTS::UnselectedEvent( TC_MESSAGE, TA_ACTION, "common.Interactive.unselected" );
|
||||||
const TOOL_EVENT EVENTS::ClearedEvent( TC_MESSAGE, TA_ACTION, "common.Interactive.cleared" );
|
const TOOL_EVENT EVENTS::ClearedEvent( TC_MESSAGE, TA_ACTION, "common.Interactive.cleared" );
|
||||||
|
|
|
@ -37,7 +37,10 @@ void SELECTION::Add( EDA_ITEM* aItem )
|
||||||
ITER i = std::lower_bound( m_items.begin(), m_items.end(), aItem );
|
ITER i = std::lower_bound( m_items.begin(), m_items.end(), aItem );
|
||||||
|
|
||||||
if( i == m_items.end() || *i > aItem )
|
if( i == m_items.end() || *i > aItem )
|
||||||
|
{
|
||||||
m_items.insert( i, aItem );
|
m_items.insert( i, aItem );
|
||||||
|
m_lastAddedItem = aItem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,7 +49,12 @@ void SELECTION::Remove( EDA_ITEM* aItem )
|
||||||
ITER i = std::lower_bound( m_items.begin(), m_items.end(), aItem );
|
ITER i = std::lower_bound( m_items.begin(), m_items.end(), aItem );
|
||||||
|
|
||||||
if( !( i == m_items.end() || *i > aItem ) )
|
if( !( i == m_items.end() || *i > aItem ) )
|
||||||
|
{
|
||||||
m_items.erase( i );
|
m_items.erase( i );
|
||||||
|
|
||||||
|
if( aItem == m_lastAddedItem )
|
||||||
|
m_lastAddedItem = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -224,7 +224,8 @@ bool TOOL_EVENT::IsSelectionEvent() const
|
||||||
{
|
{
|
||||||
return Matches( EVENTS::ClearedEvent )
|
return Matches( EVENTS::ClearedEvent )
|
||||||
|| Matches( EVENTS::UnselectedEvent )
|
|| Matches( EVENTS::UnselectedEvent )
|
||||||
|| Matches( EVENTS::SelectedEvent );
|
|| Matches( EVENTS::SelectedEvent )
|
||||||
|
|| Matches( EVENTS::PointSelectedEvent );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <kiface_base.h>
|
#include <kiface_base.h>
|
||||||
#include <kiplatform/app.h>
|
#include <kiplatform/app.h>
|
||||||
#include <kiway_express.h>
|
#include <kiway_express.h>
|
||||||
|
#include <string_utils.h>
|
||||||
#include <project/project_file.h>
|
#include <project/project_file.h>
|
||||||
#include <macros.h>
|
#include <macros.h>
|
||||||
#include <netlist_reader/netlist_reader.h>
|
#include <netlist_reader/netlist_reader.h>
|
||||||
|
@ -417,8 +418,8 @@ void CVPCB_MAINFRAME::doCloseWindow()
|
||||||
|
|
||||||
m_modified = false;
|
m_modified = false;
|
||||||
|
|
||||||
// clear highlight symbol in schematic:
|
// clear symbol selection in schematic:
|
||||||
SendMessageToEESCHEMA( true );
|
SendComponentSelectionToSch( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -708,7 +709,7 @@ void CVPCB_MAINFRAME::refreshAfterSymbolSearch( COMPONENT* aSymbol )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SendMessageToEESCHEMA();
|
SendComponentSelectionToSch();
|
||||||
DisplayStatus();
|
DisplayStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -881,40 +882,41 @@ bool CVPCB_MAINFRAME::LoadFootprintFiles()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CVPCB_MAINFRAME::SendMessageToEESCHEMA( bool aClearHighligntOnly )
|
void CVPCB_MAINFRAME::SendComponentSelectionToSch( bool aClearSelectionOnly )
|
||||||
{
|
{
|
||||||
if( m_netlist.IsEmpty() )
|
if( m_netlist.IsEmpty() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// clear highlight of previously selected symbols (if any):
|
std::string command = "$SELECT: ";
|
||||||
// Selecting a non existing symbol clears any previously highlighted symbols
|
|
||||||
std::string packet = "$CLEAR: \"HIGHLIGHTED\"";
|
|
||||||
|
|
||||||
if( Kiface().IsSingle() )
|
if( aClearSelectionOnly )
|
||||||
SendCommand( MSG_TO_SCH, packet );
|
{
|
||||||
else
|
// Sending an empty list means clearing the selection.
|
||||||
Kiway().ExpressMail( FRAME_SCH, MAIL_CROSS_PROBE, packet, this );
|
if( Kiface().IsSingle() )
|
||||||
|
SendCommand( MSG_TO_SCH, command );
|
||||||
|
else
|
||||||
|
Kiway().ExpressMail( FRAME_SCH, MAIL_SELECTION, command, this );
|
||||||
|
|
||||||
if( aClearHighligntOnly )
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int selection = m_symbolsListBox->GetSelection();
|
int selection = m_symbolsListBox->GetSelection();
|
||||||
|
|
||||||
if ( selection < 0 ) // Nothing selected
|
if( selection < 0 ) // Nothing selected
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( m_netlist.GetComponent( selection ) == nullptr )
|
if( m_netlist.GetComponent( selection ) == nullptr )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Now highlight the selected symbol:
|
// Now select the corresponding symbol on the schematic:
|
||||||
COMPONENT* symbol = m_netlist.GetComponent( selection );
|
wxString ref = m_netlist.GetComponent( selection )->GetReference();
|
||||||
|
|
||||||
packet = std::string( "$PART: \"" ) + TO_UTF8( symbol->GetReference() ) + "\"";
|
command += wxT( "F" ) + EscapeString( ref, CTX_IPC );
|
||||||
|
|
||||||
if( Kiface().IsSingle() )
|
if( Kiface().IsSingle() )
|
||||||
SendCommand( MSG_TO_SCH, packet );
|
SendCommand( MSG_TO_SCH, command );
|
||||||
else
|
else
|
||||||
Kiway().ExpressMail( FRAME_SCH, MAIL_CROSS_PROBE, packet, this );
|
Kiway().ExpressMail( FRAME_SCH, MAIL_SELECTION, command, this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1069,7 +1071,7 @@ void CVPCB_MAINFRAME::SetSelectedComponent( int aIndex, bool aSkipUpdate )
|
||||||
{
|
{
|
||||||
m_symbolsListBox->DeselectAll();
|
m_symbolsListBox->DeselectAll();
|
||||||
m_symbolsListBox->SetSelection( aIndex );
|
m_symbolsListBox->SetSelection( aIndex );
|
||||||
SendMessageToEESCHEMA();
|
SendComponentSelectionToSch();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_skipComponentSelect = false;
|
m_skipComponentSelect = false;
|
||||||
|
|
|
@ -250,10 +250,10 @@ public:
|
||||||
* Commands are:
|
* Commands are:
|
||||||
* $PART: "reference" put cursor on component anchor
|
* $PART: "reference" put cursor on component anchor
|
||||||
*
|
*
|
||||||
* @param aClearHighligntOnly use true if the message to send is only "clear highlight"
|
* @param aClearSelectionOnly use true if the message to send is only "clear clear selection"
|
||||||
* (used when exiting CvPcb)
|
* (used when exiting CvPcb)
|
||||||
*/
|
*/
|
||||||
void SendMessageToEESCHEMA( bool aClearHighligntOnly = false );
|
void SendComponentSelectionToSch( bool aClearSelectionOnly = false );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the selected component from the component listbox.
|
* Get the selected component from the component listbox.
|
||||||
|
|
|
@ -27,7 +27,9 @@
|
||||||
#include <kiway_express.h>
|
#include <kiway_express.h>
|
||||||
#include <eda_dde.h>
|
#include <eda_dde.h>
|
||||||
#include <connection_graph.h>
|
#include <connection_graph.h>
|
||||||
|
#include <sch_sheet.h>
|
||||||
#include <sch_symbol.h>
|
#include <sch_symbol.h>
|
||||||
|
#include <sch_reference_list.h>
|
||||||
#include <schematic.h>
|
#include <schematic.h>
|
||||||
#include <reporter.h>
|
#include <reporter.h>
|
||||||
#include <string_utils.h>
|
#include <string_utils.h>
|
||||||
|
@ -133,113 +135,15 @@ SCH_ITEM* SCH_EDITOR_CONTROL::FindSymbolAndItem( const wxString* aPath, const wx
|
||||||
{
|
{
|
||||||
if( crossProbingSettings.zoom_to_fit )
|
if( crossProbingSettings.zoom_to_fit )
|
||||||
{
|
{
|
||||||
EDA_RECT bbox = symbol->GetBoundingBox();
|
EDA_RECT bbox = symbol->GetBoundingBox();
|
||||||
VECTOR2I bbSize = bbox.Inflate( bbox.GetWidth() * 0.2f ).GetSize();
|
|
||||||
VECTOR2D screenSize = getView()->GetViewport().GetSize();
|
|
||||||
|
|
||||||
// This code tries to come up with a zoom factor that doesn't simply zoom in
|
m_toolMgr->GetTool<EE_SELECTION_TOOL>()->ZoomFitCrossProbeBBox( bbox );
|
||||||
// to the cross probed symbol, but instead shows a reasonable amount of the
|
|
||||||
// circuit around it to provide context. This reduces or eliminates the need
|
|
||||||
// to manually change the zoom because it's too close.
|
|
||||||
|
|
||||||
// Using the default text height as a constant to compare against, use the
|
|
||||||
// height of the bounding box of visible items for a footprint to figure out
|
|
||||||
// if this is a big symbol (like a processor) or a small symbol (like a resistor).
|
|
||||||
// This ratio is not useful by itself as a scaling factor. It must be "bent" to
|
|
||||||
// provide good scaling at varying symbol sizes. Bigger symbols need less
|
|
||||||
// scaling than small ones.
|
|
||||||
double currTextHeight = Mils2iu( DEFAULT_TEXT_SIZE );
|
|
||||||
|
|
||||||
double compRatio = bbSize.y / currTextHeight; // Ratio of symbol to text height
|
|
||||||
double compRatioBent = 1.0;
|
|
||||||
|
|
||||||
// LUT to scale zoom ratio to provide reasonable schematic context. Must work
|
|
||||||
// with symbols of varying sizes (e.g. 0402 package and 200 pin BGA).
|
|
||||||
// "first" is used as the input and "second" as the output
|
|
||||||
//
|
|
||||||
// "first" = compRatio (symbol height / default text height)
|
|
||||||
// "second" = Amount to scale ratio by
|
|
||||||
std::vector<std::pair<double, double>> lut
|
|
||||||
{
|
|
||||||
{1.25, 16}, // 32
|
|
||||||
{2.5, 12}, //24
|
|
||||||
{5, 8}, // 16
|
|
||||||
{6, 6}, //
|
|
||||||
{10, 4}, //8
|
|
||||||
{20, 2}, //4
|
|
||||||
{40, 1.5}, // 2
|
|
||||||
{100, 1}
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<std::pair<double, double>>::iterator it;
|
|
||||||
|
|
||||||
// Large symbol default is last LUT entry (1:1).
|
|
||||||
compRatioBent = lut.back().second;
|
|
||||||
|
|
||||||
// Use LUT to do linear interpolation of "compRatio" within "first", then
|
|
||||||
// use that result to linearly interpolate "second" which gives the scaling
|
|
||||||
// factor needed.
|
|
||||||
if( compRatio >= lut.front().first )
|
|
||||||
{
|
|
||||||
for( it = lut.begin(); it < lut.end() - 1; it++ )
|
|
||||||
{
|
|
||||||
if( it->first <= compRatio && next( it )->first >= compRatio )
|
|
||||||
{
|
|
||||||
|
|
||||||
double diffx = compRatio - it->first;
|
|
||||||
double diffn = next( it )->first - it->first;
|
|
||||||
|
|
||||||
compRatioBent = it->second
|
|
||||||
+ ( next( it )->second - it->second ) * diffx / diffn;
|
|
||||||
break; // We have our interpolated value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
compRatioBent = lut.front().second; // Small symbol default is first entry
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is similar to the original KiCad code that scaled the zoom to make sure
|
|
||||||
// symbols were visible on screen. It's simply a ratio of screen size to
|
|
||||||
// symbol size, and its job is to zoom in to make the component fullscreen.
|
|
||||||
// Earlier in the code the symbol BBox is given a 20% margin to add some
|
|
||||||
// breathing room. We compare the height of this enlarged symbol bbox to the
|
|
||||||
// default text height. If a symbol will end up with the sides clipped, we
|
|
||||||
// adjust later to make sure it fits on screen.
|
|
||||||
screenSize.x = std::max( 10.0, screenSize.x );
|
|
||||||
screenSize.y = std::max( 10.0, screenSize.y );
|
|
||||||
double ratio = std::max( -1.0, fabs( bbSize.y / screenSize.y ) );
|
|
||||||
|
|
||||||
// Original KiCad code for how much to scale the zoom
|
|
||||||
double kicadRatio = std::max( fabs( bbSize.x / screenSize.x ),
|
|
||||||
fabs( bbSize.y / screenSize.y ) );
|
|
||||||
|
|
||||||
// If the width of the part we're probing is bigger than what the screen width
|
|
||||||
// will be after the zoom, then punt and use the KiCad zoom algorithm since it
|
|
||||||
// guarantees the part's width will be encompassed within the screen.
|
|
||||||
if( bbSize.x > screenSize.x * ratio * compRatioBent )
|
|
||||||
{
|
|
||||||
// Use standard KiCad zoom for parts too wide to fit on screen/
|
|
||||||
ratio = kicadRatio;
|
|
||||||
compRatioBent = 1.0; // Reset so we don't modify the "KiCad" ratio
|
|
||||||
wxLogTrace( "CROSS_PROBE_SCALE",
|
|
||||||
"Part TOO WIDE for screen. Using normal KiCad zoom ratio: %1.5f",
|
|
||||||
ratio );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now that "compRatioBent" holds our final scaling factor we apply it to the
|
|
||||||
// original fullscreen zoom ratio to arrive at the final ratio itself.
|
|
||||||
ratio *= compRatioBent;
|
|
||||||
|
|
||||||
bool alwaysZoom = false; // DEBUG - allows us to minimize zooming or not
|
|
||||||
|
|
||||||
// Try not to zoom on every cross-probe; it gets very noisy
|
|
||||||
if( ( ratio < 0.5 || ratio > 1.0 ) || alwaysZoom )
|
|
||||||
getView()->SetScale( getView()->GetScale() / ratio );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_frame->FocusOnItem( symbol );
|
if( pin )
|
||||||
|
m_frame->FocusOnItem( pin );
|
||||||
|
else
|
||||||
|
m_frame->FocusOnItem( symbol );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,18 +177,6 @@ SCH_ITEM* SCH_EDITOR_CONTROL::FindSymbolAndItem( const wxString* aPath, const wx
|
||||||
|
|
||||||
m_frame->SetStatusText( msg );
|
m_frame->SetStatusText( msg );
|
||||||
|
|
||||||
m_probingPcbToSch = true; // recursion guard
|
|
||||||
|
|
||||||
{
|
|
||||||
// Clear any existing highlighting
|
|
||||||
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
|
|
||||||
|
|
||||||
if( foundItem )
|
|
||||||
m_toolMgr->RunAction( EE_ACTIONS::addItemToSel, true, foundItem );
|
|
||||||
}
|
|
||||||
|
|
||||||
m_probingPcbToSch = false;
|
|
||||||
|
|
||||||
m_frame->GetCanvas()->Refresh();
|
m_frame->GetCanvas()->Refresh();
|
||||||
|
|
||||||
return foundItem;
|
return foundItem;
|
||||||
|
@ -382,7 +274,7 @@ void SCH_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SCH_EDIT_FRAME::SendSelectItems( const std::deque<EDA_ITEM*>& aItems, bool aForce )
|
void SCH_EDIT_FRAME::SendSelectItemsToPcb( const std::deque<EDA_ITEM*>& aItems, bool aForce )
|
||||||
{
|
{
|
||||||
std::set<wxString> parts;
|
std::set<wxString> parts;
|
||||||
|
|
||||||
|
@ -552,6 +444,375 @@ void SCH_EDIT_FRAME::SendCrossProbeClearHighlight()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool findSymbolsAndPins(
|
||||||
|
const SCHEMATIC& aSchematic, const SCH_SHEET_PATH& aSheetPath,
|
||||||
|
std::unordered_map<wxString, std::vector<SCH_REFERENCE>>& aSyncSymMap,
|
||||||
|
std::unordered_map<wxString, std::unordered_map<wxString, SCH_PIN*>>& aSyncPinMap,
|
||||||
|
bool aRecursive = false )
|
||||||
|
{
|
||||||
|
if( aRecursive )
|
||||||
|
{
|
||||||
|
// Iterate over children
|
||||||
|
for( const SCH_SHEET_PATH& candidate : aSchematic.GetSheets() )
|
||||||
|
{
|
||||||
|
if( candidate == aSheetPath || !candidate.IsContainedWithin( aSheetPath ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
findSymbolsAndPins( aSchematic, candidate, aSyncSymMap, aSyncPinMap, aRecursive );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SCH_REFERENCE_LIST references;
|
||||||
|
|
||||||
|
aSheetPath.GetSymbols( references, false, true );
|
||||||
|
|
||||||
|
for( unsigned ii = 0; ii < references.GetCount(); ii++ )
|
||||||
|
{
|
||||||
|
SCH_REFERENCE& schRef = references[ii];
|
||||||
|
|
||||||
|
if( schRef.IsSplitNeeded() )
|
||||||
|
schRef.Split();
|
||||||
|
|
||||||
|
SCH_SYMBOL* symbol = schRef.GetSymbol();
|
||||||
|
wxString refNum = schRef.GetRefNumber();
|
||||||
|
wxString fullRef = schRef.GetRef() + refNum;
|
||||||
|
|
||||||
|
// Skip power symbols
|
||||||
|
if( fullRef.StartsWith( "#" ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Unannotated symbols are not supported
|
||||||
|
if( refNum.compare( "?" ) == 0 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Look for whole footprint
|
||||||
|
auto symMatchIt = aSyncSymMap.find( fullRef );
|
||||||
|
|
||||||
|
if( symMatchIt != aSyncSymMap.end() )
|
||||||
|
{
|
||||||
|
symMatchIt->second.emplace_back( schRef );
|
||||||
|
|
||||||
|
// Whole footprint was selected, no need to select pins
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for pins
|
||||||
|
auto symPinMatchIt = aSyncPinMap.find( fullRef );
|
||||||
|
|
||||||
|
if( symPinMatchIt != aSyncPinMap.end() )
|
||||||
|
{
|
||||||
|
std::unordered_map<wxString, SCH_PIN*>& pinMap = symPinMatchIt->second;
|
||||||
|
std::vector<SCH_PIN*> pinsOnSheet = symbol->GetPins( &aSheetPath );
|
||||||
|
|
||||||
|
for( SCH_PIN* pin : pinsOnSheet )
|
||||||
|
{
|
||||||
|
int pinUnit = pin->GetLibPin()->GetUnit();
|
||||||
|
|
||||||
|
if( pinUnit > 0 && pinUnit != schRef.GetUnit() )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto pinIt = pinMap.find( pin->GetNumber() );
|
||||||
|
|
||||||
|
if( pinIt != pinMap.end() )
|
||||||
|
pinIt->second = pin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool sheetContainsOnlyWantedItems(
|
||||||
|
const SCHEMATIC& aSchematic, const SCH_SHEET_PATH& aSheetPath,
|
||||||
|
std::unordered_map<wxString, std::vector<SCH_REFERENCE>>& aSyncSymMap,
|
||||||
|
std::unordered_map<wxString, std::unordered_map<wxString, SCH_PIN*>>& aSyncPinMap,
|
||||||
|
std::unordered_map<SCH_SHEET_PATH, bool>& aCache )
|
||||||
|
{
|
||||||
|
auto cacheIt = aCache.find( aSheetPath );
|
||||||
|
|
||||||
|
if( cacheIt != aCache.end() )
|
||||||
|
return cacheIt->second;
|
||||||
|
|
||||||
|
// Iterate over children
|
||||||
|
for( const SCH_SHEET_PATH& candidate : aSchematic.GetSheets() )
|
||||||
|
{
|
||||||
|
if( candidate == aSheetPath || !candidate.IsContainedWithin( aSheetPath ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bool childRet = sheetContainsOnlyWantedItems( aSchematic, candidate, aSyncSymMap,
|
||||||
|
aSyncPinMap, aCache );
|
||||||
|
|
||||||
|
if( !childRet )
|
||||||
|
{
|
||||||
|
aCache.emplace( aSheetPath, false );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SCH_REFERENCE_LIST references;
|
||||||
|
aSheetPath.GetSymbols( references, false, true );
|
||||||
|
|
||||||
|
for( unsigned ii = 0; ii < references.GetCount(); ii++ )
|
||||||
|
{
|
||||||
|
SCH_REFERENCE& schRef = references[ii];
|
||||||
|
|
||||||
|
if( schRef.IsSplitNeeded() )
|
||||||
|
schRef.Split();
|
||||||
|
|
||||||
|
wxString refNum = schRef.GetRefNumber();
|
||||||
|
wxString fullRef = schRef.GetRef() + refNum;
|
||||||
|
|
||||||
|
// Skip power symbols
|
||||||
|
if( fullRef.StartsWith( "#" ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Unannotated symbols are not supported
|
||||||
|
if( refNum.compare( "?" ) == 0 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( aSyncSymMap.find( fullRef ) == aSyncSymMap.end() )
|
||||||
|
{
|
||||||
|
aCache.emplace( aSheetPath, false );
|
||||||
|
return false; // Some symbol is not wanted.
|
||||||
|
}
|
||||||
|
|
||||||
|
if( aSyncPinMap.find( fullRef ) != aSyncPinMap.end() )
|
||||||
|
{
|
||||||
|
aCache.emplace( aSheetPath, false );
|
||||||
|
return false; // Looking for specific pins, so can't be mapped
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aCache.emplace( aSheetPath, true );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::optional<std::tuple<SCH_SHEET_PATH, SCH_ITEM*, std::vector<SCH_ITEM*>>>
|
||||||
|
findItemsFromSyncSelection( const SCHEMATIC& aSchematic, const std::string aSyncStr,
|
||||||
|
bool aFocusOnFirst )
|
||||||
|
{
|
||||||
|
wxArrayString syncArray = wxStringTokenize( aSyncStr, "," );
|
||||||
|
|
||||||
|
std::unordered_map<wxString, std::vector<SCH_REFERENCE>> syncSymMap;
|
||||||
|
std::unordered_map<wxString, std::unordered_map<wxString, SCH_PIN*>> syncPinMap;
|
||||||
|
std::unordered_map<SCH_SHEET_PATH, double> symScores;
|
||||||
|
std::unordered_map<SCH_SHEET_PATH, bool> fullyWantedCache;
|
||||||
|
|
||||||
|
std::optional<wxString> focusSymbol;
|
||||||
|
std::optional<std::pair<wxString, wxString>> focusPin;
|
||||||
|
std::unordered_map<SCH_SHEET_PATH, std::vector<SCH_ITEM*>> focusItemResults;
|
||||||
|
|
||||||
|
const SCH_SHEET_LIST allSheetsList = aSchematic.GetSheets();
|
||||||
|
|
||||||
|
// In orderedSheets, the current sheet comes first.
|
||||||
|
SCH_SHEET_PATHS orderedSheets;
|
||||||
|
orderedSheets.reserve( allSheetsList.size() );
|
||||||
|
orderedSheets.push_back( aSchematic.CurrentSheet() );
|
||||||
|
|
||||||
|
for( const SCH_SHEET_PATH& sheetPath : allSheetsList )
|
||||||
|
{
|
||||||
|
if( sheetPath != aSchematic.CurrentSheet() )
|
||||||
|
orderedSheets.push_back( sheetPath );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init sync maps from the sync string
|
||||||
|
for( int i = 0; i < syncArray.size(); i++ )
|
||||||
|
{
|
||||||
|
wxString syncEntry = syncArray[i];
|
||||||
|
|
||||||
|
if( syncEntry.empty() )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
wxString syncData = syncEntry.substr( 1 );
|
||||||
|
|
||||||
|
switch( syncEntry.GetChar( 0 ).GetValue() )
|
||||||
|
{
|
||||||
|
case 'F': // Select by footprint: F<Reference>
|
||||||
|
{
|
||||||
|
wxString symRef = UnescapeString( syncData );
|
||||||
|
|
||||||
|
if( aFocusOnFirst && ( i == 0 ) )
|
||||||
|
focusSymbol = symRef;
|
||||||
|
|
||||||
|
syncSymMap[symRef] = std::vector<SCH_REFERENCE>();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'P': // Select by pad: P<Footprint reference>/<Pad number>
|
||||||
|
{
|
||||||
|
wxString symRef = UnescapeString( syncData.BeforeFirst( '/' ) );
|
||||||
|
wxString padNum = UnescapeString( syncData.AfterFirst( '/' ) );
|
||||||
|
|
||||||
|
if( aFocusOnFirst && ( i == 0 ) )
|
||||||
|
focusPin = std::make_pair( symRef, padNum );
|
||||||
|
|
||||||
|
syncPinMap[symRef][padNum] = nullptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lambda definitions
|
||||||
|
auto flattenSyncMaps = [&syncSymMap, &syncPinMap]() -> std::vector<SCH_ITEM*>
|
||||||
|
{
|
||||||
|
std::vector<SCH_ITEM*> allVec;
|
||||||
|
|
||||||
|
for( auto const& pairSym : syncSymMap )
|
||||||
|
{
|
||||||
|
for( const SCH_REFERENCE& ref : pairSym.second )
|
||||||
|
{
|
||||||
|
allVec.push_back( ref.GetSymbol() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( auto const& pairSym : syncPinMap )
|
||||||
|
{
|
||||||
|
for( auto const& pairPin : pairSym.second )
|
||||||
|
{
|
||||||
|
if( pairPin.second )
|
||||||
|
allVec.push_back( pairPin.second );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return allVec;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto clearSyncMaps = [&syncSymMap, &syncPinMap]()
|
||||||
|
{
|
||||||
|
for( auto& pairSym : syncSymMap )
|
||||||
|
{
|
||||||
|
pairSym.second.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
for( auto& pairSym : syncPinMap )
|
||||||
|
{
|
||||||
|
for( auto& pairPin : pairSym.second )
|
||||||
|
{
|
||||||
|
pairPin.second = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto syncMapsValuesEmpty = [&syncSymMap, &syncPinMap]() -> bool
|
||||||
|
{
|
||||||
|
for( auto const& pairSym : syncSymMap )
|
||||||
|
{
|
||||||
|
if( pairSym.second.size() > 0 )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( auto const& pairSym : syncPinMap )
|
||||||
|
{
|
||||||
|
for( auto const& pairPin : pairSym.second )
|
||||||
|
{
|
||||||
|
if( pairPin.second )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto checkFocusItems = [&]( const SCH_SHEET_PATH& aSheetPath )
|
||||||
|
{
|
||||||
|
if( focusSymbol )
|
||||||
|
{
|
||||||
|
auto findIt = syncSymMap.find( *focusSymbol );
|
||||||
|
if( findIt != syncSymMap.end() )
|
||||||
|
{
|
||||||
|
if( findIt->second.size() > 0 )
|
||||||
|
{
|
||||||
|
focusItemResults[aSheetPath].push_back( findIt->second.front().GetSymbol() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( focusPin )
|
||||||
|
{
|
||||||
|
auto findIt = syncPinMap.find( focusPin->first );
|
||||||
|
if( findIt != syncPinMap.end() )
|
||||||
|
{
|
||||||
|
if( findIt->second[focusPin->second] )
|
||||||
|
{
|
||||||
|
focusItemResults[aSheetPath].push_back( findIt->second[focusPin->second] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto makeRetForSheet = [&]( const SCH_SHEET_PATH& aSheet, SCH_ITEM* aFocusItem )
|
||||||
|
{
|
||||||
|
clearSyncMaps();
|
||||||
|
|
||||||
|
// Fill sync maps
|
||||||
|
findSymbolsAndPins( aSchematic, aSheet, syncSymMap, syncPinMap );
|
||||||
|
std::vector<SCH_ITEM*> itemsVector = flattenSyncMaps();
|
||||||
|
|
||||||
|
// Add fully wanted sheets to vector
|
||||||
|
for( SCH_ITEM* item : aSheet.LastScreen()->Items().OfType( SCH_SHEET_T ) )
|
||||||
|
{
|
||||||
|
KIID_PATH kiidPath = aSheet.Path();
|
||||||
|
kiidPath.push_back( item->m_Uuid );
|
||||||
|
|
||||||
|
std::optional<SCH_SHEET_PATH> subsheetPath =
|
||||||
|
allSheetsList.GetSheetPathByKIIDPath( kiidPath );
|
||||||
|
|
||||||
|
if( !subsheetPath )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( sheetContainsOnlyWantedItems( aSchematic, *subsheetPath, syncSymMap, syncPinMap,
|
||||||
|
fullyWantedCache ) )
|
||||||
|
{
|
||||||
|
itemsVector.push_back( item );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_tuple( aSheet, aFocusItem, itemsVector );
|
||||||
|
};
|
||||||
|
|
||||||
|
if( aFocusOnFirst )
|
||||||
|
{
|
||||||
|
for( const SCH_SHEET_PATH& sheetPath : orderedSheets )
|
||||||
|
{
|
||||||
|
clearSyncMaps();
|
||||||
|
|
||||||
|
findSymbolsAndPins( aSchematic, sheetPath, syncSymMap, syncPinMap );
|
||||||
|
|
||||||
|
checkFocusItems( sheetPath );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( focusItemResults.size() > 0 )
|
||||||
|
{
|
||||||
|
for( const SCH_SHEET_PATH& sheetPath : orderedSheets )
|
||||||
|
{
|
||||||
|
auto vec = focusItemResults[sheetPath];
|
||||||
|
|
||||||
|
if( !vec.empty() )
|
||||||
|
return makeRetForSheet( sheetPath, vec.front() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( const SCH_SHEET_PATH& sheetPath : orderedSheets )
|
||||||
|
{
|
||||||
|
clearSyncMaps();
|
||||||
|
|
||||||
|
findSymbolsAndPins( aSchematic, sheetPath, syncSymMap, syncPinMap );
|
||||||
|
|
||||||
|
if( !syncMapsValuesEmpty() )
|
||||||
|
{
|
||||||
|
// Something found on sheet
|
||||||
|
return makeRetForSheet( sheetPath, nullptr );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SCH_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
|
void SCH_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
|
||||||
{
|
{
|
||||||
std::string& payload = mail.GetPayload();
|
std::string& payload = mail.GetPayload();
|
||||||
|
@ -562,6 +823,45 @@ void SCH_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
|
||||||
ExecuteRemoteCommand( payload.c_str() );
|
ExecuteRemoteCommand( payload.c_str() );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MAIL_SELECTION:
|
||||||
|
if( !eeconfig()->m_CrossProbing.on_selection )
|
||||||
|
break;
|
||||||
|
|
||||||
|
KI_FALLTHROUGH;
|
||||||
|
|
||||||
|
case MAIL_SELECTION_FORCE:
|
||||||
|
{
|
||||||
|
// $SELECT: 0,<spec1>,<spec2>,<spec3>
|
||||||
|
// Try to select specified items.
|
||||||
|
|
||||||
|
// $SELECT: 1,<spec1>,<spec2>,<spec3>
|
||||||
|
// Select and focus on <spec1> item, select other specified items that are on the same sheet.
|
||||||
|
|
||||||
|
std::string prefix = "$SELECT: ";
|
||||||
|
|
||||||
|
std::string paramStr = payload.substr( prefix.size() );
|
||||||
|
std::string syncStr = paramStr.substr( 2 );
|
||||||
|
|
||||||
|
bool focusOnFirst = ( paramStr[0] == '1' );
|
||||||
|
|
||||||
|
std::optional<std::tuple<SCH_SHEET_PATH, SCH_ITEM*, std::vector<SCH_ITEM*>>> findRet =
|
||||||
|
findItemsFromSyncSelection( Schematic(), syncStr, focusOnFirst );
|
||||||
|
|
||||||
|
if( findRet )
|
||||||
|
{
|
||||||
|
auto& [sheetPath, focusItem, items] = *findRet;
|
||||||
|
|
||||||
|
m_syncingPcbToSchSelection = true; // recursion guard
|
||||||
|
|
||||||
|
GetToolManager()->GetTool<EE_SELECTION_TOOL>()->SyncSelection( sheetPath, focusItem,
|
||||||
|
items );
|
||||||
|
|
||||||
|
m_syncingPcbToSchSelection = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case MAIL_SCH_GET_NETLIST:
|
case MAIL_SCH_GET_NETLIST:
|
||||||
{
|
{
|
||||||
if( !payload.empty() )
|
if( !payload.empty() )
|
||||||
|
|
|
@ -120,6 +120,7 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||||
|
|
||||||
m_showBorderAndTitleBlock = true; // true to show sheet references
|
m_showBorderAndTitleBlock = true; // true to show sheet references
|
||||||
m_supportsAutoSave = true;
|
m_supportsAutoSave = true;
|
||||||
|
m_syncingPcbToSchSelection = false;
|
||||||
m_aboutTitle = _( "KiCad Schematic Editor" );
|
m_aboutTitle = _( "KiCad Schematic Editor" );
|
||||||
|
|
||||||
m_findReplaceDialog = nullptr;
|
m_findReplaceDialog = nullptr;
|
||||||
|
@ -1762,10 +1763,13 @@ void SCH_EDIT_FRAME::FocusOnItem( SCH_ITEM* aItem )
|
||||||
|
|
||||||
if( aItem )
|
if( aItem )
|
||||||
{
|
{
|
||||||
aItem->SetBrightened();
|
if( !aItem->IsBrightened() )
|
||||||
|
{
|
||||||
|
aItem->SetBrightened();
|
||||||
|
|
||||||
UpdateItem( aItem );
|
UpdateItem( aItem );
|
||||||
lastBrightenedItemID = aItem->m_Uuid;
|
lastBrightenedItemID = aItem->m_Uuid;
|
||||||
|
}
|
||||||
|
|
||||||
FocusOnLocation( aItem->GetFocusPosition() );
|
FocusOnLocation( aItem->GetFocusPosition() );
|
||||||
}
|
}
|
||||||
|
|
|
@ -264,7 +264,7 @@ public:
|
||||||
* @param aForce select the element in pcbnew whether or not the user has the select option chosen
|
* @param aForce select the element in pcbnew whether or not the user has the select option chosen
|
||||||
* This is used for when the eeschema user is using the cross-probe tool
|
* This is used for when the eeschema user is using the cross-probe tool
|
||||||
*/
|
*/
|
||||||
void SendSelectItems( const std::deque<EDA_ITEM*>& aElements, bool aForce );
|
void SendSelectItemsToPcb( const std::deque<EDA_ITEM*>& aElements, bool aForce );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a net name to Pcbnew for highlighting
|
* Sends a net name to Pcbnew for highlighting
|
||||||
|
@ -772,6 +772,8 @@ public:
|
||||||
|
|
||||||
void FocusOnItem( SCH_ITEM* aItem );
|
void FocusOnItem( SCH_ITEM* aItem );
|
||||||
|
|
||||||
|
bool IsSyncingSelection() { return m_syncingPcbToSchSelection; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update a schematic symbol from a LIB_SYMBOL.
|
* Update a schematic symbol from a LIB_SYMBOL.
|
||||||
*
|
*
|
||||||
|
@ -923,6 +925,8 @@ private:
|
||||||
DIALOG_SCH_FIND* m_findReplaceDialog;
|
DIALOG_SCH_FIND* m_findReplaceDialog;
|
||||||
|
|
||||||
HIERARCHY_NAVIG_PANEL* m_hierarchy;
|
HIERARCHY_NAVIG_PANEL* m_hierarchy;
|
||||||
|
|
||||||
|
bool m_syncingPcbToSchSelection; // Recursion guard when synchronizing selection from PCB
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -866,6 +866,18 @@ void SCH_SHEET_LIST::GetSheetsWithinPath( SCH_SHEET_PATHS& aSheets,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::optional<SCH_SHEET_PATH> SCH_SHEET_LIST::GetSheetPathByKIIDPath( const KIID_PATH& aPath ) const
|
||||||
|
{
|
||||||
|
for( const SCH_SHEET_PATH& sheet : *this )
|
||||||
|
{
|
||||||
|
if( sheet.Path() == aPath )
|
||||||
|
return SCH_SHEET_PATH( sheet );
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SCH_SHEET_LIST::GetMultiUnitSymbols( SCH_MULTI_UNIT_REFERENCE_MAP &aRefList,
|
void SCH_SHEET_LIST::GetMultiUnitSymbols( SCH_MULTI_UNIT_REFERENCE_MAP &aRefList,
|
||||||
bool aIncludePowerSymbols ) const
|
bool aIncludePowerSymbols ) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,8 +32,10 @@
|
||||||
#define CLASS_DRAWSHEET_PATH_H
|
#define CLASS_DRAWSHEET_PATH_H
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include <kiid.h>
|
#include <kiid.h>
|
||||||
|
#include <wx/string.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple container for schematic symbol instance information.
|
* A simple container for schematic symbol instance information.
|
||||||
|
@ -506,6 +508,15 @@ public:
|
||||||
*/
|
*/
|
||||||
void GetSheetsWithinPath( SCH_SHEET_PATHS& aSheets, const SCH_SHEET_PATH& aSheetPath ) const;
|
void GetSheetsWithinPath( SCH_SHEET_PATHS& aSheets, const SCH_SHEET_PATH& aSheetPath ) const;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a SCH_SHEET_PATH that matches the provided KIID_PATH.
|
||||||
|
*
|
||||||
|
* @param aPath The KIID_PATH to search for.
|
||||||
|
*/
|
||||||
|
std::optional<SCH_SHEET_PATH> GetSheetPathByKIIDPath( const KIID_PATH& aPath ) const;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a #SCH_REFERENCE_LIST object to \a aRefList for each same-reference set of
|
* Add a #SCH_REFERENCE_LIST object to \a aRefList for each same-reference set of
|
||||||
* multi-unit parts in the list of sheets. The map key for each element will be the
|
* multi-unit parts in the list of sheets. The map key for each element will be the
|
||||||
|
|
|
@ -110,6 +110,9 @@ TOOL_ACTION EE_ACTIONS::removeItemsFromSel( "eeschema.InteractiveSelection.Remov
|
||||||
TOOL_ACTION EE_ACTIONS::clearSelection( "eeschema.InteractiveSelection.ClearSelection",
|
TOOL_ACTION EE_ACTIONS::clearSelection( "eeschema.InteractiveSelection.ClearSelection",
|
||||||
AS_GLOBAL );
|
AS_GLOBAL );
|
||||||
|
|
||||||
|
TOOL_ACTION EE_ACTIONS::syncSelection( "eeschema.InteractiveSelection.SyncSelection",
|
||||||
|
AS_GLOBAL );
|
||||||
|
|
||||||
|
|
||||||
// SYMBOL_EDITOR_CONTROL
|
// SYMBOL_EDITOR_CONTROL
|
||||||
//
|
//
|
||||||
|
|
|
@ -66,6 +66,9 @@ public:
|
||||||
/// Runs a selection menu to select from a list of items
|
/// Runs a selection menu to select from a list of items
|
||||||
static TOOL_ACTION selectionMenu;
|
static TOOL_ACTION selectionMenu;
|
||||||
|
|
||||||
|
/// Selection synchronization (PCB -> SCH)
|
||||||
|
static TOOL_ACTION syncSelection;
|
||||||
|
|
||||||
// Locking
|
// Locking
|
||||||
static TOOL_ACTION toggleLock;
|
static TOOL_ACTION toggleLock;
|
||||||
static TOOL_ACTION lock;
|
static TOOL_ACTION lock;
|
||||||
|
|
|
@ -338,6 +338,7 @@ void EE_INSPECTION_TOOL::setTransitions()
|
||||||
Go( &EE_INSPECTION_TOOL::PrevMarker, EE_ACTIONS::prevMarker.MakeEvent() );
|
Go( &EE_INSPECTION_TOOL::PrevMarker, EE_ACTIONS::prevMarker.MakeEvent() );
|
||||||
Go( &EE_INSPECTION_TOOL::NextMarker, EE_ACTIONS::nextMarker.MakeEvent() );
|
Go( &EE_INSPECTION_TOOL::NextMarker, EE_ACTIONS::nextMarker.MakeEvent() );
|
||||||
// See note 1:
|
// See note 1:
|
||||||
|
Go( &EE_INSPECTION_TOOL::CrossProbe, EVENTS::PointSelectedEvent );
|
||||||
Go( &EE_INSPECTION_TOOL::CrossProbe, EVENTS::SelectedEvent );
|
Go( &EE_INSPECTION_TOOL::CrossProbe, EVENTS::SelectedEvent );
|
||||||
Go( &EE_INSPECTION_TOOL::ExcludeMarker, EE_ACTIONS::excludeMarker.MakeEvent() );
|
Go( &EE_INSPECTION_TOOL::ExcludeMarker, EE_ACTIONS::excludeMarker.MakeEvent() );
|
||||||
|
|
||||||
|
|
|
@ -1477,6 +1477,7 @@ void EE_POINT_EDITOR::rollbackFromUndo()
|
||||||
|
|
||||||
void EE_POINT_EDITOR::setTransitions()
|
void EE_POINT_EDITOR::setTransitions()
|
||||||
{
|
{
|
||||||
|
Go( &EE_POINT_EDITOR::Main, EVENTS::PointSelectedEvent );
|
||||||
Go( &EE_POINT_EDITOR::Main, EVENTS::SelectedEvent );
|
Go( &EE_POINT_EDITOR::Main, EVENTS::SelectedEvent );
|
||||||
Go( &EE_POINT_EDITOR::Main, ACTIONS::activatePointEditor.MakeEvent() );
|
Go( &EE_POINT_EDITOR::Main, ACTIONS::activatePointEditor.MakeEvent() );
|
||||||
Go( &EE_POINT_EDITOR::addCorner, EE_ACTIONS::pointEditorAddCorner.MakeEvent() );
|
Go( &EE_POINT_EDITOR::addCorner, EE_ACTIONS::pointEditorAddCorner.MakeEvent() );
|
||||||
|
|
|
@ -872,7 +872,7 @@ bool EE_SELECTION_TOOL::selectPoint( EE_COLLECTOR& aCollector, const VECTOR2I& a
|
||||||
if( !aAdd && !aSubtract && !aExclusiveOr )
|
if( !aAdd && !aSubtract && !aExclusiveOr )
|
||||||
ClearSelection();
|
ClearSelection();
|
||||||
|
|
||||||
bool anyAdded = false;
|
int addedCount = 0;
|
||||||
bool anySubtracted = false;
|
bool anySubtracted = false;
|
||||||
|
|
||||||
if( aCollector.GetCount() > 0 )
|
if( aCollector.GetCount() > 0 )
|
||||||
|
@ -908,20 +908,25 @@ bool EE_SELECTION_TOOL::selectPoint( EE_COLLECTOR& aCollector, const VECTOR2I& a
|
||||||
{
|
{
|
||||||
aCollector[i]->SetFlags( flags );
|
aCollector[i]->SetFlags( flags );
|
||||||
select( aCollector[i] );
|
select( aCollector[i] );
|
||||||
anyAdded = true;
|
addedCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( anyAdded )
|
if( addedCount == 1 )
|
||||||
{
|
{
|
||||||
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
|
m_toolMgr->ProcessEvent( EVENTS::PointSelectedEvent );
|
||||||
|
|
||||||
if( aItem && aCollector.GetCount() == 1 )
|
if( aItem && aCollector.GetCount() == 1 )
|
||||||
*aItem = aCollector[0];
|
*aItem = aCollector[0];
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if( addedCount > 1 )
|
||||||
|
{
|
||||||
|
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
else if( anySubtracted )
|
else if( anySubtracted )
|
||||||
{
|
{
|
||||||
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
|
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
|
||||||
|
@ -1491,6 +1496,156 @@ int EE_SELECTION_TOOL::ClearSelection( const TOOL_EVENT& aEvent )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EE_SELECTION_TOOL::ZoomFitCrossProbeBBox( EDA_RECT bbox )
|
||||||
|
{
|
||||||
|
if( bbox.GetWidth() == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
bbox.Normalize();
|
||||||
|
|
||||||
|
VECTOR2I bbSize = bbox.Inflate( bbox.GetWidth() * 0.2f ).GetSize();
|
||||||
|
VECTOR2D screenSize = getView()->GetViewport().GetSize();
|
||||||
|
|
||||||
|
// This code tries to come up with a zoom factor that doesn't simply zoom in
|
||||||
|
// to the cross probed symbol, but instead shows a reasonable amount of the
|
||||||
|
// circuit around it to provide context. This reduces or eliminates the need
|
||||||
|
// to manually change the zoom because it's too close.
|
||||||
|
|
||||||
|
// Using the default text height as a constant to compare against, use the
|
||||||
|
// height of the bounding box of visible items for a footprint to figure out
|
||||||
|
// if this is a big symbol (like a processor) or a small symbol (like a resistor).
|
||||||
|
// This ratio is not useful by itself as a scaling factor. It must be "bent" to
|
||||||
|
// provide good scaling at varying symbol sizes. Bigger symbols need less
|
||||||
|
// scaling than small ones.
|
||||||
|
double currTextHeight = Mils2iu( DEFAULT_TEXT_SIZE );
|
||||||
|
|
||||||
|
double compRatio = bbSize.y / currTextHeight; // Ratio of symbol to text height
|
||||||
|
double compRatioBent = 1.0;
|
||||||
|
|
||||||
|
// LUT to scale zoom ratio to provide reasonable schematic context. Must work
|
||||||
|
// with symbols of varying sizes (e.g. 0402 package and 200 pin BGA).
|
||||||
|
// "first" is used as the input and "second" as the output
|
||||||
|
//
|
||||||
|
// "first" = compRatio (symbol height / default text height)
|
||||||
|
// "second" = Amount to scale ratio by
|
||||||
|
std::vector<std::pair<double, double>> lut{ { 1.25, 16 }, // 32
|
||||||
|
{ 2.5, 12 }, //24
|
||||||
|
{ 5, 8 }, // 16
|
||||||
|
{ 6, 6 }, //
|
||||||
|
{ 10, 4 }, //8
|
||||||
|
{ 20, 2 }, //4
|
||||||
|
{ 40, 1.5 }, // 2
|
||||||
|
{ 100, 1 } };
|
||||||
|
|
||||||
|
std::vector<std::pair<double, double>>::iterator it;
|
||||||
|
|
||||||
|
// Large symbol default is last LUT entry (1:1).
|
||||||
|
compRatioBent = lut.back().second;
|
||||||
|
|
||||||
|
// Use LUT to do linear interpolation of "compRatio" within "first", then
|
||||||
|
// use that result to linearly interpolate "second" which gives the scaling
|
||||||
|
// factor needed.
|
||||||
|
if( compRatio >= lut.front().first )
|
||||||
|
{
|
||||||
|
for( it = lut.begin(); it < lut.end() - 1; it++ )
|
||||||
|
{
|
||||||
|
if( it->first <= compRatio && next( it )->first >= compRatio )
|
||||||
|
{
|
||||||
|
double diffx = compRatio - it->first;
|
||||||
|
double diffn = next( it )->first - it->first;
|
||||||
|
|
||||||
|
compRatioBent = it->second + ( next( it )->second - it->second ) * diffx / diffn;
|
||||||
|
break; // We have our interpolated value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
compRatioBent = lut.front().second; // Small symbol default is first entry
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is similar to the original KiCad code that scaled the zoom to make sure
|
||||||
|
// symbols were visible on screen. It's simply a ratio of screen size to
|
||||||
|
// symbol size, and its job is to zoom in to make the component fullscreen.
|
||||||
|
// Earlier in the code the symbol BBox is given a 20% margin to add some
|
||||||
|
// breathing room. We compare the height of this enlarged symbol bbox to the
|
||||||
|
// default text height. If a symbol will end up with the sides clipped, we
|
||||||
|
// adjust later to make sure it fits on screen.
|
||||||
|
screenSize.x = std::max( 10.0, screenSize.x );
|
||||||
|
screenSize.y = std::max( 10.0, screenSize.y );
|
||||||
|
double ratio = std::max( -1.0, fabs( bbSize.y / screenSize.y ) );
|
||||||
|
|
||||||
|
// Original KiCad code for how much to scale the zoom
|
||||||
|
double kicadRatio =
|
||||||
|
std::max( fabs( bbSize.x / screenSize.x ), fabs( bbSize.y / screenSize.y ) );
|
||||||
|
|
||||||
|
// If the width of the part we're probing is bigger than what the screen width
|
||||||
|
// will be after the zoom, then punt and use the KiCad zoom algorithm since it
|
||||||
|
// guarantees the part's width will be encompassed within the screen.
|
||||||
|
if( bbSize.x > screenSize.x * ratio * compRatioBent )
|
||||||
|
{
|
||||||
|
// Use standard KiCad zoom for parts too wide to fit on screen/
|
||||||
|
ratio = kicadRatio;
|
||||||
|
compRatioBent = 1.0; // Reset so we don't modify the "KiCad" ratio
|
||||||
|
wxLogTrace( "CROSS_PROBE_SCALE",
|
||||||
|
"Part TOO WIDE for screen. Using normal KiCad zoom ratio: %1.5f", ratio );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now that "compRatioBent" holds our final scaling factor we apply it to the
|
||||||
|
// original fullscreen zoom ratio to arrive at the final ratio itself.
|
||||||
|
ratio *= compRatioBent;
|
||||||
|
|
||||||
|
bool alwaysZoom = false; // DEBUG - allows us to minimize zooming or not
|
||||||
|
|
||||||
|
// Try not to zoom on every cross-probe; it gets very noisy
|
||||||
|
if( ( ratio < 0.5 || ratio > 1.0 ) || alwaysZoom )
|
||||||
|
getView()->SetScale( getView()->GetScale() / ratio );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int EE_SELECTION_TOOL::SyncSelection( std::optional<SCH_SHEET_PATH> targetSheetPath,
|
||||||
|
SCH_ITEM* focusItem, std::vector<SCH_ITEM*> items )
|
||||||
|
{
|
||||||
|
SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
|
||||||
|
|
||||||
|
if( !editFrame || m_isSymbolEditor || m_isSymbolViewer )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if( targetSheetPath && targetSheetPath != editFrame->Schematic().CurrentSheet() )
|
||||||
|
{
|
||||||
|
editFrame->Schematic().SetCurrentSheet( *targetSheetPath );
|
||||||
|
editFrame->DisplayCurrentSheet();
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearSelection( items.size() > 0 ? true /*quiet mode*/ : false );
|
||||||
|
|
||||||
|
// Perform individual selection of each item before processing the event.
|
||||||
|
for( SCH_ITEM* item : items )
|
||||||
|
select( item );
|
||||||
|
|
||||||
|
EDA_RECT bbox = m_selection.GetBoundingBox();
|
||||||
|
|
||||||
|
if( bbox.GetWidth() != 0 && bbox.GetHeight() != 0 )
|
||||||
|
{
|
||||||
|
if( m_frame->eeconfig()->m_CrossProbing.center_on_items )
|
||||||
|
{
|
||||||
|
if( m_frame->eeconfig()->m_CrossProbing.zoom_to_fit )
|
||||||
|
ZoomFitCrossProbeBBox( bbox );
|
||||||
|
|
||||||
|
editFrame->FocusOnItem( focusItem );
|
||||||
|
|
||||||
|
if( !focusItem )
|
||||||
|
editFrame->FocusOnLocation( bbox.Centre() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_selection.Size() > 0 )
|
||||||
|
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void EE_SELECTION_TOOL::RebuildSelection()
|
void EE_SELECTION_TOOL::RebuildSelection()
|
||||||
{
|
{
|
||||||
m_selection.Clear();
|
m_selection.Clear();
|
||||||
|
@ -1604,7 +1759,7 @@ bool EE_SELECTION_TOOL::Selectable( const EDA_ITEM* aItem, const VECTOR2I* aPos,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void EE_SELECTION_TOOL::ClearSelection()
|
void EE_SELECTION_TOOL::ClearSelection( bool aQuietMode )
|
||||||
{
|
{
|
||||||
if( m_selection.Empty() )
|
if( m_selection.Empty() )
|
||||||
return;
|
return;
|
||||||
|
@ -1618,7 +1773,10 @@ void EE_SELECTION_TOOL::ClearSelection()
|
||||||
m_selection.ClearReferencePoint();
|
m_selection.ClearReferencePoint();
|
||||||
|
|
||||||
// Inform other potentially interested tools
|
// Inform other potentially interested tools
|
||||||
m_toolMgr->ProcessEvent( EVENTS::ClearedEvent );
|
if( !aQuietMode )
|
||||||
|
{
|
||||||
|
m_toolMgr->ProcessEvent( EVENTS::ClearedEvent );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,9 @@ public:
|
||||||
|
|
||||||
void OnIdle( wxIdleEvent& aEvent );
|
void OnIdle( wxIdleEvent& aEvent );
|
||||||
|
|
||||||
|
///< Zoom the screen to fit the bounding box for cross probing/selection sync.
|
||||||
|
void ZoomFitCrossProbeBBox( EDA_RECT bbox );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the set of currently selected items.
|
* @return the set of currently selected items.
|
||||||
*/
|
*/
|
||||||
|
@ -135,7 +138,7 @@ public:
|
||||||
///< Select all visible items in sheet
|
///< Select all visible items in sheet
|
||||||
int SelectAll( const TOOL_EVENT& aEvent );
|
int SelectAll( const TOOL_EVENT& aEvent );
|
||||||
|
|
||||||
void ClearSelection();
|
void ClearSelection( bool aQuietMode = false );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check conditions for an item to be selected.
|
* Check conditions for an item to be selected.
|
||||||
|
@ -170,6 +173,11 @@ public:
|
||||||
bool CollectHits( EE_COLLECTOR& aCollector, const VECTOR2I& aWhere,
|
bool CollectHits( EE_COLLECTOR& aCollector, const VECTOR2I& aWhere,
|
||||||
const std::vector<KICAD_T>& aScanTypes = { SCH_LOCATE_ANY_T } );
|
const std::vector<KICAD_T>& aScanTypes = { SCH_LOCATE_ANY_T } );
|
||||||
|
|
||||||
|
///< Set selection to items passed by parameter.
|
||||||
|
///< Zooms to fit, if enabled.
|
||||||
|
int SyncSelection( std::optional<SCH_SHEET_PATH> targetSheetPath, SCH_ITEM* focusItem,
|
||||||
|
std::vector<SCH_ITEM*> items );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SELECTION& selection() override { return m_selection; }
|
SELECTION& selection() override { return m_selection; }
|
||||||
|
|
||||||
|
|
|
@ -716,14 +716,14 @@ int SCH_EDITOR_CONTROL::ExplicitCrossProbeToPcb( const TOOL_EVENT& aEvent )
|
||||||
void SCH_EDITOR_CONTROL::doCrossProbeSchToPcb( const TOOL_EVENT& aEvent, bool aForce )
|
void SCH_EDITOR_CONTROL::doCrossProbeSchToPcb( const TOOL_EVENT& aEvent, bool aForce )
|
||||||
{
|
{
|
||||||
// Don't get in an infinite loop SCH -> PCB -> SCH -> PCB -> SCH -> ...
|
// Don't get in an infinite loop SCH -> PCB -> SCH -> PCB -> SCH -> ...
|
||||||
if( m_probingPcbToSch )
|
if( m_probingPcbToSch || m_frame->IsSyncingSelection() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
EE_SELECTION_TOOL* selTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
|
EE_SELECTION_TOOL* selTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
|
||||||
|
|
||||||
EE_SELECTION& selection = aForce ? selTool->RequestSelection() : selTool->GetSelection();
|
EE_SELECTION& selection = aForce ? selTool->RequestSelection() : selTool->GetSelection();
|
||||||
|
|
||||||
m_frame->SendSelectItems( selection.GetItems(), aForce );
|
m_frame->SendSelectItemsToPcb( selection.GetItems(), aForce );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2337,6 +2337,7 @@ void SCH_EDITOR_CONTROL::setTransitions()
|
||||||
Go( &SCH_EDITOR_CONTROL::UpdateFind, ACTIONS::updateFind.MakeEvent() );
|
Go( &SCH_EDITOR_CONTROL::UpdateFind, ACTIONS::updateFind.MakeEvent() );
|
||||||
Go( &SCH_EDITOR_CONTROL::UpdateFind, EVENTS::SelectedItemsModified );
|
Go( &SCH_EDITOR_CONTROL::UpdateFind, EVENTS::SelectedItemsModified );
|
||||||
|
|
||||||
|
Go( &SCH_EDITOR_CONTROL::CrossProbeToPcb, EVENTS::PointSelectedEvent );
|
||||||
Go( &SCH_EDITOR_CONTROL::CrossProbeToPcb, EVENTS::SelectedEvent );
|
Go( &SCH_EDITOR_CONTROL::CrossProbeToPcb, EVENTS::SelectedEvent );
|
||||||
Go( &SCH_EDITOR_CONTROL::CrossProbeToPcb, EVENTS::UnselectedEvent );
|
Go( &SCH_EDITOR_CONTROL::CrossProbeToPcb, EVENTS::UnselectedEvent );
|
||||||
Go( &SCH_EDITOR_CONTROL::CrossProbeToPcb, EVENTS::ClearedEvent );
|
Go( &SCH_EDITOR_CONTROL::CrossProbeToPcb, EVENTS::ClearedEvent );
|
||||||
|
|
|
@ -149,7 +149,7 @@ public:
|
||||||
void AssignFootprints( const std::string& aChangedSetOfReferences );
|
void AssignFootprints( const std::string& aChangedSetOfReferences );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a symbol in the schematic and an item in this symbol.
|
* Find a symbol in the schematic and an item in this symbol and select it.
|
||||||
*
|
*
|
||||||
* @param aPath The symbol path to find. Pass nullptr to search by aReference.
|
* @param aPath The symbol path to find. Pass nullptr to search by aReference.
|
||||||
* @param aReference The symbol reference designator to find, or to display in
|
* @param aReference The symbol reference designator to find, or to display in
|
||||||
|
@ -222,7 +222,7 @@ private:
|
||||||
wxFindReplaceData& aData );
|
wxFindReplaceData& aData );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_probingPcbToSch; // Recursion guard when cross-probing to PcbNew
|
bool m_probingPcbToSch; // Recursion guard when cross-probing to schematic editor
|
||||||
EDA_ITEM* m_pickerItem; // Current item for picker highlighting.
|
EDA_ITEM* m_pickerItem; // Current item for picker highlighting.
|
||||||
|
|
||||||
// Temporary storage location for Duplicate action
|
// Temporary storage location for Duplicate action
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
enum MAIL_T
|
enum MAIL_T
|
||||||
{
|
{
|
||||||
MAIL_CROSS_PROBE, // PCB<->SCH, CVPCB->SCH cross-probing.
|
MAIL_CROSS_PROBE, // PCB<->SCH, CVPCB->SCH cross-probing.
|
||||||
MAIL_SELECTION, // SCH->PCB selection synchronization.
|
MAIL_SELECTION, // SCH<->PCB selection synchronization.
|
||||||
MAIL_SELECTION_FORCE, // Explicit selection of SCH->PCB selection synchronization.
|
MAIL_SELECTION_FORCE, // Explicit selection of SCH->PCB selection synchronization.
|
||||||
MAIL_ASSIGN_FOOTPRINTS, // CVPCB->SCH footprint stuffing
|
MAIL_ASSIGN_FOOTPRINTS, // CVPCB->SCH footprint stuffing
|
||||||
MAIL_SCH_SAVE, // CVPCB->SCH save the schematic
|
MAIL_SCH_SAVE, // CVPCB->SCH save the schematic
|
||||||
|
|
|
@ -198,6 +198,7 @@ public:
|
||||||
class EVENTS
|
class EVENTS
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
const static TOOL_EVENT PointSelectedEvent;
|
||||||
const static TOOL_EVENT SelectedEvent;
|
const static TOOL_EVENT SelectedEvent;
|
||||||
const static TOOL_EVENT UnselectedEvent;
|
const static TOOL_EVENT UnselectedEvent;
|
||||||
const static TOOL_EVENT ClearedEvent;
|
const static TOOL_EVENT ClearedEvent;
|
||||||
|
|
|
@ -42,6 +42,7 @@ public:
|
||||||
KIGFX::VIEW_GROUP::VIEW_GROUP()
|
KIGFX::VIEW_GROUP::VIEW_GROUP()
|
||||||
{
|
{
|
||||||
m_isHover = false;
|
m_isHover = false;
|
||||||
|
m_lastAddedItem = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
SELECTION( const SELECTION& aOther ) :
|
SELECTION( const SELECTION& aOther ) :
|
||||||
|
@ -49,12 +50,14 @@ public:
|
||||||
{
|
{
|
||||||
m_items = aOther.m_items;
|
m_items = aOther.m_items;
|
||||||
m_isHover = aOther.m_isHover;
|
m_isHover = aOther.m_isHover;
|
||||||
|
m_lastAddedItem = aOther.m_lastAddedItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
SELECTION& operator= ( const SELECTION& aOther )
|
SELECTION& operator= ( const SELECTION& aOther )
|
||||||
{
|
{
|
||||||
m_items = aOther.m_items;
|
m_items = aOther.m_items;
|
||||||
m_isHover = aOther.m_isHover;
|
m_isHover = aOther.m_isHover;
|
||||||
|
m_lastAddedItem = aOther.m_lastAddedItem;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +114,11 @@ public:
|
||||||
return m_items;
|
return m_items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EDA_ITEM* GetLastAddedItem() const
|
||||||
|
{
|
||||||
|
return m_lastAddedItem;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a copy of this selection of items sorted by their X then Y position.
|
* Returns a copy of this selection of items sorted by their X then Y position.
|
||||||
*
|
*
|
||||||
|
@ -257,6 +265,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
OPT<VECTOR2I> m_referencePoint;
|
OPT<VECTOR2I> m_referencePoint;
|
||||||
std::deque<EDA_ITEM*> m_items;
|
std::deque<EDA_ITEM*> m_items;
|
||||||
|
EDA_ITEM* m_lastAddedItem;
|
||||||
bool m_isHover;
|
bool m_isHover;
|
||||||
|
|
||||||
// mute hidden overloaded virtual function warnings
|
// mute hidden overloaded virtual function warnings
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include <footprint.h>
|
#include <footprint.h>
|
||||||
#include <pad.h>
|
#include <pad.h>
|
||||||
#include <pcb_track.h>
|
#include <pcb_track.h>
|
||||||
|
#include <pcb_group.h>
|
||||||
#include <zone.h>
|
#include <zone.h>
|
||||||
#include <collectors.h>
|
#include <collectors.h>
|
||||||
#include <eda_dde.h>
|
#include <eda_dde.h>
|
||||||
|
@ -221,11 +222,11 @@ void PCB_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline )
|
||||||
renderSettings->SetHighlight( false );
|
renderSettings->SetHighlight( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( crossProbingSettings.center_on_items && bbox.GetWidth() > 0 && bbox.GetHeight() > 0 )
|
if( crossProbingSettings.center_on_items && bbox.GetWidth() != 0 && bbox.GetHeight() != 0 )
|
||||||
{
|
{
|
||||||
if( crossProbingSettings.zoom_to_fit )
|
if( crossProbingSettings.zoom_to_fit )
|
||||||
{
|
{
|
||||||
GetToolManager()->GetTool<PCB_SELECTION_TOOL>()->zoomFitCrossProbeBBox( bbox );
|
GetToolManager()->GetTool<PCB_SELECTION_TOOL>()->ZoomFitCrossProbeBBox( bbox );
|
||||||
}
|
}
|
||||||
|
|
||||||
FocusOnLocation( (wxPoint) bbox.Centre() );
|
FocusOnLocation( (wxPoint) bbox.Centre() );
|
||||||
|
@ -293,9 +294,108 @@ std::string FormatProbeItem( BOARD_ITEM* aItem )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PCB_EDIT_FRAME::SendMessageToEESCHEMA( BOARD_ITEM* aSyncItem )
|
template <typename ItemContainer>
|
||||||
|
void collectItemsForSyncParts( ItemContainer& aItems, std::set<wxString>& parts )
|
||||||
{
|
{
|
||||||
std::string packet = FormatProbeItem( aSyncItem );
|
for( EDA_ITEM* item : aItems )
|
||||||
|
{
|
||||||
|
switch( item->Type() )
|
||||||
|
{
|
||||||
|
case PCB_GROUP_T:
|
||||||
|
{
|
||||||
|
PCB_GROUP* group = static_cast<PCB_GROUP*>( item );
|
||||||
|
|
||||||
|
collectItemsForSyncParts( group->GetItems(), parts );
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PCB_FOOTPRINT_T:
|
||||||
|
{
|
||||||
|
FOOTPRINT* footprint = static_cast<FOOTPRINT*>( item );
|
||||||
|
wxString ref = footprint->GetReference();
|
||||||
|
|
||||||
|
parts.emplace( wxT( "F" ) + EscapeString( ref, CTX_IPC ) );
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case PCB_PAD_T:
|
||||||
|
{
|
||||||
|
PAD* pad = static_cast<PAD*>( item );
|
||||||
|
FOOTPRINT* footprint = static_cast<FOOTPRINT*>( pad->GetParentFootprint() );
|
||||||
|
wxString ref = footprint->GetReference();
|
||||||
|
|
||||||
|
parts.emplace( wxT( "P" ) + EscapeString( ref, CTX_IPC ) + wxT( "/" )
|
||||||
|
+ EscapeString( pad->GetNumber(), CTX_IPC ) );
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PCB_EDIT_FRAME::SendSelectItemsToSch( const std::deque<EDA_ITEM*>& aItems,
|
||||||
|
EDA_ITEM* aFocusItem, bool aForce )
|
||||||
|
{
|
||||||
|
std::string command = "$SELECT: ";
|
||||||
|
|
||||||
|
if( aFocusItem )
|
||||||
|
{
|
||||||
|
std::deque<EDA_ITEM*> focusItems = { aFocusItem };
|
||||||
|
std::set<wxString> focusParts;
|
||||||
|
collectItemsForSyncParts( focusItems, focusParts );
|
||||||
|
|
||||||
|
if( focusParts.size() > 0 )
|
||||||
|
{
|
||||||
|
command += "1,";
|
||||||
|
command += *focusParts.begin();
|
||||||
|
command += ",";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
command += "0,";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
command += "0,";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<wxString> parts;
|
||||||
|
collectItemsForSyncParts( aItems, parts );
|
||||||
|
|
||||||
|
if( parts.empty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for( wxString part : parts )
|
||||||
|
{
|
||||||
|
command += part;
|
||||||
|
command += ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
command.pop_back();
|
||||||
|
|
||||||
|
if( Kiface().IsSingle() )
|
||||||
|
{
|
||||||
|
SendCommand( MSG_TO_PCB, command );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Typically ExpressMail is going to be s-expression packets, but since
|
||||||
|
// we have existing interpreter of the selection packet on the other
|
||||||
|
// side in place, we use that here.
|
||||||
|
Kiway().ExpressMail( FRAME_SCH, aForce ? MAIL_SELECTION_FORCE : MAIL_SELECTION, command,
|
||||||
|
this );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PCB_EDIT_FRAME::SendCrossProbeNetName( const wxString& aNetName )
|
||||||
|
{
|
||||||
|
std::string packet = StrPrintf( "$NET: \"%s\"", TO_UTF8( aNetName ) );
|
||||||
|
|
||||||
if( !packet.empty() )
|
if( !packet.empty() )
|
||||||
{
|
{
|
||||||
|
@ -314,9 +414,9 @@ void PCB_EDIT_FRAME::SendMessageToEESCHEMA( BOARD_ITEM* aSyncItem )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PCB_EDIT_FRAME::SendCrossProbeNetName( const wxString& aNetName )
|
void PCB_EDIT_FRAME::SendCrossProbeItem( BOARD_ITEM* aSyncItem )
|
||||||
{
|
{
|
||||||
std::string packet = StrPrintf( "$NET: \"%s\"", TO_UTF8( aNetName ) );
|
std::string packet = FormatProbeItem( aSyncItem );
|
||||||
|
|
||||||
if( !packet.empty() )
|
if( !packet.empty() )
|
||||||
{
|
{
|
||||||
|
@ -503,7 +603,7 @@ void PCB_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
|
||||||
std::vector<BOARD_ITEM*> items =
|
std::vector<BOARD_ITEM*> items =
|
||||||
FindItemsFromSyncSelection( paramStr.substr( modeEnd + 1 ) );
|
FindItemsFromSyncSelection( paramStr.substr( modeEnd + 1 ) );
|
||||||
|
|
||||||
m_syncingSchToPcbSelection = true; // recursion guard
|
m_probingSchToPcb = true; // recursion guard
|
||||||
|
|
||||||
if( selectConnections )
|
if( selectConnections )
|
||||||
{
|
{
|
||||||
|
@ -516,7 +616,7 @@ void PCB_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
|
||||||
static_cast<void*>( &items ) );
|
static_cast<void*>( &items ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_syncingSchToPcbSelection = false;
|
m_probingSchToPcb = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -187,7 +187,7 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||||
m_SelLayerBox = nullptr;
|
m_SelLayerBox = nullptr;
|
||||||
m_show_layer_manager_tools = true;
|
m_show_layer_manager_tools = true;
|
||||||
m_supportsAutoSave = true;
|
m_supportsAutoSave = true;
|
||||||
m_syncingSchToPcbSelection = false;
|
m_probingSchToPcb = false;
|
||||||
|
|
||||||
// We don't know what state board was in when it was last saved, so we have to
|
// We don't know what state board was in when it was last saved, so we have to
|
||||||
// assume dirty
|
// assume dirty
|
||||||
|
@ -778,6 +778,8 @@ void PCB_EDIT_FRAME::setupUIConditions()
|
||||||
ENABLE( SELECTION_CONDITIONS::OnlyTypes( { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T } ) ) );
|
ENABLE( SELECTION_CONDITIONS::OnlyTypes( { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T } ) ) );
|
||||||
mgr->SetConditions( PCB_ACTIONS::selectSameSheet,
|
mgr->SetConditions( PCB_ACTIONS::selectSameSheet,
|
||||||
ENABLE( SELECTION_CONDITIONS::OnlyTypes( { PCB_FOOTPRINT_T } ) ) );
|
ENABLE( SELECTION_CONDITIONS::OnlyTypes( { PCB_FOOTPRINT_T } ) ) );
|
||||||
|
mgr->SetConditions( PCB_ACTIONS::selectOnSchematic,
|
||||||
|
ENABLE( SELECTION_CONDITIONS::HasTypes( { PCB_PAD_T, PCB_FOOTPRINT_T, PCB_GROUP_T } ) ) );
|
||||||
|
|
||||||
|
|
||||||
SELECTION_CONDITION singleZoneCond = SELECTION_CONDITIONS::Count( 1 )
|
SELECTION_CONDITION singleZoneCond = SELECTION_CONDITIONS::Count( 1 )
|
||||||
|
|
|
@ -637,12 +637,25 @@ public:
|
||||||
void OnNetlistChanged( BOARD_NETLIST_UPDATER& aUpdater, bool* aRunDragCommand );
|
void OnNetlistChanged( BOARD_NETLIST_UPDATER& aUpdater, bool* aRunDragCommand );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a message to the schematic editor so that it may move its cursor
|
* Send a message to the schematic editor to try to find schematic counterparts
|
||||||
* to a symbol with the same reference as the \a objectToSync.
|
* of specified PCB items and select them.
|
||||||
*
|
*
|
||||||
* @param objectToSync The object whose reference is used to synchronize Eeschema.
|
* @param aItems are the items to try to select on schematic.
|
||||||
|
* @param aFocusItem set to item to select and focus on even if selection can't be
|
||||||
|
* represented in Schematic editor fully.
|
||||||
|
* @param aForce select elements in Schematic editor whether or not the user has
|
||||||
|
* the select option chosen.
|
||||||
*/
|
*/
|
||||||
void SendMessageToEESCHEMA( BOARD_ITEM* objectToSync );
|
void SendSelectItemsToSch( const std::deque<EDA_ITEM*>& aItems, EDA_ITEM* aFocusItem,
|
||||||
|
bool aForce );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a message to the schematic editor so that it may move its cursor
|
||||||
|
* to an item with the same reference as the \a aSyncItem and highlight it.
|
||||||
|
*
|
||||||
|
* @param aSyncItem The object whose reference is used to highlight in Eeschema.
|
||||||
|
*/
|
||||||
|
void SendCrossProbeItem( BOARD_ITEM* aSyncItem );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a net name to Eeschema for highlighting.
|
* Send a net name to Eeschema for highlighting.
|
||||||
|
@ -795,7 +808,7 @@ public:
|
||||||
|
|
||||||
bool m_ZoneFillsDirty; // Board has been modified since last zone fill.
|
bool m_ZoneFillsDirty; // Board has been modified since last zone fill.
|
||||||
|
|
||||||
bool m_syncingSchToPcbSelection; // Recursion guard when synchronizing selection from schematic
|
bool m_probingSchToPcb; // Recursion guard when synchronizing selection from schematic
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend struct PCB::IFACE;
|
friend struct PCB::IFACE;
|
||||||
|
|
|
@ -1403,6 +1403,42 @@ int BOARD_EDITOR_CONTROL::ZoneDuplicate( const TOOL_EVENT& aEvent )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int BOARD_EDITOR_CONTROL::CrossProbeToSch( const TOOL_EVENT& aEvent )
|
||||||
|
{
|
||||||
|
doCrossProbePcbToSch( aEvent, false );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int BOARD_EDITOR_CONTROL::ExplicitCrossProbeToSch( const TOOL_EVENT& aEvent )
|
||||||
|
{
|
||||||
|
doCrossProbePcbToSch( aEvent, true );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BOARD_EDITOR_CONTROL::doCrossProbePcbToSch( const TOOL_EVENT& aEvent, bool aForce )
|
||||||
|
{
|
||||||
|
// Don't get in an infinite loop PCB -> SCH -> PCB -> SCH -> ...
|
||||||
|
if( m_frame->m_probingSchToPcb )
|
||||||
|
return;
|
||||||
|
|
||||||
|
PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
|
||||||
|
const PCB_SELECTION& selection = selTool->GetSelection();
|
||||||
|
EDA_ITEM* focusItem = nullptr;
|
||||||
|
|
||||||
|
if( aEvent.Matches( EVENTS::PointSelectedEvent ) )
|
||||||
|
focusItem = selection.GetLastAddedItem();
|
||||||
|
|
||||||
|
m_frame->SendSelectItemsToSch( selection.GetItems(), focusItem, aForce );
|
||||||
|
|
||||||
|
// Update 3D viewer highlighting
|
||||||
|
m_frame->Update3DView( false, frame()->GetPcbNewSettings()->m_Display.m_Live3DRefresh );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int BOARD_EDITOR_CONTROL::EditFpInFpEditor( const TOOL_EVENT& aEvent )
|
int BOARD_EDITOR_CONTROL::EditFpInFpEditor( const TOOL_EVENT& aEvent )
|
||||||
{
|
{
|
||||||
PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
|
PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
|
||||||
|
@ -1517,6 +1553,13 @@ void BOARD_EDITOR_CONTROL::setTransitions()
|
||||||
Go( &BOARD_EDITOR_CONTROL::EditFpInFpEditor, PCB_ACTIONS::editFpInFpEditor.MakeEvent() );
|
Go( &BOARD_EDITOR_CONTROL::EditFpInFpEditor, PCB_ACTIONS::editFpInFpEditor.MakeEvent() );
|
||||||
Go( &BOARD_EDITOR_CONTROL::EditFpInFpEditor, PCB_ACTIONS::editLibFpInFpEditor.MakeEvent() );
|
Go( &BOARD_EDITOR_CONTROL::EditFpInFpEditor, PCB_ACTIONS::editLibFpInFpEditor.MakeEvent() );
|
||||||
|
|
||||||
|
// Cross-select
|
||||||
|
Go( &BOARD_EDITOR_CONTROL::CrossProbeToSch, EVENTS::PointSelectedEvent );
|
||||||
|
Go( &BOARD_EDITOR_CONTROL::CrossProbeToSch, EVENTS::SelectedEvent );
|
||||||
|
Go( &BOARD_EDITOR_CONTROL::CrossProbeToSch, EVENTS::UnselectedEvent );
|
||||||
|
Go( &BOARD_EDITOR_CONTROL::CrossProbeToSch, EVENTS::ClearedEvent );
|
||||||
|
Go( &BOARD_EDITOR_CONTROL::ExplicitCrossProbeToSch, PCB_ACTIONS::selectOnSchematic.MakeEvent() );
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
Go( &BOARD_EDITOR_CONTROL::ToggleLockSelected, PCB_ACTIONS::toggleLock.MakeEvent() );
|
Go( &BOARD_EDITOR_CONTROL::ToggleLockSelected, PCB_ACTIONS::toggleLock.MakeEvent() );
|
||||||
Go( &BOARD_EDITOR_CONTROL::LockSelected, PCB_ACTIONS::lock.MakeEvent() );
|
Go( &BOARD_EDITOR_CONTROL::LockSelected, PCB_ACTIONS::lock.MakeEvent() );
|
||||||
|
|
|
@ -93,6 +93,12 @@ public:
|
||||||
|
|
||||||
int EditFpInFpEditor( const TOOL_EVENT& aEvent );
|
int EditFpInFpEditor( const TOOL_EVENT& aEvent );
|
||||||
|
|
||||||
|
///< Notify Eeschema about selected items.
|
||||||
|
int CrossProbeToSch( const TOOL_EVENT& aEvent );
|
||||||
|
|
||||||
|
///< Equivalent to the above, but initiated by the user.
|
||||||
|
int ExplicitCrossProbeToSch( const TOOL_EVENT& aEvent );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display a dialog to select a footprint to be added and allows the user to set its position.
|
* Display a dialog to select a footprint to be added and allows the user to set its position.
|
||||||
*/
|
*/
|
||||||
|
@ -128,6 +134,8 @@ private:
|
||||||
///< Set up handlers for various events.
|
///< Set up handlers for various events.
|
||||||
void setTransitions() override;
|
void setTransitions() override;
|
||||||
|
|
||||||
|
void doCrossProbePcbToSch( const TOOL_EVENT& aEvent, bool aForce );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PCB_EDIT_FRAME* m_frame;
|
PCB_EDIT_FRAME* m_frame;
|
||||||
bool m_inPlaceFootprint; // Re-entrancy guard for tool.
|
bool m_inPlaceFootprint; // Re-entrancy guard for tool.
|
||||||
|
|
|
@ -45,7 +45,6 @@ BOARD_INSPECTION_TOOL::BOARD_INSPECTION_TOOL() :
|
||||||
PCB_TOOL_BASE( "pcbnew.InspectionTool" ),
|
PCB_TOOL_BASE( "pcbnew.InspectionTool" ),
|
||||||
m_frame( nullptr )
|
m_frame( nullptr )
|
||||||
{
|
{
|
||||||
m_probingSchToPcb = false;
|
|
||||||
m_dynamicData = nullptr;
|
m_dynamicData = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1245,39 +1244,18 @@ int BOARD_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int BOARD_INSPECTION_TOOL::CrossProbePcbToSch( const TOOL_EVENT& aEvent )
|
|
||||||
{
|
|
||||||
// Don't get in an infinite loop PCB -> SCH -> PCB -> SCH -> ...
|
|
||||||
if( m_probingSchToPcb || m_frame->m_syncingSchToPcbSelection )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
|
|
||||||
const PCB_SELECTION& selection = selTool->GetSelection();
|
|
||||||
|
|
||||||
if( selection.Size() == 1 )
|
|
||||||
m_frame->SendMessageToEESCHEMA( static_cast<BOARD_ITEM*>( selection.Front() ) );
|
|
||||||
else
|
|
||||||
m_frame->SendMessageToEESCHEMA( nullptr );
|
|
||||||
|
|
||||||
// Update 3D viewer highlighting
|
|
||||||
m_frame->Update3DView( false, frame()->GetPcbNewSettings()->m_Display.m_Live3DRefresh );
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int BOARD_INSPECTION_TOOL::HighlightItem( const TOOL_EVENT& aEvent )
|
int BOARD_INSPECTION_TOOL::HighlightItem( const TOOL_EVENT& aEvent )
|
||||||
{
|
{
|
||||||
BOARD_ITEM* item = aEvent.Parameter<BOARD_ITEM*>();
|
BOARD_ITEM* item = aEvent.Parameter<BOARD_ITEM*>();
|
||||||
|
|
||||||
m_probingSchToPcb = true; // recursion guard
|
m_frame->m_probingSchToPcb = true; // recursion guard
|
||||||
{
|
{
|
||||||
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
||||||
|
|
||||||
if( item )
|
if( item )
|
||||||
m_toolMgr->RunAction( PCB_ACTIONS::selectItem, true, (void*) item );
|
m_toolMgr->RunAction( PCB_ACTIONS::selectItem, true, (void*) item );
|
||||||
}
|
}
|
||||||
m_probingSchToPcb = false;
|
m_frame->m_probingSchToPcb = false;
|
||||||
|
|
||||||
bool request3DviewRedraw = frame()->GetPcbNewSettings()->m_Display.m_Live3DRefresh;
|
bool request3DviewRedraw = frame()->GetPcbNewSettings()->m_Display.m_Live3DRefresh;
|
||||||
|
|
||||||
|
@ -1363,7 +1341,7 @@ int BOARD_INSPECTION_TOOL::HighlightItem( const TOOL_EVENT& aEvent )
|
||||||
filter.lockedItems = saved;
|
filter.lockedItems = saved;
|
||||||
|
|
||||||
// Clear the previous highlight
|
// Clear the previous highlight
|
||||||
m_frame->SendMessageToEESCHEMA( nullptr );
|
//m_frame->SendMessageToEESCHEMA( nullptr );
|
||||||
|
|
||||||
bool highContrast = settings->GetHighContrast();
|
bool highContrast = settings->GetHighContrast();
|
||||||
PCB_LAYER_ID contrastLayer = settings->GetPrimaryHighContrastLayer();
|
PCB_LAYER_ID contrastLayer = settings->GetPrimaryHighContrastLayer();
|
||||||
|
@ -1388,7 +1366,7 @@ int BOARD_INSPECTION_TOOL::HighlightItem( const TOOL_EVENT& aEvent )
|
||||||
BOARD_CONNECTED_ITEM* targetItem = static_cast<BOARD_CONNECTED_ITEM*>( collector[0] );
|
BOARD_CONNECTED_ITEM* targetItem = static_cast<BOARD_CONNECTED_ITEM*>( collector[0] );
|
||||||
|
|
||||||
if( targetItem->Type() == PCB_PAD_T )
|
if( targetItem->Type() == PCB_PAD_T )
|
||||||
m_frame->SendMessageToEESCHEMA( targetItem );
|
m_frame->SendCrossProbeItem( targetItem );
|
||||||
|
|
||||||
net = targetItem->GetNetCode();
|
net = targetItem->GetNetCode();
|
||||||
}
|
}
|
||||||
|
@ -1829,10 +1807,6 @@ void BOARD_INSPECTION_TOOL::doHideNet( int aNetCode, bool aHide )
|
||||||
|
|
||||||
void BOARD_INSPECTION_TOOL::setTransitions()
|
void BOARD_INSPECTION_TOOL::setTransitions()
|
||||||
{
|
{
|
||||||
Go( &BOARD_INSPECTION_TOOL::CrossProbePcbToSch, EVENTS::SelectedEvent );
|
|
||||||
Go( &BOARD_INSPECTION_TOOL::CrossProbePcbToSch, EVENTS::UnselectedEvent );
|
|
||||||
Go( &BOARD_INSPECTION_TOOL::CrossProbePcbToSch, EVENTS::ClearedEvent );
|
|
||||||
|
|
||||||
Go( &BOARD_INSPECTION_TOOL::LocalRatsnestTool,
|
Go( &BOARD_INSPECTION_TOOL::LocalRatsnestTool,
|
||||||
PCB_ACTIONS::localRatsnestTool.MakeEvent() );
|
PCB_ACTIONS::localRatsnestTool.MakeEvent() );
|
||||||
Go( &BOARD_INSPECTION_TOOL::HideDynamicRatsnest,
|
Go( &BOARD_INSPECTION_TOOL::HideDynamicRatsnest,
|
||||||
|
|
|
@ -57,9 +57,6 @@ public:
|
||||||
*/
|
*/
|
||||||
int ShowStatisticsDialog( const TOOL_EVENT& aEvent );
|
int ShowStatisticsDialog( const TOOL_EVENT& aEvent );
|
||||||
|
|
||||||
///< Notify Eeschema about the selected item.
|
|
||||||
int CrossProbePcbToSch( const TOOL_EVENT& aEvent );
|
|
||||||
|
|
||||||
///< Highlight net belonging to the item under the cursor.
|
///< Highlight net belonging to the item under the cursor.
|
||||||
int HighlightNet( const TOOL_EVENT& aEvent );
|
int HighlightNet( const TOOL_EVENT& aEvent );
|
||||||
|
|
||||||
|
@ -143,7 +140,6 @@ private:
|
||||||
private:
|
private:
|
||||||
PCB_EDIT_FRAME* m_frame; // Pointer to the currently used edit frame.
|
PCB_EDIT_FRAME* m_frame; // Pointer to the currently used edit frame.
|
||||||
|
|
||||||
bool m_probingSchToPcb; // Recursion guard when cross-probing to Eeschema
|
|
||||||
std::set<int> m_currentlyHighlighted; // Active net being highlighted, or -1 when off
|
std::set<int> m_currentlyHighlighted; // Active net being highlighted, or -1 when off
|
||||||
std::set<int> m_lastHighlighted; // For toggling between last two highlighted nets
|
std::set<int> m_lastHighlighted; // For toggling between last two highlighted nets
|
||||||
|
|
||||||
|
|
|
@ -300,6 +300,7 @@ void DRC_TOOL::setTransitions()
|
||||||
Go( &DRC_TOOL::PrevMarker, ACTIONS::prevMarker.MakeEvent() );
|
Go( &DRC_TOOL::PrevMarker, ACTIONS::prevMarker.MakeEvent() );
|
||||||
Go( &DRC_TOOL::NextMarker, ACTIONS::nextMarker.MakeEvent() );
|
Go( &DRC_TOOL::NextMarker, ACTIONS::nextMarker.MakeEvent() );
|
||||||
Go( &DRC_TOOL::ExcludeMarker, ACTIONS::excludeMarker.MakeEvent() );
|
Go( &DRC_TOOL::ExcludeMarker, ACTIONS::excludeMarker.MakeEvent() );
|
||||||
|
Go( &DRC_TOOL::CrossProbe, EVENTS::PointSelectedEvent );
|
||||||
Go( &DRC_TOOL::CrossProbe, EVENTS::SelectedEvent );
|
Go( &DRC_TOOL::CrossProbe, EVENTS::SelectedEvent );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1291,6 +1291,12 @@ TOOL_ACTION PCB_ACTIONS::selectSameSheet( "pcbnew.InteractiveSelection.SelectSam
|
||||||
_( "Selects all footprints and tracks in the same schematic sheet" ),
|
_( "Selects all footprints and tracks in the same schematic sheet" ),
|
||||||
BITMAPS::select_same_sheet );
|
BITMAPS::select_same_sheet );
|
||||||
|
|
||||||
|
TOOL_ACTION PCB_ACTIONS::selectOnSchematic( "pcbnew.InteractiveSelection.SelectOnSchematic",
|
||||||
|
AS_GLOBAL, 0, "",
|
||||||
|
_( "Select on Schematic" ),
|
||||||
|
_( "Selects corresponding items in Schematic editor" ),
|
||||||
|
BITMAPS::select_same_sheet );
|
||||||
|
|
||||||
TOOL_ACTION PCB_ACTIONS::filterSelection( "pcbnew.InteractiveSelection.FilterSelection",
|
TOOL_ACTION PCB_ACTIONS::filterSelection( "pcbnew.InteractiveSelection.FilterSelection",
|
||||||
AS_GLOBAL, 0, "",
|
AS_GLOBAL, 0, "",
|
||||||
_( "Filter Selected Items..." ), _( "Remove items from the selection by type" ),
|
_( "Filter Selected Items..." ), _( "Remove items from the selection by type" ),
|
||||||
|
|
|
@ -91,6 +91,9 @@ public:
|
||||||
/// Select all components on the same sheet as the selected footprint.
|
/// Select all components on the same sheet as the selected footprint.
|
||||||
static TOOL_ACTION selectSameSheet;
|
static TOOL_ACTION selectSameSheet;
|
||||||
|
|
||||||
|
/// Select symbols/pins on schematic corresponding to selected footprints/pads.
|
||||||
|
static TOOL_ACTION selectOnSchematic;
|
||||||
|
|
||||||
/// Filter the items in the current selection (invokes dialog)
|
/// Filter the items in the current selection (invokes dialog)
|
||||||
static TOOL_ACTION filterSelection;
|
static TOOL_ACTION filterSelection;
|
||||||
|
|
||||||
|
|
|
@ -1464,6 +1464,7 @@ void PCB_CONTROL::setTransitions()
|
||||||
Go( &PCB_CONTROL::Paste, ACTIONS::paste.MakeEvent() );
|
Go( &PCB_CONTROL::Paste, ACTIONS::paste.MakeEvent() );
|
||||||
Go( &PCB_CONTROL::Paste, ACTIONS::pasteSpecial.MakeEvent() );
|
Go( &PCB_CONTROL::Paste, ACTIONS::pasteSpecial.MakeEvent() );
|
||||||
|
|
||||||
|
Go( &PCB_CONTROL::UpdateMessagePanel, EVENTS::PointSelectedEvent );
|
||||||
Go( &PCB_CONTROL::UpdateMessagePanel, EVENTS::SelectedEvent );
|
Go( &PCB_CONTROL::UpdateMessagePanel, EVENTS::SelectedEvent );
|
||||||
Go( &PCB_CONTROL::UpdateMessagePanel, EVENTS::UnselectedEvent );
|
Go( &PCB_CONTROL::UpdateMessagePanel, EVENTS::UnselectedEvent );
|
||||||
Go( &PCB_CONTROL::UpdateMessagePanel, EVENTS::ClearedEvent );
|
Go( &PCB_CONTROL::UpdateMessagePanel, EVENTS::ClearedEvent );
|
||||||
|
|
|
@ -2425,6 +2425,7 @@ void PCB_POINT_EDITOR::setTransitions()
|
||||||
Go( &PCB_POINT_EDITOR::addCorner, PCB_ACTIONS::pointEditorAddCorner.MakeEvent() );
|
Go( &PCB_POINT_EDITOR::addCorner, PCB_ACTIONS::pointEditorAddCorner.MakeEvent() );
|
||||||
Go( &PCB_POINT_EDITOR::removeCorner, PCB_ACTIONS::pointEditorRemoveCorner.MakeEvent() );
|
Go( &PCB_POINT_EDITOR::removeCorner, PCB_ACTIONS::pointEditorRemoveCorner.MakeEvent() );
|
||||||
Go( &PCB_POINT_EDITOR::modifiedSelection, EVENTS::SelectedItemsModified );
|
Go( &PCB_POINT_EDITOR::modifiedSelection, EVENTS::SelectedItemsModified );
|
||||||
|
Go( &PCB_POINT_EDITOR::OnSelectionChange, EVENTS::PointSelectedEvent );
|
||||||
Go( &PCB_POINT_EDITOR::OnSelectionChange, EVENTS::SelectedEvent );
|
Go( &PCB_POINT_EDITOR::OnSelectionChange, EVENTS::SelectedEvent );
|
||||||
Go( &PCB_POINT_EDITOR::OnSelectionChange, EVENTS::UnselectedEvent );
|
Go( &PCB_POINT_EDITOR::OnSelectionChange, EVENTS::UnselectedEvent );
|
||||||
Go( &PCB_POINT_EDITOR::changeEditMethod, ACTIONS::changeEditMethod.MakeEvent() );
|
Go( &PCB_POINT_EDITOR::changeEditMethod, ACTIONS::changeEditMethod.MakeEvent() );
|
||||||
|
|
|
@ -86,6 +86,7 @@ public:
|
||||||
// This could be enabled if we have better logic for picking the target net with the mouse
|
// This could be enabled if we have better logic for picking the target net with the mouse
|
||||||
// Add( PCB_ACTIONS::deselectNet );
|
// Add( PCB_ACTIONS::deselectNet );
|
||||||
Add( PCB_ACTIONS::selectSameSheet );
|
Add( PCB_ACTIONS::selectSameSheet );
|
||||||
|
Add( PCB_ACTIONS::selectOnSchematic );
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -740,7 +741,7 @@ bool PCB_SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool anyAdded = false;
|
int addedCount = 0;
|
||||||
bool anySubtracted = false;
|
bool anySubtracted = false;
|
||||||
|
|
||||||
if( !m_additive && !m_subtractive && !m_exclusive_or )
|
if( !m_additive && !m_subtractive && !m_exclusive_or )
|
||||||
|
@ -764,12 +765,17 @@ bool PCB_SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
select( collector[i] );
|
select( collector[i] );
|
||||||
anyAdded = true;
|
addedCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( anyAdded )
|
if( addedCount == 1 )
|
||||||
|
{
|
||||||
|
m_toolMgr->ProcessEvent( EVENTS::PointSelectedEvent );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if( addedCount > 1 )
|
||||||
{
|
{
|
||||||
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
|
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
|
||||||
return true;
|
return true;
|
||||||
|
@ -1536,12 +1542,12 @@ void PCB_SELECTION_TOOL::doSyncSelection( const std::vector<BOARD_ITEM*>& aItems
|
||||||
|
|
||||||
EDA_RECT bbox = m_selection.GetBoundingBox();
|
EDA_RECT bbox = m_selection.GetBoundingBox();
|
||||||
|
|
||||||
if( bbox.GetWidth() > 0 && bbox.GetHeight() > 0 )
|
if( bbox.GetWidth() != 0 && bbox.GetHeight() != 0 )
|
||||||
{
|
{
|
||||||
if( m_frame->GetPcbNewSettings()->m_CrossProbing.center_on_items )
|
if( m_frame->GetPcbNewSettings()->m_CrossProbing.center_on_items )
|
||||||
{
|
{
|
||||||
if( m_frame->GetPcbNewSettings()->m_CrossProbing.zoom_to_fit )
|
if( m_frame->GetPcbNewSettings()->m_CrossProbing.zoom_to_fit )
|
||||||
zoomFitCrossProbeBBox( bbox );
|
ZoomFitCrossProbeBBox( bbox );
|
||||||
|
|
||||||
m_frame->FocusOnLocation( bbox.Centre() );
|
m_frame->FocusOnLocation( bbox.Centre() );
|
||||||
}
|
}
|
||||||
|
@ -1630,15 +1636,17 @@ void PCB_SELECTION_TOOL::zoomFitSelection()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PCB_SELECTION_TOOL::zoomFitCrossProbeBBox( EDA_RECT bbox )
|
void PCB_SELECTION_TOOL::ZoomFitCrossProbeBBox( EDA_RECT bbox )
|
||||||
{
|
{
|
||||||
// Should recalculate the view to zoom in on the bbox.
|
// Should recalculate the view to zoom in on the bbox.
|
||||||
auto view = getView();
|
auto view = getView();
|
||||||
|
|
||||||
if( bbox.GetWidth() == 0 && bbox.GetHeight() != 0 )
|
if( bbox.GetWidth() == 0 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//#define DEFAULT_PCBNEW_CODE // Un-comment for normal full zoom KiCad algorithm
|
bbox.Normalize();
|
||||||
|
|
||||||
|
//#define DEFAULT_PCBNEW_CODE // Un-comment for normal full zoom KiCad algorithm
|
||||||
#ifdef DEFAULT_PCBNEW_CODE
|
#ifdef DEFAULT_PCBNEW_CODE
|
||||||
auto bbSize = bbox.Inflate( bbox.GetWidth() * 0.2f ).GetSize();
|
auto bbSize = bbox.Inflate( bbox.GetWidth() * 0.2f ).GetSize();
|
||||||
auto screenSize = view->ToWorld( GetCanvas()->GetClientSize(), false );
|
auto screenSize = view->ToWorld( GetCanvas()->GetClientSize(), false );
|
||||||
|
@ -2939,7 +2947,7 @@ void PCB_SELECTION_TOOL::setTransitions()
|
||||||
Go( &PCB_SELECTION_TOOL::expandConnection, PCB_ACTIONS::selectConnection.MakeEvent() );
|
Go( &PCB_SELECTION_TOOL::expandConnection, PCB_ACTIONS::selectConnection.MakeEvent() );
|
||||||
Go( &PCB_SELECTION_TOOL::selectNet, PCB_ACTIONS::selectNet.MakeEvent() );
|
Go( &PCB_SELECTION_TOOL::selectNet, PCB_ACTIONS::selectNet.MakeEvent() );
|
||||||
Go( &PCB_SELECTION_TOOL::selectNet, PCB_ACTIONS::deselectNet.MakeEvent() );
|
Go( &PCB_SELECTION_TOOL::selectNet, PCB_ACTIONS::deselectNet.MakeEvent() );
|
||||||
Go( &PCB_SELECTION_TOOL::syncSelection, PCB_ACTIONS::syncSelection.MakeEvent() );
|
Go( &PCB_SELECTION_TOOL::syncSelection, PCB_ACTIONS::syncSelection.MakeEvent() );
|
||||||
Go( &PCB_SELECTION_TOOL::syncSelectionWithNets,
|
Go( &PCB_SELECTION_TOOL::syncSelectionWithNets,
|
||||||
PCB_ACTIONS::syncSelectionWithNets.MakeEvent() );
|
PCB_ACTIONS::syncSelectionWithNets.MakeEvent() );
|
||||||
Go( &PCB_SELECTION_TOOL::selectSameSheet, PCB_ACTIONS::selectSameSheet.MakeEvent() );
|
Go( &PCB_SELECTION_TOOL::selectSameSheet, PCB_ACTIONS::selectSameSheet.MakeEvent() );
|
||||||
|
|
|
@ -160,7 +160,7 @@ public:
|
||||||
void zoomFitSelection();
|
void zoomFitSelection();
|
||||||
|
|
||||||
///< Zoom the screen to fit the bounding box for cross probing/selection sync.
|
///< Zoom the screen to fit the bounding box for cross probing/selection sync.
|
||||||
void zoomFitCrossProbeBBox( EDA_RECT bbox );
|
void ZoomFitCrossProbeBBox( EDA_RECT bbox );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enter the group at the head of the current selection.
|
* Enter the group at the head of the current selection.
|
||||||
|
|
Loading…
Reference in New Issue