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-2019 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 <pgm_base.h>
33 #include <kiface_i.h>
34 #include <dialog_text_entry.h>
35 
36 #include <general.h>
37 #include <widgets/wx_grid.h>
39 #include <lib_edit_frame.h>
40 #include <class_library.h>
41 #include <symbol_lib_table.h>
42 #include <sch_item_struct.h>
43 #include <sch_component.h>
44 #include <dialog_helpers.h>
45 #include <bitmaps.h>
46 
47 #ifdef KICAD_SPICE
48 #include <dialog_spice_model.h>
50 #endif /* KICAD_SPICE */
51 
53 
54 
55 #define LibEditFieldsShownColumnsKey wxT( "LibEditFieldsShownColumns" )
56 
58 
59 
61  LIB_PART* aLibEntry ) :
63  m_Parent( aParent ),
64  m_libEntry( aLibEntry ),
65  m_currentAlias( wxNOT_FOUND ),
66  m_pinNameOffset( aParent, m_nameOffsetLabel, m_nameOffsetCtrl, m_nameOffsetUnits, true ),
67  m_delayedFocusCtrl( nullptr ),
68  m_delayedFocusGrid( nullptr ),
69  m_delayedFocusRow( -1 ),
70  m_delayedFocusColumn( -1 ),
71  m_delayedFocusPage( -1 )
72 {
74 
75  // Give a bit more room for combobox editors
76  m_grid->SetDefaultRowSize( m_grid->GetDefaultRowSize() + 4 );
77  m_aliasGrid->SetDefaultRowSize( m_aliasGrid->GetDefaultRowSize() + 4 );
78 
79  // Work around a bug in wxWidgets where it fails to recalculate the grid height
80  // after changing the default row size
81  m_aliasGrid->AppendRows( 1 );
82  m_aliasGrid->DeleteRows( m_grid->GetNumberRows() - 1, 1 );
83 
84  m_fields = new FIELDS_GRID_TABLE<LIB_FIELD>( this, aParent, m_libEntry );
86 
87  m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this ) );
88  m_aliasGrid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this ) );
89 
90  // Show/hide columns according to the user's preference
91  m_config->Read( LibEditFieldsShownColumnsKey, &m_shownColumns, wxT( "0 1 2 3 4 5 6 7" ) );
93  // Hide non-overridden rows in aliases grid
94  m_aliasGrid->HideRow( REFERENCE );
95  m_aliasGrid->HideRow( FOOTPRINT );
96 
97  wxGridCellAttr* attr = new wxGridCellAttr;
98  attr->SetReadOnly();
99  m_aliasGrid->SetColAttr( FDC_NAME, attr );
102 
103  attr = new wxGridCellAttr;
104  attr->SetEditor( new GRID_CELL_URL_EDITOR( this ) );
105  m_aliasGrid->SetAttr( DATASHEET, FDC_VALUE, attr );
106 
107  m_SymbolNameCtrl->SetValidator( SCH_FIELD_VALIDATOR( true, VALUE ) );
108 
109  // Configure button logos
110  m_bpAdd->SetBitmap( KiBitmap( small_plus_xpm ) );
111  m_bpDelete->SetBitmap( KiBitmap( trash_xpm ) );
112  m_bpMoveUp->SetBitmap( KiBitmap( small_up_xpm ) );
113  m_bpMoveDown->SetBitmap( KiBitmap( small_down_xpm ) );
114  m_addAliasButton->SetBitmap( KiBitmap( small_plus_xpm ) );
115  m_deleteAliasButton->SetBitmap( KiBitmap( trash_xpm ) );
116  m_addFilterButton->SetBitmap( KiBitmap( small_plus_xpm ) );
117  m_deleteFilterButton->SetBitmap( KiBitmap( trash_xpm ) );
118  m_editFilterButton->SetBitmap( KiBitmap( small_edit_xpm ) );
119 
120  m_stdSizerButtonOK->SetDefault();
121 
122 #ifndef KICAD_SPICE
123  m_spiceFieldsButton->Hide();
124 #endif
125 
126  // wxFormBuilder doesn't include this event...
127  m_grid->Connect( wxEVT_GRID_CELL_CHANGING, wxGridEventHandler( DIALOG_EDIT_COMPONENT_IN_LIBRARY::OnGridCellChanging ), NULL, this );
128  m_aliasGrid->Connect( wxEVT_GRID_CELL_CHANGING, wxGridEventHandler( DIALOG_EDIT_COMPONENT_IN_LIBRARY::OnAliasGridCellChanging ), NULL, this );
129 
130  m_grid->GetParent()->Layout();
131  m_aliasGrid->GetParent()->Layout();
132  Layout();
133 
135 }
136 
137 
139 {
140  m_lastOpenedPage = m_NoteBook->GetSelection( );
141 
143 
144  // Prevents crash bug in wxGrid's d'tor
146 
147  m_grid->Disconnect( wxEVT_GRID_CELL_CHANGING, wxGridEventHandler( DIALOG_EDIT_COMPONENT_IN_LIBRARY::OnGridCellChanging ), NULL, this );
148  m_aliasGrid->Disconnect( wxEVT_GRID_CELL_CHANGING, wxGridEventHandler( DIALOG_EDIT_COMPONENT_IN_LIBRARY::OnAliasGridCellChanging ), NULL, this );
149 
150  // Delete the GRID_TRICKS.
151  m_grid->PopEventHandler( true );
152  m_aliasGrid->PopEventHandler( true );
153 
154  // An OK will have transferred these and cleared the buffer, but we have to delete them
155  // on a Cancel.
156  for( LIB_ALIAS* alias : m_aliasesBuffer )
157  delete alias;
158 }
159 
160 
162 {
163  if( !wxDialog::TransferDataToWindow() )
164  return false;
165 
166  LIB_ALIAS* rootAlias = m_libEntry->GetAlias( m_libEntry->GetName() );
167 
168  // Push a copy of each field into m_fields
170 
171  // Datasheet field is special; grab its value from the docfilename
172  m_fields->at( DATASHEET ).SetText( rootAlias->GetDocFileName() );
173 
174  // The Y axis for components in lib is from bottom to top while the screen axis is top
175  // to bottom: we must change the y coord sign for editing
176  for( size_t i = 0; i < m_fields->size(); ++i )
177  {
178  wxPoint pos = m_fields->at( i ).GetPosition();
179  pos.y = -pos.y;
180  m_fields->at( i ).SetPosition( pos );
181  }
182 
183  // notify the grid
184  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_fields->GetNumberRows() );
185  m_grid->ProcessTableMessage( msg );
186  adjustGridColumns( m_grid->GetRect().GetWidth());
187 
188  m_SymbolNameCtrl->SetValue( m_libEntry->GetName() );
189 
190  m_DescCtrl->SetValue( rootAlias->GetDescription() );
191  m_KeywordCtrl->SetValue( rootAlias->GetKeyWords() );
192 
195  m_AsConvertButt->SetValue( m_libEntry->HasConversion() );
196  m_OptionPower->SetValue( m_libEntry->IsPower() );
197 
199  m_ShowPinNameButt->SetValue( m_libEntry->ShowPinNames() );
200  m_PinsNameInsideButt->SetValue( m_libEntry->GetPinNameOffset() != 0 );
202 
203  const LIB_ALIASES aliases = m_libEntry->GetAliases();
204 
205  for( LIB_ALIAS* alias : aliases )
206  {
207  if( alias->IsRoot() )
208  continue;
209 
210  m_aliasesBuffer.push_back( new LIB_ALIAS( *alias, m_libEntry ) );
211  m_aliasListBox->Append( alias->GetName() );
212  }
213 
214  if( m_aliasListBox->GetCount() )
215  {
216  m_aliasListBox->SetSelection( 0 );
217 
218  wxCommandEvent dummy;
219  OnSelectAlias( dummy );
220  }
221 
222  adjustAliasGridColumns( m_aliasGrid->GetClientRect().GetWidth() - 4 );
223 
225 
226  m_NoteBook->SetSelection( (unsigned) m_lastOpenedPage );
227 
228  return true;
229 }
230 
231 
233 {
235  return false;
236 
237  if( !SCH_COMPONENT::IsReferenceStringValid( m_fields->at( REFERENCE ).GetText() ) )
238  {
239  if( m_NoteBook->GetSelection() != 0 )
240  m_NoteBook->SetSelection( 0 );
241 
242  m_delayedErrorMessage = _( "References must start with a letter." );
246  m_delayedFocusPage = 0;
247 
248  return false;
249  }
250 
251  // Check for missing field names.
252  for( size_t i = MANDATORY_FIELDS; i < m_fields->size(); ++i )
253  {
254  LIB_FIELD& field = m_fields->at( i );
255  wxString fieldName = field.GetName( false );
256 
257  if( fieldName.IsEmpty() )
258  {
259  if( m_NoteBook->GetSelection() != 0 )
260  m_NoteBook->SetSelection( 0 );
261 
262  m_delayedErrorMessage = _( "Fields must have a name." );
266  m_delayedFocusPage = 0;
267 
268  return false;
269  }
270  }
271 
272  if( m_SelNumberOfUnits->GetValue() < m_libEntry->GetUnitCount() )
273  {
274  if( !IsOK( this, _( "Delete extra units from symbol?" ) ) )
275  return false;
276  }
277 
278  if( m_AsConvertButt->GetValue() && !m_libEntry->HasConversion() )
279  {
280  if( !IsOK( this, _( "Add new pins for alternate body style (DeMorgan) to symbol?" ) ) )
281  return false;
282  }
283  else if( !m_AsConvertButt->GetValue() && m_libEntry->HasConversion() )
284  {
285  if( !IsOK( this, _( "Delete alternate body style (DeMorgan) draw items from symbol?" ) ) )
286  return false;
287  }
288 
289  return true;
290 }
291 
292 
294 {
295  if( !Validate() )
296  return false;
297 
298  LIB_ALIAS* rootAlias = m_libEntry->GetAlias( m_libEntry->GetName() );
299 
301 
302  // The Y axis for components in lib is from bottom to top while the screen axis is top
303  // to bottom: we must change the y coord sign when writing back to the library
304  for( size_t i = 0; i < m_fields->size(); ++i )
305  {
306  wxPoint pos = m_fields->at( i ).GetPosition();
307  pos.y = -pos.y;
308  m_fields->at( i ).SetPosition( pos );
309  }
310 
311  // Datasheet field is special; copy it to the root alias docfilename
312  rootAlias->SetDocFileName( m_fields->at( DATASHEET ).GetText() );
313  m_fields->at( DATASHEET ).SetText( wxEmptyString );
314 
316 
317  // We need to keep the name and the value the same at the moment!
319 
320  rootAlias->SetDescription( m_DescCtrl->GetValue() );
321  rootAlias->SetKeyWords( m_KeywordCtrl->GetValue() );
322 
325 
326  m_libEntry->SetConversion( m_AsConvertButt->GetValue() );
327 
328  if( m_OptionPower->GetValue() )
329  m_libEntry->SetPower();
330  else
332 
335 
336  if( m_PinsNameInsideButt->GetValue() )
337  {
338  int offset = KiROUND( (double) m_pinNameOffset.GetValue() / IU_PER_MILS );
339 
340  // We interpret an offset of 0 as "outside", so make sure it's non-zero
341  m_libEntry->SetPinNameOffset( offset == 0 ? 20 : offset );
342  }
343  else
344  {
345  m_libEntry->SetPinNameOffset( 0 ); // pin text outside the body (name is on the pin)
346  }
347 
350 
351  for( LIB_ALIAS* alias : m_aliasesBuffer )
352  m_libEntry->AddAlias( alias ); // Transfers ownership; no need to delete
353 
354  m_aliasesBuffer.clear();
355 
356  m_libEntry->GetFootprints().Clear();
358 
360  m_Parent->OnModify();
361 
362  return true;
363 }
364 
365 
367 {
368  wxGridCellEditor* editor = m_grid->GetCellEditor( event.GetRow(), event.GetCol() );
369  wxControl* control = editor->GetControl();
370 
371  if( control && control->GetValidator() && !control->GetValidator()->Validate( control ) )
372  {
373  event.Veto();
374 
376  m_delayedFocusRow = event.GetRow();
377  m_delayedFocusColumn = event.GetCol();
378  m_delayedFocusPage = 0;
379  }
380  else if( event.GetRow() == VALUE && event.GetCol() == FDC_VALUE )
381  m_SymbolNameCtrl->ChangeValue( event.GetString() );
382 
383  editor->DecRef();
384 }
385 
386 
388 {
389  m_grid->SetCellValue( VALUE, FDC_VALUE, m_SymbolNameCtrl->GetValue() );
390 }
391 
392 
394 {
395  if( !m_delayedFocusCtrl && !m_SymbolNameCtrl->GetValidator()->Validate( m_SymbolNameCtrl ) )
396  {
398  m_delayedFocusPage = 0;
399  }
400 
401  event.Skip();
402 }
403 
404 
405 void DIALOG_EDIT_COMPONENT_IN_LIBRARY::OnAddField( wxCommandEvent& event )
406 {
407  if( !m_grid->CommitPendingChanges() )
408  return;
409 
410  int fieldID = m_fields->size();
411  LIB_FIELD newField( m_libEntry, fieldID );
412 
413  m_fields->push_back( newField );
414 
415  // notify the grid
416  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
417  m_grid->ProcessTableMessage( msg );
418 
419  m_grid->MakeCellVisible( m_fields->size() - 1, 0 );
420  m_grid->SetGridCursor( m_fields->size() - 1, 0 );
421 
422  m_grid->EnableCellEditControl();
423  m_grid->ShowCellEditControl();
424 }
425 
426 
428 {
429  int curRow = m_grid->GetGridCursorRow();
430 
431  if( curRow < 0 )
432  return;
433  else if( curRow < MANDATORY_FIELDS )
434  {
435  DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ),
436  MANDATORY_FIELDS ) );
437  return;
438  }
439 
440  m_grid->CommitPendingChanges( true /* quiet mode */ );
441 
442  m_fields->erase( m_fields->begin() + curRow );
443 
444  // notify the grid
445  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, curRow, 1 );
446  m_grid->ProcessTableMessage( msg );
447 
448  if( m_grid->GetNumberRows() > 0 )
449  {
450  m_grid->MakeCellVisible( std::max( 0, curRow-1 ), m_grid->GetGridCursorCol() );
451  m_grid->SetGridCursor( std::max( 0, curRow-1 ), m_grid->GetGridCursorCol() );
452  }
453 }
454 
455 
456 void DIALOG_EDIT_COMPONENT_IN_LIBRARY::OnMoveUp( wxCommandEvent& event )
457 {
458  if( !m_grid->CommitPendingChanges() )
459  return;
460 
461  int i = m_grid->GetGridCursorRow();
462 
463  if( i > MANDATORY_FIELDS )
464  {
465  LIB_FIELD tmp = m_fields->at( (unsigned) i );
466  m_fields->erase( m_fields->begin() + i, m_fields->begin() + i + 1 );
467  m_fields->insert( m_fields->begin() + i - 1, tmp );
468  m_grid->ForceRefresh();
469 
470  m_grid->SetGridCursor( i - 1, m_grid->GetGridCursorCol() );
471  m_grid->MakeCellVisible( m_grid->GetGridCursorRow(), m_grid->GetGridCursorCol() );
472  }
473  else
474  wxBell();
475 }
476 
477 
478 void DIALOG_EDIT_COMPONENT_IN_LIBRARY::OnMoveDown( wxCommandEvent& event )
479 {
480  if( !m_grid->CommitPendingChanges() )
481  return;
482 
483  int i = m_grid->GetGridCursorRow();
484 
485  if( i >= MANDATORY_FIELDS )
486  {
487  LIB_FIELD tmp = m_fields->at( (unsigned) i );
488  m_fields->erase( m_fields->begin() + i, m_fields->begin() + i + 1 );
489  m_fields->insert( m_fields->begin() + i + 1, tmp );
490  m_grid->ForceRefresh();
491 
492  m_grid->SetGridCursor( i + 1, m_grid->GetGridCursorCol() );
493  m_grid->MakeCellVisible( m_grid->GetGridCursorRow(), m_grid->GetGridCursorCol() );
494  }
495  else
496  wxBell();
497 }
498 
499 
500 void DIALOG_EDIT_COMPONENT_IN_LIBRARY::updateAliasName( bool aFromGrid, const wxString& aName )
501 {
502  int idx = m_aliasListBox->GetSelection();
503 
504  if( idx >= 0 )
505  {
506  m_aliasListBox->SetString( (unsigned) idx, aName );
507  m_aliasesBuffer[ idx ]->SetName( aName );
508 
509  if( aFromGrid )
510  m_AliasNameCtrl->ChangeValue( aName );
511  else
512  m_aliasGrid->SetCellValue( VALUE, FDC_VALUE, aName );
513  }
514 }
515 
516 
518 {
519  if( event.GetRow() == VALUE )
520  {
521  int idx = m_aliasListBox->GetSelection();
522  wxString newName = event.GetString();
523 
524  if( idx < 0 || !checkAliasName( newName ) )
525  {
526  event.Veto();
527 
529  m_delayedFocusRow = event.GetRow();
530  m_delayedFocusColumn = event.GetCol();
531  m_delayedFocusPage = 1;
532  }
533  else
534  updateAliasName( true, newName );
535  }
536 }
537 
538 
540 {
541  updateAliasName( false, m_AliasNameCtrl->GetValue() );
542 }
543 
544 
546 {
547  if( !m_delayedFocusCtrl && !checkAliasName( m_AliasNameCtrl->GetValue() ) )
548  {
550  m_delayedFocusPage = 1;
551  }
552 
553  event.Skip();
554 }
555 
556 
558 {
559  if( m_currentAlias >= 0 )
560  {
562 
563  alias->SetName( m_aliasGrid->GetCellValue( VALUE, FDC_VALUE ) );
564  alias->SetDocFileName( m_aliasGrid->GetCellValue( DATASHEET, FDC_VALUE ) );
565  alias->SetDescription( m_AliasDescCtrl->GetValue() );
566  alias->SetKeyWords( m_AliasKeywordsCtrl->GetValue() );
567  }
568 }
569 
570 
572 {
573 #ifdef KICAD_SPICE
574  int diff = m_fields->size();
575  auto cmp = SCH_COMPONENT( *m_libEntry, m_libEntry->GetLibId(), nullptr );
576 
577  DIALOG_SPICE_MODEL dialog( this, cmp, m_fields );
578 
579  if( dialog.ShowModal() != wxID_OK )
580  return;
581 
582  diff = m_fields->size() - diff;
583 
584  if( diff > 0 )
585  {
586  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, diff );
587  m_grid->ProcessTableMessage( msg );
588  }
589  else if( diff < 0 )
590  {
591  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, 0, diff );
592  m_grid->ProcessTableMessage( msg );
593  }
594 
595  m_grid->ForceRefresh();
596 #endif /* KICAD_SPICE */
597 }
598 
599 
601 {
603  {
604  m_aliasListBox->SetSelection( m_currentAlias ); // veto selection change
605  return;
606  }
607 
608  // Copy any pending changes back into the buffer
610 
611  LIB_ALIAS* alias = nullptr;
612  int newIdx = m_aliasListBox->GetSelection();
613 
614  if( newIdx >= 0 )
615  {
616  alias = m_aliasesBuffer[ newIdx ];
617 
618  m_aliasGrid->SetCellValue( VALUE, FDC_VALUE, alias->GetName() );
619  m_aliasGrid->SetCellValue( DATASHEET, FDC_VALUE, alias->GetDocFileName() );
620 
621  // Use ChangeValue() so we don't generate events
622  m_AliasNameCtrl->ChangeValue( alias->GetName() );
623  m_AliasDescCtrl->ChangeValue( alias->GetDescription() );
624  m_AliasKeywordsCtrl->ChangeValue( alias->GetKeyWords() );
625  }
626  else
627  {
628  m_aliasGrid->SetCellValue( VALUE, FDC_VALUE, wxEmptyString );
629  m_aliasGrid->SetCellValue( DATASHEET, FDC_VALUE, wxEmptyString );
630 
631  // Use ChangeValue() so we don't generate events
632  m_AliasNameCtrl->ChangeValue( wxEmptyString );
633  m_AliasDescCtrl->ChangeValue( wxEmptyString );
634  m_AliasKeywordsCtrl->ChangeValue( wxEmptyString );
635  }
636 
637  m_currentAlias = newIdx;
638 }
639 
640 
642 {
643  if( aName.IsEmpty() )
644  return false;
645 
646  for( int i = 0; i < (int)m_aliasListBox->GetCount(); ++i )
647  {
648  if( i == m_aliasListBox->GetSelection() )
649  continue;
650 
651  if( m_aliasListBox->GetString( i ).CmpNoCase( aName ) == 0 )
652  {
653  wxString msg;
654  msg.Printf( _( "Alias \"%s\" already exists." ), aName );
655  DisplayInfoMessage( this, msg );
656  return false;
657  }
658  }
659 
660  wxString library = m_Parent->GetCurLib();
661 
662  if( !library.empty() )
663  {
664  LIB_ALIAS* existing = Prj().SchSymbolLibTable()->LoadSymbol( library, aName );
665 
666  if( existing && existing->GetPart()->GetName() != m_libEntry->GetName() )
667  {
668  wxString msg;
669  msg.Printf( _( "Symbol name \"%s\" already exists in library \"%s\"." ), aName, library );
670  DisplayErrorMessage( this, msg );
671  return false;
672  }
673  }
674 
675  return true;
676 }
677 
678 
679 void DIALOG_EDIT_COMPONENT_IN_LIBRARY::OnAddAlias( wxCommandEvent& event )
680 {
682  return;
683 
684  wxCommandEvent dummy;
685  wxString aliasname = _( "untitled" );
686  int suffix = 1;
687 
688  while( m_libEntry->HasAlias( aliasname ) )
689  aliasname = wxString::Format( _( "untitled%i" ), suffix++ );
690 
691  LIB_ALIAS* alias = new LIB_ALIAS( aliasname, m_libEntry );
692 
693  // Initialize with parent's data
694  alias->SetDescription( m_DescCtrl->GetValue() );
695  alias->SetKeyWords( m_KeywordCtrl->GetValue() );
696  alias->SetDocFileName( m_grid->GetCellValue( DATASHEET, FDC_VALUE ) );
697 
698  m_aliasesBuffer.push_back( alias ); // transfers ownership of alias to aliasesBuffer
699 
700  m_aliasListBox->Append( aliasname );
701  m_aliasListBox->SetSelection( m_aliasListBox->GetCount() - 1 );
702  OnSelectAlias( dummy );
703 }
704 
705 
707 {
709  return;
710 
711  int sel = m_aliasListBox->GetSelection();
712 
713  if( sel == wxNOT_FOUND )
714  return;
715 
716  m_aliasListBox->Delete( (unsigned) sel );
717  m_aliasesBuffer.erase( m_aliasesBuffer.begin() + sel );
718  m_currentAlias = wxNOT_FOUND;
719 
720  if( m_aliasListBox->GetCount() == 0 )
721  m_aliasListBox->SetSelection( wxNOT_FOUND );
722  else
723  m_aliasListBox->SetSelection( std::max( 0, sel - 1 ) );
724 
725  wxCommandEvent dummy;
726  OnSelectAlias( dummy );
727 }
728 
729 
731 {
732  wxCommandEvent dummy;
734  event.Skip();
735 }
736 
737 
739 {
740  wxString filterLine;
741  LIB_PART* component = m_Parent->GetCurPart();
742 
743  if( component == NULL )
744  return;
745 
746  WX_TEXT_ENTRY_DIALOG dlg( this, _( "Filter:" ), _( "Add Footprint Filter" ), filterLine );
747 
748  if( dlg.ShowModal() == wxID_CANCEL || dlg.GetValue().IsEmpty() )
749  return;
750 
751  filterLine = dlg.GetValue();
752  filterLine.Replace( wxT( " " ), wxT( "_" ) );
753 
754  // duplicate filters do no harm, so don't be a nanny.
755 
756  m_FootprintFilterListBox->Append( filterLine );
757  m_FootprintFilterListBox->SetSelection( m_FootprintFilterListBox->GetCount() - 1 );
758 }
759 
760 
762 {
763  int ii = m_FootprintFilterListBox->GetSelection();
764 
765  if( ii >= 0 )
766  {
767  m_FootprintFilterListBox->Delete( (unsigned) ii );
768 
769  if( m_FootprintFilterListBox->GetCount() == 0 )
770  m_FootprintFilterListBox->SetSelection( wxNOT_FOUND );
771  else
772  m_FootprintFilterListBox->SetSelection( std::max( 0, ii - 1 ) );
773  }
774 }
775 
777 {
778  int idx = m_FootprintFilterListBox->GetSelection();
779 
780  if( idx >= 0 )
781  {
782  wxString filter = m_FootprintFilterListBox->GetStringSelection();
783 
784  WX_TEXT_ENTRY_DIALOG dlg( this, _( "Filter:" ), _( "Edit Footprint Filter" ), filter );
785 
786  if( dlg.ShowModal() == wxID_OK && !dlg.GetValue().IsEmpty() )
787  m_FootprintFilterListBox->SetString( (unsigned) idx, dlg.GetValue() );
788  }
789 }
790 
791 
793 {
794  // Account for scroll bars
795  aWidth -= ( m_grid->GetSize().x - m_grid->GetClientSize().x );
796 
797  m_grid->AutoSizeColumn( FDC_NAME );
798 
799  int fixedColsWidth = m_grid->GetColSize( FDC_NAME );
800 
801  for( int i = 2; i < m_grid->GetNumberCols(); i++ )
802  fixedColsWidth += m_grid->GetColSize( i );
803 
804  m_grid->SetColSize( FDC_VALUE, aWidth - fixedColsWidth );
805 }
806 
807 
809 {
810  m_aliasGrid->AutoSizeColumn( FDC_NAME );
811  m_aliasGrid->SetColSize( FDC_VALUE, aWidth - m_aliasGrid->GetColSize( FDC_NAME ) - 2 );
812 }
813 
814 
815 void DIALOG_EDIT_COMPONENT_IN_LIBRARY::OnUpdateUI( wxUpdateUIEvent& event )
816 {
817  m_OptionPartsLocked->Enable( m_SelNumberOfUnits->GetValue() > 1 );
819 
820  if( m_grid->IsCellEditControlShown() )
821  {
822  int row = m_grid->GetGridCursorRow();
823  int col = m_grid->GetGridCursorCol();
824 
825  if( row == VALUE && col == FDC_VALUE )
826  {
827  wxGridCellEditor* editor = m_grid->GetCellEditor( row, col );
828  m_SymbolNameCtrl->ChangeValue( editor->GetValue() );
829  editor->DecRef();
830  }
831  }
832 
833  // Synthesize a Select event when the selection is cleared
834  if( m_aliasListBox->GetSelection() == wxNOT_FOUND && m_currentAlias != wxNOT_FOUND )
835  {
836  wxCommandEvent dummy;
837  OnSelectAlias( dummy );
838  }
839 
840  // Handle shown columns changes
841  wxString shownColumns = m_grid->GetShownColumns();
842 
843  if( shownColumns != m_shownColumns )
844  {
845  m_shownColumns = shownColumns;
846 
847  if( !m_grid->IsCellEditControlShown() )
848  adjustGridColumns( m_grid->GetRect().GetWidth() );
849  }
850 
851  // Handle a delayed focus. The delay allows us to:
852  // a) change focus when the error was triggered from within a killFocus handler
853  // b) show the correct notebook page in the background before the error dialog comes up
854  // when triggered from an OK or a notebook page change
855 
856  if( m_delayedFocusPage >= 0 && m_NoteBook->GetSelection() != m_delayedFocusPage )
857  {
858  m_NoteBook->SetSelection( (unsigned) m_delayedFocusPage );
859  m_delayedFocusPage = -1;
860  }
861 
862  if( !m_delayedErrorMessage.IsEmpty() )
863  {
864  // We will re-enter this routine when the error dialog is displayed, so make
865  // sure we don't keep putting up more dialogs.
866  wxString msg = m_delayedErrorMessage;
867  m_delayedErrorMessage = wxEmptyString;
868 
869  // Do not use DisplayErrorMessage(); it screws up window order on Mac
870  DisplayError( nullptr, msg );
871  }
872 
873  if( m_delayedFocusCtrl )
874  {
875  m_delayedFocusCtrl->SetFocus();
876 
877  if( dynamic_cast<wxTextEntry*>( m_delayedFocusCtrl ) )
878  dynamic_cast<wxTextEntry*>( m_delayedFocusCtrl )->SelectAll();
879 
880  m_delayedFocusCtrl = nullptr;
881  }
882  else if( m_delayedFocusGrid )
883  {
884  m_delayedFocusGrid->SetFocus();
887 
888  m_delayedFocusGrid->EnableCellEditControl( true );
889  m_delayedFocusGrid->ShowCellEditControl();
890 
891  m_delayedFocusGrid = nullptr;
892  m_delayedFocusRow = -1;
894  }
895 }
896 
897 
899 {
900  adjustGridColumns( event.GetSize().GetX() );
901 
902  event.Skip();
903 }
904 
905 
907 {
908  adjustAliasGridColumns( event.GetSize().GetX() );
909 
910  event.Skip();
911 }
wxString GetName(bool aTranslate=true) const
Returns the field name.
Definition: lib_field.cpp:448
LIB_PART * GetCurPart() const
Return the current part being edited or NULL if none selected.
void OnAddFootprintFilter(wxCommandEvent &event) override
int GetUnitCount() const
Part library alias object definition.
void SetConversion(bool aSetConvert)
Set or clear the alternate body style (DeMorgan) for the part.
void SetPower()
name of datasheet
void OnUpdateUI(wxUpdateUIEvent &event) override
int GetPinNameOffset()
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Function DisplayErrorMessage displays an error message with aMessage.
Definition: confirm.cpp:257
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:121
void OnAliasNameText(wxCommandEvent &event) override
int GetNumberRows() override
LIB_ALIAS * GetAlias(size_t aIndex)
void OnEditFootprintFilter(wxCommandEvent &event) override
void OnSizeGrid(wxSizeEvent &event) override
Base schematic object class definition.
This file is part of the common library.
void updateAliasName(bool aFromGrid, const wxString &aName)
bool HasConversion() const
Test if part has more than one body conversion type (DeMorgan).
void ShowHideColumns(const wxString &shownColumns)
Show/hide the grid columns based on a tokenized string of shown column indexes.
Definition: wx_grid.cpp:119
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
Field object used in symbol libraries.
Definition: lib_field.h:59
wxConfigBase * KifaceSettings() const
Definition: kiface_i.h:103
void FinishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
LIB_FIELD & GetValueField()
Return reference to the value field.
void OnModify()
Must be called after a schematic change in order to set the "modify" flag of the current screen.
static const wxString GetDefaultFieldName(int aFieldNdx)
Function GetDefaultFieldName returns a default symbol field name for field aFieldNdx for all componen...
void SetTable(wxGridTableBase *table, bool aTakeOwnership=false)
Hide wxGrid's SetTable() method with one which doesn't mess up the grid column widths when setting th...
Definition: wx_grid.cpp:57
void OnSymbolNameText(wxCommandEvent &event) override
std::vector< LIB_ALIAS * > LIB_ALIASES
void AddAlias(const wxString &aName)
Add an alias aName to the part.
void SetDocFileName(const wxString &aDocFileName)
void OnDeleteFootprintFilter(wxCommandEvent &event) override
Field Name Module PCB, i.e. "16DIP300".
Field Reference of part, i.e. "IC21".
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
Definition: kicad.cpp:52
void OnAliasNameKillFocus(wxFocusEvent &event) override
const wxString & GetDocFileName() const
void OnMoveUp(wxCommandEvent &event) override
wxString GetCurLib() const
The nickname of the current library being edited and empty string if none.
virtual int GetValue()
Function GetValue Returns the current value in Internal Units.
DIALOG_EDIT_COMPONENT_IN_LIBRARY(LIB_EDIT_FRAME *parent, LIB_PART *aLibEntry)
Constructors.
void DestroyTable(wxGridTableBase *aTable)
Work-around for a bug in wxGrid which crashes when deleting the table if the cell edit control was no...
Definition: wx_grid.cpp:88
bool ShowPinNames()
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Construct a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:79
void SetName(const wxString &aName)
#define VALUE
bool ShowPinNumbers()
void SetUnitCount(int count)
Set the units per part count.
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:143
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
void OnFilterDClick(wxMouseEvent &event) override
void OnDeleteField(wxCommandEvent &event) override
const wxString & GetKeyWords() const
const LIB_ID & GetLibId() const
Define a library symbol object.
Helper dialog and control classes.
void OnSelectAlias(wxCommandEvent &event) override
void OnSizeAliasGrid(wxSizeEvent &event) override
void OnSymbolNameKillFocus(wxFocusEvent &event) override
LIB_PART * GetPart() const
Get the shared LIB_PART.
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:167
void SetDescription(const wxString &aDescription)
void OnMoveDown(wxCommandEvent &event) override
wxArrayString & GetFootprints()
void OnDeleteAlias(wxCommandEvent &event) override
const wxString & GetDescription() override
#define LibEditFieldsShownColumnsKey
wxString GetShownColumns()
Get a tokenized string containing the shown column indexes.
Definition: wx_grid.cpp:101
Definition the SCH_COMPONENT class for Eeschema.
wxString GetValue()
The symbol library editor main window.
bool IsPower() const
see class PGM_BASE
const wxString & GetName() const override
void RemoveAllAliases()
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.
static LIB_PART * dummy()
Used when a LIB_PART is not found in library to draw a dummy shape This component is a 400 mils squar...
#define max(a, b)
Definition: auxiliary.h:86
const wxString & GetName() const
void SetKeyWords(const wxString &aKeyWords)
virtual void SetValue(int aValue)
Function SetValue Sets new value (in Internal Units) for the text field, taking care of units convers...
void SaveCopyInUndoList(EDA_ITEM *ItemToCopy, UNDO_REDO_T undoType=UR_LIBEDIT)
Create a copy of the current component, and save it in the undo list.
size_t i
Definition: json11.cpp:597
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:70
#define IU_PER_MILS
Definition: plotter.cpp:134
The common library.
Class DIALOG_EDIT_COMPONENT_IN_LIBRARY_BASE.
virtual void SetName(const wxString &aName)
Definition of class LIB_EDIT_FRAME.
void OnAddAlias(wxCommandEvent &event) override
void OnEditSpiceModel(wxCommandEvent &event) override
class SCH_FILED_VALIDATOR
Definition for part library class.
static bool IsReferenceStringValid(const wxString &aReferenceString)
Tests for an acceptable reference string.
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.
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Function DisplayInfoMessage displays an informational message box with aMessage.
Definition: confirm.cpp:275
void SetFields(const std::vector< LIB_FIELD > &aFieldsList)
Overwrite all the existing fields in this symbol with fields supplied in aFieldsList.
void OnAddField(wxCommandEvent &event) override
FIELDS_GRID_TABLE< LIB_FIELD > * m_fields
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:243
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Function IsOK displays a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:293
bool UnitsLocked() const
Check whether part units are interchangeable.
void Enable(bool aEnable)
Function Enable Enables/diasables the label, widget and units label.
void GetFields(LIB_FIELDS &aList)
Return a list of fields within this part.
bool HasAlias(const wxString &aName) const
Test if alias aName is in part alias list.
void LockUnits(bool aLockUnits)
Set interchangeable the property for part units.
void SetNormal()
LIB_ALIASES GetAliases() const