KiCad PCB EDA Suite
dialog_edit_component_in_lib.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 <kiway.h>
26 #include <common.h>
27 #include <confirm.h>
28 #include <pgm_base.h>
29 #include <kiface_i.h>
30 #include <dialog_text_entry.h>
31 
32 #include <general.h>
33 #include <widgets/wx_grid.h>
35 #include <lib_edit_frame.h>
36 #include <class_library.h>
37 #include <symbol_lib_table.h>
38 #include <sch_item.h>
39 #include <sch_component.h>
40 #include <dialog_helpers.h>
41 #include <bitmaps.h>
42 
43 #ifdef KICAD_SPICE
44 #include <dialog_spice_model.h>
46 #endif /* KICAD_SPICE */
47 
49 
50 
51 #define LibEditFieldsShownColumnsKey wxT( "LibEditFieldsShownColumns" )
52 
54 
55 
57  LIB_PART* aLibEntry ) :
59  m_Parent( aParent ),
60  m_libEntry( aLibEntry ),
61  m_currentAlias( wxNOT_FOUND ),
62  m_pinNameOffset( aParent, m_nameOffsetLabel, m_nameOffsetCtrl, m_nameOffsetUnits, true ),
63  m_delayedFocusCtrl( nullptr ),
64  m_delayedFocusGrid( nullptr ),
65  m_delayedFocusRow( -1 ),
66  m_delayedFocusColumn( -1 ),
67  m_delayedFocusPage( -1 ),
68  m_width( 0 )
69 {
71 
72  // Give a bit more room for combobox editors
73  m_grid->SetDefaultRowSize( m_grid->GetDefaultRowSize() + 4 );
74  m_aliasGrid->SetDefaultRowSize( m_aliasGrid->GetDefaultRowSize() + 4 );
75 
76  // Work around a bug in wxWidgets where it fails to recalculate the grid height
77  // after changing the default row size
78  m_aliasGrid->AppendRows( 1 );
79  m_aliasGrid->DeleteRows( m_grid->GetNumberRows() - 1, 1 );
80 
81  m_fields = new FIELDS_GRID_TABLE<LIB_FIELD>( this, aParent, m_libEntry );
83 
84  m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this ) );
85  m_aliasGrid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this ) );
86 
87  // Show/hide columns according to the user's preference
88  m_config->Read( LibEditFieldsShownColumnsKey, &m_shownColumns, wxT( "0 1 2 3 4 5 6 7" ) );
90 
91  // Hide non-overridden rows in aliases grid
92  m_aliasGrid->HideRow( REFERENCE );
93  m_aliasGrid->HideRow( FOOTPRINT );
94 
95  wxGridCellAttr* attr = new wxGridCellAttr;
96  attr->SetReadOnly();
97  m_aliasGrid->SetColAttr( FDC_NAME, attr );
99  m_aliasGrid->SetCellValue( DATASHEET, FDC_NAME,
101 
102  attr = new wxGridCellAttr;
103  attr->SetEditor( new GRID_CELL_URL_EDITOR( this ) );
104  m_aliasGrid->SetAttr( DATASHEET, FDC_VALUE, attr );
105 
106  m_SymbolNameCtrl->SetValidator( SCH_FIELD_VALIDATOR( true, VALUE ) );
107 
108  // Configure button logos
109  m_bpAdd->SetBitmap( KiBitmap( small_plus_xpm ) );
110  m_bpDelete->SetBitmap( KiBitmap( trash_xpm ) );
111  m_bpMoveUp->SetBitmap( KiBitmap( small_up_xpm ) );
112  m_bpMoveDown->SetBitmap( KiBitmap( small_down_xpm ) );
113  m_addAliasButton->SetBitmap( KiBitmap( small_plus_xpm ) );
114  m_deleteAliasButton->SetBitmap( KiBitmap( trash_xpm ) );
115  m_addFilterButton->SetBitmap( KiBitmap( small_plus_xpm ) );
116  m_deleteFilterButton->SetBitmap( KiBitmap( trash_xpm ) );
117  m_editFilterButton->SetBitmap( KiBitmap( small_edit_xpm ) );
118 
119  m_stdSizerButtonOK->SetDefault();
120 
121 #ifndef KICAD_SPICE
122  m_spiceFieldsButton->Hide();
123 #endif
124 
125  // wxFormBuilder doesn't include this event...
126  m_grid->Connect( wxEVT_GRID_CELL_CHANGING,
128  NULL, this );
129  m_aliasGrid->Connect( wxEVT_GRID_CELL_CHANGING,
131  NULL, this );
132 
133  m_grid->GetParent()->Layout();
134  m_aliasGrid->GetParent()->Layout();
135  Layout();
136 
138 }
139 
140 
142 {
143  m_lastOpenedPage = m_NoteBook->GetSelection( );
144 
146 
147  // Prevents crash bug in wxGrid's d'tor
149 
150  m_grid->Disconnect( wxEVT_GRID_CELL_CHANGING,
152  NULL, this );
153  m_aliasGrid->Disconnect( wxEVT_GRID_CELL_CHANGING,
155  NULL, this );
156 
157  // Delete the GRID_TRICKS.
158  m_grid->PopEventHandler( true );
159  m_aliasGrid->PopEventHandler( true );
160 
161  // An OK will have transferred these and cleared the buffer, but we have to delete them
162  // on a Cancel.
163  for( LIB_ALIAS* alias : m_aliasesBuffer )
164  delete alias;
165 }
166 
167 
169 {
170  if( !wxDialog::TransferDataToWindow() )
171  return false;
172 
173  LIB_ALIAS* rootAlias = m_libEntry->GetAlias( m_libEntry->GetName() );
174 
175  // Push a copy of each field into m_fields
177 
178  // The datasheet field is special. Grab its value from the LIB_ALIAS document file
179  // member except for old libraries that saved the root alias document file in the
180  // datasheet field in the LIB_PART object.
181  if( rootAlias->GetDocFileName().IsEmpty() )
182  {
183  m_fields->at( DATASHEET ).SetText( m_libEntry->GetField( DATASHEET )->GetText() );
184  rootAlias->SetDocFileName( m_libEntry->GetField( DATASHEET )->GetText() );
185  }
186  else
187  {
188  m_fields->at( DATASHEET ).SetText( rootAlias->GetDocFileName() );
189  }
190 
191  // The Y axis for components in lib is from bottom to top while the screen axis is top
192  // to bottom: we must change the y coord sign for editing
193  for( size_t i = 0; i < m_fields->size(); ++i )
194  {
195  wxPoint pos = m_fields->at( i ).GetPosition();
196  pos.y = -pos.y;
197  m_fields->at( i ).SetPosition( pos );
198  }
199 
200  // notify the grid
201  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_fields->GetNumberRows() );
202  m_grid->ProcessTableMessage( msg );
203  adjustGridColumns( m_grid->GetRect().GetWidth());
204 
205  m_SymbolNameCtrl->SetValue( m_libEntry->GetName() );
206 
207  m_DescCtrl->SetValue( rootAlias->GetDescription() );
208  m_KeywordCtrl->SetValue( rootAlias->GetKeyWords() );
209 
212  m_AsConvertButt->SetValue( m_libEntry->HasConversion() );
213  m_OptionPower->SetValue( m_libEntry->IsPower() );
214 
216  m_ShowPinNameButt->SetValue( m_libEntry->ShowPinNames() );
217  m_PinsNameInsideButt->SetValue( m_libEntry->GetPinNameOffset() != 0 );
219 
220  const LIB_ALIASES aliases = m_libEntry->GetAliases();
221 
222  for( LIB_ALIAS* alias : aliases )
223  {
224  if( alias->IsRoot() )
225  continue;
226 
227  m_aliasesBuffer.push_back( new LIB_ALIAS( *alias, m_libEntry ) );
228  m_aliasListBox->Append( alias->GetName() );
229  }
230 
231  if( m_aliasListBox->GetCount() )
232  m_aliasListBox->SetSelection( 0 );
233 
234  wxCommandEvent dummy;
235  OnSelectAlias( dummy );
236 
237  adjustAliasGridColumns( m_aliasGrid->GetClientRect().GetWidth() - 4 );
238 
240 
241  m_NoteBook->SetSelection( (unsigned) m_lastOpenedPage );
242 
243  return true;
244 }
245 
246 
248 {
250  return false;
251 
252  if( !SCH_COMPONENT::IsReferenceStringValid( m_fields->at( REFERENCE ).GetText() ) )
253  {
254  if( m_NoteBook->GetSelection() != 0 )
255  m_NoteBook->SetSelection( 0 );
256 
257  m_delayedErrorMessage = _( "References must start with a letter." );
261  m_delayedFocusPage = 0;
262 
263  return false;
264  }
265 
266  // Check for missing field names.
267  for( size_t i = MANDATORY_FIELDS; i < m_fields->size(); ++i )
268  {
269  LIB_FIELD& field = m_fields->at( i );
270  wxString fieldName = field.GetName( false );
271 
272  if( fieldName.IsEmpty() )
273  {
274  if( m_NoteBook->GetSelection() != 0 )
275  m_NoteBook->SetSelection( 0 );
276 
277  m_delayedErrorMessage = _( "Fields must have a name." );
281  m_delayedFocusPage = 0;
282 
283  return false;
284  }
285  }
286 
287  if( m_SelNumberOfUnits->GetValue() < m_libEntry->GetUnitCount() )
288  {
289  if( !IsOK( this, _( "Delete extra units from symbol?" ) ) )
290  return false;
291  }
292 
293  if( m_AsConvertButt->GetValue() && !m_libEntry->HasConversion() )
294  {
295  if( !IsOK( this, _( "Add new pins for alternate body style (DeMorgan) to symbol?" ) ) )
296  return false;
297  }
298  else if( !m_AsConvertButt->GetValue() && m_libEntry->HasConversion() )
299  {
300  if( !IsOK( this, _( "Delete alternate body style (DeMorgan) draw items from symbol?" ) ) )
301  return false;
302  }
303 
304  return true;
305 }
306 
307 
309 {
310  if( !wxDialog::TransferDataFromWindow() )
311  return false;
312 
313  LIB_ALIAS* rootAlias = m_libEntry->GetAlias( m_libEntry->GetName() );
314  // We need to keep the name and the value the same at the moment!
315  wxString newName = m_fields->at( VALUE ).GetText();
316 
317  if( m_libEntry->GetName() != newName )
319  else
321 
322  // The Y axis for components in lib is from bottom to top while the screen axis is top
323  // to bottom: we must change the y coord sign when writing back to the library
324  for( size_t i = 0; i < m_fields->size(); ++i )
325  {
326  wxPoint pos = m_fields->at( i ).GetPosition();
327  pos.y = -pos.y;
328  m_fields->at( i ).SetPosition( pos );
329  }
330 
331  // Datasheet field is special; copy it to the root alias docfilename
332  rootAlias->SetDocFileName( m_fields->at( DATASHEET ).GetText() );
333 
335 
336  // We need to keep the name and the value the same at the moment!
337  m_libEntry->SetName( newName );
338 
339  rootAlias->SetDescription( m_DescCtrl->GetValue() );
340  rootAlias->SetKeyWords( m_KeywordCtrl->GetValue() );
341 
344 
345  m_libEntry->SetConversion( m_AsConvertButt->GetValue() );
346 
347  if( m_OptionPower->GetValue() )
348  m_libEntry->SetPower();
349  else
351 
354 
355  if( m_PinsNameInsideButt->GetValue() )
356  {
357  int offset = KiROUND( (double) m_pinNameOffset.GetValue() / IU_PER_MILS );
358 
359  // We interpret an offset of 0 as "outside", so make sure it's non-zero
360  m_libEntry->SetPinNameOffset( offset == 0 ? 20 : offset );
361  }
362  else
363  {
364  m_libEntry->SetPinNameOffset( 0 ); // pin text outside the body (name is on the pin)
365  }
366 
369 
370  for( LIB_ALIAS* alias : m_aliasesBuffer )
371  m_libEntry->AddAlias( alias ); // Transfers ownership; no need to delete
372 
373  m_aliasesBuffer.clear();
374 
375  m_libEntry->GetFootprints().Clear();
377 
378  return true;
379 }
380 
381 
383 {
384  wxGridCellEditor* editor = m_grid->GetCellEditor( event.GetRow(), event.GetCol() );
385  wxControl* control = editor->GetControl();
386 
387  if( control && control->GetValidator() && !control->GetValidator()->Validate( control ) )
388  {
389  event.Veto();
390 
392  m_delayedFocusRow = event.GetRow();
393  m_delayedFocusColumn = event.GetCol();
394  m_delayedFocusPage = 0;
395  }
396  else if( event.GetRow() == VALUE && event.GetCol() == FDC_VALUE )
397  m_SymbolNameCtrl->ChangeValue( event.GetString() );
398 
399  editor->DecRef();
400 }
401 
402 
404 {
405  m_grid->SetCellValue( VALUE, FDC_VALUE, m_SymbolNameCtrl->GetValue() );
406 }
407 
408 
410 {
411  if( !m_delayedFocusCtrl && !m_SymbolNameCtrl->GetValidator()->Validate( m_SymbolNameCtrl ) )
412  {
414  m_delayedFocusPage = 0;
415  }
416 
417  event.Skip();
418 }
419 
420 
421 void DIALOG_EDIT_COMPONENT_IN_LIBRARY::OnAddField( wxCommandEvent& event )
422 {
423  if( !m_grid->CommitPendingChanges() )
424  return;
425 
426  int fieldID = m_fields->size();
427  LIB_FIELD newField( m_libEntry, fieldID );
428 
429  m_fields->push_back( newField );
430 
431  // notify the grid
432  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
433  m_grid->ProcessTableMessage( msg );
434 
435  m_grid->MakeCellVisible( m_fields->size() - 1, 0 );
436  m_grid->SetGridCursor( m_fields->size() - 1, 0 );
437 
438  m_grid->EnableCellEditControl();
439  m_grid->ShowCellEditControl();
440 }
441 
442 
444 {
445  int curRow = m_grid->GetGridCursorRow();
446 
447  if( curRow < 0 )
448  return;
449  else if( curRow < MANDATORY_FIELDS )
450  {
451  DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ),
452  MANDATORY_FIELDS ) );
453  return;
454  }
455 
456  m_grid->CommitPendingChanges( true /* quiet mode */ );
457 
458  m_fields->erase( m_fields->begin() + curRow );
459 
460  // notify the grid
461  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, curRow, 1 );
462  m_grid->ProcessTableMessage( msg );
463 
464  if( m_grid->GetNumberRows() > 0 )
465  {
466  m_grid->MakeCellVisible( std::max( 0, curRow-1 ), m_grid->GetGridCursorCol() );
467  m_grid->SetGridCursor( std::max( 0, curRow-1 ), m_grid->GetGridCursorCol() );
468  }
469 }
470 
471 
472 void DIALOG_EDIT_COMPONENT_IN_LIBRARY::OnMoveUp( wxCommandEvent& event )
473 {
474  if( !m_grid->CommitPendingChanges() )
475  return;
476 
477  int i = m_grid->GetGridCursorRow();
478 
479  if( i > MANDATORY_FIELDS )
480  {
481  LIB_FIELD tmp = m_fields->at( (unsigned) i );
482  m_fields->erase( m_fields->begin() + i, m_fields->begin() + i + 1 );
483  m_fields->insert( m_fields->begin() + i - 1, tmp );
484  m_grid->ForceRefresh();
485 
486  m_grid->SetGridCursor( i - 1, m_grid->GetGridCursorCol() );
487  m_grid->MakeCellVisible( m_grid->GetGridCursorRow(), m_grid->GetGridCursorCol() );
488  }
489  else
490  wxBell();
491 }
492 
493 
494 void DIALOG_EDIT_COMPONENT_IN_LIBRARY::OnMoveDown( wxCommandEvent& event )
495 {
496  if( !m_grid->CommitPendingChanges() )
497  return;
498 
499  int i = m_grid->GetGridCursorRow();
500 
501  if( i >= MANDATORY_FIELDS && i + 1 < m_fields->GetNumberRows() )
502  {
503  LIB_FIELD tmp = m_fields->at( (unsigned) i );
504  m_fields->erase( m_fields->begin() + i, m_fields->begin() + i + 1 );
505  m_fields->insert( m_fields->begin() + i + 1, tmp );
506  m_grid->ForceRefresh();
507 
508  m_grid->SetGridCursor( i + 1, m_grid->GetGridCursorCol() );
509  m_grid->MakeCellVisible( m_grid->GetGridCursorRow(), m_grid->GetGridCursorCol() );
510  }
511  else
512  wxBell();
513 }
514 
515 
516 void DIALOG_EDIT_COMPONENT_IN_LIBRARY::updateAliasName( bool aFromGrid, const wxString& aName )
517 {
518  int idx = m_aliasListBox->GetSelection();
519 
520  if( idx >= 0 )
521  {
522  m_aliasListBox->SetString( (unsigned) idx, aName );
523  m_aliasesBuffer[ idx ]->SetName( aName );
524 
525  if( aFromGrid )
526  m_AliasNameCtrl->ChangeValue( aName );
527  else
528  m_aliasGrid->SetCellValue( VALUE, FDC_VALUE, aName );
529  }
530 }
531 
532 
534 {
535  if( event.GetRow() == VALUE )
536  {
537  int idx = m_aliasListBox->GetSelection();
538  wxString newName = event.GetString();
539 
540  if( idx < 0 || !checkAliasName( newName ) )
541  {
542  event.Veto();
543 
545  m_delayedFocusRow = event.GetRow();
546  m_delayedFocusColumn = event.GetCol();
547  m_delayedFocusPage = 1;
548  }
549  else
550  updateAliasName( true, newName );
551  }
552 }
553 
554 
556 {
557  updateAliasName( false, m_AliasNameCtrl->GetValue() );
558 }
559 
560 
562 {
563  if( !m_delayedFocusCtrl && !checkAliasName( m_AliasNameCtrl->GetValue() ) )
564  {
566  m_delayedFocusPage = 1;
567  }
568 
569  event.Skip();
570 }
571 
572 
574 {
575  if( m_currentAlias >= 0 )
576  {
578 
579  alias->SetName( m_aliasGrid->GetCellValue( VALUE, FDC_VALUE ) );
580  alias->SetDocFileName( m_aliasGrid->GetCellValue( DATASHEET, FDC_VALUE ) );
581  alias->SetDescription( m_AliasDescCtrl->GetValue() );
582  alias->SetKeyWords( m_AliasKeywordsCtrl->GetValue() );
583  }
584 }
585 
586 
588 {
589 #ifdef KICAD_SPICE
590  int diff = m_fields->size();
591  auto cmp = SCH_COMPONENT( *m_libEntry, m_libEntry->GetLibId(), nullptr );
592 
593  DIALOG_SPICE_MODEL dialog( this, cmp, m_fields );
594 
595  if( dialog.ShowModal() != wxID_OK )
596  return;
597 
598  diff = m_fields->size() - diff;
599 
600  if( diff > 0 )
601  {
602  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, diff );
603  m_grid->ProcessTableMessage( msg );
604  }
605  else if( diff < 0 )
606  {
607  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, 0, diff );
608  m_grid->ProcessTableMessage( msg );
609  }
610 
611  m_grid->ForceRefresh();
612 #endif /* KICAD_SPICE */
613 }
614 
615 
617 {
619  {
620  m_aliasListBox->SetSelection( m_currentAlias ); // veto selection change
621  return;
622  }
623 
624  // Copy any pending changes back into the buffer
626 
627  LIB_ALIAS* alias = nullptr;
628  int newIdx = m_aliasListBox->GetSelection();
629 
630  if( newIdx >= 0 )
631  {
632  alias = m_aliasesBuffer[ newIdx ];
633 
634  m_aliasGrid->SetCellValue( VALUE, FDC_VALUE, alias->GetName() );
635  m_aliasGrid->SetCellValue( DATASHEET, FDC_VALUE, alias->GetDocFileName() );
636  m_aliasGrid->Enable( true );
637 
638  // Use ChangeValue() so we don't generate events
639  m_AliasNameCtrl->ChangeValue( alias->GetName() );
640  m_AliasNameCtrl->Enable( true );
641  m_AliasDescCtrl->ChangeValue( alias->GetDescription() );
642  m_AliasDescCtrl->Enable( true );
643  m_AliasKeywordsCtrl->ChangeValue( alias->GetKeyWords() );
644  m_AliasKeywordsCtrl->Enable( true );
645  }
646  else
647  {
648  m_aliasGrid->SetCellValue( VALUE, FDC_VALUE, wxEmptyString );
649  m_aliasGrid->SetCellValue( DATASHEET, FDC_VALUE, wxEmptyString );
650  m_aliasGrid->Enable( false );
651 
652  // Use ChangeValue() so we don't generate events
653  m_AliasNameCtrl->ChangeValue( wxEmptyString );
654  m_AliasNameCtrl->Enable( false );
655  m_AliasDescCtrl->ChangeValue( wxEmptyString );
656  m_AliasDescCtrl->Enable( false );
657  m_AliasKeywordsCtrl->ChangeValue( wxEmptyString );
658  m_AliasKeywordsCtrl->Enable( false );
659  }
660 
661  m_currentAlias = newIdx;
662 }
663 
664 
666 {
667  if( aName.IsEmpty() )
668  return false;
669 
670  if( m_SymbolNameCtrl->GetValue().CmpNoCase( aName ) == 0 )
671  {
672  wxString msg;
673  msg.Printf( _( "Alias can not have same name as symbol." ) );
674  DisplayInfoMessage( this, msg );
675  return false;
676  }
677 
678  for( int i = 0; i < (int)m_aliasListBox->GetCount(); ++i )
679  {
680  if( i == m_aliasListBox->GetSelection() )
681  continue;
682 
683  if( m_aliasListBox->GetString( i ).CmpNoCase( aName ) == 0 )
684  {
685  wxString msg;
686  msg.Printf( _( "Alias \"%s\" already exists." ), aName );
687  DisplayInfoMessage( this, msg );
688  return false;
689  }
690  }
691 
692  wxString library = m_Parent->GetCurLib();
693 
694  if( !library.empty() )
695  {
696  LIB_ALIAS* existing = Prj().SchSymbolLibTable()->LoadSymbol( library, aName );
697 
698  if( existing && existing->GetPart()->GetName() != m_libEntry->GetName() )
699  {
700  wxString msg;
701  msg.Printf( _( "Symbol name \"%s\" already exists in library \"%s\"." ),
702  aName, library );
703  DisplayErrorMessage( this, msg );
704  return false;
705  }
706  }
707 
708  return true;
709 }
710 
711 
712 void DIALOG_EDIT_COMPONENT_IN_LIBRARY::OnAddAlias( wxCommandEvent& event )
713 {
715  return;
716 
717  wxCommandEvent dummy;
718  wxString aliasname = _( "untitled" );
719  int suffix = 1;
720 
721  while( m_aliasListBox->FindString( aliasname ) != wxNOT_FOUND )
722  aliasname = wxString::Format( _( "untitled%i" ), suffix++ );
723 
724  LIB_ALIAS* alias = new LIB_ALIAS( aliasname, m_libEntry );
725 
726  // Initialize with parent's data
727  alias->SetDescription( m_DescCtrl->GetValue() );
728  alias->SetKeyWords( m_KeywordCtrl->GetValue() );
729  alias->SetDocFileName( m_grid->GetCellValue( DATASHEET, FDC_VALUE ) );
730 
731  m_aliasesBuffer.push_back( alias ); // transfers ownership of alias to aliasesBuffer
732 
733  m_aliasListBox->Append( aliasname );
734  m_aliasListBox->SetSelection( m_aliasListBox->GetCount() - 1 );
735  OnSelectAlias( dummy );
736 }
737 
738 
740 {
742  return;
743 
744  int sel = m_aliasListBox->GetSelection();
745 
746  if( sel == wxNOT_FOUND )
747  return;
748 
749  m_aliasListBox->Delete( (unsigned) sel );
750  m_aliasesBuffer.erase( m_aliasesBuffer.begin() + sel );
751  m_currentAlias = wxNOT_FOUND;
752 
753  if( m_aliasListBox->GetCount() == 0 )
754  m_aliasListBox->SetSelection( wxNOT_FOUND );
755  else
756  m_aliasListBox->SetSelection( std::max( 0, sel - 1 ) );
757 
758  wxCommandEvent dummy;
759  OnSelectAlias( dummy );
760 }
761 
762 
764 {
765  int idx = m_FootprintFilterListBox->HitTest( event.GetPosition() );
766  wxCommandEvent dummy;
767 
768  if( idx >= 0 )
770  else
772 }
773 
774 
776 {
777  // Running the Footprint Browser gums up the works and causes the automatic cancel
778  // stuff to no longer work. So we do it here ourselves.
779  EndQuasiModal( wxID_CANCEL );
780 }
781 
782 
784 {
785  wxString filterLine;
786  LIB_PART* component = m_Parent->GetCurPart();
787 
788  if( component == NULL )
789  return;
790 
791  WX_TEXT_ENTRY_DIALOG dlg( this, _( "Filter:" ), _( "Add Footprint Filter" ), filterLine );
792 
793  if( dlg.ShowModal() == wxID_CANCEL || dlg.GetValue().IsEmpty() )
794  return;
795 
796  filterLine = dlg.GetValue();
797  filterLine.Replace( wxT( " " ), wxT( "_" ) );
798 
799  // duplicate filters do no harm, so don't be a nanny.
800 
801  m_FootprintFilterListBox->Append( filterLine );
802  m_FootprintFilterListBox->SetSelection( m_FootprintFilterListBox->GetCount() - 1 );
803 }
804 
805 
807 {
808  int ii = m_FootprintFilterListBox->GetSelection();
809 
810  if( ii >= 0 )
811  {
812  m_FootprintFilterListBox->Delete( (unsigned) ii );
813 
814  if( m_FootprintFilterListBox->GetCount() == 0 )
815  m_FootprintFilterListBox->SetSelection( wxNOT_FOUND );
816  else
817  m_FootprintFilterListBox->SetSelection( std::max( 0, ii - 1 ) );
818  }
819 }
820 
821 
823 {
824  int idx = m_FootprintFilterListBox->GetSelection();
825 
826  if( idx >= 0 )
827  {
828  wxString filter = m_FootprintFilterListBox->GetStringSelection();
829 
830  WX_TEXT_ENTRY_DIALOG dlg( this, _( "Filter:" ), _( "Edit Footprint Filter" ), filter );
831 
832  if( dlg.ShowModal() == wxID_OK && !dlg.GetValue().IsEmpty() )
833  m_FootprintFilterListBox->SetString( (unsigned) idx, dlg.GetValue() );
834  }
835 }
836 
837 
839 {
840  m_width = aWidth;
841 
842  // Account for scroll bars
843  aWidth -= ( m_grid->GetSize().x - m_grid->GetClientSize().x );
844 
845  m_grid->AutoSizeColumn( FDC_NAME );
846 
847  int fixedColsWidth = m_grid->GetColSize( FDC_NAME );
848 
849  for( int i = 2; i < m_grid->GetNumberCols(); i++ )
850  fixedColsWidth += m_grid->GetColSize( i );
851 
852  m_grid->SetColSize( FDC_VALUE, aWidth - fixedColsWidth );
853 }
854 
855 
857 {
858  m_aliasGrid->AutoSizeColumn( FDC_NAME );
859  m_aliasGrid->SetColSize( FDC_VALUE, aWidth - m_aliasGrid->GetColSize( FDC_NAME ) - 2 );
860 }
861 
862 
863 void DIALOG_EDIT_COMPONENT_IN_LIBRARY::OnUpdateUI( wxUpdateUIEvent& event )
864 {
865  m_OptionPartsLocked->Enable( m_SelNumberOfUnits->GetValue() > 1 );
867 
868  if( m_grid->IsCellEditControlShown() )
869  {
870  int row = m_grid->GetGridCursorRow();
871  int col = m_grid->GetGridCursorCol();
872 
873  if( row == VALUE && col == FDC_VALUE )
874  {
875  wxGridCellEditor* editor = m_grid->GetCellEditor( row, col );
876  m_SymbolNameCtrl->ChangeValue( editor->GetValue() );
877  editor->DecRef();
878  }
879  }
880 
881  // Synthesize a Select event when the selection is cleared
882  if( m_aliasListBox->GetSelection() == wxNOT_FOUND && m_currentAlias != wxNOT_FOUND )
883  {
884  wxCommandEvent dummy;
885  OnSelectAlias( dummy );
886  }
887 
888  // Handle shown columns changes
889  wxString shownColumns = m_grid->GetShownColumns();
890 
891  if( shownColumns != m_shownColumns )
892  {
893  m_shownColumns = shownColumns;
894 
895  if( !m_grid->IsCellEditControlShown() )
896  adjustGridColumns( m_grid->GetRect().GetWidth() );
897  }
898 
899  // Handle a delayed focus. The delay allows us to:
900  // a) change focus when the error was triggered from within a killFocus handler
901  // b) show the correct notebook page in the background before the error dialog comes up
902  // when triggered from an OK or a notebook page change
903 
904  if( m_delayedFocusPage >= 0 && m_NoteBook->GetSelection() != m_delayedFocusPage )
905  {
906  m_NoteBook->SetSelection( (unsigned) m_delayedFocusPage );
907  m_delayedFocusPage = -1;
908  }
909 
910  if( !m_delayedErrorMessage.IsEmpty() )
911  {
912  // We will re-enter this routine when the error dialog is displayed, so make
913  // sure we don't keep putting up more dialogs.
914  wxString msg = m_delayedErrorMessage;
915  m_delayedErrorMessage = wxEmptyString;
916 
917  // Do not use DisplayErrorMessage(); it screws up window order on Mac
918  DisplayError( nullptr, msg );
919  }
920 
921  if( m_delayedFocusCtrl )
922  {
923  m_delayedFocusCtrl->SetFocus();
924 
925  if( dynamic_cast<wxTextEntry*>( m_delayedFocusCtrl ) )
926  dynamic_cast<wxTextEntry*>( m_delayedFocusCtrl )->SelectAll();
927 
928  m_delayedFocusCtrl = nullptr;
929  }
930  else if( m_delayedFocusGrid )
931  {
932  m_delayedFocusGrid->SetFocus();
935 
936  m_delayedFocusGrid->EnableCellEditControl( true );
937  m_delayedFocusGrid->ShowCellEditControl();
938 
939  m_delayedFocusGrid = nullptr;
940  m_delayedFocusRow = -1;
942  }
943 }
944 
945 
947 {
948  auto new_size = event.GetSize().GetX();
949 
950  if( new_size != m_width )
951  {
952  adjustGridColumns( event.GetSize().GetX() );
953  }
954 
955  // Always propagate a wxSizeEvent:
956  event.Skip();
957 }
958 
959 
961 {
962  adjustAliasGridColumns( event.GetSize().GetX() );
963 
964  event.Skip();
965 }
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:236
wxString GetName(bool aTranslate=true) const
Returns the field name.
Definition: lib_field.cpp:366
LIB_PART * GetCurPart() const
Return the current part being edited or NULL if none selected.
void OnAddFootprintFilter(wxCommandEvent &event) override
int GetUnitCount() const
LIB_FIELD * GetField(int aId)
Return pointer to the requested field.
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)
Display an error message with aMessage.
Definition: confirm.cpp:249
void OnAliasNameText(wxCommandEvent &event) override
int GetNumberRows() override
void OnEditFootprintFilter(wxCommandEvent &event) override
void OnSizeGrid(wxSizeEvent &event) override
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...
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
LIB_ALIAS * GetAlias(size_t aIndex) const
std::vector< LIB_ALIAS * > LIB_ALIASES
void AddAlias(const wxString &aName)
Add an alias aName to the part.
void OnCancelButtonClick(wxCommandEvent &event) override
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:51
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.
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.
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:172
#define _(s)
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
void EndQuasiModal(int retCode)
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 to draw a dummy shape when a LIB_PART is not found in library.
#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...
size_t i
Definition: json11.cpp:597
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:73
#define IU_PER_MILS
Definition: plotter.cpp:135
The common library.
Class DIALOG_EDIT_COMPONENT_IN_LIBRARY_BASE.
virtual long long int GetValue()
Function GetValue Returns the current value in Internal Units.
virtual void SetName(const wxString &aName)
void OnAddAlias(wxCommandEvent &event) override
void OnEditSpiceModel(wxCommandEvent &event) override
A text control validator used for validating the text allowed in library and schematic component fiel...
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)
Display an informational message box with aMessage.
Definition: confirm.cpp:265
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
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:281
virtual const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:124
bool UnitsLocked() const
Check whether part units are interchangeable.
void SaveCopyInUndoList(EDA_ITEM *ItemToCopy, UNDO_REDO_T undoType=UR_LIBEDIT, bool aAppend=false)
Create a copy of the current component, and save it in the undo list.
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.
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:114
void LockUnits(bool aLockUnits)
Set interchangeable the property for part units.
void SetNormal()
LIB_ALIASES GetAliases() const