KiCad PCB EDA Suite
footprint_editor_utils.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) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include <fctsys.h>
25 #include <kiface_i.h>
26 #include <kiway.h>
27 #include <kiway_express.h>
28 #include <pcb_draw_panel_gal.h>
29 #include <confirm.h>
30 #include <gestfich.h>
31 #include <pgm_base.h>
32 #include <trigo.h>
34 #include <macros.h>
35 #include <invoke_pcb_dialog.h>
36 #include <pcb_layer_widget.h>
37 #include <board_commit.h>
38 #include <view/view.h>
39 #include <class_board.h>
40 #include <class_module.h>
41 #include <class_edge_mod.h>
42 #include <pcb_layer_box_selector.h>
43 #include <ratsnest_data.h>
44 #include <pcbnew.h>
45 #include <pcbnew_id.h>
46 #include <footprint_edit_frame.h>
47 #include <footprint_viewer_frame.h>
48 #include <footprint_tree_pane.h>
49 #include <fp_lib_table.h>
50 #include <widgets/lib_tree.h>
51 #include <collectors.h>
52 #include <tool/tool_manager.h>
53 #include <tools/pcb_actions.h>
55 #include <dialog_move_exact.h>
56 #include <dialog_create_array.h>
58 #include <menus_helpers.h>
59 #include <footprint_wizard_frame.h>
60 #include <config_params.h>
61 
62 #include <functional>
63 using namespace std::placeholders;
64 
65 
66 void FOOTPRINT_EDIT_FRAME::LoadModuleFromBoard( wxCommandEvent& event )
67 {
68  Load_Module_From_BOARD( NULL );
69 }
70 
71 
73 {
74  bool is_last_fp_from_brd = IsCurrentFPFromBoard();
75 
76  MODULE* module = LoadFootprint( aFPID );
77 
78  if( !module )
79  return;
80 
81  if( !Clear_Pcb( true ) )
82  return;
83 
84  GetCanvas()->GetViewControls()->SetCrossHairCursorPosition( VECTOR2D( 0, 0 ), false );
85  AddModuleToBoard( module );
86 
87  auto fp = GetBoard()->GetFirstModule();
88 
89  if( fp )
90  {
91  fp->ClearFlags();
92 
93  // if either m_Reference or m_Value are gone, reinstall them -
94  // otherwise you cannot see what you are doing on board
95  TEXTE_MODULE* ref = &fp->Reference();
96  TEXTE_MODULE* val = &fp->Value();
97 
98  if( val && ref )
99  {
100  ref->SetType( TEXTE_MODULE::TEXT_is_REFERENCE ); // just in case ...
101 
102  if( ref->GetLength() == 0 )
103  ref->SetText( wxT( "Ref**" ) );
104 
105  val->SetType( TEXTE_MODULE::TEXT_is_VALUE ); // just in case ...
106 
107  if( val->GetLength() == 0 )
108  val->SetText( wxT( "Val**" ) );
109  }
110  }
111 
112  Zoom_Automatique( false );
113 
114  Update3DView( true );
115 
116  GetScreen()->ClrModify();
117 
118  updateView();
119  GetCanvas()->Refresh();
120 
121  // Update the save items if needed.
122  if( is_last_fp_from_brd )
123  {
124  ReCreateMenuBar();
125  ReCreateHToolbar();
126  }
127 
128  m_treePane->GetLibTree()->ExpandLibId( aFPID );
129  m_treePane->GetLibTree()->CenterLibId( aFPID );
130  m_treePane->GetLibTree()->RefreshLibTree(); // update highlighting
131 }
132 
133 
135 {
136  int id = event.GetId();
137  wxPoint pos;
138 
139  wxGetMousePosition( &pos.x, &pos.y );
140  pos.y += 20;
141 
142  switch( id )
143  {
145  {
146  LIB_ID selected = m_treePane->GetLibTree()->GetSelectedLibId();
147  MODULE* module = CreateNewModule( wxEmptyString );
148 
149  if( !module )
150  break;
151 
152  if( !Clear_Pcb( true ) )
153  break;
154 
155  GetCanvas()->GetViewControls()->SetCrossHairCursorPosition( VECTOR2D( 0, 0 ), false );
156  AddModuleToBoard( module );
157 
158  // Initialize data relative to nets and netclasses (for a new
159  // module the defaults are used)
160  // This is mandatory to handle and draw pads
162  module->SetPosition( wxPoint( 0, 0 ) );
163 
164  if( GetBoard()->GetFirstModule() )
166 
167  Zoom_Automatique( false );
168  GetScreen()->SetModify();
169 
170  // If selected from the library tree then go ahead and save it there
171  if( !selected.GetLibNickname().empty() )
172  {
173  LIB_ID fpid = module->GetFPID();
174  fpid.SetLibNickname( selected.GetLibNickname() );
175  module->SetFPID( fpid );
176  SaveFootprint( module );
177  GetScreen()->ClrModify();
178  }
179 
180  updateView();
181  GetCanvas()->Refresh();
182  Update3DView( true );
183 
184  SyncLibraryTree( false );
185  }
186  break;
187 
189  {
190  LIB_ID selected = m_treePane->GetLibTree()->GetSelectedLibId();
191 
192  if( IsContentModified() )
193  {
194  if( !HandleUnsavedChanges( this, _( "The current footprint has been modified. "
195  "Save changes?" ),
196  [&]() -> bool {
197  return SaveFootprint( GetBoard()->GetFirstModule() );
198  } ) )
199  {
200  break;
201  }
202  }
203 
204  auto wizard = (FOOTPRINT_WIZARD_FRAME*) Kiway().Player( FRAME_FOOTPRINT_WIZARD, true,
205  this );
206 
207  if( wizard->ShowModal( NULL, this ) )
208  {
209  // Creates the new footprint from python script wizard
210  MODULE* module = wizard->GetBuiltFootprint();
211 
212  if( module == NULL ) // i.e. if create module command aborted
213  break;
214 
215  Clear_Pcb( false );
216 
217  GetCanvas()->GetViewControls()->SetCrossHairCursorPosition( VECTOR2D( 0, 0 ), false );
218  // Add the new object to board
219  AddModuleToBoard( module );
220 
221  // Initialize data relative to nets and netclasses (for a new
222  // module the defaults are used)
223  // This is mandatory to handle and draw pads
225  module->SetPosition( wxPoint( 0, 0 ) );
226  module->ClearFlags();
227 
228  Zoom_Automatique( false );
229  GetScreen()->SetModify();
230 
231  // If selected from the library tree then go ahead and save it there
232  if( !selected.GetLibNickname().empty() )
233  {
234  LIB_ID fpid = module->GetFPID();
235  fpid.SetLibNickname( selected.GetLibNickname() );
236  module->SetFPID( fpid );
237  SaveFootprint( module );
238  GetScreen()->ClrModify();
239  }
240 
241  updateView();
242  GetCanvas()->Refresh();
243  Update3DView( true );
244 
245  SyncLibraryTree( false );
246  }
247 
248  wizard->Destroy();
249  }
250  break;
251 
252  case ID_MODEDIT_SAVE:
253  if( !GetBoard()->GetFirstModule() ) // no loaded footprint
254  break;
255 
256  if( GetTargetFPID() == GetLoadedFPID() )
257  {
258  if( SaveFootprint( GetBoard()->GetFirstModule() ) )
259  {
260  m_toolManager->GetView()->Update( GetBoard()->GetFirstModule() );
261 
262  GetCanvas()->ForceRefresh();
263  GetScreen()->ClrModify();
264  }
265  }
266 
267  m_treePane->GetLibTree()->RefreshLibTree();
268  break;
269 
270  case ID_MODEDIT_SAVE_AS:
271  if( GetTargetFPID().GetLibItemName().empty() )
272  {
273  // Save Library As
274  const wxString& src_libNickname = GetTargetFPID().GetLibNickname();
275  wxString src_libFullName = Prj().PcbFootprintLibs()->GetFullURI( src_libNickname );
276 
277  if( SaveLibraryAs( src_libFullName ) )
278  SyncLibraryTree( true );
279  }
280  else if( GetTargetFPID() == GetLoadedFPID() )
281  {
282  // Save Board Footprint As
283  MODULE* footprint = GetBoard()->GetFirstModule();
284 
285  if( footprint && SaveFootprintAs( footprint ) )
286  {
287  m_footprintNameWhenLoaded = footprint->GetFPID().GetLibItemName();
288  m_toolManager->GetView()->Update( footprint );
289  GetScreen()->ClrModify();
290 
291  GetCanvas()->ForceRefresh();
292  SyncLibraryTree( true );
293  }
294  }
295  else
296  {
297  // Save Selected Footprint As
298  MODULE* footprint = LoadFootprint( GetTargetFPID() );
299 
300  if( footprint && SaveFootprintAs( footprint ) )
301  SyncLibraryTree( true );
302  }
303 
304  m_treePane->GetLibTree()->RefreshLibTree();
305  break;
306 
308  SaveFootprintToBoard( true );
309  break;
310 
312  SetActiveLayer( ToLAYER_ID( m_selLayerBox->GetLayerSelection() ) );
313 
314  if( GetDisplayOptions().m_ContrastModeDisplay )
315  GetCanvas()->Refresh();
316  break;
317 
318  case ID_MODEDIT_CHECK:
319  // Currently: not implemented
320  break;
321 
322  default:
323  wxLogDebug( wxT( "FOOTPRINT_EDIT_FRAME::Process_Special_Functions error" ) );
324  break;
325  }
326 }
327 
328 
330 {
331 public:
333  {
334  m_nickname = aModule->GetFPID().GetLibNickname().wx_str();
335  m_fpname = aModule->GetFPID().GetLibItemName().wx_str();
336  m_pad_count = aModule->GetPadCount( DO_NOT_INCLUDE_NPTH );
337  m_unique_pad_count = aModule->GetUniquePadCount( DO_NOT_INCLUDE_NPTH );
338  m_keywords = aModule->GetKeywords();
339  m_doc = aModule->GetDescription();
340  m_loaded = true;
341  }
342 };
343 
344 
346 {
347  LIB_ID oldFPID = aModule->GetFPID();
348 
349  DIALOG_FOOTPRINT_FP_EDITOR dialog( this, aModule );
350  dialog.ShowModal();
351 
352  // Update library tree
353  BASIC_FOOTPRINT_INFO footprintInfo( aModule );
354  wxDataViewItem treeItem = m_adapter->FindItem( oldFPID );
355 
356  if( treeItem.IsOk() ) // Can be not found in tree if the current footprint is imported from file
357  // therefore not yet in tree.
358  {
359  static_cast<LIB_TREE_NODE_LIB_ID*>( treeItem.GetID() )->Update( &footprintInfo );
360  m_treePane->GetLibTree()->RefreshLibTree();
361  }
362 
363  updateTitle(); // in case of a name change...
364 
365  UpdateMsgPanel();
366 }
367 
368 
370 {
371  switch( aItem->Type() )
372  {
373  case PCB_PAD_T:
374  InstallPadOptionsFrame( static_cast<D_PAD*>( aItem ) );
375  break;
376 
377  case PCB_MODULE_T:
378  editFootprintProperties( (MODULE*) aItem );
379  GetCanvas()->Refresh();
380  break;
381 
382  case PCB_MODULE_TEXT_T:
383  InstallTextOptionsFrame( aItem );
384  break;
385 
386  case PCB_MODULE_EDGE_T :
387  InstallGraphicItemPropertiesDialog( aItem );
388  break;
389 
391  {
392  ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( aItem );
393  bool success = false;
394  if( zone )
395  {
396  ZONE_SETTINGS zoneSettings;
397  zoneSettings << *zone;
398  if( zone->GetIsKeepout() )
399  {
400  success = InvokeKeepoutAreaEditor( this, &zoneSettings );
401  }
402  else if( zone->IsOnCopperLayer() )
403  {
404  success = InvokeCopperZonesEditor( this, &zoneSettings );
405  }
406  else
407  {
408  success = InvokeNonCopperZonesEditor( this, &zoneSettings );
409  }
410 
411  if( success )
412  {
413  BOARD_COMMIT commit( this );
414  commit.Modify( zone );
415  commit.Push( _( "Edit Zone" ) );
416  zoneSettings.ExportSetting( *zone );
417  }
418  }
419  }
420  break;
421 
422  default:
423  wxASSERT( 0 );
424  break;
425  }
426 }
427 
428 
430 {
431  return Settings().Colors().GetItemColor( LAYER_GRID );
432 }
433 
434 
436 {
438 
439  m_Layers->SelectLayer( aLayer );
440  m_Layers->OnLayerSelected();
441 
442  m_toolManager->RunAction( PCB_ACTIONS::layerChanged ); // notify other tools
443  GetCanvas()->SetFocus(); // allow capture of hotkeys
444  GetCanvas()->SetHighContrastLayer( aLayer );
445  GetCanvas()->Refresh();
446 }
447 
448 bool FOOTPRINT_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
449 {
450  if( ! Clear_Pcb( true ) )
451  return false; // //this command is aborted
452 
453  GetCanvas()->GetViewControls()->SetCrossHairCursorPosition( VECTOR2D( 0, 0 ), false );
454  Import_Module( aFileSet[0] );
455 
456  if( GetBoard()->GetFirstModule() )
458 
459  GetScreen()->ClrModify();
460  Zoom_Automatique( false );
461  GetCanvas()->Refresh();
462 
463  return true;
464 }
465 
466 
468 {
469  const std::string& payload = mail.GetPayload();
470 
471  switch( mail.Command() )
472  {
473  case MAIL_FP_EDIT:
474  if( !payload.empty() )
475  {
476  wxFileName fpFileName( payload );
477  wxString libNickname;
478  wxString msg;
479 
480  FP_LIB_TABLE* libTable = Prj().PcbFootprintLibs();
481  const LIB_TABLE_ROW* libTableRow = libTable->FindRowByURI( fpFileName.GetPath() );
482 
483  if( !libTableRow )
484  {
485  msg.Printf( _( "The current configuration does not include the footprint library\n"
486  "\"%s\".\nUse Manage Footprint Libraries to edit the configuration." ),
487  fpFileName.GetPath() );
488  DisplayErrorMessage( this, _( "Library not found in footprint library table." ), msg );
489  break;
490  }
491 
492  libNickname = libTableRow->GetNickName();
493 
494  if( !libTable->HasLibrary( libNickname, true ) )
495  {
496  msg.Printf( _( "The library with the nickname \"%s\" is not enabled\n"
497  "in the current configuration. Use Manage Footprint Libraries to\n"
498  "edit the configuration." ), libNickname );
499  DisplayErrorMessage( this, _( "Footprint library not enabled." ), msg );
500  break;
501  }
502 
503  LIB_ID fpId( libNickname, fpFileName.GetName() );
504 
505  if( m_treePane )
506  {
507  m_treePane->GetLibTree()->SelectLibId( fpId );
508  wxCommandEvent event( COMPONENT_SELECTED );
509  wxPostEvent( m_treePane, event );
510  }
511  }
512 
513  break;
514 
515  default:
516  ;
517  }
518 }
unsigned GetPadCount(INCLUDE_NPTH_T aIncludeNPTH=INCLUDE_NPTH_T(INCLUDE_NPTH)) const
GetPadCount returns the number of pads.
void BuildListOfNets()
Definition: class_board.h:716
FOOTPRINT_WIZARD_FRAME.
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:60
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:201
COMMIT & Modify(EDA_ITEM *aItem)
Modifies a given item in the model.
Definition: commit.h:103
KIWAY_EXPRESS carries a payload from one KIWAY_PLAYER to another within a PROJECT.
Definition: kiway_express.h:39
void OnEditItemRequest(BOARD_ITEM *aItem) override
const UTF8 & GetLibItemName() const
Definition: lib_id.h:114
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
Hold a record identifying a library accessed by the appropriate plug in object in the LIB_TABLE.
unsigned GetUniquePadCount(INCLUDE_NPTH_T aIncludeNPTH=INCLUDE_NPTH_T(INCLUDE_NPTH)) const
GetUniquePadCount returns the number of unique pads.
int InvokeKeepoutAreaEditor(PCB_BASE_FRAME *aCaller, ZONE_SETTINGS *aSettings)
Function InvokeKeepoutAreaEditor invokes up a modal dialog window for copper zone editing.
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:249
This file is part of the common library TODO brief description.
void SetActiveLayer(PCB_LAYER_ID aLayer) override
This file is part of the common library.
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
COLOR4D GetGridColor() override
PROJECT & Prj()
Definition: kicad.cpp:305
int InvokeNonCopperZonesEditor(PCB_BASE_FRAME *aParent, ZONE_SETTINGS *aSettings)
Function InvokeNonCopperZonesEditor invokes up a modal dialog window for non-copper zone editing.
Class that computes missing connections on a PCB.
bool OpenProjectFiles(const std::vector< wxString > &aFileSet, int aCtl=0) override
Load a KiCad board (.kicad_pcb) from aFileName.
void LoadModuleFromLibrary(LIB_ID aFPID)
The common library.
class D_PAD, a pad in a footprint
Definition: typeinfo.h:90
const LIB_ID & GetFPID() const
Definition: class_module.h:219
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
This file contains miscellaneous commonly used macros and functions.
class MODULE, a footprint
Definition: typeinfo.h:89
const wxString & GetNickName() const
PCB_LAYER_ID
A quick note on layer IDs:
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:111
#define NULL
VECTOR2< double > VECTOR2D
Definition: vector2d.h:593
VTBL_ENTRY KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=NULL)
Function Player returns the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:341
void editFootprintProperties(MODULE *aFootprint)
Run the Footprint Properties dialog and handle changes made in it.
wxString GetFullURI(const wxString &aLibNickname, bool aExpandEnvVars=true) const
Return the full URI of the library mapped to aLibNickname.
const LIB_TABLE_ROW * FindRowByURI(const wxString &aURI)
MODULE * GetFirstModule() const
Gets the first module in the list (used in footprint viewer/editor) or NULL if none.
Definition: class_board.h:275
Definition of file extensions used in Kicad.
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:97
void SetPosition(const wxPoint &aPos) override
virtual void SetActiveLayer(PCB_LAYER_ID aLayer)
Function SetActiveLayer will change the currently active layer to aLayer.
void ExportSetting(ZONE_CONTAINER &aTarget, bool aFullExport=true) const
Function ExportSetting copy settings to a given zone.
const wxString & GetKeywords() const
Definition: class_module.h:225
void SetType(TEXT_TYPE aType)
ZONE_SETTINGS handles zones parameters.
Definition: zone_settings.h:58
BOARD * GetBoard()
VTBL_ENTRY FP_LIB_TABLE * PcbFootprintLibs(KIWAY &aKiway)
Return the table of footprint libraries.
Definition: project.cpp:400
int SetLibNickname(const UTF8 &aNickname)
Override the logical library name portion of the LIB_ID to aNickname.
Definition: lib_id.cpp:193
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:93
void Process_Special_Functions(wxCommandEvent &event)
const wxString & GetDescription() const
Definition: class_module.h:222
int GetLength() const
static TOOL_ACTION layerChanged
Definition: pcb_actions.h:275
see class PGM_BASE
void LoadModuleFromBoard(wxCommandEvent &event)
Called from the main toolbar to load a footprint from board mainly to edit it.
Declaration of the eda_3d_viewer class.
#define _(s)
Definition: 3d_actions.cpp:31
wxString wx_str() const
Definition: utf8.cpp:51
static bool empty(const wxTextEntryBase *aCtrl)
BASIC_FOOTPRINT_INFO(MODULE *aModule)
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true) override
Executes the changes.
int InvokeCopperZonesEditor(PCB_BASE_FRAME *aCaller, ZONE_SETTINGS *aSettings)
Function InvokeCopperZonesEditor invokes up a modal dialog window for copper zone editing.
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: base_struct.h:256
Module description (excepted pads)
class ZONE_CONTAINER, managed by a footprint
Definition: typeinfo.h:95
MAIL_T Command()
Function Command returns the MAIL_T associated with this mail.
Definition: kiway_express.h:52
EDGE_MODULE class definition.
std::string & GetPayload()
Function Payload returns the payload, which can be any text but it typicall self identifying s-expres...
Definition: kiway_express.h:62
void SetFPID(const LIB_ID &aFPID)
Definition: class_module.h:220
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:823
void KiwayMailIn(KIWAY_EXPRESS &mail) override
Function KiwayMailIn receives KIWAY_EXPRESS messages from other players.
KICAD_T Type() const
Function Type()
Definition: base_struct.h:207
bool empty() const
Definition: utf8.h:108
KIWAY Kiway
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39