From 1e69f592f66d32b97cf4e34d32d5ab695d43495e Mon Sep 17 00:00:00 2001 From: Jon Evans Date: Sun, 24 May 2020 10:46:05 -0400 Subject: [PATCH] Rework net highlighting to use connections instead of strings Fixes https://gitlab.com/kicad/code/kicad/-/issues/1933 Fixes https://gitlab.com/kicad/code/kicad/-/issues/3921 --- eeschema/connection_graph.cpp | 28 +++++ eeschema/connection_graph.h | 12 ++ eeschema/cross-probing.cpp | 9 +- .../dialog_global_edit_text_and_graphics.cpp | 4 +- eeschema/sch_edit_frame.cpp | 1 + eeschema/sch_edit_frame.h | 13 +- eeschema/tools/sch_editor_control.cpp | 112 +++++++++++------- 7 files changed, 130 insertions(+), 49 deletions(-) diff --git a/eeschema/connection_graph.cpp b/eeschema/connection_graph.cpp index 78fb165ede..080fc802df 100644 --- a/eeschema/connection_graph.cpp +++ b/eeschema/connection_graph.cpp @@ -362,6 +362,7 @@ void CONNECTION_GRAPH::Reset() m_bus_name_to_code_map.clear(); m_net_code_to_subgraphs_map.clear(); m_net_name_to_subgraphs_map.clear(); + m_item_to_subgraph_map.clear(); m_local_label_cache.clear(); m_global_label_cache.clear(); m_last_net_code = 1; @@ -670,6 +671,7 @@ void CONNECTION_GRAPH::buildConnectionGraph() subgraph->AddItem( item ); connection->SetSubgraphCode( subgraph->m_code ); + m_item_to_subgraph_map[item] = subgraph; std::list members; @@ -703,6 +705,7 @@ void CONNECTION_GRAPH::buildConnectionGraph() if( connected_conn->SubgraphCode() == 0 ) { connected_conn->SetSubgraphCode( subgraph->m_code ); + m_item_to_subgraph_map[connected_item] = subgraph; subgraph->AddItem( connected_item ); std::copy_if( connected_item->ConnectedItems( sheet ).begin(), @@ -1990,6 +1993,31 @@ CONNECTION_SUBGRAPH* CONNECTION_GRAPH::FindSubgraphByName( } +CONNECTION_SUBGRAPH* CONNECTION_GRAPH::FindFirstSubgraphByName( const wxString& aNetName ) +{ + if( !m_net_name_to_subgraphs_map.count( aNetName ) ) + return nullptr; + + wxASSERT( !m_net_name_to_subgraphs_map.at( aNetName ).empty() ); + + return m_net_name_to_subgraphs_map.at( aNetName )[0]; +} + + +CONNECTION_SUBGRAPH* CONNECTION_GRAPH::GetSubgraphForItem( SCH_ITEM* aItem ) +{ + if( !m_item_to_subgraph_map.count( aItem ) ) + return nullptr; + + CONNECTION_SUBGRAPH* ret = m_item_to_subgraph_map.at( aItem ); + + while( ret->m_absorbed ) + ret = ret->m_absorbed_by; + + return ret; +} + + int CONNECTION_GRAPH::RunERC() { int error_count = 0; diff --git a/eeschema/connection_graph.h b/eeschema/connection_graph.h index 4025fc27b0..8ac0af601d 100644 --- a/eeschema/connection_graph.h +++ b/eeschema/connection_graph.h @@ -284,6 +284,16 @@ public: CONNECTION_SUBGRAPH* FindSubgraphByName( const wxString& aNetName, const SCH_SHEET_PATH& aPath ); + /** + * Retrieves a subgraph for the given net name, if one exists. + * Searches every sheet + * @param aNetName is the full net name to search for + * @return the subgraph matching the query, or nullptr if none is found + */ + CONNECTION_SUBGRAPH* FindFirstSubgraphByName( const wxString& aNetName ); + + CONNECTION_SUBGRAPH* GetSubgraphForItem( SCH_ITEM* aItem ); + // TODO(JE) Remove this when pressure valve is removed static bool m_allowRealTime; @@ -317,6 +327,8 @@ private: std::unordered_map> m_net_name_to_subgraphs_map; + std::map m_item_to_subgraph_map; + NET_MAP m_net_code_to_subgraphs_map; int m_last_net_code; diff --git a/eeschema/cross-probing.cpp b/eeschema/cross-probing.cpp index fd94b27a05..5954f77032 100644 --- a/eeschema/cross-probing.cpp +++ b/eeschema/cross-probing.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -187,10 +188,14 @@ void SCH_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline ) if( strcmp( idcmd, "$NET:" ) == 0 ) { - m_SelectedNetName = FROM_UTF8( text ); + wxString netName = FROM_UTF8( text ); + + if( auto sg = Schematic().ConnectionGraph()->FindFirstSubgraphByName( netName ) ) + m_highlightedConn = sg->m_driver_connection; + GetToolManager()->RunAction( EE_ACTIONS::updateNetHighlighting, true ); - SetStatusText( _( "Selected net: " ) + UnescapeString( m_SelectedNetName ) ); + SetStatusText( _( "Selected net: " ) + UnescapeString( netName ) ); return; } diff --git a/eeschema/dialogs/dialog_global_edit_text_and_graphics.cpp b/eeschema/dialogs/dialog_global_edit_text_and_graphics.cpp index 1ca90ac4fc..ced737ae97 100644 --- a/eeschema/dialogs/dialog_global_edit_text_and_graphics.cpp +++ b/eeschema/dialogs/dialog_global_edit_text_and_graphics.cpp @@ -173,9 +173,9 @@ bool DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::TransferDataToWindow() m_netFilter->SetValue( g_netFilter ); m_netFilterOpt->SetValue( true ); } - else if( !m_parent->GetSelectedNetName().IsEmpty() ) + else if( m_parent->GetHighlightedConnection() ) { - m_netFilter->SetValue( m_parent->GetSelectedNetName() ); + m_netFilter->SetValue( m_parent->GetHighlightedConnection()->Name() ); } else if( selection.GetSize() ) { diff --git a/eeschema/sch_edit_frame.cpp b/eeschema/sch_edit_frame.cpp index 15e2f3f82e..93379990f8 100644 --- a/eeschema/sch_edit_frame.cpp +++ b/eeschema/sch_edit_frame.cpp @@ -206,6 +206,7 @@ END_EVENT_TABLE() SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ): SCH_BASE_FRAME( aKiway, aParent, FRAME_SCH, wxT( "Eeschema" ), wxDefaultPosition, wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE, SCH_EDIT_FRAME_NAME ), + m_highlightedConn( nullptr ), m_item_to_repeat( nullptr ) { m_schematic = new SCHEMATIC( &Prj() ); diff --git a/eeschema/sch_edit_frame.h b/eeschema/sch_edit_frame.h index 6bb58803fc..180e75ae6c 100644 --- a/eeschema/sch_edit_frame.h +++ b/eeschema/sch_edit_frame.h @@ -123,7 +123,7 @@ class SCH_EDIT_FRAME : public SCH_BASE_FRAME private: SCHEMATIC* m_schematic; ///< The currently loaded schematic - wxString m_SelectedNetName; + const SCH_CONNECTION* m_highlightedConn; ///< The highlighted net or bus, or nullptr std::vector m_projectFileParams; std::vector m_configSettings; @@ -382,8 +382,15 @@ public: */ void SendCrossProbeClearHighlight(); - const wxString& GetSelectedNetName() const { return m_SelectedNetName; } - void SetSelectedNetName( const wxString& aNetName ) { m_SelectedNetName = aNetName; } + const SCH_CONNECTION* GetHighlightedConnection() const + { + return m_highlightedConn; + } + + void SetHighlightedConnection( const SCH_CONNECTION* aConnection ) + { + m_highlightedConn = aConnection; + } /** * Create a flat list which stores all connected objects. diff --git a/eeschema/tools/sch_editor_control.cpp b/eeschema/tools/sch_editor_control.cpp index 80718a8c8e..d088e9426a 100644 --- a/eeschema/tools/sch_editor_control.cpp +++ b/eeschema/tools/sch_editor_control.cpp @@ -685,14 +685,13 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent ) EDA_ITEM* item = collector.GetCount() == 1 ? collector[ 0 ] : nullptr; SCH_LINE* wire = dynamic_cast( item ); - wxString netName; + + const SCH_CONNECTION* conn = nullptr; if( wire ) { item = nullptr; - - if( wire->Connection( m_frame->GetCurrentSheet() ) ) - netName = wire->Connection( m_frame->GetCurrentSheet() )->Name(); + conn = wire->Connection( m_frame->GetCurrentSheet() ); } if( item && item->Type() == SCH_PIN_T ) @@ -712,9 +711,9 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent ) selectionTool->BrightenItem( m_pickerItem ); } - if( m_frame->GetSelectedNetName() != netName ) + if( m_frame->GetHighlightedConnection() != conn ) { - m_frame->SetSelectedNetName( netName ); + m_frame->SetHighlightedConnection( conn ); TOOL_EVENT dummyEvent; UpdateNetHighlighting( dummyEvent ); @@ -727,9 +726,9 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent ) if( m_pickerItem ) m_toolMgr->GetTool()->UnbrightenItem( m_pickerItem ); - if( !m_frame->GetSelectedNetName().IsEmpty() ) + if( m_frame->GetHighlightedConnection() ) { - m_frame->SetSelectedNetName( wxEmptyString ); + m_frame->SetHighlightedConnection( nullptr ); TOOL_EVENT dummyEvent; UpdateNetHighlighting( dummyEvent ); @@ -821,14 +820,13 @@ int SCH_EDITOR_CONTROL::SimTune( const TOOL_EVENT& aEvent ) static VECTOR2D CLEAR; -// TODO(JE) Probably use netcode rather than connection name here eventually static bool highlightNet( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition ) { - SCH_EDIT_FRAME* editFrame = static_cast( aToolMgr->GetToolHolder() ); - EE_SELECTION_TOOL* selTool = aToolMgr->GetTool(); + SCH_EDIT_FRAME* editFrame = static_cast( aToolMgr->GetToolHolder() ); + EE_SELECTION_TOOL* selTool = aToolMgr->GetTool(); SCH_EDITOR_CONTROL* editorControl = aToolMgr->GetTool(); - wxString netName; - bool retVal = true; + SCH_CONNECTION* conn = nullptr; + bool retVal = true; if( aPosition != CLEAR ) { @@ -846,30 +844,28 @@ static bool highlightNet( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition ) { if( item->Type() == SCH_FIELD_T ) comp = dynamic_cast( item->GetParent() ); - else - comp = dynamic_cast( item ); - } - if( comp && comp->GetPartRef() && comp->GetPartRef()->IsPower() ) - netName = comp->GetPartRef()->GetName(); - else if( item && item->Connection( editFrame->GetCurrentSheet() ) ) - netName = item->Connection( editFrame->GetCurrentSheet() )->Name(); + if( comp && comp->GetPartRef() && comp->GetPartRef()->IsPower() ) + conn = comp->Connection( editFrame->GetCurrentSheet() ); + else + conn = item->Connection( editFrame->GetCurrentSheet() ); + } } } - if( netName.empty() ) + if( !conn ) { editFrame->SetStatusText( wxT( "" ) ); editFrame->SendCrossProbeClearHighlight(); } else { - editFrame->SendCrossProbeNetName( netName ); + editFrame->SendCrossProbeNetName( conn->Name() ); editFrame->SetStatusText( wxString::Format( _( "Highlighted net: %s" ), - UnescapeString( netName ) ) ); + UnescapeString( conn->Name() ) ) ); } - editFrame->SetSelectedNetName( netName ); + editFrame->SetHighlightedConnection( conn ); TOOL_EVENT dummy; editorControl->UpdateNetHighlighting( dummy ); @@ -900,33 +896,67 @@ int SCH_EDITOR_CONTROL::UpdateNetHighlighting( const TOOL_EVENT& aEvent ) { SCH_SCREEN* screen = m_frame->GetCurrentSheet().LastScreen(); std::vector itemsToRedraw; - wxString selectedNetName = m_frame->GetSelectedNetName(); + const SCH_CONNECTION* selectedConn = m_frame->GetHighlightedConnection(); if( !screen ) return 0; + bool selectedIsBus = selectedConn ? selectedConn->IsBus() : false; + wxString selectedName = selectedConn ? selectedConn->Name() : ""; + + bool selectedIsNoNet = false; + CONNECTION_SUBGRAPH* selectedSubgraph = nullptr; + + if( selectedConn && selectedConn->Driver() == nullptr ) + { + selectedIsNoNet = true; + selectedSubgraph = m_frame->Schematic().ConnectionGraph()->GetSubgraphForItem( + selectedConn->Parent() ); + } + for( SCH_ITEM* item : screen->Items() ) { - wxString itemConnectionName; - SCH_COMPONENT* comp = nullptr; - bool redraw = item->IsBrightened(); + SCH_CONNECTION* itemConn = nullptr; + SCH_COMPONENT* comp = nullptr; + bool redraw = item->IsBrightened(); + bool highlight = false; if( item->Type() == SCH_COMPONENT_T ) comp = static_cast( item ); if( comp && comp->GetPartRef() && comp->GetPartRef()->IsPower() ) - { - itemConnectionName = comp->GetPartRef()->GetName(); - } + itemConn = comp->Connection( m_frame->GetCurrentSheet() ); else - { - SCH_CONNECTION* connection = item->Connection( m_frame->GetCurrentSheet() ); + itemConn = item->Connection( m_frame->GetCurrentSheet() ); - if( connection ) - itemConnectionName = connection->Name(); + if( selectedIsNoNet && selectedSubgraph ) + { + for( SCH_ITEM* subgraphItem : selectedSubgraph->m_items ) + { + if( item == subgraphItem ) + { + highlight = true; + break; + } + } + } + else if( selectedIsBus && itemConn && itemConn->IsNet() ) + { + for( auto& member : selectedConn->Members() ) + { + if( member->Name() == itemConn->Name() ) + { + highlight = true; + break; + } + } + } + else if( selectedConn && itemConn && selectedName == itemConn->Name() ) + { + highlight = true; } - if( !selectedNetName.IsEmpty() && itemConnectionName == selectedNetName ) + if( highlight ) item->SetBrightened(); else item->ClearBrightened(); @@ -946,7 +976,7 @@ int SCH_EDITOR_CONTROL::UpdateNetHighlighting( const TOOL_EVENT& aEvent ) SCH_CONNECTION* pin_conn = comp->GetConnectionForPin( pin, m_frame->GetCurrentSheet() ); - if( comp && pin_conn && pin_conn->Name( false ) == selectedNetName ) + if( comp && pin_conn && pin_conn->Name() == selectedName ) { comp->BrightenPin( pin ); redraw = true; @@ -973,15 +1003,13 @@ int SCH_EDITOR_CONTROL::UpdateNetHighlighting( const TOOL_EVENT& aEvent ) SCH_CONNECTION* pin_conn = pin->Connection( m_frame->GetCurrentSheet() ); bool redrawPin = pin->IsBrightened(); - if( pin_conn && pin_conn->Name() == selectedNetName ) + if( pin_conn && pin_conn->Name() == selectedName ) pin->SetBrightened(); else pin->ClearBrightened(); - redrawPin |= pin->IsBrightened(); - - if( redrawPin ) - itemsToRedraw.push_back( pin ); + redrawPin ^= pin->IsBrightened(); + redraw |= redrawPin; } }