diff --git a/eeschema/net_navigator.cpp b/eeschema/net_navigator.cpp index 6db444e686..8f879d0d51 100644 --- a/eeschema/net_navigator.cpp +++ b/eeschema/net_navigator.cpp @@ -24,49 +24,123 @@ #include #include #include +#include +#include +#include #include #include #include #include -class NET_NAVIGATOR_ITEM_DATA : public wxTreeItemData +static wxString GetNetNavigatorItemText( const SCH_ITEM* aItem, + const SCH_SHEET_PATH& aSheetPath, + UNITS_PROVIDER* aUnitsProvider ) { -public: - NET_NAVIGATOR_ITEM_DATA( const SCH_SHEET_PATH& aSheetPath, const SCH_ITEM* aItem ) : - m_sheetPath( aSheetPath ), - m_item( aItem ) + wxString retv; + + wxCHECK( aItem && aUnitsProvider, retv ); + + switch( aItem->Type() ) { + case SCH_LINE_T: + { + const SCH_LINE* line = static_cast( aItem ); + + wxCHECK( line, retv ); + + if( aItem->GetLayer() == LAYER_WIRE ) + { + retv.Printf( _( "Wire from %s, %s to %s, %s" ), + aUnitsProvider->MessageTextFromValue( line->GetStartPoint().x ), + aUnitsProvider->MessageTextFromValue( line->GetStartPoint().y ), + aUnitsProvider->MessageTextFromValue( line->GetEndPoint().x ), + aUnitsProvider->MessageTextFromValue( line->GetEndPoint().y ) ); + } + else if( aItem->GetLayer() == LAYER_BUS ) + { + retv.Printf( _( "Bus from %s, %s to %s, %s" ), + aUnitsProvider->MessageTextFromValue( line->GetStartPoint().x ), + aUnitsProvider->MessageTextFromValue( line->GetStartPoint().y ), + aUnitsProvider->MessageTextFromValue( line->GetEndPoint().x ), + aUnitsProvider->MessageTextFromValue( line->GetEndPoint().y ) ); + } + else + { + retv = _( "Graphic line not connectable" ); + } + + break; + } + case SCH_PIN_T: + { + const SCH_PIN* pin = static_cast( aItem ); + wxCHECK( pin, retv ); + + SCH_SYMBOL* symbol = pin->GetParentSymbol(); + wxCHECK( symbol, retv ); + + retv.Printf( _( "Symbol %s pin %s" ), symbol->GetRef( &aSheetPath, true ), + pin->GetNumber() ); + break; + } + case SCH_SHEET_PIN_T: + { + const SCH_SHEET_PIN* pin = static_cast( aItem ); + wxCHECK( pin, retv ); + + SCH_SHEET* sheet = pin->GetParent(); + wxCHECK( sheet, retv ); + + retv.Printf( _( "Sheet %s pin %s" ), sheet->GetName(), pin->GetText() ); + break; + } + case SCH_LABEL_T: + { + const SCH_LABEL* label = static_cast( aItem ); + wxCHECK( label, retv ); + + retv.Printf( _( "Label %s at %s, %s" ), label->GetText(), + aUnitsProvider->MessageTextFromValue( label->GetPosition().x ), + aUnitsProvider->MessageTextFromValue( label->GetPosition().y ) ); + break; + } + case SCH_GLOBAL_LABEL_T: + { + const SCH_GLOBALLABEL* label = static_cast( aItem ); + wxCHECK( label, retv ); + + retv.Printf( _( "Global label %s at %s, %s" ), label->GetText(), + aUnitsProvider->MessageTextFromValue( label->GetPosition().x ), + aUnitsProvider->MessageTextFromValue( label->GetPosition().y ) ); + break; + } + case SCH_HIER_LABEL_T: + { + const SCH_HIERLABEL* label = static_cast( aItem ); + wxCHECK( label, retv ); + + retv.Printf( _( "Hierarchical label %s at %s, %s" ), label->GetText(), + aUnitsProvider->MessageTextFromValue( label->GetPosition().x ), + aUnitsProvider->MessageTextFromValue( label->GetPosition().y ) ); + break; + } + case SCH_JUNCTION_T: + { + const SCH_JUNCTION* junction = static_cast( aItem ); + wxCHECK( junction, retv ); + + retv.Printf( _( "Junction at %s, %s" ), + aUnitsProvider->MessageTextFromValue( junction->GetPosition().x ), + aUnitsProvider->MessageTextFromValue( junction->GetPosition().y ) ); + break; + } + default: + retv.Printf( _( "Unhandled item type %d" ), aItem->Type() ); } - NET_NAVIGATOR_ITEM_DATA() : - m_item( nullptr ) - { - } - - SCH_SHEET_PATH& GetSheetPath() { return m_sheetPath; } - const SCH_ITEM* GetItem() const { return m_item; } - - bool operator==( const NET_NAVIGATOR_ITEM_DATA& aRhs ) const - { - return ( m_sheetPath == aRhs.m_sheetPath ) && ( m_item == aRhs.m_item ); - } - - NET_NAVIGATOR_ITEM_DATA& operator=( const NET_NAVIGATOR_ITEM_DATA& aItemData ) - { - if( this == &aItemData ) - return *this; - - m_sheetPath = aItemData.m_sheetPath; - m_item = aItemData.m_item; - - return *this; - } - -private: - SCH_SHEET_PATH m_sheetPath; - const SCH_ITEM* m_item; -}; + return retv; +} void SCH_EDIT_FRAME::MakeNetNavigatorNode( const wxString& aNetName, wxTreeItemId aParentId, @@ -107,26 +181,31 @@ void SCH_EDIT_FRAME::MakeNetNavigatorNode( const wxString& aNetName, wxTreeItemI for( const SCH_ITEM* item : subGraph->GetItems() ) { + SCH_ITEM_SET& connectedItems = const_cast( item )->ConnectedItems( sheetPath ); + wxLogDebug( wxS( "Item \"%s\" has %zu connected items." ), + item->GetItemDescription( this ), connectedItems.size() ); + itemData = new NET_NAVIGATOR_ITEM_DATA( sheetPath, item ); - wxTreeItemId id = m_netNavigator->AppendItem( sheetId, item->GetItemDescription( this ), + wxTreeItemId id = m_netNavigator->AppendItem( sheetId, + GetNetNavigatorItemText( item, sheetPath, + this ), -1, -1, itemData ); if( aSelection && *aSelection == *itemData ) { expandId = sheetId; + m_netNavigator->EnsureVisible( id ); m_netNavigator->SelectItem( id ); } } } - if( expandId != m_netNavigator->GetRootItem() ) + if( !aSelection ) m_netNavigator->Expand( aParentId ); - - m_netNavigator->Expand( expandId ); } -void SCH_EDIT_FRAME::RefreshNetNavigator() +void SCH_EDIT_FRAME::RefreshNetNavigator( const NET_NAVIGATOR_ITEM_DATA* aSelection ) { wxCHECK( m_netNavigator, /* void */ ); @@ -170,7 +249,55 @@ void SCH_EDIT_FRAME::RefreshNetNavigator() { wxTreeItemId rootId = m_netNavigator->AddRoot( m_highlightedConn, 0 ); - MakeNetNavigatorNode( m_highlightedConn, rootId ); + MakeNetNavigatorNode( m_highlightedConn, rootId, aSelection ); + } +} + + +void SCH_EDIT_FRAME::SelectNetNavigatorItem( const NET_NAVIGATOR_ITEM_DATA* aSelection ) +{ + wxCHECK( m_netNavigator, /* void */ ); + + // Maybe in the future we can do something like collapse the tree for an empty selection. + // For now, leave the tree selection in its current state. + if( !aSelection ) + return; + + wxTreeItemIdValue sheetCookie; + NET_NAVIGATOR_ITEM_DATA* itemData = nullptr; + wxTreeItemId rootId = m_netNavigator->GetRootItem(); + wxTreeItemId sheetId = m_netNavigator->GetFirstChild( rootId, sheetCookie ); + + while( sheetId.IsOk() ) + { + if( m_netNavigator->ItemHasChildren( sheetId ) ) + { + wxTreeItemIdValue itemCookie; + wxTreeItemId itemId = m_netNavigator->GetFirstChild( sheetId, itemCookie ); + + while( itemId.IsOk() ) + { + itemData = dynamic_cast( m_netNavigator->GetItemData( itemId ) ); + + wxCHECK2( itemData, continue ); + + if( *itemData == *aSelection ) + { + if( !m_netNavigator->IsVisible( itemId ) ) + { + m_netNavigator->CollapseAll(); + m_netNavigator->EnsureVisible( itemId ); + } + + m_netNavigator->SelectItem( itemId ); + return; + } + + itemId = m_netNavigator->GetNextSibling( itemId ); + } + + sheetId = m_netNavigator->GetNextSibling( sheetId ); + } } } @@ -200,6 +327,18 @@ void SCH_EDIT_FRAME::onNetNavigatorSelection( wxTreeEvent& aEvent ) if( m_netNavigator->GetItemParent( id ) != m_netNavigator->GetRootItem() && itemData->GetItem() ) { + // Make sure we didn't remove the item and/or the screen it resides on before we access it. + const SCH_ITEM* item = itemData->GetItem(); + + // Don't search for child items in screen r-tree. + item = ( ( item->Type() == SCH_SHEET_PIN_T ) || ( item->Type() == SCH_PIN_T ) ) ? + static_cast( item->GetParent() ) : item; + + const SCH_SCREEN* screen = itemData->GetSheetPath().LastScreen(); + + wxCHECK( screen, /* void */ ); + wxCHECK( screen->Items().contains( item, true ), /* void */ ); + FocusOnLocation( itemData->GetItem()->GetBoundingBox().Centre() ); } diff --git a/eeschema/sch_edit_frame.cpp b/eeschema/sch_edit_frame.cpp index 240eb469ea..0ebcc7ff4c 100644 --- a/eeschema/sch_edit_frame.cpp +++ b/eeschema/sch_edit_frame.cpp @@ -2364,12 +2364,36 @@ wxTreeCtrl* SCH_EDIT_FRAME::createHighlightedNetNavigator() } -void SCH_EDIT_FRAME::SetHighlightedConnection( const wxString& aConnection ) +void SCH_EDIT_FRAME::SetHighlightedConnection( const wxString& aConnection, + const NET_NAVIGATOR_ITEM_DATA* aSelection ) { bool refreshNetNavigator = aConnection != m_highlightedConn; m_highlightedConn = aConnection; if( refreshNetNavigator ) - RefreshNetNavigator(); + RefreshNetNavigator( aSelection ); +} + + +void SCH_EDIT_FRAME::unitsChangeRefresh() +{ + if( m_netNavigator && !m_highlightedConn.IsEmpty() ) + { + NET_NAVIGATOR_ITEM_DATA itemData; + wxTreeItemId selection = m_netNavigator->GetSelection(); + bool refreshSelection = selection.IsOk() && ( selection != m_netNavigator->GetRootItem() ); + + if( refreshSelection ) + { + NET_NAVIGATOR_ITEM_DATA* tmp = + dynamic_cast( m_netNavigator->GetItemData( selection ) ); + + wxCHECK( tmp, /* void */ ); + itemData = *tmp; + } + + m_netNavigator->DeleteAllItems(); + RefreshNetNavigator( refreshSelection ? &itemData : nullptr ); + } } diff --git a/eeschema/sch_edit_frame.h b/eeschema/sch_edit_frame.h index 3e45ebb747..c776e19f4a 100644 --- a/eeschema/sch_edit_frame.h +++ b/eeschema/sch_edit_frame.h @@ -61,7 +61,7 @@ class DIALOG_SCH_FIND; class wxFindReplaceData; class RESCUER; class HIERARCHY_PANE; -class NET_NAVIGATOR_ITEM_DATA; + // @todo Move this to transform alone with all of the transform manipulation code. /// enum used in RotationMiroir() @@ -98,6 +98,48 @@ enum SCH_CLEANUP_FLAGS wxDECLARE_EVENT( EDA_EVT_SCHEMATIC_CHANGED, wxCommandEvent ); +/** + * Tree view item data for the net navigator. + */ +class NET_NAVIGATOR_ITEM_DATA : public wxTreeItemData +{ +public: + NET_NAVIGATOR_ITEM_DATA( const SCH_SHEET_PATH& aSheetPath, const SCH_ITEM* aItem ) : + m_sheetPath( aSheetPath ), + m_item( aItem ) + { + } + + NET_NAVIGATOR_ITEM_DATA() : + m_item( nullptr ) + { + } + + SCH_SHEET_PATH& GetSheetPath() { return m_sheetPath; } + const SCH_ITEM* GetItem() const { return m_item; } + + bool operator==( const NET_NAVIGATOR_ITEM_DATA& aRhs ) const + { + return ( m_sheetPath == aRhs.m_sheetPath ) && ( m_item == aRhs.m_item ); + } + + NET_NAVIGATOR_ITEM_DATA& operator=( const NET_NAVIGATOR_ITEM_DATA& aItemData ) + { + if( this == &aItemData ) + return *this; + + m_sheetPath = aItemData.m_sheetPath; + m_item = aItemData.m_item; + + return *this; + } + +private: + SCH_SHEET_PATH m_sheetPath; + const SCH_ITEM* m_item; +}; + + /** * Schematic editor (Eeschema) main window. */ @@ -312,7 +354,8 @@ public: return m_highlightedConn; } - void SetHighlightedConnection( const wxString& aConnection ); + void SetHighlightedConnection( const wxString& aConnection, + const NET_NAVIGATOR_ITEM_DATA* aSelection = nullptr ); /** * Check if we are ready to write a netlist file for the current schematic. @@ -864,11 +907,13 @@ public: return wxS( "NetNavigator" ); } - void RefreshNetNavigator(); + void RefreshNetNavigator( const NET_NAVIGATOR_ITEM_DATA* aSelection = nullptr ); void MakeNetNavigatorNode( const wxString& aNetName, wxTreeItemId aParentId, const NET_NAVIGATOR_ITEM_DATA* aSelection = nullptr ); + void SelectNetNavigatorItem( const NET_NAVIGATOR_ITEM_DATA* aSelection = nullptr ); + void ToggleNetNavigator(); DECLARE_EVENT_TABLE() @@ -896,6 +941,8 @@ protected: void onCloseErcDialog( wxCommandEvent& aEvent ); + void unitsChangeRefresh() override; + private: // Called when resizing the Hierarchy Navigator panel void OnResizeHierarchyNavigator( wxSizeEvent& aEvent ); diff --git a/eeschema/tools/ee_selection_tool.cpp b/eeschema/tools/ee_selection_tool.cpp index bc1320a3df..4de18dca27 100644 --- a/eeschema/tools/ee_selection_tool.cpp +++ b/eeschema/tools/ee_selection_tool.cpp @@ -417,6 +417,16 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent ) collector[ 0 ]->DoHypertextAction( m_frame ); selCancelled = true; } + else if( collector[0]->IsBrightened() ) + { + if( SCH_EDIT_FRAME* schframe = dynamic_cast( m_frame ) ) + { + NET_NAVIGATOR_ITEM_DATA itemData( schframe->GetCurrentSheet(), + collector[0] ); + + schframe->SelectNetNavigatorItem( &itemData ); + } + } } if( !selCancelled ) diff --git a/eeschema/tools/sch_editor_control.cpp b/eeschema/tools/sch_editor_control.cpp index 35d7194b20..24a2856179 100644 --- a/eeschema/tools/sch_editor_control.cpp +++ b/eeschema/tools/sch_editor_control.cpp @@ -760,6 +760,7 @@ static bool highlightNet( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition ) EE_SELECTION_TOOL* selTool = aToolMgr->GetTool(); SCH_EDITOR_CONTROL* editorControl = aToolMgr->GetTool(); SCH_CONNECTION* conn = nullptr; + SCH_ITEM* item = nullptr; bool retVal = true; if( aPosition != CLEAR ) @@ -773,7 +774,7 @@ static bool highlightNet( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition ) } else { - SCH_ITEM* item = static_cast( selTool->GetNode( aPosition ) ); + item = static_cast( selTool->GetNode( aPosition ) ); SCH_SYMBOL* symbol = dynamic_cast( item ); if( item ) @@ -811,8 +812,9 @@ static bool highlightNet( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition ) } else { + NET_NAVIGATOR_ITEM_DATA itemData( editFrame->GetCurrentSheet(), item ); editFrame->SetCrossProbeConnection( conn ); - editFrame->SetHighlightedConnection( connectionName ); + editFrame->SetHighlightedConnection( connectionName, &itemData ); } editFrame->UpdateNetHighlightStatus();