KiCad PCB EDA Suite
dialog_edit_component_in_lib.cpp
Go to the documentation of this file.
1 
5 /*
6  * This program source code file is part of KiCad, a free EDA CAD application.
7  *
8  * Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, you may find one here:
22  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
23  * or you may search the http://www.gnu.org website for the version 2 license,
24  * or you may write to the Free Software Foundation, Inc.,
25  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26  */
27 
28 #include <fctsys.h>
29 #include <kiway.h>
30 #include <common.h>
31 #include <confirm.h>
32 #include <gestfich.h>
33 #include <pgm_base.h>
34 
35 #include <general.h>
36 #include <libeditframe.h>
37 #include <class_library.h>
38 #include <eeschema_id.h> // for MAX_UNIT_COUNT_PER_PACKAGE definition
39 #include <symbol_lib_table.h>
40 
42 
44 
47 {
48  m_Parent = aParent;
49  m_RecreateToolbar = false;
50 
51  initDlg();
52 
53  // Now all widgets have the size fixed, call FinishDialogSettings
55 }
56 
57 
59 {
60  m_lastOpenedPage = m_NoteBook->GetSelection( );
61 }
62 
63 /* Initialize state of check boxes and texts
64 */
66 {
67  m_AliasLocation = -1;
68 
69  LIB_PART* component = m_Parent->GetCurPart();
70 
71  if( component == NULL )
72  {
73  SetTitle( _( "Library Component Properties" ) );
74  return;
75  }
76 
77  wxString title;
78  bool isRoot = m_Parent->GetAliasName().CmpNoCase( component->GetName() ) == 0;
79 
80  if( !isRoot )
81  {
82  title.Printf( _( "Properties for %s (alias of %s)" ),
84  GetChars( component->GetName() ) );
85  }
86  else
87  title.Printf( _( "Properties for %s" ), GetChars( component->GetName() ) );
88 
89  SetTitle( title );
90  InitPanelDoc();
92 
93  if( isRoot && component->GetAliasCount() == 1 )
94  m_ButtonDeleteAllAlias->Enable( false );
95 
96  /* Place list of alias names in listbox */
97  m_PartAliasListCtrl->Append( component->GetAliasNames( false ) );
98 
99  if( component->GetAliasCount() <= 1 )
100  {
101  m_ButtonDeleteAllAlias->Enable( false );
102  m_ButtonDeleteOneAlias->Enable( false );
103  }
104 
105  /* Read the Footprint Filter list */
106  m_FootprintFilterListBox->Append( component->GetFootPrints() );
107 
108  if( component->GetFootPrints().GetCount() == 0 )
109  {
110  m_ButtonDeleteAllFootprintFilter->Enable( false );
111  m_ButtonDeleteOneFootprintFilter->Enable( false );
112  m_buttonEditOneFootprintFilter->Enable( false );
113  }
114 
115  m_NoteBook->SetSelection( m_lastOpenedPage );
116 
117  m_stdSizerButtonOK->SetDefault();
118 }
119 
120 
122 {
123  EndModal( wxID_CANCEL );
124 }
125 
126 
127 
129 {
130  LIB_ALIAS* alias;
131  LIB_PART* component = m_Parent->GetCurPart();
132 
133  if( component == NULL )
134  return;
135 
136  wxString aliasname = m_Parent->GetAliasName();
137 
138  if( aliasname.IsEmpty() )
139  return;
140 
141  alias = component->GetAlias( aliasname );
142 
143  if( alias != NULL )
144  {
145  m_DocCtrl->SetValue( alias->GetDescription() );
146  m_KeywordsCtrl->SetValue( alias->GetKeyWords() );
147  m_DocfileCtrl->SetValue( alias->GetDocFileName() );
148  }
149 }
150 
151 
152 /*
153  * create the basic panel for component properties editing
154  */
156 {
157  LIB_PART* component = m_Parent->GetCurPart();
158 
159  if( m_Parent->GetShowDeMorgan() )
160  m_AsConvertButt->SetValue( true );
161 
162  int maxUnits = MAX_UNIT_COUNT_PER_PACKAGE;
163  m_SelNumberOfUnits->SetRange (1, maxUnits );
164 
166  _( "Number of Units (max allowed %d)" ), maxUnits ) );
167 
168 
169  /* Default values for a new component. */
170  if( component == NULL )
171  {
172  m_ShowPinNumButt->SetValue( true );
173  m_ShowPinNameButt->SetValue( true );
174  m_PinsNameInsideButt->SetValue( true );
175  m_SelNumberOfUnits->SetValue( 1 );
176  m_SetSkew->SetValue( 40 );
177  m_OptionPower->SetValue( false );
178  m_OptionPartsLocked->SetValue( false );
179  return;
180  }
181 
182  m_ShowPinNumButt->SetValue( component->ShowPinNumbers() );
183  m_ShowPinNameButt->SetValue( component->ShowPinNames() );
184  m_PinsNameInsideButt->SetValue( component->GetPinNameOffset() != 0 );
185  m_SelNumberOfUnits->SetValue( component->GetUnitCount() );
186  m_SetSkew->SetValue( component->GetPinNameOffset() );
187  m_OptionPower->SetValue( component->IsPower() );
188  m_OptionPartsLocked->SetValue( component->UnitsLocked() && component->GetUnitCount() > 1 );
189 }
190 
191 
192 void DIALOG_EDIT_COMPONENT_IN_LIBRARY::OnOkClick( wxCommandEvent& event )
193 {
194  /* Update the doc, keyword and doc filename strings */
195  LIB_ALIAS* alias;
196  LIB_PART* component = m_Parent->GetCurPart();
197 
198  if( component == NULL )
199  {
200  EndModal( wxID_CANCEL );
201  return;
202  }
203 
204  m_Parent->SaveCopyInUndoList( component );
205 
206  alias = component->GetAlias( m_Parent->GetAliasName() );
207 
208  wxCHECK_RET( alias != NULL,
209  wxT( "Alias \"" ) + m_Parent->GetAliasName() + wxT( "\" of component \"" ) +
210  component->GetName() + wxT( "\" does not exist." ) );
211 
212  alias->SetDescription( m_DocCtrl->GetValue() );
213  alias->SetKeyWords( m_KeywordsCtrl->GetValue() );
214  alias->SetDocFileName( m_DocfileCtrl->GetValue() );
215 
216  component->SetAliases( m_PartAliasListCtrl->GetStrings() );
217 
218  int unitCount = m_SelNumberOfUnits->GetValue();
219  ChangeNbUnitsPerPackage( unitCount );
220 
221  if( m_AsConvertButt->GetValue() )
222  {
223  if( !m_Parent->GetShowDeMorgan() )
224  {
225  m_Parent->SetShowDeMorgan( true );
226  SetUnsetConvert();
227  }
228  }
229  else
230  {
231  if( m_Parent->GetShowDeMorgan() )
232  {
233  m_Parent->SetShowDeMorgan( false );
234  SetUnsetConvert();
235  }
236  }
237 
238  component->SetShowPinNumbers( m_ShowPinNumButt->GetValue() );
239  component->SetShowPinNames( m_ShowPinNameButt->GetValue() );
240 
241  if( m_PinsNameInsideButt->GetValue() == false )
242  component->SetPinNameOffset( 0 ); // pin text outside the body (name is on the pin)
243  else
244  {
245  component->SetPinNameOffset( m_SetSkew->GetValue() );
246  // Ensure component->m_TextInside != 0, because the meaning is "text outside".
247  if( component->GetPinNameOffset() == 0 )
248  component->SetPinNameOffset( 20 ); // give a reasonnable value
249  }
250 
251  if( m_OptionPower->GetValue() == true )
252  component->SetPower();
253  else
254  component->SetNormal();
255 
256  /* Set the option "Units locked".
257  * Obviously, cannot be true if there is only one part */
258  component->LockUnits( m_OptionPartsLocked->GetValue() );
259 
260  if( component->GetUnitCount() <= 1 )
261  component->LockUnits( false );
262 
263  /* Update the footprint filter list */
264  component->GetFootPrints().Clear();
265  component->GetFootPrints() = m_FootprintFilterListBox->GetStrings();
266 
267  EndModal( wxID_OK );
268 }
269 
270 
272 {
273  if( m_Parent == NULL )
274  return;
275 
276  LIB_ALIAS* parent_alias;
277  LIB_PART* component = m_Parent->GetCurPart();
278 
279  if( component == NULL )
280  return;
281 
282  // search for the main alias: this is the first alias in alias list
283  // something like the main component
284  parent_alias = component->GetAlias( 0 );
285 
286  if( parent_alias == NULL ) // Should never occur (bug)
287  return;
288 
289  m_DocCtrl->SetValue( parent_alias->GetDescription() );
290  m_DocfileCtrl->SetValue( parent_alias->GetDocFileName() );
291  m_KeywordsCtrl->SetValue( parent_alias->GetKeyWords() );
292 }
293 
294 
296 {
297  if( m_PartAliasListCtrl->FindString( m_Parent->GetAliasName() ) != wxNOT_FOUND )
298  {
299  wxString msg;
300  msg.Printf( _( "Alias <%s> cannot be removed while it is being edited!" ),
302  DisplayError( this, msg );
303  return;
304  }
305 
306  if( IsOK( this, _( "Remove all aliases from list?" ) ) )
307  {
308  m_PartAliasListCtrl->Clear();
309  m_ButtonDeleteAllAlias->Enable( false );
310  m_ButtonDeleteOneAlias->Enable( false );
311  }
312 }
313 
314 
315 /* Add a new name to the alias list box
316  * New name cannot be the root name, and must not exists
317  */
319 {
320  wxString aliasname;
321  LIB_PART* component = m_Parent->GetCurPart();
322  wxString library = m_Parent->GetCurLib();
323 
324  if( component == NULL )
325  return;
326 
327  wxTextEntryDialog dlg( this, _( "New Alias:" ), _( "Symbol alias:" ), aliasname );
328 
329  if( dlg.ShowModal() != wxID_OK )
330  return; // cancelled by user
331 
332  aliasname = dlg.GetValue( );
333 
334  aliasname.Replace( wxT( " " ), wxT( "_" ) );
335 
336  if( aliasname.IsEmpty() )
337  return;
338 
339  if( m_PartAliasListCtrl->FindString( aliasname ) != wxNOT_FOUND )
340  {
341  wxString msg;
342  msg.Printf( _( "Alias or component name <%s> already in use." ),
343  GetChars( aliasname ) );
344  DisplayError( this, msg );
345  return;
346  }
347 
348  if( !library.empty() && Prj().SchSymbolLibTable()->LoadSymbol( library, aliasname ) != NULL )
349  {
350  wxString msg;
351  msg.Printf( _( "Symbol name '%s' already exists in library '%s'." ), aliasname, library );
352  DisplayError( this, msg );
353  return;
354  }
355 
356  m_PartAliasListCtrl->Append( aliasname );
357 
358  if( m_Parent->GetAliasName().CmpNoCase( component->GetName() ) == 0 )
359  m_ButtonDeleteAllAlias->Enable( true );
360 
361  m_ButtonDeleteOneAlias->Enable( true );
362 }
363 
364 
366 {
367  wxString aliasname = m_PartAliasListCtrl->GetStringSelection();
368 
369  if( aliasname.IsEmpty() )
370  return;
371 
372  if( aliasname.CmpNoCase( m_Parent->GetAliasName() ) == 0 )
373  {
374  wxString msg;
375  msg.Printf( _( "Alias <%s> cannot be removed while it is being edited!" ),
376  GetChars( aliasname ) );
377  DisplayError( this, msg );
378  return;
379  }
380 
381  m_PartAliasListCtrl->Delete( m_PartAliasListCtrl->GetSelection() );
382  LIB_PART* component = m_Parent->GetCurPart();
383 
384  if( component )
385  component->RemoveAlias( aliasname );
386 
387  if( m_PartAliasListCtrl->IsEmpty() )
388  {
389  m_ButtonDeleteAllAlias->Enable( false );
390  m_ButtonDeleteOneAlias->Enable( false );
391  }
392 }
393 
394 
395 /*
396  * Change the number of parts per package.
397  */
399 {
400  LIB_PART* part = m_Parent->GetCurPart();
401 
402  if( !part || part->GetUnitCount() == MaxUnit || MaxUnit < 1 )
403  return false;
404 
405  if( MaxUnit < part->GetUnitCount()
406  && !IsOK( this, _( "Delete extra parts from component?" ) ) )
407  return false;
408 
409  part->SetUnitCount( MaxUnit );
410  return true;
411 }
412 
413 
414 /*
415  * Set or clear the component alternate body style ( DeMorgan ).
416  */
418 {
419  LIB_PART* component = m_Parent->GetCurPart();
420 
421  if( component == NULL || ( m_Parent->GetShowDeMorgan() == component->HasConversion() ) )
422  return false;
423 
424  if( m_Parent->GetShowDeMorgan() )
425  {
426  if( !IsOK( this, _( "Add new pins for alternate body style ( DeMorgan ) to component?" ) ) )
427  return false;
428  }
429  else if( component->HasConversion() )
430  {
431  if( !IsOK( this, _( "Delete alternate body style (DeMorgan) draw items from component?" ) ) )
432  {
433  m_Parent->SetShowDeMorgan( true );
434  return false;
435  }
436  }
437 
438  component->SetConversion( m_Parent->GetShowDeMorgan() );
439  m_Parent->OnModify();
440 
441  return true;
442 }
443 
444 
446 {
447  PROJECT& prj = Prj();
448  SEARCH_STACK* search = prj.SchSearchS();
449 
450  wxString mask = wxT( "*" );
451  wxString docpath = prj.GetRString( PROJECT::DOC_PATH );
452 
453  if( !docpath )
454  docpath = search->LastVisitedPath( wxT( "doc" ) );
455 
456  wxString fullFileName = EDA_FILE_SELECTOR( _( "Doc Files" ),
457  docpath,
458  wxEmptyString,
459  wxEmptyString,
460  mask,
461  this,
462  wxFD_OPEN,
463  true );
464  if( fullFileName.IsEmpty() )
465  return;
466 
467  /* If the path is already in the library search paths
468  * list, just add the library name to the list. Otherwise, add
469  * the library name with the full or relative path.
470  * the relative path, when possible is preferable,
471  * because it preserve use of default libraries paths, when the path is a sub path of
472  * these default paths
473  */
474  wxFileName fn = fullFileName;
475 
476  prj.SetRString( PROJECT::DOC_PATH, fn.GetPath() );
477 
478  wxString filename = search->FilenameWithRelativePathInSearchList(
479  fullFileName, wxPathOnly( Prj().GetProjectFullName() ) );
480 
481  // Filenames are always stored in unix like mode, ie separator "\" is stored as "/"
482  // to ensure files are identical under unices and windows
483 #ifdef __WINDOWS__
484  filename.Replace( wxT( "\\" ), wxT( "/" ) );
485 #endif
486  m_DocfileCtrl->SetValue( filename );
487 }
488 
489 
491 {
492  if( IsOK( this, _( "OK to delete the footprint filter list ?" ) ) )
493  {
494  m_FootprintFilterListBox->Clear();
495  m_ButtonDeleteAllFootprintFilter->Enable( false );
496  m_ButtonDeleteOneFootprintFilter->Enable( false );
497  m_buttonEditOneFootprintFilter->Enable( false );
498  }
499 }
500 
501 
502 /* Add a new name to the footprint filter list box
503  * Obvioulsy, cannot be void
504  */
506 {
507  wxString Line;
508  LIB_PART* component = m_Parent->GetCurPart();
509 
510  if( component == NULL )
511  return;
512 
513  wxTextEntryDialog dlg( this, _( "Add Footprint Filter" ), _( "Footprint Filter" ), Line );
514  if( dlg.ShowModal() != wxID_OK )
515  return; // cancelled by user
516 
517  Line = dlg.GetValue();
518  Line.Replace( wxT( " " ), wxT( "_" ) );
519 
520  if( Line.IsEmpty() )
521  return;
522 
523  /* test for an existing name: */
524  int index = m_FootprintFilterListBox->FindString( Line );
525 
526  if( index != wxNOT_FOUND )
527  {
528  wxString msg;
529 
530  msg.Printf( _( "Foot print filter <%s> is already defined." ), GetChars( Line ) );
531  DisplayError( this, msg );
532  return;
533  }
534 
535  m_FootprintFilterListBox->Append( Line );
536  m_ButtonDeleteAllFootprintFilter->Enable( true );
537  m_ButtonDeleteOneFootprintFilter->Enable( true );
538  m_buttonEditOneFootprintFilter->Enable( true );
539 }
540 
541 
543 {
544  LIB_PART* component = m_Parent->GetCurPart();
545  int ii = m_FootprintFilterListBox->GetSelection();
546 
547  m_FootprintFilterListBox->Delete( ii );
548 
549  if( !component || ( m_FootprintFilterListBox->GetCount() == 0 ) )
550  {
551  m_ButtonDeleteAllFootprintFilter->Enable( false );
552  m_ButtonDeleteOneFootprintFilter->Enable( false );
553  m_buttonEditOneFootprintFilter->Enable( false );
554  }
555 }
556 
558 {
559  int idx = m_FootprintFilterListBox->GetSelection();
560 
561  if( idx < 0 )
562  return;
563 
564  wxString filter = m_FootprintFilterListBox->GetStringSelection();
565 
566  wxTextEntryDialog dlg( this, wxEmptyString, _( "Edit footprint filter" ), filter );
567 
568  if( dlg.ShowModal() != wxID_OK )
569  return; // Aborted by user
570 
571  filter = dlg.GetValue();
572 
573  if( filter.IsEmpty() )
574  return; // do not accept blank filter.
575 
576  m_FootprintFilterListBox->SetString( idx, filter );
577 }
578 
579 
581 {
582  if( m_SelNumberOfUnits->GetValue() <= 1 )
583  m_OptionPartsLocked->Enable( false );
584  else
585  m_OptionPartsLocked->Enable( true );
586 }
bool UnitsLocked() const
Part library alias object definition.
void SetConversion(bool aSetConvert)
Set or clear the alternate body style (DeMorgan) for the part.
void SetPower()
DIALOG_EDIT_COMPONENT_IN_LIBRARY(LIB_EDIT_FRAME *parent)
Constructors.
Class PROJECT holds project specific data.
Definition: project.h:56
int GetPinNameOffset()
bool HasConversion() const
Test if part has more than one body conversion type (DeMorgan).
This file is part of the common library TODO brief description.
bool IsPower() const
LIB_ALIAS * GetAlias(size_t aIndex)
This file is part of the common library.
void CopyDocFromRootToAlias(wxCommandEvent &event) override
void AddFootprintFilter(wxCommandEvent &event) override
void AddAliasOfPart(wxCommandEvent &event) override
void FinishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
void OnUpdateInterchangeableUnits(wxUpdateUIEvent &event) override
void OnModify()
Must be called after a schematic change in order to set the "modify" flag of the current screen...
#define MAX_UNIT_COUNT_PER_PACKAGE
The maximum number of units per package.
Definition: eeschema_id.h:48
Class SEARCH_STACK looks for files in a number of places.
Definition: search_stack.h:41
void DeleteAliasOfPart(wxCommandEvent &event) override
size_t GetAliasCount() const
void SetDocFileName(const wxString &aDocFileName)
void SetShowDeMorgan(bool show)
Definition: libeditframe.h:435
void OnCancelClick(wxCommandEvent &event) override
void OnOkClick(wxCommandEvent &event) override
bool ShowPinNames()
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
bool ShowPinNumbers()
LIB_PART * GetCurPart() const
Return the current part being edited or NULL if none selected.
Definition: libeditframe.h:158
void SetUnitCount(int count)
Set the units per part count.
const wxString & GetName() const
wxString GetDescription() const
wxString EDA_FILE_SELECTOR(const wxString &aTitle, const wxString &aPath, const wxString &aFileName, const wxString &aExtension, const wxString &aWildcard, wxWindow *aParent, int aStyle, const bool aKeepWorkingDirectory, const wxPoint &aPosition, wxString *aMruPath)
Function EDA_FILE_SELECTOR.
Definition: gestfich.cpp:82
Class LIB_PART defines a library part object.
void EditOneFootprintFilter(wxCommandEvent &event) override
wxString GetCurLib() const
The nickname of the current library being edited and empty string if none.
void DeleteAllFootprintFilter(wxCommandEvent &event) override
void SetDescription(const wxString &aDescription)
void DeleteOneFootprintFilter(wxCommandEvent &event) override
VTBL_ENTRY void SetRString(RSTRING_T aStringId, const wxString &aString)
Function SetRString stores a "retained string", which is any session and project specific string iden...
Definition: project.cpp:173
int GetUnitCount() const
wxString GetDocFileName() const
void SetAliases(const wxArrayString &aAliasList)
const wxString & GetAliasName()
Definition: libeditframe.h:404
VTBL_ENTRY const wxString & GetRString(RSTRING_T aStringId)
Function GetRString returns a "retained string", which is any session and project specific string ide...
Definition: project.cpp:188
The symbol library editor main window.
Definition: libeditframe.h:58
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
see class PGM_BASE
void RemoveAlias(const wxString &aName)
bool GetShowDeMorgan()
Definition: libeditframe.h:433
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
void SetShowPinNumbers(bool aShow)
Set or clear the pin number visibility flag.
void SetKeyWords(const wxString &aKeyWords)
const wxString LastVisitedPath(const wxString &aSubPathToSearch=wxEmptyString)
Function LastVisitedPath is a quirky function inherited from old code that seems to serve particular ...
wxArrayString GetAliasNames(bool aIncludeRoot=true) const
wxArrayString & GetFootPrints()
void DeleteAllAliasOfPart(wxCommandEvent &event) override
void BrowseAndSelectDocFile(wxCommandEvent &event) override
The common library.
Class DIALOG_EDIT_COMPONENT_IN_LIBRARY_BASE.
Definition for part library class.
void SetShowPinNames(bool aShow)
Set or clear the pin name visibility flag.
void SetPinNameOffset(int aOffset)
Set the offset in mils of the pin name text from the pin symbol.
wxString GetKeyWords() const
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:73
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Function IsOK displays a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:131
Definition of class LIB_EDIT_FRAME.
wxString FilenameWithRelativePathInSearchList(const wxString &aFullFilename, const wxString &aBaseDir)
Function FilenameWithRelativePathInSearchList returns the shortest possible path which can be use lat...
void LockUnits(bool aLockUnits)
void SetNormal()
void SaveCopyInUndoList(EDA_ITEM *ItemToCopy)
Create a copy of the current component, and save it in the undo list.