KiCad PCB EDA Suite
dialog_lib_symbol_properties.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-2021 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 <bitmaps.h>
25 #include <confirm.h>
27 #include <kiway.h>
28 #include <symbol_edit_frame.h>
29 #include <symbol_library_manager.h>
30 #include <math/util.h> // for KiROUND
31 #include <sch_symbol.h>
33 #include <widgets/wx_grid.h>
34 #include <string_utils.h>
35 
36 #ifdef KICAD_SPICE
37 #include <dialog_spice_model.h>
38 #endif /* KICAD_SPICE */
39 
42 #include <symbol_editor_settings.h>
43 
44 
48 
49 
51  LIB_SYMBOL* aLibEntry ) :
53  m_Parent( aParent ),
54  m_libEntry( aLibEntry ),
55  m_pinNameOffset( aParent, m_nameOffsetLabel, m_nameOffsetCtrl, m_nameOffsetUnits, true ),
56  m_delayedFocusCtrl( nullptr ),
57  m_delayedFocusGrid( nullptr ),
58  m_delayedFocusRow( -1 ),
59  m_delayedFocusColumn( -1 ),
60  m_delayedFocusPage( -1 ),
61  m_width( 0 )
62 {
63  // Give a bit more room for combobox editors
64  m_grid->SetDefaultRowSize( m_grid->GetDefaultRowSize() + 4 );
65  m_fields = new FIELDS_GRID_TABLE<LIB_FIELD>( this, aParent, m_grid, m_libEntry );
67  m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this ) );
68  m_grid->SetSelectionMode( wxGrid::wxGridSelectRows );
69 
70  // Show/hide columns according to the user's preference
73 
74  wxGridCellAttr* attr = new wxGridCellAttr;
75  attr->SetEditor( new GRID_CELL_URL_EDITOR( this, Prj().SchSearchS() ) );
76  m_grid->SetAttr( DATASHEET_FIELD, FDC_VALUE, attr );
77 
78  m_SymbolNameCtrl->SetValidator( SCH_FIELD_VALIDATOR( true, VALUE_FIELD ) );
79 
80  // Configure button logos
81  m_bpAdd->SetBitmap( KiBitmap( BITMAPS::small_plus ) );
82  m_bpDelete->SetBitmap( KiBitmap( BITMAPS::small_trash ) );
83  m_bpMoveUp->SetBitmap( KiBitmap( BITMAPS::small_up ) );
84  m_bpMoveDown->SetBitmap( KiBitmap( BITMAPS::small_down ) );
88 
89  if( aParent->IsSymbolFromLegacyLibrary() && !aParent->IsSymbolFromSchematic() )
90  {
91  m_stdSizerButtonCancel->SetDefault();
92  m_stdSizerButtonOK->SetLabel( _( "Read Only" ) );
93  m_stdSizerButtonOK->Enable( false );
94  }
95  else
96  {
97  m_stdSizerButtonOK->SetDefault();
98  }
99 
100 #ifndef KICAD_SPICE
101  m_spiceFieldsButton->Hide();
102 #endif
103 
104  // wxFormBuilder doesn't include this event...
105  m_grid->Connect( wxEVT_GRID_CELL_CHANGING,
107  nullptr, this );
108 
110  {
111  if( ( m_lastLayout == DIALOG_LIB_SYMBOL_PROPERTIES::ALIAS && aLibEntry->IsRoot() )
112  || ( m_lastLayout == DIALOG_LIB_SYMBOL_PROPERTIES::PARENT && aLibEntry->IsAlias() ) )
113  {
114  resetSize();
115  }
116  }
117 
120 
121  m_grid->GetParent()->Layout();
123  Layout();
124 
126 }
127 
128 
130 {
131  m_lastOpenedPage = m_NoteBook->GetSelection( );
132 
135 
136  // Prevents crash bug in wxGrid's d'tor
138 
139  m_grid->Disconnect( wxEVT_GRID_CELL_CHANGING,
141  nullptr, this );
142 
143  // Delete the GRID_TRICKS.
144  m_grid->PopEventHandler( true );
145 }
146 
147 
149 {
150  if( !wxDialog::TransferDataToWindow() )
151  return false;
152 
153  // Push a copy of each field into m_updateFields
155 
156  // The Y axis for components in lib is from bottom to top while the screen axis is top
157  // to bottom: we must change the y coord sign for editing
158  for( size_t i = 0; i < m_fields->size(); ++i )
159  {
160  wxPoint pos = m_fields->at( i ).GetPosition();
161  pos.y = -pos.y;
162  m_fields->at( i ).SetPosition( pos );
163  }
164 
165  // notify the grid
166  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_fields->GetNumberRows() );
167  m_grid->ProcessTableMessage( msg );
168  adjustGridColumns( m_grid->GetRect().GetWidth() );
169 
170  m_SymbolNameCtrl->ChangeValue( UnescapeString( m_libEntry->GetName() ) );
171 
172  m_DescCtrl->ChangeValue( m_libEntry->GetDescription() );
173  m_KeywordCtrl->ChangeValue( m_libEntry->GetKeyWords() );
176  m_libEntry->GetUnitCount() == 1 );
177 
178  // If a symbol contains no conversion-specific pins or graphic items, symbol->HasConversion()
179  // will return false. But when editing a symbol with DeMorgan option set, we don't want to
180  // keep turning it off just because there aren't any conversion-specific items yet, so we force
181  // it to on if the parent frame has it enabled.
182  m_AsConvertButt->SetValue( m_Parent->GetShowDeMorgan() );
183 
184  m_OptionPower->SetValue( m_libEntry->IsPower() );
187 
189  m_ShowPinNameButt->SetValue( m_libEntry->ShowPinNames() );
190  m_PinsNameInsideButt->SetValue( m_libEntry->GetPinNameOffset() != 0 );
192 
193  wxArrayString tmp = m_libEntry->GetFPFilters();
194  m_FootprintFilterListBox->Append( tmp );
195 
196  // Populate the list of root parts for inherited objects.
197  if( m_libEntry->IsAlias() )
198  {
199  wxArrayString rootSymbolNames;
200  wxString libName = m_Parent->GetCurLib();
201 
202  // Someone forgot to set the current library in the editor frame window.
203  wxCHECK( !libName.empty(), false );
204 
205  m_Parent->GetLibManager().GetRootSymbolNames( libName, rootSymbolNames );
206  m_inheritanceSelectCombo->Append( rootSymbolNames );
207 
208  LIB_SYMBOL_SPTR rootSymbol = m_libEntry->GetParent().lock();
209 
210  wxCHECK( rootSymbol, false );
211 
212  wxString parentName = UnescapeString( rootSymbol->GetName() );
213  int selection = m_inheritanceSelectCombo->FindString( parentName );
214 
215  wxCHECK( selection != wxNOT_FOUND, false );
216  m_inheritanceSelectCombo->SetSelection( selection );
217 
218  m_lastOpenedPage = 0;
219  }
220 
221  m_NoteBook->SetSelection( (unsigned) m_lastOpenedPage );
222 
223  return true;
224 }
225 
226 
228 {
229  if( !m_grid->CommitPendingChanges() )
230  return false;
231 
232  // Alias symbol reference can be empty because it inherits from the parent symbol.
233  if( m_libEntry->IsRoot() &&
235  {
236  if( m_NoteBook->GetSelection() != 0 )
237  m_NoteBook->SetSelection( 0 );
238 
239  m_delayedErrorMessage = _( "References must start with a letter." );
243  m_delayedFocusPage = 0;
244 
245  return false;
246  }
247 
248  // Check for missing field names.
249  for( size_t i = MANDATORY_FIELDS; i < m_fields->size(); ++i )
250  {
251  LIB_FIELD& field = m_fields->at( i );
252  wxString fieldName = field.GetName( false );
253 
254  if( fieldName.IsEmpty() )
255  {
256  if( m_NoteBook->GetSelection() != 0 )
257  m_NoteBook->SetSelection( 0 );
258 
259  m_delayedErrorMessage = _( "Fields must have a name." );
262  m_delayedFocusRow = i;
263  m_delayedFocusPage = 0;
264 
265  return false;
266  }
267  }
268 
269  // Verify that the parent name is set if the symbol is inherited
270  if( m_libEntry->IsAlias() )
271  {
272  wxString parentName = m_inheritanceSelectCombo->GetValue();
273 
274  if( parentName.IsEmpty() )
275  {
276  m_delayedErrorMessage = _( "Aliased symbol must have a parent selected" );
277 
278  return false;
279  }
280  }
281 
282  /*
283  * Confirm destructive actions.
284  */
285 
286  if( m_SelNumberOfUnits->GetValue() < m_libEntry->GetUnitCount() )
287  {
288  if( !IsOK( this, _( "Delete extra units from symbol?" ) ) )
289  return false;
290  }
291 
292  if( !m_AsConvertButt->GetValue() && m_libEntry->HasConversion() )
293  {
294  if( !IsOK( this, _( "Delete alternate body style (De Morgan) from symbol?" ) ) )
295  return false;
296  }
297 
298  return true;
299 }
300 
301 
303 {
304  if( !wxDialog::TransferDataFromWindow() )
305  return false;
306 
307  if( !m_grid->CommitPendingChanges() )
308  return false;
309 
310  // We need to keep the name and the value the same at the moment!
311  wxString newName = m_fields->at( VALUE_FIELD ).GetText();
312  wxString oldName = m_libEntry->GetName();
313 
314  if( oldName != newName )
315  {
316  wxString libName = m_Parent->GetCurLib();
317 
318  if( m_Parent->GetLibManager().SymbolExists( newName, libName ) )
319  {
320  wxString msg;
321 
322  msg.Printf( _( "The name '%s' conflicts with an existing entry in the library '%s'." ),
323  UnescapeString( newName ),
324  libName );
325  DisplayErrorMessage( this, msg );
326  return false;
327  }
328 
330  }
331  else
332  {
334  }
335 
336  // The Y axis for components in lib is from bottom to top while the screen axis is top
337  // to bottom: we must change the y coord sign when writing back to the library
338  for( size_t i = 0; i < m_fields->size(); ++i )
339  {
340  wxPoint pos = m_fields->at( i ).GetPosition();
341  pos.y = -pos.y;
342  m_fields->at( i ).SetPosition( pos );
343  m_fields->at( i ).SetId( i );
344  }
345 
347 
348  // Update the parent for inherited symbols
349  if( m_libEntry->IsAlias() )
350  {
351  wxString parentName = EscapeString( m_inheritanceSelectCombo->GetValue(), CTX_LIBID );
352 
353  // The parentName was verified to be non-empty in the Validator
354  wxString libName = m_Parent->GetCurLib();
355 
356  // Get the parent from the libManager based on the name set in the inheritance combo box.
357  LIB_SYMBOL* newParent = m_Parent->GetLibManager().GetAlias( parentName, libName );
358 
359  // Verify that the requested parent exists
360  wxCHECK( newParent, false );
361 
362  // Verify that the new parent is not an alias.
363  wxCHECK( !newParent->IsAlias(), false );
364 
365  m_libEntry->SetParent( newParent );
366  }
367 
368  // We need to keep the name and the value the same at the moment!
369  m_libEntry->SetName( newName );
370  m_libEntry->SetDescription( m_DescCtrl->GetValue() );
371  m_libEntry->SetKeyWords( m_KeywordCtrl->GetValue() );
374  !m_OptionPartsInterchangeable->GetValue() );
375  m_libEntry->SetConversion( m_AsConvertButt->GetValue() );
376  m_Parent->SetShowDeMorgan( m_AsConvertButt->GetValue() );
377 
378  if( m_OptionPower->GetValue() )
379  m_libEntry->SetPower();
380  else
382 
385 
388 
389  if( m_PinsNameInsideButt->GetValue() )
390  {
391  int offset = KiROUND( (double) m_pinNameOffset.GetValue() );
392 
393  // We interpret an offset of 0 as "outside", so make sure it's non-zero
394  m_libEntry->SetPinNameOffset( offset == 0 ? 20 : offset );
395  }
396  else
397  {
398  m_libEntry->SetPinNameOffset( 0 ); // pin text outside the body (name is on the pin)
399  }
400 
402 
404 
405  // It's possible that the symbol being edited has no pins, in which case there may be no
406  // alternate body style objects causing #LIB_SYMBOL::HasCoversion() to always return false.
407  // This allows the user to edit the alternate body style just in case this condition occurs.
408  m_Parent->SetShowDeMorgan( m_AsConvertButt->GetValue() );
409 
410  return true;
411 }
412 
413 
415 {
416  wxGridCellEditor* editor = m_grid->GetCellEditor( event.GetRow(), event.GetCol() );
417  wxControl* control = editor->GetControl();
418 
419  if( control && control->GetValidator() && !control->GetValidator()->Validate( control ) )
420  {
421  event.Veto();
422 
424  m_delayedFocusRow = event.GetRow();
425  m_delayedFocusColumn = event.GetCol();
426  m_delayedFocusPage = 0;
427  }
428  else if( event.GetCol() == FDC_NAME )
429  {
430  wxString newName = event.GetString();
431 
432  for( int i = 0; i < m_grid->GetNumberRows(); ++i )
433  {
434  if( i == event.GetRow() )
435  continue;
436 
437  if( newName.CmpNoCase( m_grid->GetCellValue( i, FDC_NAME ) ) == 0 )
438  {
439  DisplayError( this, wxString::Format( _( "The name '%s' is already in use." ),
440  newName ) );
441  event.Veto();
442  m_delayedFocusRow = event.GetRow();
443  m_delayedFocusColumn = event.GetCol();
444  }
445  }
446  }
447  else if( event.GetRow() == VALUE_FIELD && event.GetCol() == FDC_VALUE )
448  {
449  m_SymbolNameCtrl->ChangeValue( event.GetString() );
450  }
451 
452  editor->DecRef();
453 }
454 
455 
457 {
458  if( !m_Parent->IsSymbolFromSchematic() || m_OptionPower->IsChecked() )
459  m_grid->SetCellValue( VALUE_FIELD, FDC_VALUE, m_SymbolNameCtrl->GetValue() );
460 }
461 
462 
464 {
465  if( !m_delayedFocusCtrl )
466  {
467  // If the validation fails and we throw up a dialog then GTK will give us another
468  // KillFocus event and we end up in infinite recursion. So we use m_delayedFocusCtrl
469  // as a re-entrancy block and then clear it again if validation passes.
471  m_delayedFocusPage = 0;
472 
473  if( m_SymbolNameCtrl->GetValidator()->Validate( m_SymbolNameCtrl ) )
474  {
475  m_delayedFocusCtrl = nullptr;
476  m_delayedFocusPage = -1;
477  }
478  }
479 
480  event.Skip();
481 }
482 
483 
484 void DIALOG_LIB_SYMBOL_PROPERTIES::OnAddField( wxCommandEvent& event )
485 {
486  if( !m_grid->CommitPendingChanges() )
487  return;
488 
490  int fieldID = m_fields->size();
491  LIB_FIELD newField( m_libEntry, fieldID );
492 
493  newField.SetTextSize( wxSize( Mils2iu( settings->m_Defaults.text_size ),
494  Mils2iu( settings->m_Defaults.text_size ) ) );
495 
496  m_fields->push_back( newField );
497 
498  // notify the grid
499  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
500  m_grid->ProcessTableMessage( msg );
501 
502  m_grid->MakeCellVisible( (int) m_fields->size() - 1, 0 );
503  m_grid->SetGridCursor( (int) m_fields->size() - 1, 0 );
504 
505  m_grid->EnableCellEditControl();
506  m_grid->ShowCellEditControl();
507 
508  OnModify();
509 }
510 
511 
512 void DIALOG_LIB_SYMBOL_PROPERTIES::OnDeleteField( wxCommandEvent& event )
513 {
514  wxArrayInt selectedRows = m_grid->GetSelectedRows();
515 
516  if( selectedRows.empty() && m_grid->GetGridCursorRow() >= 0 )
517  selectedRows.push_back( m_grid->GetGridCursorRow() );
518 
519  if( selectedRows.empty() )
520  return;
521 
522  for( int row : selectedRows )
523  {
524  if( row < MANDATORY_FIELDS )
525  {
526  DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ),
527  MANDATORY_FIELDS ) );
528  return;
529  }
530  }
531 
532  m_grid->CommitPendingChanges( true /* quiet mode */ );
533 
534  // Reverse sort so deleting a row doesn't change the indexes of the other rows.
535  selectedRows.Sort( []( int* first, int* second ) { return *second - *first; } );
536 
537  for( int row : selectedRows )
538  {
539  m_fields->erase( m_fields->begin() + row );
540 
541  // notify the grid
542  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 );
543  m_grid->ProcessTableMessage( msg );
544 
545  if( m_grid->GetNumberRows() > 0 )
546  {
547  m_grid->MakeCellVisible( std::max( 0, row-1 ), m_grid->GetGridCursorCol() );
548  m_grid->SetGridCursor( std::max( 0, row-1 ), m_grid->GetGridCursorCol() );
549  }
550  }
551 
552  OnModify();
553 }
554 
555 
556 void DIALOG_LIB_SYMBOL_PROPERTIES::OnMoveUp( wxCommandEvent& event )
557 {
558  if( !m_grid->CommitPendingChanges() )
559  return;
560 
561  int i = m_grid->GetGridCursorRow();
562 
563  if( i > MANDATORY_FIELDS )
564  {
565  LIB_FIELD tmp = m_fields->at( (unsigned) i );
566  m_fields->erase( m_fields->begin() + i, m_fields->begin() + i + 1 );
567  m_fields->insert( m_fields->begin() + i - 1, tmp );
568  m_grid->ForceRefresh();
569 
570  m_grid->SetGridCursor( i - 1, m_grid->GetGridCursorCol() );
571  m_grid->MakeCellVisible( m_grid->GetGridCursorRow(), m_grid->GetGridCursorCol() );
572 
573  OnModify();
574  }
575  else
576  {
577  wxBell();
578  }
579 }
580 
581 
582 void DIALOG_LIB_SYMBOL_PROPERTIES::OnMoveDown( wxCommandEvent& event )
583 {
584  if( !m_grid->CommitPendingChanges() )
585  return;
586 
587  int i = m_grid->GetGridCursorRow();
588 
589  if( i >= MANDATORY_FIELDS && i + 1 < m_fields->GetNumberRows() )
590  {
591  LIB_FIELD tmp = m_fields->at( (unsigned) i );
592  m_fields->erase( m_fields->begin() + i, m_fields->begin() + i + 1 );
593  m_fields->insert( m_fields->begin() + i + 1, tmp );
594  m_grid->ForceRefresh();
595 
596  m_grid->SetGridCursor( i + 1, m_grid->GetGridCursorCol() );
597  m_grid->MakeCellVisible( m_grid->GetGridCursorRow(), m_grid->GetGridCursorCol() );
598 
599  OnModify();
600  }
601  else
602  {
603  wxBell();
604  }
605 }
606 
607 
609 {
610 #ifdef KICAD_SPICE
611  int diff = m_fields->size();
612  auto symbol = SCH_SYMBOL( *m_libEntry, m_libEntry->GetLibId(), nullptr, 0 );
613 
614  DIALOG_SPICE_MODEL dialog( this, symbol, m_fields );
615 
616  if( dialog.ShowModal() != wxID_OK )
617  return;
618 
619  diff = (int) m_fields->size() - diff;
620 
621  if( diff > 0 )
622  {
623  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, diff );
624  m_grid->ProcessTableMessage( msg );
625  }
626  else if( diff < 0 )
627  {
628  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, 0, -diff );
629  m_grid->ProcessTableMessage( msg );
630  }
631 
632  OnModify();
633  m_grid->ForceRefresh();
634 #endif /* KICAD_SPICE */
635 }
636 
637 
639 {
640  int idx = m_FootprintFilterListBox->HitTest( event.GetPosition() );
641  wxCommandEvent dummy;
642 
643  if( idx >= 0 )
645  else
647 }
648 
649 
651 {
652  // Running the Footprint Browser gums up the works and causes the automatic cancel
653  // stuff to no longer work. So we do it here ourselves.
654  EndQuasiModal( wxID_CANCEL );
655 }
656 
657 
659 {
660  wxString filterLine;
661  WX_TEXT_ENTRY_DIALOG dlg( this, _( "Filter:" ), _( "Add Footprint Filter" ), filterLine );
662 
663  if( dlg.ShowModal() == wxID_CANCEL || dlg.GetValue().IsEmpty() )
664  return;
665 
666  filterLine = dlg.GetValue();
667  filterLine.Replace( wxT( " " ), wxT( "_" ) );
668 
669  // duplicate filters do no harm, so don't be a nanny.
670 
671  m_FootprintFilterListBox->Append( filterLine );
672  m_FootprintFilterListBox->SetSelection( (int) m_FootprintFilterListBox->GetCount() - 1 );
673 
674  OnModify();
675 }
676 
677 
679 {
680  int ii = m_FootprintFilterListBox->GetSelection();
681 
682  if( ii >= 0 )
683  {
684  m_FootprintFilterListBox->Delete( (unsigned) ii );
685 
686  if( m_FootprintFilterListBox->GetCount() == 0 )
687  m_FootprintFilterListBox->SetSelection( wxNOT_FOUND );
688  else
689  m_FootprintFilterListBox->SetSelection( std::max( 0, ii - 1 ) );
690  }
691 
692  OnModify();
693 }
694 
695 
697 {
698  int idx = m_FootprintFilterListBox->GetSelection();
699 
700  if( idx >= 0 )
701  {
702  wxString filter = m_FootprintFilterListBox->GetStringSelection();
703 
704  WX_TEXT_ENTRY_DIALOG dlg( this, _( "Filter:" ), _( "Edit Footprint Filter" ), filter );
705 
706  if( dlg.ShowModal() == wxID_OK && !dlg.GetValue().IsEmpty() )
707  {
708  m_FootprintFilterListBox->SetString( (unsigned) idx, dlg.GetValue() );
709  OnModify();
710  }
711  }
712 }
713 
714 
716 {
717  m_width = aWidth;
718 
719  // Account for scroll bars
720  aWidth -= ( m_grid->GetSize().x - m_grid->GetClientSize().x );
721 
722  m_grid->AutoSizeColumn( FDC_NAME );
723 
724  int fixedColsWidth = m_grid->GetColSize( FDC_NAME );
725 
726  for( int i = 2; i < m_grid->GetNumberCols(); i++ )
727  fixedColsWidth += m_grid->GetColSize( i );
728 
729  m_grid->SetColSize( FDC_VALUE, aWidth - fixedColsWidth );
730 }
731 
732 
733 void DIALOG_LIB_SYMBOL_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
734 {
735  m_OptionPartsInterchangeable->Enable( m_SelNumberOfUnits->GetValue() > 1 );
737 
738  if( m_grid->IsCellEditControlShown() )
739  {
740  int row = m_grid->GetGridCursorRow();
741  int col = m_grid->GetGridCursorCol();
742 
743  if( row == VALUE_FIELD && col == FDC_VALUE )
744  {
745  wxGridCellEditor* editor = m_grid->GetCellEditor( row, col );
746  m_SymbolNameCtrl->ChangeValue( editor->GetValue() );
747  editor->DecRef();
748  }
749  }
750 
751  // Handle shown columns changes
752  wxString shownColumns = m_grid->GetShownColumns();
753 
754  if( shownColumns != m_shownColumns )
755  {
756  m_shownColumns = shownColumns;
757 
758  if( !m_grid->IsCellEditControlShown() )
759  adjustGridColumns( m_grid->GetRect().GetWidth() );
760  }
761 
762  // Handle a delayed focus. The delay allows us to:
763  // a) change focus when the error was triggered from within a killFocus handler
764  // b) show the correct notebook page in the background before the error dialog comes up
765  // when triggered from an OK or a notebook page change
766 
767  if( m_delayedFocusPage >= 0 && m_NoteBook->GetSelection() != m_delayedFocusPage )
768  {
769  m_NoteBook->ChangeSelection( (unsigned) m_delayedFocusPage );
770  m_delayedFocusPage = -1;
771  }
772 
773  if( !m_delayedErrorMessage.IsEmpty() )
774  {
775  // We will re-enter this routine when the error dialog is displayed, so make
776  // sure we don't keep putting up more dialogs.
777  wxString msg = m_delayedErrorMessage;
778  m_delayedErrorMessage = wxEmptyString;
779 
780  // Do not use DisplayErrorMessage(); it screws up window order on Mac
781  DisplayError( nullptr, msg );
782  }
783 
784  if( m_delayedFocusCtrl )
785  {
786  m_delayedFocusCtrl->SetFocus();
787 
788  if( auto textEntry = dynamic_cast<wxTextEntry*>( m_delayedFocusCtrl ) )
789  textEntry->SelectAll();
790 
791  m_delayedFocusCtrl = nullptr;
792  }
793  else if( m_delayedFocusGrid )
794  {
795  m_delayedFocusGrid->SetFocus();
798 
799  m_delayedFocusGrid->EnableCellEditControl( true );
800  m_delayedFocusGrid->ShowCellEditControl();
801 
802  m_delayedFocusGrid = nullptr;
803  m_delayedFocusRow = -1;
805  }
806 }
807 
808 
810 {
811  auto new_size = event.GetSize().GetX();
812 
813  if( new_size != m_width )
814  {
815  adjustGridColumns( event.GetSize().GetX() );
816  }
817 
818  // Always propagate a wxSizeEvent:
819  event.Skip();
820 }
821 
822 
824 {
825  bSizerLowerBasicPanel->Show( !aIsAlias );
826  m_inheritanceSelectCombo->Enable( aIsAlias );
827  m_inheritsStaticText->Enable( aIsAlias );
828  m_grid->ForceRefresh();
829 }
830 
831 
832 void DIALOG_LIB_SYMBOL_PROPERTIES::onPowerCheckBox( wxCommandEvent& aEvent )
833 {
834  if( m_OptionPower->IsChecked() )
835  {
836  m_excludeFromBomCheckBox->SetValue( true );
837  m_excludeFromBoardCheckBox->SetValue( true );
838  m_excludeFromBomCheckBox->Enable( false );
839  m_excludeFromBoardCheckBox->Enable( false );
840  }
841  else
842  {
843  m_excludeFromBomCheckBox->Enable( true );
844  m_excludeFromBoardCheckBox->Enable( true );
845  }
846 
847  OnModify();
848 }
849 
850 
851 void DIALOG_LIB_SYMBOL_PROPERTIES::OnText( wxCommandEvent& event )
852 {
853  OnModify();
854 }
855 
856 
857 void DIALOG_LIB_SYMBOL_PROPERTIES::OnCombobox( wxCommandEvent& event )
858 {
859  OnModify();
860 }
861 
862 
863 void DIALOG_LIB_SYMBOL_PROPERTIES::OnCheckBox( wxCommandEvent& event )
864 {
865  OnModify();
866 }
867 
868 
870 {
871  OnModify();
872 }
873 
874 
875 void DIALOG_LIB_SYMBOL_PROPERTIES::OnSpinCtrlText( wxCommandEvent& event )
876 {
877  OnModify();
878 }
879 
880 
void onPowerCheckBox(wxCommandEvent &aEvent) override
Field Reference of part, i.e. "IC21".
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:279
void SetPinNameOffset(int aOffset)
Set the offset in mils of the pin name text from the pin symbol.
Definition: lib_symbol.h:571
wxString GetValue() const
void OnEditSpiceModel(wxCommandEvent &event) override
LIB_SYMBOL_REF & GetParent()
Definition: lib_symbol.h:124
void OnCheckBox(wxCommandEvent &event) override
int GetPinNameOffset() const
Definition: lib_symbol.h:572
void SetFields(const std::vector< LIB_FIELD > &aFieldsList)
Overwrite all the existing fields in this symbol with fields supplied in aFieldsList.
Definition: lib_symbol.cpp:965
void GetRootSymbolNames(const wxString &aLibName, wxArrayString &aRootSymbolNames)
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:292
void OnModify()
int GetNumberRows() override
void SetIncludeOnBoard(bool aIncludeOnBoard)
Set or clear include in board netlist flag.
Definition: lib_symbol.h:603
This file is part of the common library.
wxString GetName() const override
Definition: lib_symbol.h:133
void ShowHideColumns(const wxString &shownColumns)
Show/hide the grid columns based on a tokenized string of shown column indexes.
Definition: wx_grid.cpp:172
void SetShowDeMorgan(bool show)
SYMBOL_EDITOR_SETTINGS * GetSettings() const
void SetConversion(bool aSetConvert, bool aDuplicatePins=true)
Set or clear the alternate body style (DeMorgan) for the symbol.
A KICAD version of wxTextEntryDialog which supports the various improvements/work-arounds from DIALOG...
Field object used in symbol libraries.
Definition: lib_field.h:59
bool IsAlias() const
Definition: lib_symbol.h:172
void SetUnitCount(int aCount, bool aDuplicateDrawItems=true)
Set the units per symbol count.
std::shared_ptr< LIB_SYMBOL > LIB_SYMBOL_SPTR
shared pointer to LIB_SYMBOL
Definition: lib_symbol.h:42
bool ShowPinNumbers() const
Definition: lib_symbol.h:588
bool GetIncludeOnBoard() const
Definition: lib_symbol.h:604
bool IsPower() const
Definition: lib_symbol.cpp:459
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:258
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:93
Define a library symbol object.
Definition: lib_symbol.h:96
wxString GetCurLib() const
The nickname of the current library being edited and empty string if none.
bool GetShowDeMorgan() const
bool IsSymbolFromSchematic() const
wxString GetName(bool aUseDefaultName=true) const
Return the field name.
Definition: lib_field.cpp:393
name of datasheet
void GetFields(std::vector< LIB_FIELD * > &aList)
Return a list of fields within this symbol.
Definition: lib_symbol.cpp:982
void UpdateAfterSymbolProperties(wxString *aOldName=nullptr)
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:139
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:72
bool SymbolExists(const wxString &aAlias, const wxString &aLibrary) const
Return true if symbol with a specific alias exists in library (either original one or buffered).
void OnMoveUp(wxCommandEvent &event) override
bool HasConversion() const
Test if symbol has more than one body conversion type (DeMorgan).
void OnCancelButtonClick(wxCommandEvent &event) override
void OnEditFootprintFilter(wxCommandEvent &event) override
void OnAddField(wxCommandEvent &event) override
void OnText(wxCommandEvent &event) override
void SetShowPinNames(bool aShow)
Set or clear the pin name visibility flag.
Definition: lib_symbol.h:579
wxString GetKeyWords() const
Definition: lib_symbol.h:155
Field Value of part, i.e. "3.3K".
void OnSpinCtrlText(wxCommandEvent &event) override
LIB_ID GetLibId() const override
Definition: lib_symbol.h:135
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
virtual void SetName(const wxString &aName)
Definition: lib_symbol.cpp:362
int GetUnitCount() const override
For items with units, return the number of units.
void SaveCopyInUndoList(EDA_ITEM *aItem, UNDO_REDO aUndoType=UNDO_REDO::LIBEDIT, bool aAppend=false)
Create a copy of the current symbol, and save it in the undo list.
SYMBOL_LIBRARY_MANAGER & GetLibManager()
void SetDescription(const wxString &aDescription)
Definition: lib_symbol.h:140
bool ShowPinNames() const
Definition: lib_symbol.h:580
#define _(s)
void SetParent(LIB_SYMBOL *aParent=nullptr)
Definition: lib_symbol.cpp:371
void OnDeleteFootprintFilter(wxCommandEvent &event) override
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:226
void OnSizeGrid(wxSizeEvent &event) override
void OnUpdateUI(wxUpdateUIEvent &event) override
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:105
void OnSymbolNameText(wxCommandEvent &event) override
wxString UnescapeString(const wxString &aSource)
void OnMoveDown(wxCommandEvent &event) override
void OnDeleteField(wxCommandEvent &event) override
bool UnitsLocked() const
Check whether symbol units are interchangeable.
Definition: lib_symbol.h:241
FIELDS_GRID_TABLE< LIB_FIELD > * m_fields
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
Class DIALOG_LIB_SYMBOL_PROPERTIES_BASE.
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
wxString GetShownColumns()
Get a tokenized string containing the shown column indexes.
Definition: wx_grid.cpp:153
void EndQuasiModal(int retCode)
Schematic symbol object.
Definition: sch_symbol.h:78
void OnAddFootprintFilter(wxCommandEvent &event) override
void SetIncludeInBom(bool aIncludeInBom)
Set or clear the include in schematic bill of materials flag.
Definition: lib_symbol.h:595
void SetFPFilters(const wxArrayString &aFilters)
Definition: lib_symbol.h:181
void SetPower()
Definition: lib_symbol.cpp:468
void SetShowPinNumbers(bool aShow)
Set or clear the pin number visibility flag.
Definition: lib_symbol.h:587
void resetSize()
Clear the existing dialog size and position.
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:73
wxArrayString GetFPFilters() const
Definition: lib_symbol.h:183
LIB_SYMBOL * GetAlias(const wxString &aAlias, const wxString &aLibrary) const
Return either an alias of a working LIB_SYMBOL copy, or alias of the original symbol if there is no w...
virtual long long int GetValue()
Return the current value in Internal Units.
void OnCombobox(wxCommandEvent &event) override
bool IsRoot() const override
For symbols derived from other symbols, IsRoot() indicates no derivation.
Definition: lib_symbol.h:171
A text control validator used for validating the text allowed in library and schematic symbol fields.
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
wxString GetDescription() override
Definition: lib_symbol.h:142
static bool IsReferenceStringValid(const wxString &aReferenceString)
Test for an acceptable reference string.
Definition: sch_symbol.cpp:498
bool IsSymbolFromLegacyLibrary() const
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:323
void OnSymbolNameKillFocus(wxFocusEvent &event) override
void SetKeyWords(const wxString &aKeyWords)
Definition: lib_symbol.h:153
void SetNormal()
Definition: lib_symbol.cpp:486
void Enable(bool aEnable)
Enable/disable the label, widget and units label.
void OnSpinCtrl(wxSpinEvent &event) override
void LockUnits(bool aLockUnits)
Set interchangeable the property for symbol units.
Definition: lib_symbol.h:235
DIALOG_LIB_SYMBOL_PROPERTIES(SYMBOL_EDIT_FRAME *parent, LIB_SYMBOL *aLibEntry)
bool GetIncludeInBom() const
Definition: lib_symbol.h:596
virtual void ChangeValue(int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion WITHOUT trigger...
The symbol library editor main window.
void OnFilterDClick(wxMouseEvent &event) override