KiCad PCB EDA Suite
footprint_editor_control.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) 2014-2019 CERN
5  * Copyright (C) 2019-2020 KiCad Developers, see AUTHORS.txt for contributors.
6  * @author Maciej Suminski <maciej.suminski@cern.ch>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
27 #include "kicad_clipboard.h"
28 #include <tool/tool_manager.h>
29 #include <tools/pcb_actions.h>
30 #include <view/view_controls.h>
31 #include <footprint_edit_frame.h>
32 #include <pcbnew_id.h>
33 #include <confirm.h>
34 #include <bitmaps.h>
35 #include <footprint.h>
36 #include <project.h>
37 #include <fp_lib_table.h>
40 #include <footprint_wizard_frame.h>
41 #include <kiway.h>
43 
44 
46  PCB_TOOL_BASE( "pcbnew.ModuleEditor" ),
47  m_frame( nullptr ),
48  m_checkerDialog( nullptr )
49 {
50 }
51 
52 
54 {
55 }
56 
57 
59 {
60  m_frame = getEditFrame<FOOTPRINT_EDIT_FRAME>();
61 
62  if( m_checkerDialog )
64 }
65 
66 
68 {
69  // Build a context menu for the footprint tree
70  //
71  CONDITIONAL_MENU& ctxMenu = m_menu.GetMenu();
72 
73  auto libSelectedCondition =
74  [ this ]( const SELECTION& aSel )
75  {
76  LIB_ID sel = m_frame->GetTreeFPID();
77  return !sel.GetLibNickname().empty() && sel.GetLibItemName().empty();
78  };
79  // The libInferredCondition allows you to do things like New Symbol and Paste with a
80  // symbol selected (in other words, when we know the library context even if the library
81  // itself isn't selected.
82  auto libInferredCondition =
83  [ this ]( const SELECTION& aSel )
84  {
85  LIB_ID sel = m_frame->GetTreeFPID();
86  return !sel.GetLibNickname().empty();
87  };
88  auto pinnedLibSelectedCondition =
89  [ this ]( const SELECTION& aSel )
90  {
92  return current && current->m_Type == LIB_TREE_NODE::LIB && current->m_Pinned;
93  };
94  auto unpinnedLibSelectedCondition =
95  [ this ](const SELECTION& aSel )
96  {
98  return current && current->m_Type == LIB_TREE_NODE::LIB && !current->m_Pinned;
99  };
100  auto fpSelectedCondition =
101  [ this ]( const SELECTION& aSel )
102  {
103  LIB_ID sel = m_frame->GetTreeFPID();
104  return !sel.GetLibNickname().empty() && !sel.GetLibItemName().empty();
105  };
106 
107  ctxMenu.AddItem( ACTIONS::pinLibrary, unpinnedLibSelectedCondition );
108  ctxMenu.AddItem( ACTIONS::unpinLibrary, pinnedLibSelectedCondition );
109 
110  ctxMenu.AddSeparator();
111  ctxMenu.AddItem( PCB_ACTIONS::newFootprint, libSelectedCondition );
112 #ifdef KICAD_SCRIPTING
113  ctxMenu.AddItem( PCB_ACTIONS::createFootprint, libSelectedCondition );
114 #endif
115 
116  ctxMenu.AddSeparator();
117  ctxMenu.AddItem( ACTIONS::save, libSelectedCondition || libInferredCondition );
118  ctxMenu.AddItem( ACTIONS::saveAs, libSelectedCondition );
119  ctxMenu.AddItem( ACTIONS::saveCopyAs, fpSelectedCondition );
120  ctxMenu.AddItem( ACTIONS::revert, libSelectedCondition || libInferredCondition );
121 
122  ctxMenu.AddSeparator();
123  ctxMenu.AddItem( PCB_ACTIONS::cutFootprint, fpSelectedCondition );
124  ctxMenu.AddItem( PCB_ACTIONS::copyFootprint, fpSelectedCondition );
125  ctxMenu.AddItem( PCB_ACTIONS::pasteFootprint, libInferredCondition );
126  ctxMenu.AddItem( PCB_ACTIONS::deleteFootprint, fpSelectedCondition );
127 
128  ctxMenu.AddSeparator();
129  ctxMenu.AddItem( PCB_ACTIONS::importFootprint, libInferredCondition );
130  ctxMenu.AddItem( PCB_ACTIONS::exportFootprint, fpSelectedCondition );
131 
132  return true;
133 }
134 
135 
137 {
138  LIB_ID selected = m_frame->GetTreeFPID();
139  FOOTPRINT* newFootprint = m_frame->CreateNewFootprint( wxEmptyString );
140 
141  if( !newFootprint )
142  return 0;
143 
144  if( !m_frame->Clear_Pcb( true ) )
145  return 0;
146 
148  m_frame->AddFootprintToBoard( newFootprint );
149 
150  // Initialize data relative to nets and netclasses (for a new footprint the defaults are
151  // used). This is mandatory to handle and draw pads.
152  board()->BuildListOfNets();
153  newFootprint->SetPosition( wxPoint( 0, 0 ) );
154  newFootprint->ClearFlags();
155 
156  m_frame->Zoom_Automatique( false );
158 
159  // If selected from the library tree then go ahead and save it there
160  if( !selected.GetLibNickname().empty() )
161  {
162  LIB_ID fpid = newFootprint->GetFPID();
163  fpid.SetLibNickname( selected.GetLibNickname() );
164  newFootprint->SetFPID( fpid );
165  m_frame->SaveFootprint( newFootprint );
166  m_frame->ClearModify();
167  }
168 
169  m_frame->UpdateView();
170  m_frame->Update3DView( true );
171 
172  m_frame->SyncLibraryTree( false );
173  return 0;
174 }
175 
176 
178 {
179  LIB_ID selected = m_frame->GetTreeFPID();
180 
181  if( m_frame->IsContentModified() )
182  {
183  if( !HandleUnsavedChanges( m_frame, _( "The current footprint has been modified. "
184  "Save changes?" ),
185  [&]() -> bool
186  {
187  return m_frame->SaveFootprint( footprint() );
188  } ) )
189  {
190  return 0;
191  }
192  }
193 
195  true, m_frame );
196 
197  if( wizard->ShowModal( NULL, m_frame ) )
198  {
199  // Creates the new footprint from python script wizard
200  FOOTPRINT* newFootprint = wizard->GetBuiltFootprint();
201 
202  if( newFootprint ) // i.e. if create footprint command is OK
203  {
204  m_frame->Clear_Pcb( false );
205 
207  // Add the new object to board
208  m_frame->AddFootprintToBoard( newFootprint );
209 
210  // Initialize data relative to nets and netclasses (for a new footprint the defaults
211  // are used). This is mandatory to handle and draw pads.
212  board()->BuildListOfNets();
213  newFootprint->SetPosition( wxPoint( 0, 0 ) );
214  newFootprint->ClearFlags();
215 
216  m_frame->Zoom_Automatique( false );
218 
219  // If selected from the library tree then go ahead and save it there
220  if( !selected.GetLibNickname().empty() )
221  {
222  LIB_ID fpid = newFootprint->GetFPID();
223  fpid.SetLibNickname( selected.GetLibNickname() );
224  newFootprint->SetFPID( fpid );
225  m_frame->SaveFootprint( newFootprint );
226  m_frame->ClearModify();
227  }
228 
229  m_frame->UpdateView();
230  canvas()->Refresh();
231  m_frame->Update3DView( true );
232 
233  m_frame->SyncLibraryTree( false );
234  }
235  }
236 
237  wizard->Destroy();
238  return 0;
239 }
240 
241 
243 {
244  if( !footprint() ) // no loaded footprint
245  return 0;
246 
248  {
249  if( m_frame->SaveFootprint( footprint() ) )
250  {
251  view()->Update( footprint() );
252 
253  canvas()->ForceRefresh();
254  m_frame->ClearModify();
255  m_frame->UpdateTitle();
256  }
257  }
258 
260  return 0;
261 }
262 
263 
265 {
267  {
268  // Save Library As
269  const wxString& src_libNickname = m_frame->GetTargetFPID().GetLibNickname();
270  wxString src_libFullName = m_frame->Prj().PcbFootprintLibs()->GetFullURI( src_libNickname );
271 
272  if( m_frame->SaveLibraryAs( src_libFullName ) )
273  m_frame->SyncLibraryTree( true );
274  }
275  else if( m_frame->GetTargetFPID() == m_frame->GetLoadedFPID() )
276  {
277  // Save Board Footprint As
278  if( footprint() && m_frame->SaveFootprintAs( footprint() ) )
279  {
280  view()->Update( footprint() );
281  m_frame->ClearModify();
282 
283  canvas()->ForceRefresh();
284  m_frame->SyncLibraryTree( true );
285  }
286  }
287  else
288  {
289  // Save Selected Footprint As
291 
293  m_frame->SyncLibraryTree( true );
294  }
295 
297  return 0;
298 }
299 
300 
302 {
303  getEditFrame<FOOTPRINT_EDIT_FRAME>()->RevertFootprint();
304  return 0;
305 }
306 
307 
309 {
310  LIB_ID fpID = m_frame->GetTreeFPID();
311 
312  if( fpID == m_frame->GetLoadedFPID() )
314  else
315  m_copiedFootprint.reset( m_frame->LoadFootprint( fpID ) );
316 
317  if( aEvent.IsAction( &PCB_ACTIONS::cutFootprint ) )
318  DeleteFootprint( aEvent );
319 
320  return 0;
321 }
322 
323 
325 {
327  {
328  wxString newLib = m_frame->GetTreeFPID().GetLibNickname();
329  wxString newName = m_copiedFootprint->GetFPID().GetLibItemName();
330 
331  while( m_frame->Prj().PcbFootprintLibs()->FootprintExists( newLib, newName ) )
332  newName += _( "_copy" );
333 
334  m_copiedFootprint->SetFPID( LIB_ID( newLib, newName ) );
336 
337  m_frame->SyncLibraryTree( true );
338  m_frame->FocusOnLibID( m_copiedFootprint->GetFPID() );
339  }
340 
341  return 0;
342 }
343 
344 
346 {
347  FOOTPRINT_EDIT_FRAME* frame = getEditFrame<FOOTPRINT_EDIT_FRAME>();
348 
349  if( frame->DeleteFootprintFromLibrary( frame->GetTargetFPID(), true ) )
350  {
351  if( frame->GetTargetFPID() == frame->GetLoadedFPID() )
352  frame->Clear_Pcb( false );
353 
354  frame->SyncLibraryTree( true );
355  }
356 
357  return 0;
358 }
359 
360 
362 {
363  bool is_last_fp_from_brd = m_frame->IsCurrentFPFromBoard();
364 
365  if( !m_frame->Clear_Pcb( true ) )
366  return -1; // this command is aborted
367 
370 
373 
375 
376  // Update the save items if needed.
377  if( is_last_fp_from_brd )
378  {
381  }
382 
384  m_frame->OnModify();
385  return 0;
386 }
387 
388 
390 {
391  LIB_ID fpID = m_frame->GetTreeFPID();
392  FOOTPRINT* fp;
393 
394  if( !fpID.IsValid() )
396  else
397  fp = m_frame->LoadFootprint( fpID );
398 
399  m_frame->ExportFootprint( fp );
400  return 0;
401 }
402 
403 
405 {
407  return 0;
408 }
409 
410 
412 {
413  LIB_TREE_NODE* currentNode = m_frame->GetCurrentTreeNode();
414 
415  if( currentNode && !currentNode->m_Pinned )
416  {
417  currentNode->m_Pinned = true;
419  }
420 
421  return 0;
422 }
423 
424 
426 {
427  LIB_TREE_NODE* currentNode = m_frame->GetCurrentTreeNode();
428 
429  if( currentNode && currentNode->m_Pinned )
430  {
431  currentNode->m_Pinned = false;
433  }
434 
435  return 0;
436 }
437 
438 
440 {
442  return 0;
443 }
444 
445 
447 {
449 
450  if( footprint )
451  {
452  getEditFrame<FOOTPRINT_EDIT_FRAME>()->OnEditItemRequest( footprint );
453  m_frame->GetCanvas()->Refresh();
454  }
455  return 0;
456 }
457 
458 
460 {
461  getEditFrame<FOOTPRINT_EDIT_FRAME>()->ShowPadPropertiesDialog( nullptr );
462  return 0;
463 }
464 
465 
467 {
468  FOOTPRINT_EDIT_FRAME* editFrame = getEditFrame<FOOTPRINT_EDIT_FRAME>();
469  DIALOG_CLEANUP_GRAPHICS dlg( editFrame, true );
470 
471  dlg.ShowModal();
472  return 0;
473 }
474 
475 
477 {
478  if( !m_checkerDialog )
479  {
481 
482  m_checkerDialog->Show( true );
483  }
484  else // The dialog is just not visible (because the user has double clicked on an error item)
485  {
487  m_checkerDialog->Show( true );
488  }
489  return 0;
490 }
491 
492 
494 {
495  if( m_checkerDialog )
496  {
497  m_checkerDialog->Destroy();
498  m_checkerDialog = nullptr;
499  }
500 }
501 
502 
504 {
512 
517 
520 
522 
524 
530 }
int Save(const TOOL_EVENT &aEvent)
int DefaultPadProperties(const TOOL_EVENT &aEvent)
Edit the properties used for new pad creation.
static TOOL_ACTION pinLibrary
Definition: actions.h:112
void BuildListOfNets()
Definition: board.h:726
FOOTPRINT_WIZARD_FRAME.
bool HandleUnsavedChanges(wxWindow *aParent, const wxString &aMessage, const std::function< bool()> &aSaveFunction)
Display a dialog with Save, Cancel and Discard Changes buttons.
Definition: confirm.cpp:208
void LoadFootprintFromLibrary(LIB_ID aFPID)
const UTF8 & GetLibItemName() const
Definition: lib_id.h:106
TOOL_MENU m_menu
The functions below are not yet implemented - their interface may change.
static TOOL_ACTION footprintProperties
Definition: pcb_actions.h:372
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:56
void ForceRefresh()
Force a redraw.
void ReCreateHToolbar() override
Create the main horizontal toolbar for the footprint editor.
DIALOG_FOOTPRINT_CHECKER * m_checkerDialog
KIGFX::VIEW_CONTROLS * GetViewControls() const
Return a pointer to the #VIEW_CONTROLS instance used in the panel.
int PasteFootprint(const TOOL_EVENT &aEvent)
BOARD * board() const
This file is part of the common library.
static TOOL_ACTION checkFootprint
Definition: pcb_actions.h:375
static TOOL_ACTION cleanupGraphics
Definition: pcb_actions.h:321
virtual void Update3DView(bool aReloadRequest, const wxString *aTitle=nullptr)
Update the 3D view, if the viewer is opened by this frame.
std::unique_ptr< FOOTPRINT > m_copiedFootprint
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:46
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:215
static TOOL_ACTION zoomFitScreen
Definition: actions.h:99
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:141
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:345
bool Init() override
Init() is called once upon a registration of the tool.
int ImportFootprint(const TOOL_EVENT &aEvent)
static TOOL_ACTION unpinLibrary
Definition: actions.h:113
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
FOOTPRINT_EDIT_FRAME * m_frame
bool IsValid() const
Check if this LID_ID is valid.
Definition: lib_id.h:168
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
int CreateFootprint(const TOOL_EVENT &aEvent)
static TOOL_ACTION createFootprint
Definition: pcb_actions.h:357
static TOOL_ACTION saveCopyAs
Definition: actions.h:56
static TOOL_ACTION cutFootprint
Definition: pcb_actions.h:366
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
Definition: tool_event.cpp:70
static TOOL_ACTION copyFootprint
Definition: pcb_actions.h:367
int CleanupGraphics(const TOOL_EVENT &aEvent)
bool IsContentModified() override
Get if any footprints or libraries have been modified but not saved.
int ToggleFootprintTree(const TOOL_EVENT &aEvent)
PCB_BASE_EDIT_FRAME * frame() const
virtual void Zoom_Automatique(bool aWarpPointer)
Redraw the screen with best zoom level and the best centering that shows all the page or the board.
void ReCreateMenuBar() override
(Re)Create the menubar for the Footprint Editor frame
void ExportFootprint(FOOTPRINT *aFootprint)
Create a file containing only one footprint.
void SyncLibraryTree(bool aProgress)
Synchronize the footprint library tree to the current state of the footprint library table.
void RegenerateLibraryTree()
Filter, sort, and redisplay the library tree.
bool Clear_Pcb(bool aQuery)
Delete all and reinitialize the current board.
Definition: initpcb.cpp:96
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const override
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: pcb_view.cpp:92
static TOOL_ACTION toggleFootprintTree
Definition: pcb_actions.h:350
FOOTPRINT * GetFirstFootprint() const
Gets the first footprint on the board or nullptr.
Definition: board.h:373
#define NULL
VECTOR2< double > VECTOR2D
Definition: vector2d.h:622
int CutCopyFootprint(const TOOL_EVENT &aEvent)
bool SaveLibraryAs(const wxString &aLibraryPath)
Save a library to a new name and/or library type.
void OnModify() override
Must be called after a footprint change in order to set the "modify" flag of the current screen and p...
BOARD_DRC_ITEMS_PROVIDER is an implementation of the RC_ITEMS_PROVIDER interface which uses a BOARD i...
static TOOL_ACTION exportFootprint
Definition: pcb_actions.h:370
void FocusOnLibID(const LIB_ID &aLibID)
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
wxString GetFullURI(const wxString &aLibNickname, bool aExpandEnvVars=true) const
Return the full URI of the library mapped to aLibNickname.
static TOOL_ACTION editFootprint
Definition: pcb_actions.h:364
static TOOL_ACTION save
Definition: actions.h:54
LIB_ID GetTargetFPID() const
Return the LIB_ID of the part selected in the footprint tree, or the loaded part if there is no selec...
bool SaveFootprintInLibrary(FOOTPRINT *aFootprint, const wxString &aLibraryName)
Generic, UI-independent tool event.
Definition: tool_event.h:173
FOOTPRINT * footprint() const
KIGFX::PCB_VIEW * view() const
int Revert(const TOOL_EVENT &aEvent)
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:92
FOOTPRINT * LoadFootprint(const LIB_ID &aFootprintId)
Attempt to load aFootprintId from the footprint library table.
const LIB_ID & GetFPID() const
Definition: footprint.h:190
int NewFootprint(const TOOL_EVENT &aEvent)
virtual void SetCrossHairCursorPosition(const VECTOR2D &aPosition, bool aWarpView=true)=0
Move the graphic crosshair cursor to the requested position expressed in world coordinates.
Model class in the component selector Model-View-Adapter (mediated MVC) architecture.
LIB_TREE_NODE * GetCurrentTreeNode() const
static TOOL_ACTION importFootprint
Definition: pcb_actions.h:369
bool Show(bool show) override
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
void AddSeparator(int aOrder=ANY_ORDER)
Add a separator to the menu.
virtual FP_LIB_TABLE * PcbFootprintLibs(KIWAY &aKiway)
Return the table of footprint libraries.
int SetLibNickname(const UTF8 &aNickname)
Override the logical library name portion of the LIB_ID to aNickname.
Definition: lib_id.cpp:193
void setTransitions() override
< Set up handlers for various events.
FOOTPRINT * CreateNewFootprint(const wxString &aFootprintName)
Creates a new footprint, at position 0,0.
void SetFPID(const LIB_ID &aFPID)
Definition: footprint.h:191
static TOOL_ACTION defaultPadProperties
Definition: pcb_actions.h:373
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
int EditFootprint(const TOOL_EVENT &aEvent)
int DeleteFootprint(const TOOL_EVENT &aEvent)
int CheckFootprint(const TOOL_EVENT &aEvent)
void SetMarkersProvider(RC_ITEMS_PROVIDER *aProvider)
static TOOL_ACTION saveAs
Definition: actions.h:55
LIB_ID GetLoadedFPID() const
Return the LIB_ID of the part being edited.
int ExportFootprint(const TOOL_EVENT &aEvent)
#define _(s)
Definition: 3d_actions.cpp:33
enum TYPE m_Type
bool SaveFootprintAs(FOOTPRINT *aFootprint)
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
int UnpinLibrary(const TOOL_EVENT &aEvent)
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:203
static TOOL_ACTION pasteFootprint
Definition: pcb_actions.h:368
int SaveAs(const TOOL_EVENT &aEvent)
void AddFootprintToBoard(FOOTPRINT *aFootprint) override
Override from PCB_BASE_EDIT_FRAME which adds a footprint to the editor's dummy board,...
void RefreshLibraryTree()
Reload displayed items and sets view.
BOARD * GetBoard() const
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:42
void SetModify()
Definition: base_screen.h:59
void SetPosition(const wxPoint &aPos) override
Definition: footprint.cpp:1437
PCB_DRAW_PANEL_GAL * canvas() const
bool SaveFootprint(FOOTPRINT *aFootprint)
Save in an existing library a given footprint.
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Add a menu entry to run a TOOL_ACTION on selected items.
virtual void ClearUndoRedoList()
Clear the undo and redo list using ClearUndoORRedoList()
static TOOL_ACTION deleteFootprint
Definition: pcb_actions.h:365
int PinLibrary(const TOOL_EVENT &aEvent)
bool FootprintExists(const wxString &aNickname, const wxString &aFootprintName)
Indicates whether or not the given footprint already exists in the given library.
LIB_ID GetTreeFPID() const
Return the LIB_ID of the part or library selected in the footprint tree.
static TOOL_ACTION revert
Definition: actions.h:58
static TOOL_ACTION newFootprint
Definition: pcb_actions.h:354
int Properties(const TOOL_EVENT &aEvent)
FOOTPRINT * ImportFootprint(const wxString &aName=wxT(""))
Read a file containing only one footprint.
bool empty() const
Definition: utf8.h:103