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 The 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
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
23#include <wx/log.h>
24#include <wx/srchctrl.h>
25#include <wx/wupdlock.h>
26#include <core/profile.h>
27#include <tool/tool_manager.h>
28#include <kiface_base.h>
29#include <confirm.h>
30#include <sch_edit_frame.h>
31#include <sch_bus_entry.h>
32#include <sch_line.h>
33#include <sch_junction.h>
34#include <sch_no_connect.h>
35#include <sch_sheet_pin.h>
36#include <string_utils.h>
37#include <trace_helpers.h>
38#include <advanced_config.h>
42#include <tools/sch_actions.h>
43#include <mail_type.h>
44#include <wx/filename.h>
46#include <wx/clntdata.h>
47#include <regex>
48#include <eeschema_settings.h>
49
50
51static wxString GetNetNavigatorItemText( const SCH_ITEM* aItem,
52 const SCH_SHEET_PATH& aSheetPath,
53 UNITS_PROVIDER* aUnitsProvider )
54{
55 wxString retv;
56
57 wxCHECK( aItem && aUnitsProvider, retv );
58
59 switch( aItem->Type() )
60 {
61 case SCH_LINE_T:
62 {
63 const SCH_LINE* line = static_cast<const SCH_LINE*>( aItem );
64
65 if( aItem->GetLayer() == LAYER_WIRE )
66 {
67 retv.Printf( _( "Wire from (%s, %s) to (%s, %s)" ),
68 aUnitsProvider->MessageTextFromValue( line->GetStartPoint().x ),
69 aUnitsProvider->MessageTextFromValue( line->GetStartPoint().y ),
70 aUnitsProvider->MessageTextFromValue( line->GetEndPoint().x ),
71 aUnitsProvider->MessageTextFromValue( line->GetEndPoint().y ) );
72 }
73 else if( aItem->GetLayer() == LAYER_BUS )
74 {
75 retv.Printf( _( "Bus from (%s, %s) to (%s, %s)" ),
76 aUnitsProvider->MessageTextFromValue( line->GetStartPoint().x ),
77 aUnitsProvider->MessageTextFromValue( line->GetStartPoint().y ),
78 aUnitsProvider->MessageTextFromValue( line->GetEndPoint().x ),
79 aUnitsProvider->MessageTextFromValue( line->GetEndPoint().y ) );
80 }
81 else
82 {
83 retv = _( "Graphic line not connectable" );
84 }
85
86 break;
87 }
88 case SCH_PIN_T:
89 {
90 const SCH_PIN* pin = static_cast<const SCH_PIN*>( aItem );
91
92 if( const SYMBOL* symbol = pin->GetParentSymbol() )
93 {
94 retv.Printf( _( "Symbol '%s' pin '%s'" ),
95 symbol->GetRef( &aSheetPath, true ),
96 UnescapeString( pin->GetNumber() ) );
97
98 if( wxString pinName = UnescapeString( pin->GetShownName() ); !pinName.IsEmpty() )
99 {
100 retv += wxString::Format( " (%s)", pinName );
101 }
102 }
103
104 break;
105 }
106 case SCH_SHEET_PIN_T:
107 {
108 const SCH_SHEET_PIN* pin = static_cast<const SCH_SHEET_PIN*>( aItem );
109
110 if( SCH_SHEET* sheet = pin->GetParent() )
111 {
112 retv.Printf( _( "Sheet '%s' pin '%s'" ),
113 sheet->GetName(),
114 UnescapeString( pin->GetText() ) );
115 }
116
117 break;
118 }
119 case SCH_LABEL_T:
120 {
121 const SCH_LABEL* label = static_cast<const SCH_LABEL*>( aItem );
122
123 retv.Printf( _( "Label '%s' at (%s, %s)" ),
124 UnescapeString( label->GetText() ),
125 aUnitsProvider->MessageTextFromValue( label->GetPosition().x ),
126 aUnitsProvider->MessageTextFromValue( label->GetPosition().y ) );
127 break;
128 }
130 {
131 const SCH_GLOBALLABEL* label = static_cast<const SCH_GLOBALLABEL*>( aItem );
132
133 retv.Printf( _( "Global label '%s' at (%s, %s)" ),
134 UnescapeString( label->GetText() ),
135 aUnitsProvider->MessageTextFromValue( label->GetPosition().x ),
136 aUnitsProvider->MessageTextFromValue( label->GetPosition().y ) );
137 break;
138 }
139 case SCH_HIER_LABEL_T:
140 {
141 const SCH_HIERLABEL* label = static_cast<const SCH_HIERLABEL*>( aItem );
142
143 retv.Printf( _( "Hierarchical label '%s' at (%s, %s)" ),
144 UnescapeString( label->GetText() ),
145 aUnitsProvider->MessageTextFromValue( label->GetPosition().x ),
146 aUnitsProvider->MessageTextFromValue( label->GetPosition().y ) );
147 break;
148 }
149 case SCH_JUNCTION_T:
150 {
151 const SCH_JUNCTION* junction = static_cast<const SCH_JUNCTION*>( aItem );
152
153 retv.Printf( _( "Junction at (%s, %s)" ),
154 aUnitsProvider->MessageTextFromValue( junction->GetPosition().x ),
155 aUnitsProvider->MessageTextFromValue( junction->GetPosition().y ) );
156 break;
157 }
158 case SCH_NO_CONNECT_T:
159 {
160 const SCH_NO_CONNECT* nc = static_cast<const SCH_NO_CONNECT*>( aItem );
161
162 retv.Printf( _( "No-Connect at (%s, %s)" ),
163 aUnitsProvider->MessageTextFromValue( nc->GetPosition().x ),
164 aUnitsProvider->MessageTextFromValue( nc->GetPosition().y ) );
165 break;
166 }
168 {
169 const SCH_BUS_WIRE_ENTRY* entry = static_cast<const SCH_BUS_WIRE_ENTRY*>( aItem );
170
171 retv.Printf( _( "Bus to wire entry from (%s, %s) to (%s, %s)" ),
172 aUnitsProvider->MessageTextFromValue( entry->GetPosition().x ),
173 aUnitsProvider->MessageTextFromValue( entry->GetPosition().y ),
174 aUnitsProvider->MessageTextFromValue( entry->GetEnd().x ),
175 aUnitsProvider->MessageTextFromValue( entry->GetEnd().y ) );
176 break;
177 }
179 {
180 const SCH_BUS_BUS_ENTRY* entry = static_cast<const SCH_BUS_BUS_ENTRY*>( aItem );
181
182 retv.Printf( _( "Bus to bus entry from (%s, %s) to (%s, %s)" ),
183 aUnitsProvider->MessageTextFromValue( entry->GetPosition().x ),
184 aUnitsProvider->MessageTextFromValue( entry->GetPosition().y ),
185 aUnitsProvider->MessageTextFromValue( entry->GetEnd().x ),
186 aUnitsProvider->MessageTextFromValue( entry->GetEnd().y ) );
187 break;
188 }
190 {
191 const SCH_DIRECTIVE_LABEL* entry = static_cast<const SCH_DIRECTIVE_LABEL*>( aItem );
192
193 retv.Printf( _( "Netclass label '%s' at (%s, %s)" ),
194 UnescapeString( entry->GetText() ),
195 aUnitsProvider->MessageTextFromValue( entry->GetPosition().x ),
196 aUnitsProvider->MessageTextFromValue( entry->GetPosition().y ) );
197 break;
198 }
199 default:
200 retv.Printf( _( "Unhandled item type %d" ), aItem->Type() );
201 }
202
203 return retv;
204}
205
206
207void SCH_EDIT_FRAME::MakeNetNavigatorNode( const wxString& aNetName, wxTreeItemId aParentId,
208 const NET_NAVIGATOR_ITEM_DATA* aSelection,
210{
211 wxCHECK( !aNetName.IsEmpty(), /* void */ );
212 wxCHECK( m_schematic, /* void */ );
213 wxCHECK( m_netNavigator, /* void */ );
214
215 const auto itemsBySheet = aQuery.NetItems( aNetName, true );
216
217 for( const auto& [sheetPath, items] : itemsBySheet )
218 {
219 wxCHECK2( sheetPath.Last(), continue );
220 auto* itemData = new NET_NAVIGATOR_ITEM_DATA( sheetPath, nullptr );
221
222 // Build path string for net navigator - include top-level sheet name to distinguish
223 // multiple top-level sheets
224 wxString txt;
225
226 if( !sheetPath.empty() && sheetPath.at( 0 )->GetScreen() )
227 {
228 // Get the top-level sheet name
229 txt = sheetPath.at( 0 )->GetField( FIELD_T::SHEET_NAME )->GetShownText( FOR_GUI );
230
231 if( txt.IsEmpty() )
232 {
233 wxFileName fn( sheetPath.at( 0 )->GetScreen()->GetFileName() );
234 txt = fn.GetName();
235 }
236
237 // Add sub-sheet names
238 for( unsigned i = 1; i < sheetPath.size(); i++ )
239 txt << wxS( "/" ) << sheetPath.at( i )->GetField( FIELD_T::SHEET_NAME )->GetShownText( FOR_GUI );
240 }
241 else
242 {
243 txt = sheetPath.PathHumanReadable( true, true );
244 }
245
246 wxTreeItemId sheetId = m_netNavigator->AppendItem( aParentId, txt, -1, -1, itemData );
247
248 if( aSelection && *aSelection == *itemData )
249 m_netNavigator->SelectItem( sheetId );
250
251 for( const SCH_ITEM* item : items )
252 {
253 if( item->Type() == SCH_LINE_T
254 || item->Type() == SCH_JUNCTION_T
255 || item->Type() == SCH_BUS_WIRE_ENTRY_T
256 || item->Type() == SCH_BUS_BUS_ENTRY_T )
257 {
258 continue;
259 }
260
261 itemData = new NET_NAVIGATOR_ITEM_DATA( sheetPath, item );
262 wxTreeItemId id = m_netNavigator->AppendItem( sheetId,
263 GetNetNavigatorItemText( item, sheetPath, this ),
264 -1, -1, itemData );
265
266 if( aSelection && *aSelection == *itemData )
267 {
268 m_netNavigator->EnsureVisible( id );
269 m_netNavigator->SelectItem( id );
270 }
271 }
272
273 m_netNavigator->SortChildren( sheetId );
274 }
275
276 // Sort the items in the tree control alphabetically
277 m_netNavigator->SortChildren( aParentId );
278 m_netNavigator->Expand( aParentId );
279}
280
281
283 const std::vector<wxString>* aChangedNets )
284{
285 wxCHECK( m_netNavigator && m_schematic, /* void */ );
286
287 if( !m_netNavigator->IsShownOnScreen() || !m_schematic->HasHierarchy() )
288 {
289 m_netNavigatorStale = true;
290 return;
291 }
292
293 const bool incremental = aChangedNets && !m_netNavigatorStale && !m_netNavigator->IsEmpty()
295
296 if( !aSelection && !m_netNavigator->IsEmpty()
297 && ( incremental || ( !m_highlightedConn.IsEmpty()
299 {
300 const wxTreeItemId selected = m_netNavigator->GetSelection();
301
302 if( selected.IsOk() )
303 aSelection = dynamic_cast<NET_NAVIGATOR_ITEM_DATA*>( m_netNavigator->GetItemData( selected ) );
304 }
305
306 // Selection data can belong to the tree that is about to be deleted
307 NET_NAVIGATOR_ITEM_DATA selection;
308
309 if( aSelection )
310 {
311 selection = *aSelection;
312 aSelection = &selection;
313 }
314
316 m_netNavigatorFilter->Enable( m_highlightedConn.IsEmpty() );
317
319 size_t nodeCnt = 0;
320
321 wxWindowUpdateLocker updateLock( m_netNavigator );
322 PROF_TIMER timer;
323
324 if( !incremental )
325 {
326 m_netNavigatorNodes.clear();
327 m_netNavigator->DeleteAllItems();
329 m_netNavigatorStale = false;
330 }
331
332 const auto rebuildNode = [&]( const wxString& name, wxTreeItemId node )
333 {
334 wxTreeItemId selected = m_netNavigator->GetSelection();
335
336 while( selected.IsOk() && selected != node )
337 selected = m_netNavigator->GetItemParent( selected );
338
339 const bool restoreSelection = selected == node;
340 const bool expanded = m_netNavigator->IsExpanded( node );
341 std::set<KIID_PATH> expandedSheets;
342 wxTreeItemIdValue cookie;
343
344 for( wxTreeItemId sheet = m_netNavigator->GetFirstChild( node, cookie ); sheet.IsOk();
345 sheet = m_netNavigator->GetNextChild( node, cookie ) )
346 {
347 if( m_netNavigator->IsExpanded( sheet ) )
348 {
349 if( auto* data = dynamic_cast<NET_NAVIGATOR_ITEM_DATA*>( m_netNavigator->GetItemData( sheet ) ) )
350 expandedSheets.insert( data->GetSheetPath().PathRef() );
351 }
352 }
353
354 m_netNavigator->DeleteChildren( node );
355 MakeNetNavigatorNode( name, node, restoreSelection ? aSelection : nullptr, query );
356
357 for( wxTreeItemId sheet = m_netNavigator->GetFirstChild( node, cookie ); sheet.IsOk();
358 sheet = m_netNavigator->GetNextChild( node, cookie ) )
359 {
360 auto* data = dynamic_cast<NET_NAVIGATOR_ITEM_DATA*>( m_netNavigator->GetItemData( sheet ) );
361
362 if( data && expandedSheets.contains( data->GetSheetPath().PathRef() ) )
363 m_netNavigator->Expand( sheet );
364 }
365
366 if( !expanded )
367 m_netNavigator->Collapse( node );
368 };
369
370 wxString filter = m_highlightedConn.IsEmpty() ? m_netNavigatorFilterValue : wxString();
371
372 // Determine search mode from settings
374 bool useWildcard = cfg ? cfg->m_AuiPanels.net_nav_search_mode_wildcard : true;
375
376 // For wildcard mode, wrap filter with wildcards for substring matching by default
377 // unless user has already specified wildcards
378 wxString globFilter;
379 std::unique_ptr<std::regex> regexFilter;
380
381 if( !filter.IsEmpty() )
382 {
383 if( useWildcard )
384 {
385 globFilter = filter;
386 if( !globFilter.Contains( wxT( "*" ) ) && !globFilter.Contains( wxT( "?" ) ) )
387 globFilter = wxT( "*" ) + globFilter + wxT( "*" );
388 }
389 else
390 {
391 // Regex mode - compile the regex pattern
392 try
393 {
394 regexFilter = std::make_unique<std::regex>(
395 filter.ToStdString(),
396 std::regex_constants::icase | std::regex_constants::ECMAScript );
397 }
398 catch( const std::regex_error& )
399 {
400 // Invalid regex - no filtering
401 regexFilter.reset();
402 }
403 }
404 }
405
406 if( m_highlightedConn.IsEmpty() )
407 {
408 // Create a tree of all nets in the schematic.
409 wxTreeItemId rootId = incremental ? m_netNavigator->GetRootItem()
410 : m_netNavigator->AddRoot( _( "Nets" ), 0 );
411 const auto names = incremental ? *aChangedNets : query.NetNames();
412 // Legacy names arrive sorted by escaped name, engine names in publication order
413 bool sortRoot = !incremental && ADVANCED_CFG::GetCfg().m_ConnectivityEngine;
414
415 for( const wxString& netName : names )
416 {
417 if( netName.IsEmpty() )
418 continue;
419
420 auto existing = m_netNavigatorNodes.find( netName );
421
422 if( incremental && !m_schematic->Connectivity().NetByName( netName ) )
423 {
424 if( existing != m_netNavigatorNodes.end() )
425 {
426 m_netNavigator->Delete( existing->second );
427 m_netNavigatorNodes.erase( existing );
428 }
429
430 continue;
431 }
432
433 wxString displayName = UnescapeString( netName );
434
435 // Apply filter based on mode
436 if( !filter.IsEmpty() )
437 {
438 bool matches = false;
439
440 if( useWildcard && !globFilter.IsEmpty() )
441 {
442 // Use glob-based matching (supports * and ? wildcards), case-insensitive
443 matches = WildCompareString( globFilter, displayName, false );
444 }
445 else if( !useWildcard && regexFilter )
446 {
447 // Use regex matching
448 try
449 {
450 matches = std::regex_search( displayName.ToStdString(), *regexFilter );
451 }
452 catch( const std::regex_error& )
453 {
454 matches = false;
455 }
456 }
457
458 if( !matches )
459 continue;
460 }
461
462 nodeCnt++;
463
464 if( existing != m_netNavigatorNodes.end() )
465 {
466 rebuildNode( netName, existing->second );
467 }
468 else
469 {
470 wxTreeItemId netId = m_netNavigator->AppendItem( rootId, displayName, -1, -1 );
471 m_netNavigatorNodes.emplace( netName, netId );
472 MakeNetNavigatorNode( netName, netId, incremental ? nullptr : aSelection, query );
473 sortRoot |= incremental;
474 }
475 }
476
477 if( sortRoot )
478 m_netNavigator->SortChildren( rootId );
479
480 if( !incremental )
481 m_netNavigator->Expand( rootId );
482 }
483 else
484 {
485 if( !incremental )
486 {
487 wxTreeItemId rootId = m_netNavigator->AddRoot( UnescapeString( m_highlightedConn ) );
488 m_netNavigatorNodes.emplace( m_highlightedConn, rootId );
489 MakeNetNavigatorNode( m_highlightedConn, rootId, aSelection, query );
490 nodeCnt++;
491 }
492 else if( std::ranges::find( *aChangedNets, m_highlightedConn ) != aChangedNets->end() )
493 {
494 rebuildNode( m_highlightedConn, m_netNavigator->GetRootItem() );
495 nodeCnt++;
496 }
497 }
498
499 timer.Stop();
500
501 wxLogTrace( traceUiProfile, wxS( "Adding %zu nodes to net navigator took %s." ),
502 nodeCnt, timer.to_string() );
503}
504
505
507{
508 wxCHECK( m_netNavigator, nullptr );
509
510 wxTreeItemId id = m_netNavigator->GetSelection();
511
512 if( !id.IsOk() )
513 return nullptr;
514
515 wxTreeItemId nextId;
516 wxTreeItemId netNode = m_netNavigator->GetRootItem();
517
518 std::vector<wxTreeItemId> netItems;
519 std::list<wxTreeItemId> itemList;
520 itemList.push_back( netNode );
521
522 while( !itemList.empty() )
523 {
524 wxTreeItemId current = itemList.front();
525 itemList.pop_front();
526
527 wxTreeItemIdValue cookie;
528 wxTreeItemId child = m_netNavigator->GetFirstChild( current, cookie );
529
530 while( child.IsOk() )
531 {
532 if( m_netNavigator->ItemHasChildren( child ) )
533 itemList.push_back( child );
534 else
535 netItems.push_back( child );
536
537 child = m_netNavigator->GetNextSibling( child );
538 }
539 }
540
541 // Locate current item and move forward or backward with wrap
542 auto it = std::find( netItems.begin(), netItems.end(), id );
543
544 if( it != netItems.end() )
545 {
546 if( aNext )
547 {
548 ++it;
549 if( it == netItems.end() )
550 it = netItems.begin();
551 }
552 else
553 {
554 if( it == netItems.begin() )
555 it = netItems.end();
556 --it;
557 }
558 nextId = *it;
559 }
560
561 if( nextId.IsOk() )
562 {
563 if( !m_netNavigator->IsVisible( nextId ) )
564 {
565 m_netNavigator->CollapseAll();
566 m_netNavigator->EnsureVisible( nextId );
567 }
568
569 m_netNavigator->UnselectAll();
570 m_netNavigator->SelectItem( nextId );
571
572 auto* data = static_cast<NET_NAVIGATOR_ITEM_DATA*>( m_netNavigator->GetItemData( nextId ) );
573
574 if( data && data->GetItem() )
575 return data->GetItem();
576 }
577
578 return nullptr;
579}
580
581
583{
584 wxCHECK( m_netNavigator, /* void */ );
585 wxCHECK( !m_netNavigator->IsFrozen(), /* void */ );
586
587 // Maybe in the future we can do something like collapse the tree for an empty selection.
588 // For now, leave the tree selection in its current state.
589 if( !aSelection )
590 return;
591
592 wxTreeItemId rootId = m_netNavigator->GetRootItem();
593
594 if( !rootId.IsOk() )
595 return;
596
597 wxTreeItemIdValue sheetCookie;
598 NET_NAVIGATOR_ITEM_DATA* itemData = nullptr;
599 wxTreeItemId sheetId = m_netNavigator->GetFirstChild( rootId, sheetCookie );
600
601 while( sheetId.IsOk() )
602 {
603 if( m_netNavigator->ItemHasChildren( sheetId ) )
604 {
605 wxTreeItemIdValue itemCookie;
606 wxTreeItemId itemId = m_netNavigator->GetFirstChild( sheetId, itemCookie );
607
608 while( itemId.IsOk() )
609 {
610 itemData = dynamic_cast<NET_NAVIGATOR_ITEM_DATA*>( m_netNavigator->GetItemData( itemId ) );
611
612 wxCHECK2( itemData, continue );
613
614 if( *itemData == *aSelection )
615 {
616 if( !m_netNavigator->IsVisible( itemId ) )
617 {
618 m_netNavigator->CollapseAll();
619 m_netNavigator->EnsureVisible( itemId );
620 }
621
622 m_netNavigator->SelectItem( itemId );
623 return;
624 }
625
626 itemId = m_netNavigator->GetNextSibling( itemId );
627 }
628
629 sheetId = m_netNavigator->GetNextSibling( sheetId );
630 }
631 }
632}
633
634
636{
637 if( !m_netNavigator || m_netNavigator->IsFrozen() )
638 return nullptr;
639
640 wxTreeItemId id = m_netNavigator->GetSelection();
641
642 if( !id.IsOk() || ( id == m_netNavigator->GetRootItem() ) )
643 return nullptr;
644
645 auto* itemData = dynamic_cast<NET_NAVIGATOR_ITEM_DATA*>( m_netNavigator->GetItemData( id ) );
646
647 wxCHECK( itemData, nullptr );
648
649 return itemData->GetItem();
650}
651
652
653void SCH_EDIT_FRAME::onNetNavigatorDPIChanged( wxDPIChangedEvent& aEvent )
654{
655 aEvent.Skip();
656
657 // wxMSW rescales the control font without the virtual SetFont() that would recompute the
658 // generic tree's row height, and the per-item text extents only rebuild with the items
659 CallAfter(
660 [this]
661 {
662 wxCHECK( m_netNavigator, /* void */ );
663
664 NET_NAVIGATOR_ITEM_DATA selection;
665 NET_NAVIGATOR_ITEM_DATA* selected = nullptr;
666 wxTreeItemId id = m_netNavigator->GetSelection();
667
668 // RefreshNetNavigator() only carries the selection across a rebuild by itself
669 // while a connection is highlighted
670 if( id.IsOk() )
671 {
672 if( auto* data = dynamic_cast<NET_NAVIGATOR_ITEM_DATA*>( m_netNavigator->GetItemData( id ) ) )
673 {
674 selection = *data;
675 selected = &selection;
676 }
677 }
678
679 m_netNavigator->RecalculateRowHeight();
680 m_netNavigatorStale = true;
681 RefreshNetNavigator( selected );
682 } );
683}
684
685
687{
688 if( !m_netNavigator || m_netNavigator->IsFrozen() )
689 return;
690
691 wxTreeItemId id = aEvent.GetItem();
692
693 // Clicking on the root item (net name ) does nothing.
694 if( id == m_netNavigator->GetRootItem() )
695 return;
696
697 auto* itemData = dynamic_cast<NET_NAVIGATOR_ITEM_DATA*>( m_netNavigator->GetItemData( id ) );
698
699 // Just a net name when we have all nets displayed.
700 if( !itemData )
701 return;
702
703 if( GetCurrentSheet() != itemData->GetSheetPath() )
704 GetToolManager()->RunAction<SCH_SHEET_PATH*>( SCH_ACTIONS::changeSheet, &itemData->GetSheetPath() );
705
706 // Do not focus on item when a sheet tree node is selected.
707 if( m_netNavigator->GetItemParent( id ) != m_netNavigator->GetRootItem() && itemData->GetItem() )
708 {
709 // Make sure we didn't remove the item and/or the screen it resides on before we access it.
710 const SCH_ITEM* item = itemData->GetItem();
711
712 // Don't search for child items in screen r-tree.
713 item = ( item->Type() == SCH_SHEET_PIN_T || item->Type() == SCH_PIN_T )
714 ? static_cast<const SCH_ITEM*>( item->GetParent() )
715 : item;
716
717 const SCH_SCREEN* screen = itemData->GetSheetPath().LastScreen();
718
719 wxCHECK( screen, /* void */ );
720 wxCHECK( screen->Items().contains( item, true ), /* void */ );
721
722 FocusOnLocation( itemData->GetItem()->GetBoundingBox().Centre() );
723 }
724
725 GetCanvas()->Refresh();
726}
727
728
730{
731 if( !m_netNavigator || m_netNavigator->IsFrozen() )
732 return;
733
734 aEvent.Skip();
735}
736
737
739{
741
742 wxCHECK( cfg, /* void */ );
743
744 wxAuiPaneInfo& netNavigatorPane = m_auimgr.GetPane( NetNavigatorPaneName() );
745
746 netNavigatorPane.Show( !netNavigatorPane.IsShown() );
748
749 cfg->m_AuiPanels.show_net_nav_panel = netNavigatorPane.IsShown();
750
751 if( netNavigatorPane.IsShown() )
752 {
753 if( netNavigatorPane.IsFloating() )
754 {
755 netNavigatorPane.FloatingSize( cfg->m_AuiPanels.net_nav_panel_float_size );
756 m_auimgr.Update();
757 }
758 else if( cfg->m_AuiPanels.net_nav_panel_docked_size.GetWidth() > 0 )
759 {
760 // SetAuiPaneSize also updates m_auimgr
761 SetAuiPaneSize( m_auimgr, netNavigatorPane,
762 cfg->m_AuiPanels.net_nav_panel_docked_size.GetWidth(), -1 );
763 }
764 }
765 else
766 {
767 if( netNavigatorPane.IsFloating() )
768 {
769 cfg->m_AuiPanels.net_nav_panel_float_size = netNavigatorPane.floating_size;
770 }
771 else
772 {
774 }
775
776 m_auimgr.Update();
777 }
778
779 if( netNavigatorPane.IsShown() )
780 {
781 NET_NAVIGATOR_ITEM_DATA* itemData = nullptr;
782
783 wxTreeItemId selection = m_netNavigator->GetSelection();
784
785 if( selection.IsOk() )
786 itemData = dynamic_cast<NET_NAVIGATOR_ITEM_DATA*>( m_netNavigator->GetItemData( selection ) );
787
788 RefreshNetNavigator( itemData );
789 }
790}
791
792
793void SCH_EDIT_FRAME::FindNetInInspector( const wxString& aNetName )
794{
795 if( !m_netNavigator || aNetName.IsEmpty() )
796 return;
797
798 // Ensure the net navigator is shown
799 wxAuiPaneInfo& netNavigatorPane = m_auimgr.GetPane( NetNavigatorPaneName() );
800
801 if( !netNavigatorPane.IsShown() )
803
804 // Clear any net highlights
805 SetHighlightedConnection( wxEmptyString );
807
808 // Set the search text to the aNetName
810 m_netNavigatorFilter->SetValue( aNetName );
811
812 m_netNavigatorFilterValue = aNetName;
813
814 // Refresh the tree
816}
817
818
819void SCH_EDIT_FRAME::onResizeNetNavigator( wxSizeEvent& aEvent )
820{
821 aEvent.Skip();
822
823 // Called when resizing the Hierarchy Navigator panel
824 // Store the current pane size
825 // It allows to retrieve the last defined pane size when switching between
826 // docked and floating pane state
827 // Note: *DO NOT* call m_auimgr.Update() here: it crashes KiCad at least on Windows
828
829 EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
830
831 // During deletion/cleanup operations, settings may be temporarily unavailable
832 if( !cfg )
833 return;
834
835 wxAuiPaneInfo& netNavigatorPane = m_auimgr.GetPane( NetNavigatorPaneName() );
836
837 if( m_netNavigator->IsShownOnScreen() )
838 {
839 cfg->m_AuiPanels.net_nav_panel_float_size = netNavigatorPane.floating_size;
840
841 // initialize net_nav_panel_docked_width and best size only if the netNavigatorPane
842 // width is > 0 (i.e. if its size is already set and has meaning)
843 // if it is floating, its size is not initialized (only floating_size is initialized)
844 // initializing netNavigatorPane.best_size is useful when switching to float pane and
845 // after switching to the docked pane, to retrieve the last docked pane width
846 if( netNavigatorPane.rect.width > 50 ) // 50 is a good margin
847 {
848 cfg->m_AuiPanels.net_nav_panel_docked_size.SetWidth( netNavigatorPane.rect.width );
849 netNavigatorPane.best_size.x = netNavigatorPane.rect.width;
850 }
851 }
852}
const char * name
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
wxAuiManager m_auimgr
void FocusOnLocation(const VECTOR2I &aPos, bool aAllowScroll=true)
Useful to focus on a particular location, in find functions.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
EDA_ITEM * GetParent() const
Definition eda_item.h:112
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:118
bool contains(const SCH_ITEM *aItem, bool aRobust=false) const
Determine if a given item exists in the tree.
Definition sch_rtree.h:140
APP_SETTINGS_BASE * KifaceSettings() const
Definition kiface_base.h:92
Tree view item data for the net navigator.
const SCH_ITEM * GetItem() const
A small class to help profiling.
Definition profile.h:46
void Stop()
Save the time when this function was called, and set the counter stane to stop.
Definition profile.h:86
std::string to_string()
Definition profile.h:154
static TOOL_ACTION changeSheet
static TOOL_ACTION updateNetHighlighting
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.
One UI operation's hierarchy index.
NET_ITEMS_BY_SHEET NetItems(const wxString &aName, bool aIncludeBusParents, bool aIncludeBusMembers=false) const
std::vector< wxString > NetNames() const
wxString m_netNavigatorConnection
void onResizeNetNavigator(wxSizeEvent &aEvent)
void updateSelectionFilterVisbility() override
Selection filter panel doesn't have a dedicated visibility control, so show it if any other AUI panel...
void onNetNavigatorSelChanging(wxTreeEvent &aEvent)
NET_NAVIGATOR_TREE * m_netNavigator
void MakeNetNavigatorNode(const wxString &aNetName, wxTreeItemId aParentId, const NET_NAVIGATOR_ITEM_DATA *aSelection, const SCH_CONNECTIVITY::NAVIGATION_QUERY &aQuery)
void RefreshNetNavigator(const NET_NAVIGATOR_ITEM_DATA *aSelection=nullptr, const std::vector< wxString > *aChangedNets=nullptr)
SCHEMATIC * m_schematic
The currently loaded schematic.
SCH_SHEET_PATH & GetCurrentSheet() const
wxString m_netNavigatorFilterValue
const SCH_ITEM * GetSelectedNetNavigatorItem() const
wxSearchCtrl * m_netNavigatorFilter
std::map< wxString, wxTreeItemId > m_netNavigatorNodes
const SCH_ITEM * SelectNextPrevNetNavigatorItem(bool aNext)
void SetHighlightedConnection(const wxString &aConnection, const NET_NAVIGATOR_ITEM_DATA *aSelection=nullptr, bool aForceNetNavigatorRefresh=false)
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 onNetNavigatorDPIChanged(wxDPIChangedEvent &aEvent)
void onNetNavigatorSelection(wxTreeEvent &aEvent)
void FindNetInInspector(const wxString &aNetName)
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:170
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition sch_item.h:353
VECTOR2I GetPosition() const override
Segment description base class to describe items which have 2 end points (track, wire,...
Definition sch_line.h:39
VECTOR2I GetEndPoint() const
Definition sch_line.h:145
VECTOR2I GetStartPoint() const
Definition sch_line.h:136
VECTOR2I GetPosition() const override
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:122
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
VECTOR2I GetPosition() const override
Definition sch_text.h:143
A base class for LIB_SYMBOL and SCH_SYMBOL.
Definition symbol.h:60
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
@ FOR_GUI
Definition common.h:91
This file is part of the common library.
#define _(s)
bool m_ConnectivityEngine
Use the schematic connectivity engine instead of CONNECTION_GRAPH.
const wxChar *const traceUiProfile
Flag to enable user interface profile tracing.
@ LAYER_WIRE
Definition layer_ids.h:474
@ LAYER_BUS
Definition layer_ids.h:475
static wxString GetNetNavigatorItemText(const SCH_ITEM *aItem, const SCH_SHEET_PATH &aSheetPath, UNITS_PROVIDER *aUnitsProvider)
bool WildCompareString(const wxString &pattern, const wxString &string_to_tst, bool case_sensitive)
Compare a string against wild card (* and ?) pattern using the usual rules.
wxString UnescapeString(const wxString &aSource)
KIBIS_PIN * pin
wxLogTrace helper definitions.
@ SCH_LINE_T
Definition typeinfo.h:159
@ SCH_NO_CONNECT_T
Definition typeinfo.h:156
@ SCH_DIRECTIVE_LABEL_T
Definition typeinfo.h:167
@ SCH_LABEL_T
Definition typeinfo.h:163
@ SCH_HIER_LABEL_T
Definition typeinfo.h:165
@ SCH_BUS_BUS_ENTRY_T
Definition typeinfo.h:158
@ SCH_SHEET_PIN_T
Definition typeinfo.h:170
@ SCH_BUS_WIRE_ENTRY_T
Definition typeinfo.h:157
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:164
@ SCH_JUNCTION_T
Definition typeinfo.h:155
@ SCH_PIN_T
Definition typeinfo.h:149
Definition of file extensions used in Kicad.
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.