KiCad PCB EDA Suite
Loading...
Searching...
No Matches
net_navigator.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2023 Rivos
5 * Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * @author Wayne Stambaugh <[email protected]>
8 *
9 * This program is free software: you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation, either version 3 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#include <wx/log.h>
24#include <tool/tool_manager.h>
25#include <kiface_base.h>
26#include <sch_edit_frame.h>
27#include <sch_bus_entry.h>
28#include <sch_line.h>
29#include <sch_junction.h>
30#include <sch_sheet_pin.h>
31#include <schematic.h>
32#include <connection_graph.h>
34#include <tools/ee_actions.h>
35
36
37static wxString GetNetNavigatorItemText( const SCH_ITEM* aItem,
38 const SCH_SHEET_PATH& aSheetPath,
39 UNITS_PROVIDER* aUnitsProvider )
40{
41 wxString retv;
42
43 wxCHECK( aItem && aUnitsProvider, retv );
44
45 switch( aItem->Type() )
46 {
47 case SCH_LINE_T:
48 {
49 const SCH_LINE* line = static_cast<const SCH_LINE*>( aItem );
50
51 wxCHECK( line, retv );
52
53 if( aItem->GetLayer() == LAYER_WIRE )
54 {
55 retv.Printf( _( "Wire from %s, %s to %s, %s" ),
56 aUnitsProvider->MessageTextFromValue( line->GetStartPoint().x ),
57 aUnitsProvider->MessageTextFromValue( line->GetStartPoint().y ),
58 aUnitsProvider->MessageTextFromValue( line->GetEndPoint().x ),
59 aUnitsProvider->MessageTextFromValue( line->GetEndPoint().y ) );
60 }
61 else if( aItem->GetLayer() == LAYER_BUS )
62 {
63 retv.Printf( _( "Bus from %s, %s to %s, %s" ),
64 aUnitsProvider->MessageTextFromValue( line->GetStartPoint().x ),
65 aUnitsProvider->MessageTextFromValue( line->GetStartPoint().y ),
66 aUnitsProvider->MessageTextFromValue( line->GetEndPoint().x ),
67 aUnitsProvider->MessageTextFromValue( line->GetEndPoint().y ) );
68 }
69 else
70 {
71 retv = _( "Graphic line not connectable" );
72 }
73
74 break;
75 }
76 case SCH_PIN_T:
77 {
78 const SCH_PIN* pin = static_cast<const SCH_PIN*>( aItem );
79 wxCHECK( pin, retv );
80
81 SCH_SYMBOL* symbol = pin->GetParentSymbol();
82 wxCHECK( symbol, retv );
83
84 retv.Printf( _( "Symbol '%s' pin '%s'" ), symbol->GetRef( &aSheetPath, true ),
85 pin->GetNumber() );
86 break;
87 }
88 case SCH_SHEET_PIN_T:
89 {
90 const SCH_SHEET_PIN* pin = static_cast<const SCH_SHEET_PIN*>( aItem );
91 wxCHECK( pin, retv );
92
93 SCH_SHEET* sheet = pin->GetParent();
94 wxCHECK( sheet, retv );
95
96 retv.Printf( _( "Sheet '%s' pin '%s'" ), sheet->GetName(), pin->GetText() );
97 break;
98 }
99 case SCH_LABEL_T:
100 {
101 const SCH_LABEL* label = static_cast<const SCH_LABEL*>( aItem );
102 wxCHECK( label, retv );
103
104 retv.Printf( _( "Label '%s' at %s, %s" ), label->GetText(),
105 aUnitsProvider->MessageTextFromValue( label->GetPosition().x ),
106 aUnitsProvider->MessageTextFromValue( label->GetPosition().y ) );
107 break;
108 }
110 {
111 const SCH_GLOBALLABEL* label = static_cast<const SCH_GLOBALLABEL*>( aItem );
112 wxCHECK( label, retv );
113
114 retv.Printf( _( "Global label '%s' at %s, %s" ), label->GetText(),
115 aUnitsProvider->MessageTextFromValue( label->GetPosition().x ),
116 aUnitsProvider->MessageTextFromValue( label->GetPosition().y ) );
117 break;
118 }
119 case SCH_HIER_LABEL_T:
120 {
121 const SCH_HIERLABEL* label = static_cast<const SCH_HIERLABEL*>( aItem );
122 wxCHECK( label, retv );
123
124 retv.Printf( _( "Hierarchical label '%s' at %s, %s" ), label->GetText(),
125 aUnitsProvider->MessageTextFromValue( label->GetPosition().x ),
126 aUnitsProvider->MessageTextFromValue( label->GetPosition().y ) );
127 break;
128 }
129 case SCH_JUNCTION_T:
130 {
131 const SCH_JUNCTION* junction = static_cast<const SCH_JUNCTION*>( aItem );
132 wxCHECK( junction, retv );
133
134 retv.Printf( _( "Junction at %s, %s" ),
135 aUnitsProvider->MessageTextFromValue( junction->GetPosition().x ),
136 aUnitsProvider->MessageTextFromValue( junction->GetPosition().y ) );
137 break;
138 }
140 {
141 const SCH_BUS_WIRE_ENTRY* entry = static_cast<const SCH_BUS_WIRE_ENTRY*>( aItem );
142 wxCHECK( entry, retv );
143
144 retv.Printf( _( "Bus to wire entry from %s, %s to %s, %s" ),
145 aUnitsProvider->MessageTextFromValue( entry->GetPosition().x ),
146 aUnitsProvider->MessageTextFromValue( entry->GetPosition().y ),
147 aUnitsProvider->MessageTextFromValue( entry->GetEnd().x ),
148 aUnitsProvider->MessageTextFromValue( entry->GetEnd().y ) );
149 break;
150 }
152 {
153 const SCH_BUS_BUS_ENTRY* entry = static_cast<const SCH_BUS_BUS_ENTRY*>( aItem );
154 wxCHECK( entry, retv );
155
156 retv.Printf( _( "Bus to bus entry from %s, %s to %s, %s" ),
157 aUnitsProvider->MessageTextFromValue( entry->GetPosition().x ),
158 aUnitsProvider->MessageTextFromValue( entry->GetPosition().y ),
159 aUnitsProvider->MessageTextFromValue( entry->GetEnd().x ),
160 aUnitsProvider->MessageTextFromValue( entry->GetEnd().y ) );
161 break;
162 }
163 default:
164 retv.Printf( _( "Unhandled item type %d" ), aItem->Type() );
165 }
166
167 return retv;
168}
169
170
171void SCH_EDIT_FRAME::MakeNetNavigatorNode( const wxString& aNetName, wxTreeItemId aParentId,
172 const NET_NAVIGATOR_ITEM_DATA* aSelection )
173{
174 wxCHECK( !aNetName.IsEmpty(), /* void */ );
175 wxCHECK( m_schematic, /* void */ );
176 wxCHECK( m_netNavigator, /* void */ );
177
178 wxTreeItemId expandId = aParentId;
179 CONNECTION_GRAPH* connectionGraph = m_schematic->ConnectionGraph();
180
181 wxCHECK( connectionGraph, /* void */ );
182
183 wxString sheetPathPrefix;
184 const std::vector<CONNECTION_SUBGRAPH*> subgraphs =
185 connectionGraph->GetAllSubgraphs( aNetName );
186
187 for( const CONNECTION_SUBGRAPH* subGraph : subgraphs )
188 {
189 NET_NAVIGATOR_ITEM_DATA* itemData = nullptr;
190 SCH_SHEET_PATH sheetPath = subGraph->GetSheet();
191
192 wxCHECK2( subGraph && sheetPath.Last(), continue );
193
194 if( subGraph->GetItems().empty() )
195 continue;
196
197 itemData = new NET_NAVIGATOR_ITEM_DATA( sheetPath, nullptr );
198
199 bool stripTrailingSeparator = !sheetPath.Last()->IsRootSheet();
200 wxString txt = sheetPath.PathHumanReadable( true, stripTrailingSeparator );
201 wxTreeItemId sheetId = m_netNavigator->AppendItem( aParentId, txt, -1, -1, itemData );
202
203 if( aSelection && *aSelection == *itemData )
204 m_netNavigator->SelectItem( sheetId );
205
206 // If there is only one sheet in the schematic, always expand the sheet tree.
207 if( Schematic().GetSheets().size() == 1 )
208 expandId = sheetId;
209
210 for( const SCH_ITEM* item : subGraph->GetItems() )
211 {
212 KICAD_T type = item->Type();
213
214 if( ( type == SCH_LINE_T ) || ( type == SCH_JUNCTION_T )
215 || ( type == SCH_BUS_WIRE_ENTRY_T ) || ( type == SCH_BUS_BUS_ENTRY_T ) )
216 continue;
217
218 itemData = new NET_NAVIGATOR_ITEM_DATA( sheetPath, item );
219 wxTreeItemId id = m_netNavigator->AppendItem( sheetId,
220 GetNetNavigatorItemText( item, sheetPath,
221 this ),
222 -1, -1, itemData );
223
224 if( aSelection && *aSelection == *itemData )
225 {
226 expandId = sheetId;
227 m_netNavigator->EnsureVisible( id );
228 m_netNavigator->SelectItem( id );
229 }
230 }
231 }
232
233 m_netNavigator->Expand( aParentId );
234}
235
236
238{
239 wxCHECK( m_netNavigator, /* void */ );
240
241 if( m_netNavigator->IsEmpty() && m_highlightedConn.IsEmpty() )
242 return;
243
244 if( !m_netNavigator->IsEmpty() && m_highlightedConn.IsEmpty() )
245 {
246 m_netNavigator->DeleteAllItems();
247 return;
248 }
249
250 if( !m_netNavigator->IsEmpty() )
251 {
252 const wxString shownNetName = m_netNavigator->GetItemText( m_netNavigator->GetRootItem() );
253
254 if( shownNetName != m_highlightedConn )
255 {
256 m_netNavigator->DeleteAllItems();
257
258 wxTreeItemId rootId = m_netNavigator->AddRoot( m_highlightedConn, 0 );
259
260 MakeNetNavigatorNode( m_highlightedConn, rootId, aSelection );
261 }
262 else
263 {
264 NET_NAVIGATOR_ITEM_DATA* itemData = nullptr;
265
266 wxTreeItemId selection = m_netNavigator->GetSelection();
267
268 if( selection.IsOk() )
269 itemData = dynamic_cast<NET_NAVIGATOR_ITEM_DATA*>( m_netNavigator->GetItemData( selection ) );
270
271 m_netNavigator->DeleteAllItems();
272 wxTreeItemId rootId = m_netNavigator->AddRoot( m_highlightedConn, 0 );
273
274 MakeNetNavigatorNode( m_highlightedConn, rootId, itemData );
275 }
276 }
277 else
278 {
279 wxTreeItemId rootId = m_netNavigator->AddRoot( m_highlightedConn, 0 );
280
281 MakeNetNavigatorNode( m_highlightedConn, rootId, aSelection );
282 }
283}
284
285
287{
288 wxCHECK( m_netNavigator, /* void */ );
289
290 // Maybe in the future we can do something like collapse the tree for an empty selection.
291 // For now, leave the tree selection in its current state.
292 if( !aSelection )
293 return;
294
295 wxTreeItemIdValue sheetCookie;
296 NET_NAVIGATOR_ITEM_DATA* itemData = nullptr;
297 wxTreeItemId rootId = m_netNavigator->GetRootItem();
298 wxTreeItemId sheetId = m_netNavigator->GetFirstChild( rootId, sheetCookie );
299
300 while( sheetId.IsOk() )
301 {
302 if( m_netNavigator->ItemHasChildren( sheetId ) )
303 {
304 wxTreeItemIdValue itemCookie;
305 wxTreeItemId itemId = m_netNavigator->GetFirstChild( sheetId, itemCookie );
306
307 while( itemId.IsOk() )
308 {
309 itemData = dynamic_cast<NET_NAVIGATOR_ITEM_DATA*>( m_netNavigator->GetItemData( itemId ) );
310
311 wxCHECK2( itemData, continue );
312
313 if( *itemData == *aSelection )
314 {
315 if( !m_netNavigator->IsVisible( itemId ) )
316 {
317 m_netNavigator->CollapseAll();
318 m_netNavigator->EnsureVisible( itemId );
319 }
320
321 m_netNavigator->SelectItem( itemId );
322 return;
323 }
324
325 itemId = m_netNavigator->GetNextSibling( itemId );
326 }
327
328 sheetId = m_netNavigator->GetNextSibling( sheetId );
329 }
330 }
331}
332
333
335{
336 if( !m_netNavigator )
337 return nullptr;
338
339 wxTreeItemId id = m_netNavigator->GetSelection();
340
341 if( !id.IsOk() || ( id == m_netNavigator->GetRootItem() ) )
342 return nullptr;
343
344 NET_NAVIGATOR_ITEM_DATA* itemData =
345 dynamic_cast<NET_NAVIGATOR_ITEM_DATA*>( m_netNavigator->GetItemData( id ) );
346
347 wxCHECK( itemData, nullptr );
348
349 return itemData->GetItem();
350}
351
352
354{
355 wxCHECK( m_netNavigator, /* void */ );
356
357 wxTreeItemId id = aEvent.GetItem();
358
359 // Clicking on the root item (net name ) does nothing.
360 if( id == m_netNavigator->GetRootItem() )
361 return;
362
363 NET_NAVIGATOR_ITEM_DATA* itemData =
364 dynamic_cast<NET_NAVIGATOR_ITEM_DATA*>( m_netNavigator->GetItemData( id ) );
365
366 wxCHECK( itemData, /* void */ );
367
368 if( GetCurrentSheet() != itemData->GetSheetPath() )
369 {
370 Schematic().SetCurrentSheet( itemData->GetSheetPath() );
372 }
373
374 // Do not focus on item when a sheet tree node is selected.
375 if( m_netNavigator->GetItemParent( id ) != m_netNavigator->GetRootItem()
376 && itemData->GetItem() )
377 {
378 // Make sure we didn't remove the item and/or the screen it resides on before we access it.
379 const SCH_ITEM* item = itemData->GetItem();
380
381 // Don't search for child items in screen r-tree.
382 item = ( ( item->Type() == SCH_SHEET_PIN_T ) || ( item->Type() == SCH_PIN_T ) ) ?
383 static_cast<const SCH_ITEM*>( item->GetParent() ) : item;
384
385 const SCH_SCREEN* screen = itemData->GetSheetPath().LastScreen();
386
387 wxCHECK( screen, /* void */ );
388 wxCHECK( screen->Items().contains( item, true ), /* void */ );
389
390 FocusOnLocation( itemData->GetItem()->GetBoundingBox().Centre() );
391 }
392
393 GetCanvas()->Refresh();
394}
395
396
398{
399 wxCHECK( m_netNavigator, /* void */ );
400}
401
402
404{
406
407 wxCHECK( cfg, /* void */ );
408
409 wxAuiPaneInfo& netNavigatorPane = m_auimgr.GetPane( NetNavigatorPaneName() );
410
411 netNavigatorPane.Show( !netNavigatorPane.IsShown() );
412
413 cfg->m_AuiPanels.show_net_nav_panel = netNavigatorPane.IsShown();
414
415 if( netNavigatorPane.IsShown() )
416 {
417 if( netNavigatorPane.IsFloating() )
418 {
419 netNavigatorPane.FloatingSize( cfg->m_AuiPanels.net_nav_panel_float_size );
420 m_auimgr.Update();
421 }
422 else if( cfg->m_AuiPanels.net_nav_panel_docked_size.GetWidth() > 0 )
423 {
424 // SetAuiPaneSize also updates m_auimgr
425 SetAuiPaneSize( m_auimgr, netNavigatorPane,
426 cfg->m_AuiPanels.net_nav_panel_docked_size.GetWidth(), -1 );
427 }
428 }
429 else
430 {
431 if( netNavigatorPane.IsFloating() )
432 {
433 cfg->m_AuiPanels.net_nav_panel_float_size = netNavigatorPane.floating_size;
434 }
435 else
436 {
438 }
439
440 m_auimgr.Update();
441 }
442}
443
444
445void SCH_EDIT_FRAME::onResizeNetNavigator( wxSizeEvent& aEvent )
446{
447 aEvent.Skip();
448
449 // Called when resizing the Hierarchy Navigator panel
450 // Store the current pane size
451 // It allows to retrieve the last defined pane size when switching between
452 // docked and floating pane state
453 // Note: *DO NOT* call m_auimgr.Update() here: it crashes Kicad at least on Windows
454
455 EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
456
457 wxCHECK( cfg, /* void */ );
458
459 wxAuiPaneInfo& netNavigatorPane = m_auimgr.GetPane( NetNavigatorPaneName() );
460
461 if( m_netNavigator->IsShown() )
462 {
463 cfg->m_AuiPanels.net_nav_panel_float_size = netNavigatorPane.floating_size;
464
465 // initialize net_nav_panel_docked_width and best size only if the netNavigatorPane
466 // width is > 0 (i.e. if its size is already set and has meaning)
467 // if it is floating, its size is not initialized (only floating_size is initialized)
468 // initializing netNavigatorPane.best_size is useful when switching to float pane and
469 // after switching to the docked pane, to retrieve the last docked pane width
470 if( netNavigatorPane.rect.width > 50 ) // 50 is a good margin
471 {
472 cfg->m_AuiPanels.net_nav_panel_docked_size.SetWidth( netNavigatorPane.rect.width );
473 netNavigatorPane.best_size.x = netNavigatorPane.rect.width;
474 }
475 }
476}
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
Vec Centre() const
Definition: box2.h:71
Calculates the connectivity of a schematic and generates netlists.
const std::vector< CONNECTION_SUBGRAPH * > GetAllSubgraphs(const wxString &aNetName) const
A subgraph is a set of items that are electrically connected on a single sheet.
wxAuiManager m_auimgr
void FocusOnLocation(const VECTOR2I &aPos)
Useful to focus on a particular location, in find functions.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:74
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
EDA_ITEM * GetParent() const
Definition: eda_item.h:99
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:95
bool contains(const SCH_ITEM *aItem, bool aRobust=false) const
Determine if a given item exists in the tree.
Definition: sch_rtree.h:125
APP_SETTINGS_BASE * KifaceSettings() const
Definition: kiface_base.h:95
Tree view item data for the net navigator.
const SCH_ITEM * GetItem() const
SCH_SHEET_PATH & GetSheetPath()
CONNECTION_GRAPH * ConnectionGraph() const override
Definition: schematic.h:146
void SetCurrentSheet(const SCH_SHEET_PATH &aPath) override
Definition: schematic.h:141
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
EESCHEMA_SETTINGS * eeconfig() const
Class for a bus to bus entry.
VECTOR2I GetPosition() const override
VECTOR2I GetEnd() const
Class for a wire to bus entry.
wxTreeCtrl * m_netNavigator
void ToggleNetNavigator()
void onResizeNetNavigator(wxSizeEvent &aEvent)
void onNetNavigatorSelChanging(wxTreeEvent &aEvent)
SCHEMATIC * m_schematic
The currently loaded schematic.
SCH_SHEET_PATH & GetCurrentSheet() const
const SCH_ITEM * GetSelectedNetNavigatorItem() const
SCHEMATIC & Schematic() const
void RefreshNetNavigator(const NET_NAVIGATOR_ITEM_DATA *aSelection=nullptr)
void DisplayCurrentSheet()
Draw the current sheet on the display.
void SelectNetNavigatorItem(const NET_NAVIGATOR_ITEM_DATA *aSelection=nullptr)
wxString m_highlightedConn
The highlighted net or bus or empty string.
static const wxString NetNavigatorPaneName()
void MakeNetNavigatorNode(const wxString &aNetName, wxTreeItemId aParentId, const NET_NAVIGATOR_ITEM_DATA *aSelection=nullptr)
void onNetNavigatorSelection(wxTreeEvent &aEvent)
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:150
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition: sch_item.h:257
VECTOR2I GetPosition() const override
Definition: sch_junction.h:106
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:40
VECTOR2I GetEndPoint() const
Definition: sch_line.h:145
VECTOR2I GetStartPoint() const
Definition: sch_line.h:140
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:109
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
const SCH_SHEET * GetSheet(unsigned aIndex) const
wxString PathHumanReadable(bool aUseShortRootName=true, bool aStripTrailingSeparator=false) const
Return the sheet path in a human readable form made from the sheet names.
SCH_SCREEN * LastScreen()
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet_pin.h:66
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:57
bool IsRootSheet() const
Definition: sch_sheet.cpp:193
wxString GetName() const
Definition: sch_sheet.h:107
Schematic symbol object.
Definition: sch_symbol.h:81
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:720
VECTOR2I GetPosition() const override
Definition: sch_text.h:126
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
A lower-precision version of StringFromValue().
#define _(s)
@ LAYER_WIRE
Definition: layer_ids.h:349
@ LAYER_BUS
Definition: layer_ids.h:350
static wxString GetNetNavigatorItemText(const SCH_ITEM *aItem, const SCH_SHEET_PATH &aSheetPath, UNITS_PROVIDER *aUnitsProvider)
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
@ SCH_LINE_T
Definition: typeinfo.h:145
@ SCH_LABEL_T
Definition: typeinfo.h:150
@ SCH_HIER_LABEL_T
Definition: typeinfo.h:152
@ SCH_BUS_BUS_ENTRY_T
Definition: typeinfo.h:144
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:156
@ SCH_BUS_WIRE_ENTRY_T
Definition: typeinfo.h:143
@ SCH_GLOBAL_LABEL_T
Definition: typeinfo.h:151
@ SCH_JUNCTION_T
Definition: typeinfo.h:141
@ SCH_PIN_T
Definition: typeinfo.h:158
void SetAuiPaneSize(wxAuiManager &aManager, wxAuiPaneInfo &aPane, int aWidth, int aHeight)
Sets the size of an AUI pane, working around http://trac.wxwidgets.org/ticket/13180.