KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_base_frame.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) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <algorithm>
22#include <advanced_config.h>
23#include <base_units.h>
24#include <kiplatform/io.h>
27#include <kiway.h>
29#include <pgm_base.h>
30#include <eda_list_dialog.h>
33#include <eeschema_settings.h>
37#include <sch_draw_panel.h>
39#include <sch_group.h>
40#include <sch_view.h>
41#include <sch_painter.h>
42#include <sch_shape.h>
45#include <widgets/wx_infobar.h>
46#include <string_utils.h>
47#include <confirm.h>
49#include <project_sch.h>
52#include <sch_base_frame.h>
54#include <design_block.h>
55#include <thread_pool.h>
56#include <tool/actions.h>
57#include <tool/action_toolbar.h>
58#include <tool/tool_manager.h>
61#include <trace_helpers.h>
62#include <view/view_controls.h>
63#include <widgets/kistatusbar.h>
64#include <wx/choicdlg.h>
65#include <wx/evtloop.h>
66#include <wx/fswatcher.h>
67#include <wx/log.h>
68#include <wx/msgdlg.h>
69#include <trace_helpers.h>
70
71#if defined(__linux__) || defined(__FreeBSD__)
73#else
75#include <wx/fdrepdlg.h>
76#endif
77
78
80 LEGACY_SYMBOL_LIB* aCacheLib, wxWindow* aParent, bool aShowErrorMsg )
81{
82 wxCHECK_MSG( aLibMgr, nullptr, wxS( "Invalid symbol library manager adapter." ) );
83
84 LIB_SYMBOL* symbol = nullptr;
85
86 try
87 {
88 symbol = aLibMgr->LoadSymbol( aLibId );
89
90 if( !symbol && aCacheLib )
91 {
92 wxCHECK_MSG( aCacheLib->IsCache(), nullptr, wxS( "Invalid cache library." ) );
93
94 wxString cacheName = aLibId.GetLibNickname().wx_str();
95 cacheName << "_" << aLibId.GetLibItemName();
96 symbol = aCacheLib->FindSymbol( cacheName );
97 }
98 }
99 catch( const IO_ERROR& ioe )
100 {
101 if( aShowErrorMsg )
102 {
103 wxString msg = wxString::Format( _( "Error loading symbol %s from library '%s'." ),
104 aLibId.GetLibItemName().wx_str(),
105 aLibId.GetLibNickname().wx_str() );
106 DisplayErrorMessage( aParent, msg, ioe.What() );
107 }
108 }
109
110 return symbol;
111}
112
113
114SCH_BASE_FRAME::SCH_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aWindowType,
115 const wxString& aTitle, const wxPoint& aPosition,
116 const wxSize& aSize, long aStyle, const wxString& aFrameName ) :
117 EDA_DRAW_FRAME( aKiway, aParent, aWindowType, aTitle, aPosition, aSize, aStyle,
118 aFrameName, schIUScale ),
119 m_selectionFilterPanel( nullptr ),
120 m_findReplaceDialog( nullptr ),
121 m_base_frame_defaults( nullptr, "base_Frame_defaults" ),
123 m_watcherIsDir( false ),
125{
126 m_findReplaceData = std::make_unique<SCH_SEARCH_DATA>();
127
128 if( ( aStyle & wxFRAME_NO_TASKBAR ) == 0 )
129 createCanvas();
130
131 Bind( wxEVT_IDLE,
132 [this]( wxIdleEvent& aEvent )
133 {
134 // Handle cursor adjustments. While we can get motion and key events through
135 // wxWidgets, we can't get modifier-key-up events.
136 if( m_toolManager )
137 {
139
140 if( selTool )
141 selTool->OnIdle( aEvent );
142 }
143 } );
144
145 Pgm().GetBackgroundJobMonitor().RegisterStatusBar( static_cast<KISTATUSBAR*>( GetStatusBar() ) );
146
148}
149
150
153{
154 Pgm().GetBackgroundJobMonitor().UnregisterStatusBar( static_cast<KISTATUSBAR*>( GetStatusBar() ) );
155}
156
157
159{
160 GetCanvas()->SetEvtHandlerEnabled( false );
162
163 // Shutdown all running tools
164 if( m_toolManager )
165 m_toolManager->ShutdownAllTools();
166
167 // Close the find dialog and preserve its setting if it is displayed.
169 {
171 m_replaceStringHistoryList = m_findReplaceDialog->GetReplaceEntries();
172
173 m_findReplaceDialog->Destroy();
174 m_findReplaceDialog = nullptr;
175 }
176
177 // This class is pure virtual. Derived class will finish shutdown and Destroy().
178}
179
180
185
186
188{
189 return dynamic_cast<EESCHEMA_SETTINGS*>( config() );
190}
191
192
197
198
200{
201 switch( GetFrameType() )
202 {
203 case FRAME_SCH:
204 default:
205 return GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" );
206
208 case FRAME_SCH_VIEWER:
210 return GetAppSettings<SYMBOL_EDITOR_SETTINGS>( "symbol_editor" );
211 }
212}
213
214
215void SCH_BASE_FRAME::SetPageSettings( const PAGE_INFO& aPageSettings )
216{
217 GetScreen()->SetPageSettings( aPageSettings );
218}
219
220
222{
223 return GetScreen()->GetPageSettings();
224}
225
226
228{
229 // GetSizeIU is compile time dependent:
230 return GetScreen()->GetPageSettings().GetSizeIU( schIUScale.IU_PER_MILS );
231}
232
233
235{
236 wxASSERT( GetScreen() );
237 return GetScreen()->GetTitleBlock();
238}
239
240
242{
243 wxASSERT( GetScreen() );
244 GetScreen()->SetTitleBlock( aTitleBlock );
245}
246
247
249{
250 wxString line;
251 BASE_SCREEN* screen = GetScreen();
252
253 if( !screen )
254 return;
255
257
258 // Display absolute and relative coordinates
260 VECTOR2D d = cursorPos - screen->m_LocalOrigin;
261
262 line.Printf( wxS( "X %s Y %s" ),
263 MessageTextFromValue( cursorPos.x, false ),
264 MessageTextFromValue( cursorPos.y, false ) );
265 SetStatusText( line, 2 );
266
267 line.Printf( wxS( "dx %s dy %s dist %s" ),
268 MessageTextFromValue( d.x, false ),
269 MessageTextFromValue( d.y, false ),
270 MessageTextFromValue( hypot( d.x, d.y ), false ) );
271 SetStatusText( line, 3 );
272
275}
276
277
278LIB_SYMBOL* SCH_BASE_FRAME::GetLibSymbol( const LIB_ID& aLibId, bool aUseCacheLib,
279 bool aShowErrorMsg )
280{
281 LEGACY_SYMBOL_LIB* cache =
282 ( aUseCacheLib ) ? PROJECT_SCH::LegacySchLibs( &Prj() )->GetCacheLibrary() : nullptr;
283
284 return SchGetLibSymbol( aLibId, PROJECT_SCH::SymbolLibAdapter( &Prj() ), cache, this,
285 aShowErrorMsg );
286}
287
288
289void SCH_BASE_FRAME::RedrawScreen( const VECTOR2I& aCenterPoint, bool aWarpPointer )
290{
291 GetCanvas()->GetView()->SetCenter( aCenterPoint );
292
293 if( aWarpPointer )
295
296 GetCanvas()->Refresh();
297}
298
299
301{
302 if( GetCanvas() && GetCanvas()->GetView() )
303 {
306 }
307}
308
309
314
315
317{
318 if( GetCanvas() && GetCanvas()->GetView() )
319 {
320 if( KIGFX::PAINTER* painter = GetCanvas()->GetView()->GetPainter() )
321 return static_cast<SCH_RENDER_SETTINGS*>( painter->GetSettings() );
322 }
323
324 return nullptr;
325}
326
327
329{
331
332 SetCanvas( new SCH_DRAW_PANEL( this, wxID_ANY, wxPoint( 0, 0 ), m_frameSize,
335}
336
337
339{
341
342 try
343 {
344 if( !m_spaceMouse )
345 {
346#if defined(__linux__) || defined(__FreeBSD__)
347 m_spaceMouse = std::make_unique<SPNAV_2D_PLUGIN>( GetCanvas() );
348 m_spaceMouse->SetScale( schIUScale.IU_PER_MILS / pcbIUScale.IU_PER_MILS );
349#else
350 m_spaceMouse = std::make_unique<NL_SCHEMATIC_PLUGIN>();
351#endif
352 }
353
354 m_spaceMouse->SetCanvas( GetCanvas() );
355 }
356 catch( const std::exception& e )
357 {
358 wxLogTrace( wxT( "KI_TRACE_NAVLIB" ), wxS( "%s" ), e.what() );
359 }
360 catch( ... )
361 {
362 wxLogTrace( wxT( "KI_TRACE_NAVLIB" ),
363 wxT( "Unknown exception during SpaceMouse initialization" ) );
364 }
365}
366
367
368void SCH_BASE_FRAME::UpdateItem( EDA_ITEM* aItem, bool isAddOrDelete, bool aUpdateRtree )
369{
370 EDA_ITEM* parent = aItem->GetParent();
371
372 if( aItem->Type() == SCH_SHEET_PIN_T )
373 {
374 // Sheet pins aren't in the view. Refresh their parent.
375 if( parent )
376 GetCanvas()->GetView()->Update( parent );
377 }
378 else
379 {
380 if( aItem->Type() == SCH_SHAPE_T )
381 static_cast<SCH_SHAPE*>( aItem )->UpdateHatching();
382
383 if( !isAddOrDelete )
384 GetCanvas()->GetView()->Update( aItem );
385
386 // Some children are drawn from their parents. Mark them for re-paint.
387 if( parent && ( parent->Type() == SCH_SYMBOL_T
388 || parent->Type() == SCH_SHEET_T
389 || parent->Type() == SCH_LABEL_LOCATE_ANY_T
390 || parent->Type() == SCH_TABLE_T ) )
391 {
392 GetCanvas()->GetView()->Update( parent, KIGFX::REPAINT );
393 }
394 }
395
396 /*
397 * Be careful when calling this. Update will invalidate RTree iterators, so you cannot
398 * call this while doing things like `for( SCH_ITEM* item : screen->Items() )`
399 */
400 if( aUpdateRtree && dynamic_cast<SCH_ITEM*>( aItem ) )
401 {
402 GetScreen()->Update( static_cast<SCH_ITEM*>( aItem ) );
403
404 /*
405 * If we are updating the group, we also need to update all the children otherwise
406 * their positions will remain stale in the RTree
407 */
408 if( SCH_GROUP* group = dynamic_cast<SCH_GROUP*>( aItem ) )
409 {
410 group->RunOnChildren(
411 [&]( SCH_ITEM* item )
412 {
413 GetScreen()->Update( item );
414 },
416 }
417 }
418
419 // Calling Refresh() here introduces a bi-stable state: when doing operations on a
420 // large number of items if at some point the refresh timer times out and does a
421 // refresh it will take long enough that the next item will also time out, and the
422 // next, and the next, etc.
423 // GetCanvas()->Refresh();
424}
425
426
428{
429 // We currently have two zoom-dependent renderings: text, which is rendered as bitmap text
430 // when too small to see the difference, and selection shadows.
431 //
432 // Because non-selected text is cached by OpenGL, we only apply the bitmap performance hack
433 // to selected text items.
434 //
435 // Thus, as it currently stands, all zoom-dependent items can be found in the list of selected
436 // items.
437 if( m_toolManager )
438 {
439 SCH_SELECTION_TOOL* selectionTool = m_toolManager->GetTool<SCH_SELECTION_TOOL>();
440 SELECTION& selection = selectionTool->GetSelection();
441 KIGFX::SCH_VIEW* view = GetCanvas()->GetView();
442
443 for( EDA_ITEM* item : selection )
444 {
445 if( item->RenderAsBitmap( view->GetGAL()->GetWorldScale() ) != item->IsShownAsBitmap()
447 {
448 view->Update( item, KIGFX::REPAINT );
449
450 EDA_ITEM* parent = item->GetParent();
451
452 // Symbol children are drawn from their parents. Mark them for re-paint.
453 if( parent && parent->Type() == SCH_SYMBOL_T )
454 GetCanvas()->GetView()->Update( parent, KIGFX::REPAINT );
455 }
456 }
457 }
458}
459
460
462{
463 // Null pointers will cause boost::ptr_vector to raise a boost::bad_pointer exception which
464 // will be unhandled. There is no valid reason to pass an invalid EDA_ITEM pointer to the
465 // screen append function.
466 wxCHECK( aItem, /* void */ );
467
468 SCH_SCREEN* screen = aScreen;
469
470 if( aScreen == nullptr )
471 screen = GetScreen();
472
473 if( aItem->Type() != SCH_TABLECELL_T )
474 screen->Append( (SCH_ITEM*) aItem );
475
476 if( screen == GetScreen() )
477 {
478 GetCanvas()->GetView()->Add( aItem );
479 UpdateItem( aItem, true ); // handle any additional parent semantics
480 }
481}
482
483
485{
486 auto screen = aScreen;
487
488 if( aScreen == nullptr )
489 screen = GetScreen();
490
491 if( screen == GetScreen() )
492 GetCanvas()->GetView()->Remove( aItem );
493
494 if( aItem->Type() != SCH_TABLECELL_T )
495 screen->Remove( (SCH_ITEM*) aItem );
496
497 if( screen == GetScreen() )
498 UpdateItem( aItem, true ); // handle any additional parent semantics
499}
500
501
503{
504 // Let tools add things to the view if necessary
505 if( m_toolManager )
507
509}
510
511
516
517
519{
520 wxString findString;
521
522 SCH_SELECTION& selection = m_toolManager->GetTool<SCH_SELECTION_TOOL>()->GetSelection();
523
524 if( selection.Size() == 1 )
525 {
526 EDA_ITEM* front = selection.Front();
527
528 switch( front->Type() )
529 {
530 case SCH_SYMBOL_T:
531 {
532 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( front );
533 findString = UnescapeString( symbol->GetField( FIELD_T::VALUE )->GetText() );
534 break;
535 }
536
537 case SCH_FIELD_T:
538 findString = UnescapeString( static_cast<SCH_FIELD*>( front )->GetText() );
539 break;
540
541 case SCH_LABEL_T:
543 case SCH_HIER_LABEL_T:
544 case SCH_SHEET_PIN_T:
545 findString = UnescapeString( static_cast<SCH_LABEL_BASE*>( front )->GetText() );
546 break;
547
548 case SCH_TEXT_T:
549 findString = UnescapeString( static_cast<SCH_TEXT*>( front )->GetText() );
550
551 if( findString.Contains( wxT( "\n" ) ) )
552 findString = findString.Before( '\n' );
553
554 break;
555
556 default:
557 break;
558 }
559 }
560
562 m_findReplaceDialog->Destroy();
563
564 m_findReplaceDialog = new DIALOG_SCH_FIND( this, static_cast<SCH_SEARCH_DATA*>( m_findReplaceData.get() ),
565 wxDefaultPosition, wxDefaultSize, aReplace ? wxFR_REPLACEDIALOG : 0 );
566
567 m_findReplaceDialog->SetFindEntries( m_findStringHistoryList, findString );
569 m_findReplaceDialog->Show( true );
570}
571
572
573void SCH_BASE_FRAME::ShowFindReplaceStatus( const wxString& aMsg, int aStatusTime )
574{
575 // Prepare the infobar, since we don't know its state
576 m_infoBar->RemoveAllButtons();
577 m_infoBar->AddCloseButton();
578
579 m_infoBar->ShowMessageFor( aMsg, aStatusTime, wxICON_INFORMATION );
580}
581
582
584{
585 m_infoBar->Dismiss();
586}
587
588
590{
592 m_replaceStringHistoryList = m_findReplaceDialog->GetReplaceEntries();
593
594 m_findReplaceDialog->Destroy();
595 m_findReplaceDialog = nullptr;
596
598}
599
600
614
615
617{
618 if( !m_colorSettings || aForceRefresh )
619 {
621 wxString colorTheme = cfg ? cfg->m_ColorTheme : wxString( "" );
622
624 {
625 if( SYMBOL_EDITOR_SETTINGS* sym_edit_cfg = GetAppSettings<SYMBOL_EDITOR_SETTINGS>( "symbol_editor" ) )
626 {
627 if( !sym_edit_cfg->m_UseEeschemaColorSettings )
628 colorTheme = sym_edit_cfg->m_ColorTheme;
629 }
630 }
631
632 const_cast<SCH_BASE_FRAME*>( this )->m_colorSettings = ::GetColorSettings( colorTheme );
633 }
634
635 return m_colorSettings;
636}
637
638
643
644
645void SCH_BASE_FRAME::handleActivateEvent( wxActivateEvent& aEvent )
646{
648
649 if( m_spaceMouse )
650 m_spaceMouse->SetFocus( aEvent.GetActive() );
651}
652
653
654void SCH_BASE_FRAME::handleIconizeEvent( wxIconizeEvent& aEvent )
655{
657
658 if( m_spaceMouse )
659 m_spaceMouse->SetFocus( false );
660}
661
662
664 std::vector<wxArrayString>& aItemsToDisplay )
665{
666 aHeaders.Add( _( "Library" ) );
667 aHeaders.Add( _( "Description" ) );
668
672 std::vector<wxString> libNicknames = adapter->GetLibraryNames();
673 std::vector<wxArrayString> unpinned;
674
675 for( const wxString& nickname : libNicknames )
676 {
677 wxArrayString item;
678 wxString description = adapter->GetLibraryDescription( nickname ).value_or( wxEmptyString );
679
680 if( alg::contains( project.m_PinnedSymbolLibs, nickname )
681 || alg::contains( cfg->m_Session.pinned_symbol_libs, nickname ) )
682 {
683 item.Add( LIB_TREE_MODEL_ADAPTER::GetPinningSymbol() + nickname );
684 item.Add( description );
685 aItemsToDisplay.push_back( item );
686 }
687 else
688 {
689 item.Add( nickname );
690 item.Add( description );
691 unpinned.push_back( item );
692 }
693 }
694
695 std::sort( aItemsToDisplay.begin(), aItemsToDisplay.end(),
696 []( const wxArrayString& a, const wxArrayString& b )
697 {
698 return StrNumCmp( a[0], b[0], true ) < 0;
699 } );
700
701 std::sort( unpinned.begin(), unpinned.end(),
702 []( const wxArrayString& a, const wxArrayString& b )
703 {
704 return StrNumCmp( a[0], b[0], true ) < 0;
705 } );
706
707 std::ranges::copy( unpinned, std::back_inserter( aItemsToDisplay ) );
708}
709
710
711wxString SCH_BASE_FRAME::SelectLibrary( const wxString& aDialogTitle, const wxString& aListLabel,
712 const std::vector<std::pair<wxString, bool*>>& aExtraCheckboxes )
713{
714 static const int ID_MAKE_NEW_LIBRARY = wxID_HIGHEST;
715
716 // Keep asking the user for a new name until they give a valid one or cancel the operation
717 while( true )
718 {
719 wxArrayString headers;
720 std::vector<wxArrayString> itemsToDisplay;
721
722 GetLibraryItemsForListDialog( headers, itemsToDisplay );
723
724 wxString libraryName = Prj().GetRString( PROJECT::SCH_LIB_SELECT );
725
726 EDA_LIST_DIALOG dlg( this, aDialogTitle, headers, itemsToDisplay, libraryName, false );
727 dlg.SetListLabel( aListLabel );
728
729 for( const auto& [label, val] : aExtraCheckboxes )
730 dlg.AddExtraCheckbox( label, val );
731
732 wxButton* newLibraryButton = new wxButton( &dlg, ID_MAKE_NEW_LIBRARY, _( "New Library..." ) );
733 dlg.m_ButtonsSizer->Prepend( 80, 20 );
734 dlg.m_ButtonsSizer->Prepend( newLibraryButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
735
736 newLibraryButton->Bind( wxEVT_BUTTON,
737 [&dlg]( wxCommandEvent& )
738 {
739 dlg.EndModal( ID_MAKE_NEW_LIBRARY );
741
742 dlg.Layout();
743 dlg.GetSizer()->Fit( &dlg );
744
745 int ret = dlg.ShowModal();
746
747 switch( ret )
748 {
749 case wxID_CANCEL:
750 return wxEmptyString;
751
752 case wxID_OK:
753 libraryName = dlg.GetTextSelection();
754 Prj().SetRString( PROJECT::SCH_LIB_SELECT, libraryName );
756 return libraryName;
757
759 {
760 SYMBOL_LIBRARY_MANAGER mgr( *this );
761 wxFileName fn( Prj().GetRString( PROJECT::SCH_LIB_PATH ) );
762 bool useGlobalTable = false;
763 FILEDLG_HOOK_NEW_LIBRARY tableChooser( useGlobalTable );
764
765 if( !LibraryFileBrowser( _( "Create New Library" ), false, fn, FILEEXT::KiCadSymbolLibFileWildcard(),
766 FILEEXT::KiCadSymbolLibFileExtension, false, &tableChooser ) )
767 {
768 break;
769 }
770
771 libraryName = fn.GetName();
772 Prj().SetRString( PROJECT::SCH_LIB_PATH, fn.GetPath() );
773
777
778 if( adapter->HasLibrary( libraryName, false ) )
779 {
780 DisplayError( this, wxString::Format( _( "Library '%s' already exists." ), libraryName ) );
781 break;
782 }
783
784 if( !mgr.CreateLibrary( fn.GetFullPath(), scope ) )
785 DisplayError( this, wxString::Format( _( "Could not add library '%s'." ), libraryName ) );
786
787 break;
788 }
789
790 default:
791 break;
792 }
793 }
794}
795
796
798{
799 Unbind( wxEVT_FSWATCHER, &SCH_BASE_FRAME::OnSymChange, this );
800
801 if( m_watcher )
802 {
803 wxLogTrace( traceLibWatch, "Remove watch" );
804 m_watcher->RemoveAll();
805 m_watcher->SetOwner( nullptr );
806 m_watcher.reset();
807 }
808
809 if( !aID )
810 return;
811
813 std::optional<wxString> uri = manager.GetFullURI( LIBRARY_TABLE_TYPE::SYMBOL,
814 aID->GetLibNickname() );
815
816 if( !uri )
817 {
818 wxLogTrace( traceLibWatch, "Could not get URI for library %s",
819 wxString( aID->GetLibNickname().c_str() ) );
820 return;
821 }
822
823 wxString tmp = ExpandEnvVarSubstitutions( *uri, &Prj() );
824
825 wxLogTrace( traceLibWatch, "Setting up watcher for %s", tmp );
826
827 if( wxFileName::DirExists( tmp ) )
828 {
829 m_watcherFileName.AssignDir( tmp );
830 m_watcherIsDir = true;
832 m_watcherFileName.GetPath(),
833 wxS( "*." ) + wxString( FILEEXT::KiCadSymbolLibFileExtension ) );
834 }
835 else
836 {
837 m_watcherFileName.Assign( tmp );
838 m_watcherIsDir = false;
839
840 if( !m_watcherFileName.FileExists() )
841 return;
842
843 wxLogNull silence;
844 m_watcherTimestamp = m_watcherFileName.GetModificationTime().GetValue().GetValue();
845 }
846
847 // File system watcher requires an active event loop. If we're being called during
848 // library enumeration before the main event loop is running, skip watcher creation.
849 if( !wxEventLoopBase::GetActive() )
850 return;
851
852 Bind( wxEVT_FSWATCHER, &SCH_BASE_FRAME::OnSymChange, this );
853 m_watcher = std::make_unique<wxFileSystemWatcher>();
854 m_watcher->SetOwner( this );
855
856 wxFileName fn;
857 fn.AssignDir( m_watcherFileName.GetPath() );
858 fn.DontFollowLink();
859
860 {
861 // Silence OS errors that come from the watcher
862 wxLogNull silence;
863 m_watcher->Add( fn );
864 }
865}
866
867
868void SCH_BASE_FRAME::OnSymChange( wxFileSystemWatcherEvent& aEvent )
869{
870 wxLogTrace( traceLibWatch, "OnSymChange: %s, watcher file: %s",
871 aEvent.GetPath().GetFullPath(), m_watcherFileName.GetFullPath() );
872
873 if( !m_watcher || !m_watcher.get() || m_watcherFileName.GetPath().IsEmpty() )
874 return;
875
876 if( m_watcherIsDir )
877 {
878 // For directory-based libraries, accept events for any file within the directory
879 wxString eventPath = aEvent.GetPath().GetFullPath();
880 wxString dirPath = m_watcherFileName.GetPath();
881
882 if( !eventPath.StartsWith( dirPath ) )
883 return;
884 }
885 else
886 {
887 if( aEvent.GetPath() != m_watcherFileName )
888 return;
889 }
890
891 // Start the debounce timer (set to 1 second)
892 if( !m_watcherDebounceTimer.StartOnce( 1000 ) )
893 {
894 wxLogTrace( traceLibWatch, "Failed to start the debounce timer" );
895 return;
896 }
897}
898
899
901{
902 if( aEvent.GetId() != m_watcherDebounceTimer.GetId() )
903 {
904 aEvent.Skip();
905 return;
906 }
907
909 {
910 wxLogTrace( traceLibWatch, "Restarting debounce timer" );
911 m_watcherDebounceTimer.StartOnce( 3000 );
912 return;
913 }
914
915 // If the frame is currently disabled then a quasi-modal/modal dialog is open on top
916 // of it (for example the symbol properties dialog). Reloading the library now would
917 // delete the LIB_SYMBOL the dialog is editing and crash on dialog close. Defer the
918 // reload until the dialog is dismissed.
919 if( !IsEnabled() )
920 {
921 wxLogTrace( traceLibWatch, "Frame disabled (dialog open); restarting debounce timer" );
922 m_watcherDebounceTimer.StartOnce( 1000 );
923 return;
924 }
925
926 // An interactive tool (move, draw, place pin/text) holds references into the current symbol
927 // while its event loop runs. Reloading now would free those out from under the running tool
928 // and crash. Restart the timer before touching the watcher timestamp so the reload is retried
929 // once the tool finishes rather than silently dropped.
930 if( !ToolStackIsEmpty() )
931 {
932 wxLogTrace( traceLibWatch, "Interactive tool active; restarting debounce timer" );
933 m_watcherDebounceTimer.StartOnce( 1000 );
934 return;
935 }
936
937 wxLogTrace( traceLibWatch, "OnSymChangeDebounceTimer" );
938
939 long long currentTimestamp = 0;
940
941 if( m_watcherIsDir )
942 {
943 currentTimestamp = KIPLATFORM::IO::TimestampDir(
944 m_watcherFileName.GetPath(),
945 wxS( "*." ) + wxString( FILEEXT::KiCadSymbolLibFileExtension ) );
946 }
947 else
948 {
949 wxLogNull silence;
950 wxDateTime lastModified = m_watcherFileName.GetModificationTime();
951
952 if( !lastModified.IsValid() )
953 return;
954
955 currentTimestamp = lastModified.GetValue().GetValue();
956 }
957
958 if( currentTimestamp == m_watcherTimestamp )
959 return;
960
961 m_watcherTimestamp = currentTimestamp;
962
964
966 || IsOK( this, _( "The library containing the current symbol has changed.\n"
967 "Do you want to reload the library?" ) ) )
968 {
969 wxLogTrace( traceLibWatch, "Sending refresh symbol mail" );
970
971 // For directory libraries, GetFullPath() appends a trailing separator which
972 // won't match the library table URI. Use GetPath() for directories instead.
973 std::string libName = m_watcherIsDir
974 ? m_watcherFileName.GetPath().ToStdString()
975 : m_watcherFileName.GetFullPath().ToStdString();
976
979 }
980
982}
983
984
986{
987 if( m_toolManager )
988 return m_toolManager->GetTool<SCH_SELECTION_TOOL>();
989
990 return nullptr;
991}
992
993
995{
996 SCH_SELECTION_FILTER_EVENT evt( aOptions );
997 wxPostEvent( this, evt );
998}
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:123
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
static TOOL_ACTION updateFind
Definition actions.h:120
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
wxString m_ColorTheme
Active color theme name.
void UnregisterStatusBar(KISTATUSBAR *aStatusBar)
Removes status bar from handling.
void RegisterStatusBar(KISTATUSBAR *aStatusBar)
Add a status bar for handling.
Handles how to draw a screen (a board, a schematic ...)
Definition base_screen.h:37
VECTOR2D m_LocalOrigin
Relative Screen cursor coordinate (on grid) in user units.
Definition base_screen.h:86
Color settings are a bit different than most of the settings objects in that there can be more than o...
COLOR4D GetColor(int aLayer) const
int ShowModal() override
FRAME_T GetFrameType() const
virtual APP_SETTINGS_BASE * config() const
Return the settings object used in SaveSettings(), and is overloaded in KICAD_MANAGER_FRAME.
virtual void handleIconizeEvent(wxIconizeEvent &aEvent)
Handle a window iconize event.
WX_INFOBAR * m_infoBar
virtual bool IsContentModified() const
Get if the contents of the frame have been modified since the last save.
bool IsType(FRAME_T aType) const
wxArrayString m_replaceStringHistoryList
virtual void ActivateGalCanvas()
Use to start up the GAL drawing canvas.
COLOR_SETTINGS * m_colorSettings
EDA_DRAW_PANEL_GAL::GAL_TYPE m_canvasType
The current canvas type.
virtual BASE_SCREEN * GetScreen() const
Return a pointer to a BASE_SCREEN or one of its derivatives.
void DisplayUnitsMsg()
Display current unit pane in the status bar.
GAL_DISPLAY_OPTIONS_IMPL & GetGalDisplayOptions()
Return a reference to the gal rendering options used by GAL for rendering.
void SetCanvas(EDA_DRAW_PANEL_GAL *aPanel)
EDA_DRAW_FRAME(KIWAY *aKiway, wxWindow *aParent, FRAME_T aFrameType, const wxString &aTitle, const wxPoint &aPos, const wxSize &aSize, long aStyle, const wxString &aFrameName, const EDA_IU_SCALE &aIuScale)
bool LibraryFileBrowser(const wxString &aTitle, bool doOpen, wxFileName &aFilename, const wxString &wildcard, const wxString &ext, bool isDirectory, FILEDLG_HOOK_NEW_LIBRARY *aFileDlgHook=nullptr)
virtual void handleActivateEvent(wxActivateEvent &aEvent)
Handle a window activation event.
void UpdateStatusBar() override
Update the status bar information.
virtual EDA_DRAW_PANEL_GAL * GetCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
virtual void DisplayGridMsg()
Display current grid size in the status bar.
EDA_DRAW_PANEL_GAL::GAL_TYPE loadCanvasTypeSetting()
Return the canvas type stored in the application settings.
wxArrayString m_findStringHistoryList
std::unique_ptr< EDA_SEARCH_DATA > m_findReplaceData
void CommonSettingsChanged(int aFlags) override
Notification event that some of the common (suite-wide) settings have changed.
void StopDrawing()
Prevent the GAL canvas from further drawing until it is recreated or StartDrawing() is called.
KIGFX::VIEW_CONTROLS * GetViewControls() const
Return a pointer to the #VIEW_CONTROLS instance used in the panel.
void ForceRefresh()
Force a redraw.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
KIGFX::GAL * GetGAL() const
Return a pointer to the GAL instance used in the panel.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:96
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:108
EDA_ITEM * GetParent() const
Definition eda_item.h:110
A dialog which shows:
wxString GetTextSelection(int aColumn=0)
Return the selected text from aColumn in the wxListCtrl in the dialog.
void SetListLabel(const wxString &aLabel)
void AddExtraCheckbox(const wxString &aLabel, bool *aValuePtr)
Add a checkbox value to the dialog.
void GetExtraCheckboxValues()
Fills in the value pointers from the checkboxes after the dialog has run.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
void SetAxesColor(const COLOR4D &aAxesColor)
Set the axes color.
double GetWorldScale() const
Get the world scale.
Contains all the knowledge about how to draw graphical object onto any particular output device.
Definition painter.h:55
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
virtual void LoadColors(const COLOR_SETTINGS *aSettings)
static std::vector< KICAD_T > g_ScaledSelectionTypes
void Update(const KIGFX::VIEW_ITEM *aItem, int aUpdateFlags) const override
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition sch_view.cpp:73
virtual void CenterOnCursor()=0
Set the viewport center to the current cursor position and warps the cursor to the screen center.
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition view.cpp:300
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition view.cpp:404
GAL * GetGAL() const
Return the GAL this view is using to draw graphical primitives.
Definition view.h:207
void RecacheAllItems()
Rebuild GAL display lists.
Definition view.cpp:1552
void UpdateAllItems(int aUpdateFlags)
Update all items in the view according to the given flags.
Definition view.cpp:1686
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition view.h:225
void SetCenter(const VECTOR2D &aCenter)
Set the center point of the VIEW (i.e.
Definition view.cpp:663
void MarkTargetDirty(int aTarget)
Set or clear target 'dirty' flag.
Definition view.h:657
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition kiway.h:311
virtual void ExpressMail(FRAME_T aDestination, MAIL_T aCommand, std::string &aPayload, wxWindow *aSource=nullptr, bool aFromOtherThread=false)
Send aPayload to aDestination from aSource.
Definition kiway.cpp:496
Object used to load, save, search, and otherwise manipulate symbol library files.
LIB_SYMBOL * FindSymbol(const wxString &aName) const
Find LIB_SYMBOL by aName.
std::optional< wxString > GetLibraryDescription(const wxString &aNickname) const
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library tables.
std::vector< wxString > GetLibraryNames() const
Returns a list of library nicknames that are available (skips any that failed to load)
std::optional< wxString > GetFullURI(LIBRARY_TABLE_TYPE aType, const wxString &aNickname, bool aSubstituted=false)
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
const UTF8 & GetLibItemName() const
Definition lib_id.h:98
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition lib_id.h:83
Define a library symbol object.
Definition lib_symbol.h:79
static const wxString GetPinningSymbol()
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition page_info.h:75
const VECTOR2D GetSizeIU(double aIUScale) const
Gets the page size in internal units.
Definition page_info.h:173
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition pgm_base.cpp:528
virtual BACKGROUND_JOBS_MONITOR & GetBackgroundJobMonitor() const
Definition pgm_base.h:130
virtual LIBRARY_MANAGER & GetLibraryManager() const
Definition pgm_base.h:126
The backing store for a PROJECT, in JSON format.
static SYMBOL_LIBRARY_ADAPTER * SymbolLibAdapter(PROJECT *aProject)
Accessor for project symbol library manager adapter.
static LEGACY_SYMBOL_LIBS * LegacySchLibs(PROJECT *aProject)
Returns the list of symbol libraries from a legacy (pre-5.x) design This is only used from the remapp...
@ SCH_LIB_SELECT
Definition project.h:217
@ SCH_LIB_PATH
Definition project.h:216
virtual PROJECT_FILE & GetProjectFile() const
Definition project.h:200
virtual void SetRString(RSTRING_T aStringId, const wxString &aString)
Store a "retained string", which is any session and project specific string identified in enum RSTRIN...
Definition project.cpp:355
virtual const wxString & GetRString(RSTRING_T aStringId)
Return a "retained string", which is any session and project specific string identified in enum RSTRI...
Definition project.cpp:366
virtual void RedrawScreen(const VECTOR2I &aCenterPoint, bool aWarpPointer)
SCH_BASE_FRAME(KIWAY *aKiway, wxWindow *aParent, FRAME_T aWindowType, const wxString &aTitle, const wxPoint &aPosition, const wxSize &aSize, long aStyle, const wxString &aFrameName)
void UpdateStatusBar() override
Update the status bar information.
void RemoveFromScreen(EDA_ITEM *aItem, SCH_SCREEN *aScreen) override
Remove an item from the screen (and view) aScreen is the screen the item is located on,...
SCH_RENDER_SETTINGS * GetRenderSettings()
void doCloseWindow() override
void ActivateGalCanvas() override
Use to start up the GAL drawing canvas.
const VECTOR2I GetPageSizeIU() const override
Works off of GetPageSettings() to return the size of the paper page in the internal units of this par...
void SetPageSettings(const PAGE_INFO &aPageSettings) override
void handleIconizeEvent(wxIconizeEvent &aEvent) override
Handle a window iconize event.
void OnSymChange(wxFileSystemWatcherEvent &aEvent)
Handler for Symbol change events.
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
SYMBOL_EDITOR_SETTINGS * libeditconfig() const
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
APP_SETTINGS_BASE * GetViewerSettingsBase() const
void HighlightSelectionFilter(const SCH_SELECTION_FILTER_OPTIONS &aOptions)
void HardRedraw() override
Rebuild the GAL and redraws the screen.
DIALOG_SCH_FIND * m_findReplaceDialog
SCHEMATIC_SETTINGS m_base_frame_defaults
Only used by symbol_editor. Eeschema should be using the one inside the SCHEMATIC.
wxTimer m_watcherDebounceTimer
void CommonSettingsChanged(int aFlags) override
Notification event that some of the common (suite-wide) settings have changed.
void ShowFindReplaceDialog(bool aReplace)
Run the Find or Find & Replace dialog.
SCH_SELECTION_TOOL * GetSelectionTool() override
void SyncView()
Mark all items for refresh.
std::unique_ptr< NL_SCHEMATIC_PLUGIN > m_spaceMouse
void GetLibraryItemsForListDialog(wxArrayString &aHeaders, std::vector< wxArrayString > &aItemsToDisplay)
std::unique_ptr< wxFileSystemWatcher > m_watcher
These are file watchers for the symbol library tables.
wxString SelectLibrary(const wxString &aDialogTitle, const wxString &aListLabel, const std::vector< std::pair< wxString, bool * > > &aExtraCheckboxes={})
Display a list of loaded libraries and allows the user to select a library.
virtual ~SCH_BASE_FRAME()
Needs to be in the cpp file to encode the sizeof() for std::unique_ptr.
const TITLE_BLOCK & GetTitleBlock() const override
void RefreshZoomDependentItems()
Mark selected items for refresh.
EESCHEMA_SETTINGS * eeconfig() const
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock) override
PANEL_SCH_SELECTION_FILTER * m_selectionFilterPanel
LIB_SYMBOL * GetLibSymbol(const LIB_ID &aLibId, bool aUseCacheLib=false, bool aShowErrorMsg=false)
Load symbol from symbol library table.
virtual void UpdateItem(EDA_ITEM *aItem, bool isAddOrDelete=false, bool aUpdateRtree=false)
Mark an item for refresh.
void handleActivateEvent(wxActivateEvent &aEvent) override
Handle a window activation event.
COLOR_SETTINGS * GetColorSettings(bool aForceRefresh=false) const override
Returns a pointer to the active color theme settings.
void OnFindDialogClose()
Notification that the Find dialog has closed.
wxFileName m_watcherFileName
void setSymWatcher(const LIB_ID *aSymbol)
Creates (or removes) a watcher on the specified symbol library.
void AddToScreen(EDA_ITEM *aItem, SCH_SCREEN *aScreen=nullptr) override
Add an item to the screen (and view) aScreen is the screen the item is located on,...
const PAGE_INFO & GetPageSettings() const override
void ShowFindReplaceStatus(const wxString &aMsg, int aStatusTime)
COLOR4D GetDrawBgColor() const override
void OnSymChangeDebounceTimer(wxTimerEvent &aEvent)
Handler for the filesystem watcher debounce timer.
long long m_watcherTimestamp
void ClearFindReplaceStatus()
COLOR4D GetLayerColor(SCH_LAYER_ID aLayer)
Helper to retrieve a layer color from the global color settings.
KIGFX::SCH_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:128
A set of SCH_ITEMs (i.e., without duplicates).
Definition sch_group.h:48
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:162
const PAGE_INFO & GetPageSettings() const
Definition sch_screen.h:137
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
Definition sch_screen.h:164
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition sch_screen.h:138
TITLE_BLOCK & GetTitleBlock()
Definition sch_screen.h:161
void Update(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Update aItem's bounding box in the tree.
SCH_SELECTION & GetSelection()
void OnIdle(wxIdleEvent &aEvent)
Zoom the screen to fit the bounding box for cross probing/selection sync.
Schematic symbol object.
Definition sch_symbol.h:69
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
EDA_ITEM * Front() const
Definition selection.h:173
int Size() const
Returns the number of selected parts.
Definition selection.h:117
An interface to the global shared library manager that is schematic-specific and linked to one projec...
LIB_SYMBOL * LoadSymbol(const wxString &aNickname, const wxString &aName)
Load a LIB_SYMBOL having aName from the library given by aNickname.
Class to handle modifications to the symbol libraries.
bool CreateLibrary(const wxString &aFilePath, LIBRARY_TABLE_SCOPE aScope)
Create an empty library and adds it to the library table.
Hold the information shown in the lower right corner of a plot, printout, or editing view.
Definition title_block.h:37
TOOL_MANAGER * m_toolManager
bool ToolStackIsEmpty()
@ MODEL_RELOAD
Model changes (the sheet for a schematic)
Definition tool_base.h:76
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
const char * c_str() const
Definition utf8.h:104
wxString wx_str() const
Definition utf8.cpp:41
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition common.cpp:704
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:274
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:217
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:192
This file is part of the common library.
#define _(s)
@ RECURSE
Definition eda_item.h:49
FRAME_T
The set of EDA_BASE_FRAME derivatives, typically stored in EDA_BASE_FRAME::m_Ident.
Definition frame_type.h:29
@ FRAME_SCH_SYMBOL_EDITOR
Definition frame_type.h:31
@ FRAME_SCH_VIEWER
Definition frame_type.h:32
@ FRAME_SCH
Definition frame_type.h:30
@ FRAME_SYMBOL_CHOOSER
Definition frame_type.h:33
static const std::string KiCadSymbolLibFileExtension
static wxString KiCadSymbolLibFileWildcard()
const wxChar *const traceLibWatch
Flag to enable debug output for library file watch refreshes.
SCH_LAYER_ID
Eeschema drawing layers.
Definition layer_ids.h:447
@ LAYER_SCHEMATIC_GRID_AXES
Definition layer_ids.h:485
@ LAYER_SCHEMATIC_BACKGROUND
Definition layer_ids.h:486
LIBRARY_TABLE_SCOPE
@ MAIL_REFRESH_SYMBOL
Definition mail_type.h:56
@ REPAINT
Item needs to be redrawn.
Definition view_item.h:54
@ ALL
All except INITIAL_ADD.
Definition view_item.h:55
@ TARGET_NONCACHED
Auxiliary rendering target (noncached)
Definition definitions.h:34
long long TimestampDir(const wxString &aDirPath, const wxString &aFilespec)
Computes a hash of modification times and sizes for files matching a pattern.
Definition unix/io.cpp:123
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition kicad_algo.h:96
Declaration of the NL_SCHEMATIC_PLUGIN class.
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
LIB_SYMBOL * SchGetLibSymbol(const LIB_ID &aLibId, SYMBOL_LIBRARY_ADAPTER *aLibMgr, LEGACY_SYMBOL_LIB *aCacheLib, wxWindow *aParent, bool aShowErrorMsg)
Load symbol from symbol library table.
LIB_SYMBOL * SchGetLibSymbol(const LIB_ID &aLibId, SYMBOL_LIBRARY_ADAPTER *aLibMgr, LEGACY_SYMBOL_LIB *aCacheLib=nullptr, wxWindow *aParent=nullptr, bool aShowErrorMsg=false)
Load symbol from symbol library table.
Class to handle a set of SCH_ITEMs.
T * GetAppSettings(const char *aFilename)
KIWAY Kiway(KFCTL_STANDALONE)
wxString UnescapeString(const wxString &aSource)
std::vector< wxString > pinned_symbol_libs
@ ID_MAKE_NEW_LIBRARY
@ VALUE
Field Value of part, i.e. "3.3K".
wxLogTrace helper definitions.
@ SCH_TABLE_T
Definition typeinfo.h:162
@ SCH_SYMBOL_T
Definition typeinfo.h:169
@ SCH_TABLECELL_T
Definition typeinfo.h:163
@ SCH_FIELD_T
Definition typeinfo.h:147
@ SCH_LABEL_T
Definition typeinfo.h:164
@ SCH_SHEET_T
Definition typeinfo.h:172
@ SCH_SHAPE_T
Definition typeinfo.h:146
@ SCH_HIER_LABEL_T
Definition typeinfo.h:166
@ SCH_LABEL_LOCATE_ANY_T
Definition typeinfo.h:188
@ SCH_SHEET_PIN_T
Definition typeinfo.h:171
@ SCH_TEXT_T
Definition typeinfo.h:148
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:165
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
VECTOR2< double > VECTOR2D
Definition vector2d.h:682
Definition of file extensions used in Kicad.