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  // Datasheet field is special; grab its value from the docfilename
179  m_fields->at( DATASHEET ).SetText( rootAlias->GetDocFileName() );
180 
181  // The Y axis for components in lib is from bottom to top while the screen axis is top
182  // to bottom: we must change the y coord sign for editing
183  for( size_t i = 0; i < m_fields->size(); ++i )
184  {
185  wxPoint pos = m_fields->at( i ).GetPosition();
186  pos.y = -pos.y;
187  m_fields->at( i ).SetPosition( pos );
188  }
189 
190  // notify the grid
191  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_fields->GetNumberRows() );
192  m_grid->ProcessTableMessage( msg );
193  adjustGridColumns( m_grid->GetRect().GetWidth());
194 
195  m_SymbolNameCtrl->SetValue( m_libEntry->GetName() );
196 
197  m_DescCtrl->SetValue( rootAlias->GetDescription() );
198  m_KeywordCtrl->SetValue( rootAlias->GetKeyWords() );
199 
202  m_AsConvertButt->SetValue( m_libEntry->HasConversion() );
203  m_OptionPower->SetValue( m_libEntry->IsPower() );
204 
206  m_ShowPinNameButt->SetValue( m_libEntry->ShowPinNames() );
207  m_PinsNameInsideButt->SetValue( m_libEntry->GetPinNameOffset() != 0 );
209 
210  const LIB_ALIASES aliases = m_libEntry->GetAliases();
211 
212  for( LIB_ALIAS* alias : aliases )
213  {
214  if( alias->IsRoot() )
215  continue;
216 
217  m_aliasesBuffer.push_back( new LIB_ALIAS( *alias, m_libEntry ) );
218  m_aliasListBox->Append( alias->GetName() );
219  }
220 
221  if( m_aliasListBox->GetCount() )
222  m_aliasListBox->SetSelection( 0 );
223 
224  wxCommandEvent dummy;
225  OnSelectAlias( dummy );
226 
227  adjustAliasGridColumns( m_aliasGrid->GetClientRect().GetWidth() - 4 );
228 
230 
231  m_NoteBook->SetSelection( (unsigned) m_lastOpenedPage );
232 
233  return true;
234 }
235 
236 
238 {
240  return false;
241 
242  if( !SCH_COMPONENT::IsReferenceStringValid( m_fields->at( REFERENCE ).GetText() ) )
243  {
244  if( m_NoteBook->GetSelection() != 0 )
245  m_NoteBook->SetSelection( 0 );
246 
247  m_delayedErrorMessage = _( "References must start with a letter." );
251  m_delayedFocusPage = 0;
252 
253  return false;
254  }
255 
256  // Check for missing field names.
257  for( size_t i = MANDATORY_FIELDS; i < m_fields->size(); ++i )
258  {
259  LIB_FIELD& field = m_fields->at( i );
260  wxString fieldName = field.GetName( false );
261 
262  if( fieldName.IsEmpty() )
263  {
264  if( m_NoteBook->GetSelection() != 0 )
265  m_NoteBook->SetSelection( 0 );
266 
267  m_delayedErrorMessage = _( "Fields must have a name." );
271  m_delayedFocusPage = 0;
272 
273  return false;
274  }
275  }
276 
277  if( m_SelNumberOfUnits->GetValue() < m_libEntry->GetUnitCount() )
278  {
279  if( !IsOK( this, _( "Delete extra units from symbol?" ) ) )
280  return false;
281  }
282 
283  if( m_AsConvertButt->GetValue() && !m_libEntry->HasConversion() )
284  {
285  if( !IsOK( this, _( "Add new pins for alternate body style (DeMorgan) to symbol?" ) ) )
286  return false;
287  }
288  else if( !m_AsConvertButt->GetValue() && m_libEntry->HasConversion() )
289  {
290  if( !IsOK( this, _( "Delete alternate body style (DeMorgan) draw items from symbol?" ) ) )
291  return false;
292  }
293 
294  return true;
295 }
296 
297 
299 {
300  if( !wxDialog::TransferDataFromWindow() )
301  return false;
302 
303  LIB_ALIAS* rootAlias = m_libEntry->GetAlias( m_libEntry->GetName() );
304  // We need to keep the name and the value the same at the moment!
305  wxString newName = m_libEntry->GetValueField().GetText();
306 
307  if( m_libEntry->GetName() != newName )
309  else
311 
312  // The Y axis for components in lib is from bottom to top while the screen axis is top
313  // to bottom: we must change the y coord sign when writing back to the library
314  for( size_t i = 0; i < m_fields->size(); ++i )
315  {
316  wxPoint pos = m_fields->at( i ).GetPosition();
317  pos.y = -pos.y;
318  m_fields->at( i ).SetPosition( pos );
319  }
320 
321  // Datasheet field is special; copy it to the root alias docfilename
322  rootAlias->SetDocFileName( m_fields->at( DATASHEET ).GetText() );
323  m_fields->at( DATASHEET ).SetText( wxEmptyString );
324 
326 
327  // We need to keep the name and the value the same at the moment!
328  m_libEntry->SetName( newName );
329 
330  rootAlias->SetDescription( m_DescCtrl->GetValue() );
331  rootAlias->SetKeyWords( m_KeywordCtrl->GetValue() );
332 
335 
336  m_libEntry->SetConversion( m_AsConvertButt->GetValue() );
337 
338  if( m_OptionPower->GetValue() )
339  m_libEntry->SetPower();
340  else
342 
345 
346  if( m_PinsNameInsideButt->GetValue() )
347  {
348  int offset = KiROUND( (double) m_pinNameOffset.GetValue() / IU_PER_MILS );
349 
350  // We interpret an offset of 0 as "outside", so make sure it's non-zero
351  m_libEntry->SetPinNameOffset( offset == 0 ? 20 : offset );
352  }
353  else
354  {
355  m_libEntry->SetPinNameOffset( 0 ); // pin text outside the body (name is on the pin)
356  }
357 
360 
361  for( LIB_ALIAS* alias : m_aliasesBuffer )
362  m_libEntry->AddAlias( alias ); // Transfers ownership; no need to delete
363 
364  m_aliasesBuffer.clear();
365 
366  m_libEntry->GetFootprints().Clear();
368 
369  return true;
370 }
371 
372 
374 {
375  wxGridCellEditor* editor = m_grid->GetCellEditor( event.GetRow(), event.GetCol() );
376  wxControl* control = editor->GetControl();
377 
378  if( control && control->GetValidator() && !control->GetValidator()->Validate( control ) )
379  {
380  event.Veto();
381 
383  m_delayedFocusRow = event.GetRow();
384  m_delayedFocusColumn = event.GetCol();
385  m_delayedFocusPage = 0;
386  }
387  else if( event.GetRow() == VALUE && event.GetCol() == FDC_VALUE )
388  m_SymbolNameCtrl->ChangeValue( event.GetString() );
389 
390  editor->DecRef();
391 }
392 
393 
395 {
396  m_grid->SetCellValue( VALUE, FDC_VALUE, m_SymbolNameCtrl->GetValue() );
397 }
398 
399 
401 {
402  if( !m_delayedFocusCtrl && !m_SymbolNameCtrl->GetValidator()->Validate( m_SymbolNameCtrl ) )
403  {
405  m_delayedFocusPage = 0;
406  }
407 
408  event.Skip();
409 }
410 
411 
412 void DIALOG_EDIT_COMPONENT_IN_LIBRARY::OnAddField( wxCommandEvent& event )
413 {
414  if( !m_grid->CommitPendingChanges() )
415  return;
416 
417  int fieldID = m_fields->size();
418  LIB_FIELD newField( m_libEntry, fieldID );
419 
420  m_fields->push_back( newField );
421 
422  // notify the grid
423  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
424  m_grid->ProcessTableMessage( msg );
425 
426  m_grid->MakeCellVisible( m_fields->size() - 1, 0 );
427  m_grid->SetGridCursor( m_fields->size() - 1, 0 );
428 
429  m_grid->EnableCellEditControl();
430  m_grid->ShowCellEditControl();
431 }
432 
433 
435 {
436  int curRow = m_grid->GetGridCursorRow();
437 
438  if( curRow < 0 )
439  return;
440  else if( curRow < MANDATORY_FIELDS )
441  {
442  DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ),
443  MANDATORY_FIELDS ) );
444  return;
445  }
446 
447  m_grid->CommitPendingChanges( true /* quiet mode */ );
448 
449  m_fields->erase( m_fields->begin() + curRow );
450 
451  // notify the grid
452  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, curRow, 1 );
453  m_grid->ProcessTableMessage( msg );
454 
455  if( m_grid->GetNumberRows() > 0 )
456  {
457  m_grid->MakeCellVisible( std::max( 0, curRow-1 ), m_grid->GetGridCursorCol() );
458  m_grid->SetGridCursor( std::max( 0, curRow-1 ), m_grid->GetGridCursorCol() );
459  }
460 }
461 
462 
463 void DIALOG_EDIT_COMPONENT_IN_LIBRARY::OnMoveUp( wxCommandEvent& event )
464 {
465  if( !m_grid->CommitPendingChanges() )
466  return;
467 
468  int i = m_grid->GetGridCursorRow();
469 
470  if( i > MANDATORY_FIELDS )
471  {
472  LIB_FIELD tmp = m_fields->at( (unsigned) i );
473  m_fields->erase( m_fields->begin() + i, m_fields->begin() + i + 1 );
474  m_fields->insert( m_fields->begin() + i - 1, tmp );
475  m_grid->ForceRefresh();
476 
477  m_grid->SetGridCursor( i - 1, m_grid->GetGridCursorCol() );
478  m_grid->MakeCellVisible( m_grid->GetGridCursorRow(), m_grid->GetGridCursorCol() );
479  }
480  else
481  wxBell();
482 }
483 
484 
485 void DIALOG_EDIT_COMPONENT_IN_LIBRARY::OnMoveDown( wxCommandEvent& event )
486 {
487  if( !m_grid->CommitPendingChanges() )
488  return;
489 
490  int i = m_grid->GetGridCursorRow();
491 
492  if( i >= MANDATORY_FIELDS && i + 1 < m_fields->GetNumberRows() )
493  {
494  LIB_FIELD tmp = m_fields->at( (unsigned) i );
495  m_fields->erase( m_fields->begin() + i, m_fields->begin() + i + 1 );
496  m_fields->insert( m_fields->begin() + i + 1, tmp );
497  m_grid->ForceRefresh();
498 
499  m_grid->SetGridCursor( i + 1, m_grid->GetGridCursorCol() );
500  m_grid->MakeCellVisible( m_grid->GetGridCursorRow(), m_grid->GetGridCursorCol() );
501  }
502  else
503  wxBell();
504 }
505 
506 
507 void DIALOG_EDIT_COMPONENT_IN_LIBRARY::updateAliasName( bool aFromGrid, const wxString& aName )
508 {
509  int idx = m_aliasListBox->GetSelection();
510 
511  if( idx >= 0 )
512  {
513  m_aliasListBox->SetString( (unsigned) idx, aName );
514  m_aliasesBuffer[ idx ]->SetName( aName );
515 
516  if( aFromGrid )
517  m_AliasNameCtrl->ChangeValue( aName );
518  else
519  m_aliasGrid->SetCellValue( VALUE, FDC_VALUE, aName );
520  }
521 }
522 
523 
525 {
526  if( event.GetRow() == VALUE )
527  {
528  int idx = m_aliasListBox->GetSelection();
529  wxString newName = event.GetString();
530 
531  if( idx < 0 || !checkAliasName( newName ) )
532  {
533  event.Veto();
534 
536  m_delayedFocusRow = event.GetRow();
537  m_delayedFocusColumn = event.GetCol();
538  m_delayedFocusPage = 1;
539  }
540  else
541  updateAliasName( true, newName );
542  }
543 }
544 
545 
547 {
548  updateAliasName( false, m_AliasNameCtrl->GetValue() );
549 }
550 
551 
553 {
554  if( !m_delayedFocusCtrl && !checkAliasName( m_AliasNameCtrl->GetValue() ) )
555  {
557  m_delayedFocusPage = 1;
558  }
559 
560  event.Skip();
561 }
562 
563 
565 {
566  if( m_currentAlias >= 0 )
567  {
569 
570  alias->SetName( m_aliasGrid->GetCellValue( VALUE, FDC_VALUE ) );
571  alias->SetDocFileName( m_aliasGrid->GetCellValue( DATASHEET, FDC_VALUE ) );
572  alias->SetDescription( m_AliasDescCtrl->GetValue() );
573  alias->SetKeyWords( m_AliasKeywordsCtrl->GetValue() );
574  }
575 }
576 
577 
579 {
580 #ifdef KICAD_SPICE
581  int diff = m_fields->size();
582  auto cmp = SCH_COMPONENT( *m_libEntry, m_libEntry->GetLibId(), nullptr );
583 
584  DIALOG_SPICE_MODEL dialog( this, cmp, m_fields );
585 
586  if( dialog.ShowModal() != wxID_OK )
587  return;
588 
589  diff = m_fields->size() - diff;
590 
591  if( diff > 0 )
592  {
593  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, diff );
594  m_grid->ProcessTableMessage( msg );
595  }
596  else if( diff < 0 )
597  {
598  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, 0, diff );
599  m_grid->ProcessTableMessage( msg );
600  }
601 
602  m_grid->ForceRefresh();
603 #endif /* KICAD_SPICE */
604 }
605 
606 
608 {
610  {
611  m_aliasListBox->SetSelection( m_currentAlias ); // veto selection change
612  return;
613  }
614 
615  // Copy any pending changes back into the buffer
617 
618  LIB_ALIAS* alias = nullptr;
619  int newIdx = m_aliasListBox->GetSelection();
620 
621  if( newIdx >= 0 )
622  {
623  alias = m_aliasesBuffer[ newIdx ];
624 
625  m_aliasGrid->SetCellValue( VALUE, FDC_VALUE, alias->GetName() );
626  m_aliasGrid->SetCellValue( DATASHEET, FDC_VALUE, alias->GetDocFileName() );
627  m_aliasGrid->Enable( true );
628 
629  // Use ChangeValue() so we don't generate events
630  m_AliasNameCtrl->ChangeValue( alias->GetName() );
631  m_AliasNameCtrl->Enable( true );
632  m_AliasDescCtrl->ChangeValue( alias->GetDescription() );
633  m_AliasDescCtrl->Enable( true );
634  m_AliasKeywordsCtrl->ChangeValue( alias->GetKeyWords() );
635  m_AliasKeywordsCtrl->Enable( true );
636  }
637  else
638  {
639  m_aliasGrid->SetCellValue( VALUE, FDC_VALUE, wxEmptyString );
640  m_aliasGrid->SetCellValue( DATASHEET, FDC_VALUE, wxEmptyString );
641  m_aliasGrid->Enable( false );
642 
643  // Use ChangeValue() so we don't generate events
644  m_AliasNameCtrl->ChangeValue( wxEmptyString );
645  m_AliasNameCtrl->Enable( false );
646  m_AliasDescCtrl->ChangeValue( wxEmptyString );
647  m_AliasDescCtrl->Enable( false );
648  m_AliasKeywordsCtrl->ChangeValue( wxEmptyString );
649  m_AliasKeywordsCtrl->Enable( false );
650  }
651 
652  m_currentAlias = newIdx;
653 }
654 
655 
657 {
658  if( aName.IsEmpty() )
659  return false;
660 
661  if( m_SymbolNameCtrl->GetValue().CmpNoCase( aName ) == 0 )
662  {
663  wxString msg;
664  msg.Printf( _( "Alias can not have same name as symbol." ) );
665  DisplayInfoMessage( this, msg );
666  return false;
667  }
668 
669  for( int i = 0; i < (int)m_aliasListBox->GetCount(); ++i )
670  {
671  if( i == m_aliasListBox->GetSelection() )
672  continue;
673 
674  if( m_aliasListBox->GetString( i ).CmpNoCase( aName ) == 0 )
675  {
676  wxString msg;
677  msg.Printf( _( "Alias \"%s\" already exists." ), aName );
678  DisplayInfoMessage( this, msg );
679  return false;
680  }
681  }
682 
683  wxString library = m_Parent->GetCurLib();
684 
685  if( !library.empty() )
686  {
687  LIB_ALIAS* existing = Prj().SchSymbolLibTable()->LoadSymbol( library, aName );
688 
689  if( existing && existing->GetPart()->GetName() != m_libEntry->GetName() )
690  {
691  wxString msg;
692  msg.Printf( _( "Symbol name \"%s\" already exists in library \"%s\"." ),
693  aName, library );
694  DisplayErrorMessage( this, msg );
695  return false;
696  }
697  }
698 
699  return true;
700 }
701 
702 
703 void DIALOG_EDIT_COMPONENT_IN_LIBRARY::OnAddAlias( wxCommandEvent& event )
704 {
706  return;
707 
708  wxCommandEvent dummy;
709  wxString aliasname = _( "untitled" );
710  int suffix = 1;
711 
712  while( m_aliasListBox->FindString( aliasname ) != wxNOT_FOUND )
713  aliasname = wxString::Format( _( "untitled%i" ), suffix++ );
714 
715  LIB_ALIAS* alias = new LIB_ALIAS( aliasname, m_libEntry );
716 
717  // Initialize with parent's data
718  alias->SetDescription( m_DescCtrl->GetValue() );
719  alias->SetKeyWords( m_KeywordCtrl->GetValue() );
720  alias->SetDocFileName( m_grid->GetCellValue( DATASHEET, FDC_VALUE ) );
721 
722  m_aliasesBuffer.push_back( alias ); // transfers ownership of alias to aliasesBuffer
723 
724  m_aliasListBox->Append( aliasname );
725  m_aliasListBox->SetSelection( m_aliasListBox->GetCount() - 1 );
726  OnSelectAlias( dummy );
727 }
728 
729 
731 {
733  return;
734 
735  int sel = m_aliasListBox->GetSelection();
736 
737  if( sel == wxNOT_FOUND )
738  return;
739 
740  m_aliasListBox->Delete( (unsigned) sel );
741  m_aliasesBuffer.erase( m_aliasesBuffer.begin() + sel );
742  m_currentAlias = wxNOT_FOUND;
743 
744  if( m_aliasListBox->GetCount() == 0 )
745  m_aliasListBox->SetSelection( wxNOT_FOUND );
746  else
747  m_aliasListBox->SetSelection( std::max( 0, sel - 1 ) );
748 
749  wxCommandEvent dummy;
750  OnSelectAlias( dummy );
751 }
752 
753 
755 {
756  int idx = m_FootprintFilterListBox->HitTest( event.GetPosition() );
757  wxCommandEvent dummy;
758 
759  if( idx >= 0 )
761  else
763 }
764 
765 
767 {
768  // Running the Footprint Browser gums up the works and causes the automatic cancel
769  // stuff to no longer work. So we do it here ourselves.
770  EndQuasiModal( wxID_CANCEL );
771 }
772 
773 
775 {
776  wxString filterLine;
777  LIB_PART* component = m_Parent->GetCurPart();
778 
779  if( component == NULL )
780  return;
781 
782  WX_TEXT_ENTRY_DIALOG dlg( this, _( "Filter:" ), _( "Add Footprint Filter" ), filterLine );
783 
784  if( dlg.ShowModal() == wxID_CANCEL || dlg.GetValue().IsEmpty() )
785  return;
786 
787  filterLine = dlg.GetValue();
788  filterLine.Replace( wxT( " " ), wxT( "_" ) );
789 
790  // duplicate filters do no harm, so don't be a nanny.
791 
792  m_FootprintFilterListBox->Append( filterLine );
793  m_FootprintFilterListBox->SetSelection( m_FootprintFilterListBox->GetCount() - 1 );
794 }
795 
796 
798 {
799  int ii = m_FootprintFilterListBox->GetSelection();
800 
801  if( ii >= 0 )
802  {
803  m_FootprintFilterListBox->Delete( (unsigned) ii );
804 
805  if( m_FootprintFilterListBox->GetCount() == 0 )
806  m_FootprintFilterListBox->SetSelection( wxNOT_FOUND );
807  else
808  m_FootprintFilterListBox->SetSelection( std::max( 0, ii - 1 ) );
809  }
810 }
811 
812 
814 {
815  int idx = m_FootprintFilterListBox->GetSelection();
816 
817  if( idx >= 0 )
818  {
819  wxString filter = m_FootprintFilterListBox->GetStringSelection();
820 
821  WX_TEXT_ENTRY_DIALOG dlg( this, _( "Filter:" ), _( "Edit Footprint Filter" ), filter );
822 
823  if( dlg.ShowModal() == wxID_OK && !dlg.GetValue().IsEmpty() )
824  m_FootprintFilterListBox->SetString( (unsigned) idx, dlg.GetValue() );
825  }
826 }
827 
828 
830 {
831  m_width = aWidth;
832 
833  // Account for scroll bars
834  aWidth -= ( m_grid->GetSize().x - m_grid->GetClientSize().x );
835 
836  m_grid->AutoSizeColumn( FDC_NAME );
837 
838  int fixedColsWidth = m_grid->GetColSize( FDC_NAME );
839 
840  for( int i = 2; i < m_grid->GetNumberCols(); i++ )
841  fixedColsWidth += m_grid->GetColSize( i );
842 
843  m_grid->SetColSize( FDC_VALUE, aWidth - fixedColsWidth );
844 }
845 
846 
848 {
849  m_aliasGrid->AutoSizeColumn( FDC_NAME );
850  m_aliasGrid->SetColSize( FDC_VALUE, aWidth - m_aliasGrid->GetColSize( FDC_NAME ) - 2 );
851 }
852 
853 
854 void DIALOG_EDIT_COMPONENT_IN_LIBRARY::OnUpdateUI( wxUpdateUIEvent& event )
855 {
856  m_OptionPartsLocked->Enable( m_SelNumberOfUnits->GetValue() > 1 );
858 
859  if( m_grid->IsCellEditControlShown() )
860  {
861  int row = m_grid->GetGridCursorRow();
862  int col = m_grid->GetGridCursorCol();
863 
864  if( row == VALUE && col == FDC_VALUE )
865  {
866  wxGridCellEditor* editor = m_grid->GetCellEditor( row, col );
867  m_SymbolNameCtrl->ChangeValue( editor->GetValue() );
868  editor->DecRef();
869  }
870  }
871 
872  // Synthesize a Select event when the selection is cleared
873  if( m_aliasListBox->GetSelection() == wxNOT_FOUND && m_currentAlias != wxNOT_FOUND )
874  {
875  wxCommandEvent dummy;
876  OnSelectAlias( dummy );
877  }
878 
879  // Handle shown columns changes
880  wxString shownColumns = m_grid->GetShownColumns();
881 
882  if( shownColumns != m_shownColumns )
883  {
884  m_shownColumns = shownColumns;
885 
886  if( !m_grid->IsCellEditControlShown() )
887  adjustGridColumns( m_grid->GetRect().GetWidth() );
888  }
889 
890  // Handle a delayed focus. The delay allows us to:
891  // a) change focus when the error was triggered from within a killFocus handler
892  // b) show the correct notebook page in the background before the error dialog comes up
893  // when triggered from an OK or a notebook page change
894 
895  if( m_delayedFocusPage >= 0 && m_NoteBook->GetSelection() != m_delayedFocusPage )
896  {
897  m_NoteBook->SetSelection( (unsigned) m_delayedFocusPage );
898  m_delayedFocusPage = -1;
899  }
900 
901  if( !m_delayedErrorMessage.IsEmpty() )
902  {
903  // We will re-enter this routine when the error dialog is displayed, so make
904  // sure we don't keep putting up more dialogs.
905  wxString msg = m_delayedErrorMessage;
906  m_delayedErrorMessage = wxEmptyString;
907 
908  // Do not use DisplayErrorMessage(); it screws up window order on Mac
909  DisplayError( nullptr, msg );
910  }
911 
912  if( m_delayedFocusCtrl )
913  {
914  m_delayedFocusCtrl->SetFocus();
915 
916  if( dynamic_cast<wxTextEntry*>( m_delayedFocusCtrl ) )
917  dynamic_cast<wxTextEntry*>( m_delayedFocusCtrl )->SelectAll();
918 
919  m_delayedFocusCtrl = nullptr;
920  }
921  else if( m_delayedFocusGrid )
922  {
923  m_delayedFocusGrid->SetFocus();
926 
927  m_delayedFocusGrid->EnableCellEditControl( true );
928  m_delayedFocusGrid->ShowCellEditControl();
929 
930  m_delayedFocusGrid = nullptr;
931  m_delayedFocusRow = -1;
933  }
934 }
935 
936 
938 {
939  auto new_size = event.GetSize().GetX();
940 
941  if( new_size != m_width )
942  {
943  adjustGridColumns( event.GetSize().GetX() );
944  }
945 
946  // Always propagate a wxSizeEvent:
947  event.Skip();
948 }
949 
950 
952 {
953  adjustAliasGridColumns( event.GetSize().GetX() );
954 
955  event.Skip();
956 }
wxString GetName(bool aTranslate=true) const
Returns the field name.
Definition: lib_field.cpp:408
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:258
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
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:147
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)
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...
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: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
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)
Function DisplayInfoMessage displays an informational message box with aMessage.
Definition: confirm.cpp:276
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:244
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Function IsOK displays a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:294
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.
void LockUnits(bool aLockUnits)
Set interchangeable the property for part units.
void SetNormal()
LIB_ALIASES GetAliases() const