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