Change the bus selection behavior of the schematic net highlight tool.

[CHANGED] Bus highlight tool now supports toggling between highlighting
          only the bus objects and highlighting the bus and all of the
          bus member objects.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/15388

(cherry picked from commit f6c99816b2)
This commit is contained in:
Wayne Stambaugh 2023-11-17 07:15:43 -05:00
parent 31e79ef54f
commit 402c139957
2 changed files with 141 additions and 91 deletions

View File

@ -806,18 +806,20 @@ static bool highlightNet( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition )
} }
} }
wxString connectionName = ( conn ) ? conn->Name() : wxS( "" ); wxString connectionName = ( conn ) ? conn->Name() : wxString( wxS( "" ) );
if( !conn || connectionName == editFrame->GetHighlightedConnection() ) if( !conn || connectionName == editFrame->GetHighlightedConnection() )
{ {
editFrame->SetStatusText( wxT( "" ) ); editFrame->SetStatusText( wxT( "" ) );
editFrame->SendCrossProbeClearHighlight(); editFrame->SendCrossProbeClearHighlight();
editFrame->SetHighlightedConnection( wxEmptyString ); editFrame->SetHighlightedConnection( wxEmptyString );
editorControl->SetHighlightBusMembers( false );
} }
else else
{ {
editFrame->SetCrossProbeConnection( conn ); editFrame->SetCrossProbeConnection( conn );
editFrame->SetHighlightedConnection( connectionName ); editFrame->SetHighlightedConnection( connectionName );
editorControl->SetHighlightBusMembers( false );
} }
editFrame->UpdateNetHighlightStatus(); editFrame->UpdateNetHighlightStatus();
@ -1014,155 +1016,193 @@ int SCH_EDITOR_CONTROL::AssignNetclass( const TOOL_EVENT& aEvent )
int SCH_EDITOR_CONTROL::UpdateNetHighlighting( const TOOL_EVENT& aEvent ) int SCH_EDITOR_CONTROL::UpdateNetHighlighting( const TOOL_EVENT& aEvent )
{ {
wxCHECK( m_frame, 0 );
const SCH_SHEET_PATH& sheetPath = m_frame->GetCurrentSheet();
SCH_SCREEN* screen = m_frame->GetCurrentSheet().LastScreen(); SCH_SCREEN* screen = m_frame->GetCurrentSheet().LastScreen();
CONNECTION_GRAPH* connectionGraph = m_frame->Schematic().ConnectionGraph(); CONNECTION_GRAPH* connectionGraph = m_frame->Schematic().ConnectionGraph();
wxString selectedName = m_frame->GetHighlightedConnection();
std::set<wxString> connNames;
std::vector<EDA_ITEM*> itemsToRedraw; std::vector<EDA_ITEM*> itemsToRedraw;
wxCHECK( screen && connectionGraph, 0 ); wxCHECK( screen && connectionGraph, 0 );
bool selectedIsBus = false; if( !selectedName.IsEmpty() )
wxString selectedName = m_frame->GetHighlightedConnection();
bool selectedIsNoNet = false;
CONNECTION_SUBGRAPH* selectedSubgraph = nullptr;
for( SCH_ITEM* item : screen->Items() )
{ {
bool redraw = item->IsBrightened(); connNames.emplace( selectedName );
bool highlight = false;
if( !selectedName.IsEmpty() ) if( m_highlightBusMembers )
{ {
SCH_CONNECTION* itemConn = nullptr; CONNECTION_SUBGRAPH* sg = connectionGraph->FindSubgraphByName( selectedName,
SCH_SYMBOL* symbol = nullptr; sheetPath );
if( item->Type() == SCH_SYMBOL_T ) wxCHECK( sg, 0 );
symbol = static_cast<SCH_SYMBOL*>( item );
if( symbol && symbol->GetLibSymbolRef() && symbol->GetLibSymbolRef()->IsPower() ) for( const SCH_ITEM* item : sg->GetItems() )
itemConn = symbol->Connection();
else
itemConn = item->Connection();
if( itemConn && ( selectedName == itemConn->Name() ) )
{ {
selectedIsBus = itemConn->IsBus(); wxCHECK2( item, continue );
if( itemConn->Driver() == nullptr ) SCH_CONNECTION* connection = item->Connection();
{
selectedIsNoNet = true;
selectedSubgraph = connectionGraph->GetSubgraphForItem( itemConn->Parent() );
}
if( selectedIsNoNet && selectedSubgraph ) wxCHECK2( connection, continue );
for( const std::shared_ptr<SCH_CONNECTION>& member : connection->AllMembers() )
{ {
for( SCH_ITEM* subgraphItem : selectedSubgraph->GetItems() ) if( member )
{ connNames.emplace( member->Name() );
if( item == subgraphItem )
{
highlight = true;
break;
}
}
}
else if( selectedIsBus && itemConn && itemConn->IsNet() )
{
for( const std::shared_ptr<SCH_CONNECTION>& member : itemConn->Members() )
{
if( member->Name() == itemConn->Name() )
{
highlight = true;
break;
}
else if( member->IsBus() )
{
for( const std::shared_ptr<SCH_CONNECTION>& bus_member :
member->Members() )
{
if( bus_member->Name() == itemConn->Name() )
{
highlight = true;
break;
}
}
}
}
}
else if( !selectedName.IsEmpty() && itemConn
&& ( selectedName == itemConn->Name() ) )
{
highlight = true;
} }
} }
} }
}
if( highlight ) for( SCH_ITEM* item : screen->Items() )
item->SetBrightened(); {
else wxCHECK2( item, continue );
item->ClearBrightened();
redraw |= item->IsBrightened(); if( !item->IsConnectable() )
continue;
SCH_ITEM* redrawItem = nullptr;
if( item->Type() == SCH_SYMBOL_T ) if( item->Type() == SCH_SYMBOL_T )
{ {
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item ); SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
redraw |= symbol->HasBrightenedPins(); wxCHECK2( symbol, continue );
symbol->ClearBrightenedPins();
for( SCH_PIN* pin : symbol->GetPins() ) for( SCH_PIN* pin : symbol->GetPins() )
{ {
SCH_CONNECTION* pin_conn = pin->Connection(); SCH_CONNECTION* pin_conn = pin->Connection();
if( pin_conn && pin_conn->Name() == selectedName ) wxCHECK2( pin_conn, continue );
if( !pin->IsBrightened() && connNames.count( pin_conn->Name() ) )
{ {
pin->SetBrightened(); pin->SetBrightened();
redraw = true; redrawItem = symbol;
}
else if( pin->IsBrightened() && !connNames.count( pin_conn->Name() ) )
{
pin->ClearBrightened();
redrawItem = symbol;
} }
} }
if( symbol->GetLibSymbolRef() && symbol->GetLibSymbolRef()->IsPower() ) if( symbol->IsPower() )
{ {
wxCHECK2( symbol->GetPins().size(), continue );
SCH_CONNECTION* pinConn = symbol->GetPins()[0]->Connection();
wxCHECK2( pinConn, continue );
std::vector<SCH_FIELD>& fields = symbol->GetFields(); std::vector<SCH_FIELD>& fields = symbol->GetFields();
for( int id : { REFERENCE_FIELD, VALUE_FIELD } ) for( int id : { REFERENCE_FIELD, VALUE_FIELD } )
{ {
if( item->IsBrightened() && fields[id].IsVisible() ) if( !fields[id].IsVisible() )
continue;
if( !item->IsBrightened() && connNames.count( pinConn->Name() ) )
{
fields[id].SetBrightened(); fields[id].SetBrightened();
else redrawItem = symbol;
}
else if( item->IsBrightened() && !connNames.count( pinConn->Name() ) )
{
fields[id].ClearBrightened(); fields[id].ClearBrightened();
redrawItem = symbol;
}
} }
} }
} }
else if( item->Type() == SCH_SHEET_T ) else if( item->Type() == SCH_SHEET_T )
{ {
for( SCH_SHEET_PIN* pin : static_cast<SCH_SHEET*>( item )->GetPins() ) SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
wxCHECK2( sheet, continue );
for( SCH_SHEET_PIN* pin : sheet->GetPins() )
{ {
wxCHECK2( pin, continue );
SCH_CONNECTION* pin_conn = pin->Connection(); SCH_CONNECTION* pin_conn = pin->Connection();
bool redrawPin = pin->IsBrightened();
if( pin_conn && pin_conn->Name() == selectedName ) wxCHECK2( pin_conn, continue );
if( !pin->IsBrightened() && connNames.count( pin_conn->Name() ) )
{
pin->SetBrightened(); pin->SetBrightened();
else redrawItem = sheet;
}
else if( pin->IsBrightened() && !connNames.count( pin_conn->Name() ) )
{
pin->ClearBrightened(); pin->ClearBrightened();
redrawItem = sheet;
}
}
}
else
{
SCH_CONNECTION* itemConn = item->Connection();
redrawPin ^= pin->IsBrightened(); wxCHECK2( itemConn, continue );
redraw |= redrawPin;
bool selectedIsNoNet = false;
CONNECTION_SUBGRAPH* selectedSubgraph = nullptr;
if( itemConn->Driver() == nullptr )
{
selectedIsNoNet = true;
selectedSubgraph = connectionGraph->GetSubgraphForItem( itemConn->Parent() );
}
if( selectedIsNoNet && selectedSubgraph )
{
for( SCH_ITEM* subgraphItem : selectedSubgraph->GetItems() )
{
if( !item->IsBrightened() && ( item == subgraphItem ) )
{
item->SetBrightened();
redrawItem = item;
}
else if( item->IsBrightened() && ( item != subgraphItem ) )
{
item->ClearBrightened();
redrawItem = item;
}
}
}
else
{
if( !item->IsBrightened() && connNames.count( itemConn->Name() ) )
{
item->SetBrightened();
redrawItem = item;
}
else if( item->IsBrightened() && !connNames.count( itemConn->Name() ) )
{
item->ClearBrightened();
redrawItem = item;
}
} }
} }
if( redraw ) if( redrawItem )
itemsToRedraw.push_back( item ); itemsToRedraw.push_back( redrawItem );
} }
// Be sure highlight change will be redrawn if( itemsToRedraw.size() )
KIGFX::VIEW* view = getView(); {
// Be sure highlight change will be redrawn
KIGFX::VIEW* view = getView();
for( EDA_ITEM* redrawItem : itemsToRedraw ) for( EDA_ITEM* redrawItem : itemsToRedraw )
view->Update( (KIGFX::VIEW_ITEM*)redrawItem, KIGFX::VIEW_UPDATE_FLAGS::REPAINT ); view->Update( (KIGFX::VIEW_ITEM*)redrawItem, KIGFX::VIEW_UPDATE_FLAGS::REPAINT );
m_frame->GetCanvas()->Refresh(); m_frame->GetCanvas()->Refresh();
}
return 0; return 0;
} }

View File

@ -42,7 +42,8 @@ public:
EE_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.EditorControl" ), EE_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.EditorControl" ),
m_probingPcbToSch( false ), m_probingPcbToSch( false ),
m_pickerItem( nullptr ), m_pickerItem( nullptr ),
m_duplicateIsHoverSelection( false ) m_duplicateIsHoverSelection( false ),
m_highlightBusMembers( false )
{ } { }
~SCH_EDITOR_CONTROL() { } ~SCH_EDITOR_CONTROL() { }
@ -157,6 +158,13 @@ public:
bool aSearchHierarchy, SCH_SEARCH_T aSearchType, bool aSearchHierarchy, SCH_SEARCH_T aSearchType,
const wxString& aSearchText ); const wxString& aSearchText );
void SetHighlightBusMembers( bool aHighlightBusMembers )
{
m_highlightBusMembers = aHighlightBusMembers;
}
bool GetHighlightBusMembers() const { return m_highlightBusMembers; }
private: private:
///< copy selection to clipboard or to m_duplicateClipboard ///< copy selection to clipboard or to m_duplicateClipboard
bool doCopy( bool aUseDuplicateClipboard = false ); bool doCopy( bool aUseDuplicateClipboard = false );
@ -211,6 +219,8 @@ private:
std::string m_duplicateClipboard; // Temporary storage for Duplicate action std::string m_duplicateClipboard; // Temporary storage for Duplicate action
bool m_duplicateIsHoverSelection; bool m_duplicateIsHoverSelection;
bool m_highlightBusMembers;
// A map of sheet filename --> screens for the clipboard contents. We use these to hook up // A map of sheet filename --> screens for the clipboard contents. We use these to hook up
// cut/paste operations for unsaved sheet content. // cut/paste operations for unsaved sheet content.
std::map<wxString, SCH_SCREEN*> m_supplementaryClipboard; std::map<wxString, SCH_SCREEN*> m_supplementaryClipboard;