You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

669 lines
22 KiB

  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 <stambaughw@gmail.com>
  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. #include <wx/log.h>
  23. #include <core/profile.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_no_connect.h>
  31. #include <sch_sheet_pin.h>
  32. #include <schematic.h>
  33. #include <string_utils.h>
  34. #include <trace_helpers.h>
  35. #include <connection_graph.h>
  36. #include <widgets/wx_aui_utils.h>
  37. #include <tools/sch_actions.h>
  38. static wxString GetNetNavigatorItemText( const SCH_ITEM* aItem,
  39. const SCH_SHEET_PATH& aSheetPath,
  40. UNITS_PROVIDER* aUnitsProvider )
  41. {
  42. wxString retv;
  43. wxCHECK( aItem && aUnitsProvider, retv );
  44. switch( aItem->Type() )
  45. {
  46. case SCH_LINE_T:
  47. {
  48. const SCH_LINE* line = static_cast<const SCH_LINE*>( aItem );
  49. if( aItem->GetLayer() == LAYER_WIRE )
  50. {
  51. retv.Printf( _( "Wire from %s, %s to %s, %s" ),
  52. aUnitsProvider->MessageTextFromValue( line->GetStartPoint().x ),
  53. aUnitsProvider->MessageTextFromValue( line->GetStartPoint().y ),
  54. aUnitsProvider->MessageTextFromValue( line->GetEndPoint().x ),
  55. aUnitsProvider->MessageTextFromValue( line->GetEndPoint().y ) );
  56. }
  57. else if( aItem->GetLayer() == LAYER_BUS )
  58. {
  59. retv.Printf( _( "Bus from %s, %s to %s, %s" ),
  60. aUnitsProvider->MessageTextFromValue( line->GetStartPoint().x ),
  61. aUnitsProvider->MessageTextFromValue( line->GetStartPoint().y ),
  62. aUnitsProvider->MessageTextFromValue( line->GetEndPoint().x ),
  63. aUnitsProvider->MessageTextFromValue( line->GetEndPoint().y ) );
  64. }
  65. else
  66. {
  67. retv = _( "Graphic line not connectable" );
  68. }
  69. break;
  70. }
  71. case SCH_PIN_T:
  72. {
  73. const SCH_PIN* pin = static_cast<const SCH_PIN*>( aItem );
  74. if( const SYMBOL* symbol = pin->GetParentSymbol() )
  75. {
  76. retv.Printf( _( "Symbol '%s' pin '%s'" ),
  77. symbol->GetRef( &aSheetPath, true ),
  78. UnescapeString( pin->GetNumber() ) );
  79. if( wxString pinName = UnescapeString( pin->GetShownName() ); !pinName.IsEmpty() )
  80. {
  81. retv += wxString::Format( " (%s)", pinName );
  82. }
  83. }
  84. break;
  85. }
  86. case SCH_SHEET_PIN_T:
  87. {
  88. const SCH_SHEET_PIN* pin = static_cast<const SCH_SHEET_PIN*>( aItem );
  89. if( SCH_SHEET* sheet = pin->GetParent() )
  90. {
  91. retv.Printf( _( "Sheet '%s' pin '%s'" ),
  92. sheet->GetName(),
  93. UnescapeString( pin->GetText() ) );
  94. }
  95. break;
  96. }
  97. case SCH_LABEL_T:
  98. {
  99. const SCH_LABEL* label = static_cast<const SCH_LABEL*>( aItem );
  100. retv.Printf( _( "Label '%s' at %s, %s" ),
  101. UnescapeString( label->GetText() ),
  102. aUnitsProvider->MessageTextFromValue( label->GetPosition().x ),
  103. aUnitsProvider->MessageTextFromValue( label->GetPosition().y ) );
  104. break;
  105. }
  106. case SCH_GLOBAL_LABEL_T:
  107. {
  108. const SCH_GLOBALLABEL* label = static_cast<const SCH_GLOBALLABEL*>( aItem );
  109. retv.Printf( _( "Global label '%s' at %s, %s" ),
  110. UnescapeString( label->GetText() ),
  111. aUnitsProvider->MessageTextFromValue( label->GetPosition().x ),
  112. aUnitsProvider->MessageTextFromValue( label->GetPosition().y ) );
  113. break;
  114. }
  115. case SCH_HIER_LABEL_T:
  116. {
  117. const SCH_HIERLABEL* label = static_cast<const SCH_HIERLABEL*>( aItem );
  118. retv.Printf( _( "Hierarchical label '%s' at %s, %s" ),
  119. UnescapeString( label->GetText() ),
  120. aUnitsProvider->MessageTextFromValue( label->GetPosition().x ),
  121. aUnitsProvider->MessageTextFromValue( label->GetPosition().y ) );
  122. break;
  123. }
  124. case SCH_JUNCTION_T:
  125. {
  126. const SCH_JUNCTION* junction = static_cast<const SCH_JUNCTION*>( aItem );
  127. retv.Printf( _( "Junction at %s, %s" ),
  128. aUnitsProvider->MessageTextFromValue( junction->GetPosition().x ),
  129. aUnitsProvider->MessageTextFromValue( junction->GetPosition().y ) );
  130. break;
  131. }
  132. case SCH_NO_CONNECT_T:
  133. {
  134. const SCH_NO_CONNECT* nc = static_cast<const SCH_NO_CONNECT*>( aItem );
  135. retv.Printf( _( "No-Connect at %s, %s" ),
  136. aUnitsProvider->MessageTextFromValue( nc->GetPosition().x ),
  137. aUnitsProvider->MessageTextFromValue( nc->GetPosition().y ) );
  138. break;
  139. }
  140. case SCH_BUS_WIRE_ENTRY_T:
  141. {
  142. const SCH_BUS_WIRE_ENTRY* entry = static_cast<const SCH_BUS_WIRE_ENTRY*>( aItem );
  143. retv.Printf( _( "Bus to wire entry from %s, %s to %s, %s" ),
  144. aUnitsProvider->MessageTextFromValue( entry->GetPosition().x ),
  145. aUnitsProvider->MessageTextFromValue( entry->GetPosition().y ),
  146. aUnitsProvider->MessageTextFromValue( entry->GetEnd().x ),
  147. aUnitsProvider->MessageTextFromValue( entry->GetEnd().y ) );
  148. break;
  149. }
  150. case SCH_BUS_BUS_ENTRY_T:
  151. {
  152. const SCH_BUS_BUS_ENTRY* entry = static_cast<const SCH_BUS_BUS_ENTRY*>( aItem );
  153. retv.Printf( _( "Bus to bus entry from %s, %s to %s, %s" ),
  154. aUnitsProvider->MessageTextFromValue( entry->GetPosition().x ),
  155. aUnitsProvider->MessageTextFromValue( entry->GetPosition().y ),
  156. aUnitsProvider->MessageTextFromValue( entry->GetEnd().x ),
  157. aUnitsProvider->MessageTextFromValue( entry->GetEnd().y ) );
  158. break;
  159. }
  160. case SCH_DIRECTIVE_LABEL_T:
  161. {
  162. const SCH_DIRECTIVE_LABEL* entry = static_cast<const SCH_DIRECTIVE_LABEL*>( aItem );
  163. retv.Printf( _( "Netclass label '%s' at %s, %s" ),
  164. UnescapeString( entry->GetText() ),
  165. aUnitsProvider->MessageTextFromValue( entry->GetPosition().x ),
  166. aUnitsProvider->MessageTextFromValue( entry->GetPosition().y ) );
  167. break;
  168. }
  169. default:
  170. retv.Printf( _( "Unhandled item type %d" ), aItem->Type() );
  171. }
  172. return retv;
  173. }
  174. void SCH_EDIT_FRAME::MakeNetNavigatorNode( const wxString& aNetName, wxTreeItemId aParentId,
  175. const NET_NAVIGATOR_ITEM_DATA* aSelection,
  176. bool aSingleSheetSchematic )
  177. {
  178. wxCHECK( !aNetName.IsEmpty(), /* void */ );
  179. wxCHECK( m_schematic, /* void */ );
  180. wxCHECK( m_netNavigator, /* void */ );
  181. wxTreeItemId expandId = aParentId;
  182. CONNECTION_GRAPH* connectionGraph = m_schematic->ConnectionGraph();
  183. wxCHECK( connectionGraph, /* void */ );
  184. std::set<CONNECTION_SUBGRAPH*> subgraphs;
  185. {
  186. const std::vector<CONNECTION_SUBGRAPH*>& tmp = connectionGraph->GetAllSubgraphs( aNetName );
  187. subgraphs.insert( tmp.begin(), tmp.end() );
  188. }
  189. for( CONNECTION_SUBGRAPH* sg : subgraphs )
  190. {
  191. for( const auto& [_, bus_sgs] : sg->GetBusParents() )
  192. {
  193. for( const CONNECTION_SUBGRAPH* bus_sg : bus_sgs )
  194. {
  195. const std::vector<CONNECTION_SUBGRAPH*>& tmp =
  196. connectionGraph->GetAllSubgraphs( bus_sg->GetNetName() );
  197. subgraphs.insert( tmp.begin(), tmp.end() );
  198. }
  199. }
  200. }
  201. std::map<wxString, wxTreeItemId> sheetIds;
  202. for( const CONNECTION_SUBGRAPH* subGraph : subgraphs )
  203. {
  204. NET_NAVIGATOR_ITEM_DATA* itemData = nullptr;
  205. SCH_SHEET_PATH sheetPath = subGraph->GetSheet();
  206. wxCHECK2( subGraph && sheetPath.Last(), continue );
  207. if( subGraph->GetItems().empty() )
  208. continue;
  209. itemData = new NET_NAVIGATOR_ITEM_DATA( sheetPath, nullptr );
  210. bool stripTrailingSeparator = !sheetPath.Last()->IsRootSheet();
  211. wxString txt = sheetPath.PathHumanReadable( true, stripTrailingSeparator );
  212. wxTreeItemId sheetId;
  213. if( auto sheetIdIt = sheetIds.find( txt ); sheetIdIt != sheetIds.end() )
  214. {
  215. sheetId = sheetIdIt->second;
  216. }
  217. else
  218. {
  219. sheetIds[txt] = m_netNavigator->AppendItem( aParentId, txt, -1, -1, itemData );
  220. sheetId = sheetIds[txt];
  221. }
  222. if( aSelection && *aSelection == *itemData )
  223. m_netNavigator->SelectItem( sheetId );
  224. // If there is only one sheet in the schematic, always expand the sheet tree.
  225. if( aSingleSheetSchematic )
  226. expandId = sheetId;
  227. for( const SCH_ITEM* item : subGraph->GetItems() )
  228. {
  229. if( item->Type() == SCH_LINE_T
  230. || item->Type() == SCH_JUNCTION_T
  231. || item->Type() == SCH_BUS_WIRE_ENTRY_T
  232. || item->Type() == SCH_BUS_BUS_ENTRY_T )
  233. {
  234. continue;
  235. }
  236. itemData = new NET_NAVIGATOR_ITEM_DATA( sheetPath, item );
  237. wxTreeItemId id = m_netNavigator->AppendItem( sheetId,
  238. GetNetNavigatorItemText( item, sheetPath, this ),
  239. -1, -1, itemData );
  240. if( aSelection && *aSelection == *itemData )
  241. {
  242. expandId = sheetId;
  243. m_netNavigator->EnsureVisible( id );
  244. m_netNavigator->SelectItem( id );
  245. }
  246. }
  247. m_netNavigator->SortChildren( sheetId );
  248. }
  249. // Sort the items in the tree control alphabetically
  250. m_netNavigator->SortChildren( aParentId );
  251. m_netNavigator->Expand( aParentId );
  252. }
  253. void SCH_EDIT_FRAME::RefreshNetNavigator( const NET_NAVIGATOR_ITEM_DATA* aSelection )
  254. {
  255. wxCHECK( m_netNavigator, /* void */ );
  256. if( !m_netNavigator->IsShown() )
  257. return;
  258. bool singleSheetSchematic = m_schematic->Hierarchy().size() == 1;
  259. size_t nodeCnt = 0;
  260. m_netNavigator->Freeze();
  261. PROF_TIMER timer;
  262. if( m_highlightedConn.IsEmpty() )
  263. {
  264. m_netNavigator->DeleteAllItems();
  265. // Create a tree of all nets in the schematic.
  266. wxTreeItemId rootId = m_netNavigator->AddRoot( _( "Nets" ), 0 );
  267. const NET_MAP& netMap = m_schematic->ConnectionGraph()->GetNetMap();
  268. for( const auto& net : netMap )
  269. {
  270. // Skip bus member subgraphs for the moment.
  271. if( net.first.Name.IsEmpty() )
  272. continue;
  273. nodeCnt++;
  274. wxTreeItemId netId = m_netNavigator->AppendItem( rootId,
  275. UnescapeString( net.first.Name ) );
  276. MakeNetNavigatorNode( net.first.Name, netId, aSelection, singleSheetSchematic );
  277. }
  278. m_netNavigator->Expand( rootId );
  279. }
  280. else if( !m_netNavigator->IsEmpty() )
  281. {
  282. const wxString shownNetName = m_netNavigator->GetItemText( m_netNavigator->GetRootItem() );
  283. if( shownNetName != m_highlightedConn )
  284. {
  285. m_netNavigator->DeleteAllItems();
  286. nodeCnt++;
  287. wxTreeItemId rootId = m_netNavigator->AddRoot( UnescapeString( m_highlightedConn ), 0 );
  288. MakeNetNavigatorNode( m_highlightedConn, rootId, aSelection, singleSheetSchematic );
  289. }
  290. else
  291. {
  292. NET_NAVIGATOR_ITEM_DATA* itemData = nullptr;
  293. wxTreeItemId selection = m_netNavigator->GetSelection();
  294. if( selection.IsOk() )
  295. itemData = dynamic_cast<NET_NAVIGATOR_ITEM_DATA*>( m_netNavigator->GetItemData( selection ) );
  296. m_netNavigator->DeleteAllItems();
  297. nodeCnt++;
  298. wxTreeItemId rootId = m_netNavigator->AddRoot( UnescapeString( m_highlightedConn ), 0 );
  299. MakeNetNavigatorNode( m_highlightedConn, rootId, itemData, singleSheetSchematic );
  300. }
  301. }
  302. else
  303. {
  304. nodeCnt++;
  305. wxTreeItemId rootId = m_netNavigator->AddRoot( UnescapeString( m_highlightedConn ), 0 );
  306. MakeNetNavigatorNode( m_highlightedConn, rootId, aSelection, singleSheetSchematic );
  307. }
  308. timer.Stop();
  309. wxLogTrace( traceUiProfile, wxS( "Adding %zu nodes to net navigator took %s." ),
  310. nodeCnt, timer.to_string() );
  311. m_netNavigator->Thaw();
  312. }
  313. const SCH_ITEM* SCH_EDIT_FRAME::SelectNextPrevNetNavigatorItem( bool aNext )
  314. {
  315. wxCHECK( m_netNavigator, nullptr );
  316. wxTreeItemId id = m_netNavigator->GetSelection();
  317. if( !id.IsOk() )
  318. return nullptr;
  319. wxTreeItemId nextId;
  320. wxTreeItemId netNode = m_netNavigator->GetRootItem();
  321. std::vector<wxTreeItemId> netItems;
  322. std::list<wxTreeItemId> itemList;
  323. itemList.push_back( netNode );
  324. while( !itemList.empty() )
  325. {
  326. wxTreeItemId current = itemList.front();
  327. itemList.pop_front();
  328. wxTreeItemIdValue cookie;
  329. wxTreeItemId child = m_netNavigator->GetFirstChild( current, cookie );
  330. while( child.IsOk() )
  331. {
  332. if( m_netNavigator->ItemHasChildren( child ) )
  333. itemList.push_back( child );
  334. else
  335. netItems.push_back( child );
  336. child = m_netNavigator->GetNextSibling( child );
  337. }
  338. }
  339. // Locate current item and move forward or backward with wrap
  340. auto it = std::find( netItems.begin(), netItems.end(), id );
  341. if( it != netItems.end() )
  342. {
  343. if( aNext )
  344. {
  345. ++it;
  346. if( it == netItems.end() )
  347. it = netItems.begin();
  348. }
  349. else
  350. {
  351. if( it == netItems.begin() )
  352. it = netItems.end();
  353. --it;
  354. }
  355. nextId = *it;
  356. }
  357. if( nextId.IsOk() )
  358. {
  359. if( !m_netNavigator->IsVisible( nextId ) )
  360. {
  361. m_netNavigator->CollapseAll();
  362. m_netNavigator->EnsureVisible( nextId );
  363. }
  364. m_netNavigator->UnselectAll();
  365. m_netNavigator->SelectItem( nextId );
  366. auto* data = static_cast<NET_NAVIGATOR_ITEM_DATA*>( m_netNavigator->GetItemData( nextId ) );
  367. if( data && data->GetItem() )
  368. return data->GetItem();
  369. }
  370. return nullptr;
  371. }
  372. void SCH_EDIT_FRAME::SelectNetNavigatorItem( const NET_NAVIGATOR_ITEM_DATA* aSelection )
  373. {
  374. wxCHECK( m_netNavigator, /* void */ );
  375. wxCHECK( !m_netNavigator->IsFrozen(), /* void */ );
  376. // Maybe in the future we can do something like collapse the tree for an empty selection.
  377. // For now, leave the tree selection in its current state.
  378. if( !aSelection )
  379. return;
  380. wxTreeItemId rootId = m_netNavigator->GetRootItem();
  381. if( !rootId.IsOk() )
  382. return;
  383. wxTreeItemIdValue sheetCookie;
  384. NET_NAVIGATOR_ITEM_DATA* itemData = nullptr;
  385. wxTreeItemId sheetId = m_netNavigator->GetFirstChild( rootId, sheetCookie );
  386. while( sheetId.IsOk() )
  387. {
  388. if( m_netNavigator->ItemHasChildren( sheetId ) )
  389. {
  390. wxTreeItemIdValue itemCookie;
  391. wxTreeItemId itemId = m_netNavigator->GetFirstChild( sheetId, itemCookie );
  392. while( itemId.IsOk() )
  393. {
  394. itemData = dynamic_cast<NET_NAVIGATOR_ITEM_DATA*>( m_netNavigator->GetItemData( itemId ) );
  395. wxCHECK2( itemData, continue );
  396. if( *itemData == *aSelection )
  397. {
  398. if( !m_netNavigator->IsVisible( itemId ) )
  399. {
  400. m_netNavigator->CollapseAll();
  401. m_netNavigator->EnsureVisible( itemId );
  402. }
  403. m_netNavigator->SelectItem( itemId );
  404. return;
  405. }
  406. itemId = m_netNavigator->GetNextSibling( itemId );
  407. }
  408. sheetId = m_netNavigator->GetNextSibling( sheetId );
  409. }
  410. }
  411. }
  412. const SCH_ITEM* SCH_EDIT_FRAME::GetSelectedNetNavigatorItem() const
  413. {
  414. if( !m_netNavigator || m_netNavigator->IsFrozen() )
  415. return nullptr;
  416. wxTreeItemId id = m_netNavigator->GetSelection();
  417. if( !id.IsOk() || ( id == m_netNavigator->GetRootItem() ) )
  418. return nullptr;
  419. auto* itemData = dynamic_cast<NET_NAVIGATOR_ITEM_DATA*>( m_netNavigator->GetItemData( id ) );
  420. wxCHECK( itemData, nullptr );
  421. return itemData->GetItem();
  422. }
  423. void SCH_EDIT_FRAME::onNetNavigatorSelection( wxTreeEvent& aEvent )
  424. {
  425. wxCHECK( m_netNavigator, /* void */ );
  426. wxCHECK( !m_netNavigator->IsFrozen(), /* void */ );
  427. wxTreeItemId id = aEvent.GetItem();
  428. // Clicking on the root item (net name ) does nothing.
  429. if( id == m_netNavigator->GetRootItem() )
  430. return;
  431. auto* itemData = dynamic_cast<NET_NAVIGATOR_ITEM_DATA*>( m_netNavigator->GetItemData( id ) );
  432. // Just a net name when we have all nets displayed.
  433. if( !itemData )
  434. return;
  435. if( GetCurrentSheet() != itemData->GetSheetPath() )
  436. GetToolManager()->RunAction<SCH_SHEET_PATH*>( SCH_ACTIONS::changeSheet, &itemData->GetSheetPath() );
  437. // Do not focus on item when a sheet tree node is selected.
  438. if( m_netNavigator->GetItemParent( id ) != m_netNavigator->GetRootItem() && itemData->GetItem() )
  439. {
  440. // Make sure we didn't remove the item and/or the screen it resides on before we access it.
  441. const SCH_ITEM* item = itemData->GetItem();
  442. // Don't search for child items in screen r-tree.
  443. item = ( item->Type() == SCH_SHEET_PIN_T || item->Type() == SCH_PIN_T )
  444. ? static_cast<const SCH_ITEM*>( item->GetParent() )
  445. : item;
  446. const SCH_SCREEN* screen = itemData->GetSheetPath().LastScreen();
  447. wxCHECK( screen, /* void */ );
  448. wxCHECK( screen->Items().contains( item, true ), /* void */ );
  449. FocusOnLocation( itemData->GetItem()->GetBoundingBox().Centre() );
  450. }
  451. GetCanvas()->Refresh();
  452. }
  453. void SCH_EDIT_FRAME::onNetNavigatorSelChanging( wxTreeEvent& aEvent )
  454. {
  455. wxCHECK( m_netNavigator, /* void */ );
  456. wxCHECK( !m_netNavigator->IsFrozen(), /* void */ );
  457. aEvent.Skip();
  458. }
  459. void SCH_EDIT_FRAME::ToggleNetNavigator()
  460. {
  461. EESCHEMA_SETTINGS* cfg = eeconfig();
  462. wxCHECK( cfg, /* void */ );
  463. wxAuiPaneInfo& netNavigatorPane = m_auimgr.GetPane( NetNavigatorPaneName() );
  464. netNavigatorPane.Show( !netNavigatorPane.IsShown() );
  465. updateSelectionFilterVisbility();
  466. cfg->m_AuiPanels.show_net_nav_panel = netNavigatorPane.IsShown();
  467. if( netNavigatorPane.IsShown() )
  468. {
  469. if( netNavigatorPane.IsFloating() )
  470. {
  471. netNavigatorPane.FloatingSize( cfg->m_AuiPanels.net_nav_panel_float_size );
  472. m_auimgr.Update();
  473. }
  474. else if( cfg->m_AuiPanels.net_nav_panel_docked_size.GetWidth() > 0 )
  475. {
  476. // SetAuiPaneSize also updates m_auimgr
  477. SetAuiPaneSize( m_auimgr, netNavigatorPane,
  478. cfg->m_AuiPanels.net_nav_panel_docked_size.GetWidth(), -1 );
  479. }
  480. }
  481. else
  482. {
  483. if( netNavigatorPane.IsFloating() )
  484. {
  485. cfg->m_AuiPanels.net_nav_panel_float_size = netNavigatorPane.floating_size;
  486. }
  487. else
  488. {
  489. cfg->m_AuiPanels.net_nav_panel_docked_size = m_netNavigator->GetSize();
  490. }
  491. m_auimgr.Update();
  492. }
  493. if( netNavigatorPane.IsShown() )
  494. {
  495. NET_NAVIGATOR_ITEM_DATA* itemData = nullptr;
  496. wxTreeItemId selection = m_netNavigator->GetSelection();
  497. if( selection.IsOk() )
  498. itemData = dynamic_cast<NET_NAVIGATOR_ITEM_DATA*>( m_netNavigator->GetItemData( selection ) );
  499. RefreshNetNavigator( itemData );
  500. }
  501. }
  502. void SCH_EDIT_FRAME::onResizeNetNavigator( wxSizeEvent& aEvent )
  503. {
  504. aEvent.Skip();
  505. // Called when resizing the Hierarchy Navigator panel
  506. // Store the current pane size
  507. // It allows to retrieve the last defined pane size when switching between
  508. // docked and floating pane state
  509. // Note: *DO NOT* call m_auimgr.Update() here: it crashes KiCad at least on Windows
  510. EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
  511. wxCHECK( cfg, /* void */ );
  512. wxAuiPaneInfo& netNavigatorPane = m_auimgr.GetPane( NetNavigatorPaneName() );
  513. if( m_netNavigator->IsShownOnScreen() )
  514. {
  515. cfg->m_AuiPanels.net_nav_panel_float_size = netNavigatorPane.floating_size;
  516. // initialize net_nav_panel_docked_width and best size only if the netNavigatorPane
  517. // width is > 0 (i.e. if its size is already set and has meaning)
  518. // if it is floating, its size is not initialized (only floating_size is initialized)
  519. // initializing netNavigatorPane.best_size is useful when switching to float pane and
  520. // after switching to the docked pane, to retrieve the last docked pane width
  521. if( netNavigatorPane.rect.width > 50 ) // 50 is a good margin
  522. {
  523. cfg->m_AuiPanels.net_nav_panel_docked_size.SetWidth( netNavigatorPane.rect.width );
  524. netNavigatorPane.best_size.x = netNavigatorPane.rect.width;
  525. }
  526. }
  527. }