KiCad PCB EDA Suite
dialog_edit_component_in_schematic.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) 2004-2020 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 
25 
26 #include <wx/tooltip.h>
27 
28 #include <confirm.h>
29 #include <kiface_i.h>
30 #include <menus_helpers.h>
31 #include <pgm_base.h>
32 
33 #include <widgets/wx_grid.h>
35 #include <ee_collectors.h>
36 #include <class_library.h>
37 #include <eeschema_settings.h>
38 #include <fields_grid_table.h>
39 #include <invoke_sch_dialog.h>
40 #include <sch_draw_panel.h>
41 #include <sch_edit_frame.h>
42 #include <sch_reference_list.h>
43 #include <symbol_lib_table.h>
44 #include <schematic.h>
45 
46 #ifdef KICAD_SPICE
47 #include <dialog_spice_model.h>
48 #endif /* KICAD_SPICE */
49 
50 
52  SCH_COMPONENT* aComponent ) :
54 {
55  m_cmp = aComponent;
56  m_part = m_cmp->GetPartRef().get();
57  m_fields = new FIELDS_GRID_TABLE<SCH_FIELD>( this, aParent, m_part );
58 
59  m_width = 0;
62 
63 #ifndef KICAD_SPICE
64  m_spiceFieldsButton->Hide();
65 #endif /* not KICAD_SPICE */
66 
67  // disable some options inside the edit dialog which can cause problems while dragging
68  if( m_cmp->IsDragging() )
69  {
70  m_rbOrientation->Disable();
71  m_rbMirror->Disable();
72  m_libraryNameTextCtrl->Disable();
73  }
74 
75  // Give a bit more room for combobox editors
76  m_grid->SetDefaultRowSize( m_grid->GetDefaultRowSize() + 4 );
77 
79  m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this ) );
80 
81  // Show/hide columns according to user's preference
82  auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
83 
84  if( cfg )
85  {
86  m_shownColumns = cfg->m_Appearance.edit_component_visible_columns;
88  }
89 
90  wxToolTip::Enable( true );
91  m_stdDialogButtonSizerOK->SetDefault();
92 
93  // Configure button logos
95  m_bpAdd->SetBitmap( KiBitmap( small_plus_xpm ) );
96  m_bpDelete->SetBitmap( KiBitmap( trash_xpm ) );
97  m_bpMoveUp->SetBitmap( KiBitmap( small_up_xpm ) );
98  m_bpMoveDown->SetBitmap( KiBitmap( small_down_xpm ) );
99 
100  // Set font sizes
101  wxFont infoFont = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
102  infoFont.SetSymbolicSize( wxFONTSIZE_SMALL );
103  m_timeStampLabel->SetFont( infoFont );
104  m_textCtrlTimeStamp->SetFont( infoFont );
105  m_textCtrlTimeStamp->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_MENU ) );
106 
107  // wxFormBuilder doesn't include this event...
108  m_grid->Connect( wxEVT_GRID_CELL_CHANGING,
110  NULL, this );
111 
113 }
114 
115 
117 {
118  auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
119 
120  if( cfg )
121  cfg->m_Appearance.edit_component_visible_columns = m_grid->GetShownColumns();
122 
123  // Prevents crash bug in wxGrid's d'tor
125 
126  m_grid->Disconnect( wxEVT_GRID_CELL_CHANGING,
128  NULL, this );
129 
130  // Delete the GRID_TRICKS.
131  m_grid->PopEventHandler( true );
132 }
133 
134 
136 {
137  return dynamic_cast<SCH_EDIT_FRAME*>( wxDialog::GetParent() );
138 }
139 
140 
142 {
143  if( !wxDialog::TransferDataToWindow() )
144  return false;
145 
146  std::set<wxString> defined;
147 
148  // Push a copy of each field into m_updateFields
149  for( int i = 0; i < m_cmp->GetFieldCount(); ++i )
150  {
151  SCH_FIELD field( *m_cmp->GetField( i ) );
152 
153  // change offset to be symbol-relative
154  field.Offset( -m_cmp->GetPosition() );
155 
156  defined.insert( field.GetName() );
157  m_fields->push_back( field );
158  }
159 
160  // Add in any template fieldnames not yet defined:
161  for( const TEMPLATE_FIELDNAME& templateFieldname : GetParent()->GetTemplateFieldNames() )
162  {
163  if( defined.count( templateFieldname.m_Name ) <= 0 )
164  {
165  SCH_FIELD field( wxPoint( 0, 0 ), -1, m_cmp, templateFieldname.m_Name );
166  field.SetVisible( templateFieldname.m_Visible );
167  m_fields->push_back( field );
168  }
169  }
170 
171  // notify the grid
172  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_fields->size() );
173  m_grid->ProcessTableMessage( msg );
174  AdjustGridColumns( m_grid->GetRect().GetWidth() );
175 
176  // If a multi-unit component, set up the unit selector and interchangeable checkbox.
177  if( m_cmp->GetUnitCount() > 1 )
178  {
179  for( int ii = 1; ii <= m_cmp->GetUnitCount(); ii++ )
180  m_unitChoice->Append( LIB_PART::SubReference( ii, false ) );
181 
182  if( m_cmp->GetUnit() <= ( int )m_unitChoice->GetCount() )
183  m_unitChoice->SetSelection( m_cmp->GetUnit() - 1 );
184  }
185  else
186  {
187  m_unitLabel->Enable( false );
188  m_unitChoice->Enable( false );
189  }
190 
191  if( m_part != nullptr && m_part->HasConversion() )
192  {
193  if( m_cmp->GetConvert() > LIB_ITEM::LIB_CONVERT::BASE )
194  m_cbAlternateSymbol->SetValue( true );
195  }
196  else
197  m_cbAlternateSymbol->Enable( false );
198 
199  // Set the symbol orientation and mirroring.
200  int orientation = m_cmp->GetOrientation() & ~( CMP_MIRROR_X | CMP_MIRROR_Y );
201 
202  if( orientation == CMP_ORIENT_90 )
203  m_rbOrientation->SetSelection( 1 );
204  else if( orientation == CMP_ORIENT_180 )
205  m_rbOrientation->SetSelection( 2 );
206  else if( orientation == CMP_ORIENT_270 )
207  m_rbOrientation->SetSelection( 3 );
208  else
209  m_rbOrientation->SetSelection( 0 );
210 
211  int mirror = m_cmp->GetOrientation() & ( CMP_MIRROR_X | CMP_MIRROR_Y );
212 
213  if( mirror == CMP_MIRROR_X )
214  m_rbMirror->SetSelection( 1 );
215  else if( mirror == CMP_MIRROR_Y )
216  m_rbMirror->SetSelection( 2 );
217  else
218  m_rbMirror->SetSelection( 0 );
219 
220  // Set the component's unique ID time stamp.
221  m_textCtrlTimeStamp->SetValue( m_cmp->m_Uuid.AsString() );
222 
223  // Set the component's library name.
224  m_libraryNameTextCtrl->SetValue( m_cmp->GetLibId().Format() );
225 
226  m_cbExcludeFromBom->SetValue( !m_cmp->GetIncludeInBom() );
228 
229  Layout();
230 
231  return true;
232 }
233 
234 
236 {
237  std::vector<COMPONENT_SELECTION> dummy;
238 
239  LIB_ID id;
240  id.Parse( m_libraryNameTextCtrl->GetValue(), LIB_ID::ID_SCH );
241 
242  auto sel = GetParent()->SelectCompFromLibTree( nullptr, dummy, true, 0, 0, false, &id );
243 
244  if( !sel.LibId.IsValid() )
245  return;
246 
247  m_libraryNameTextCtrl->SetValue( sel.LibId.Format() );
248 
249  LIB_PART* entry = GetParent()->GetLibPart( sel.LibId );
250 
251  if( entry )
252  {
253  // Update the value field for Power symbols
254  if( entry->IsPower() )
255  m_grid->SetCellValue( VALUE, FDC_VALUE, sel.LibId.GetLibItemName() );
256 
257  // Update the units control
258  int unit = m_unitChoice->GetSelection();
259  m_unitChoice->Clear();
260 
261  if( entry->GetUnitCount() > 1 )
262  {
263  for( int ii = 1; ii <= entry->GetUnitCount(); ii++ )
264  m_unitChoice->Append( LIB_PART::SubReference( ii, false ) );
265 
266  if( unit < 0 || static_cast<unsigned>( unit ) >= m_unitChoice->GetCount() )
267  unit = 0;
268 
269  m_unitChoice->SetSelection( unit );
270  m_unitLabel->Enable( true );
271  m_unitChoice->Enable( true );
272  }
273  else
274  {
275  m_unitChoice->SetSelection( -1 );
276  m_unitLabel->Enable( false );
277  m_unitChoice->Enable( false );
278  }
279 
280  // Update the deMorgan conversion controls
281  bool conversion = m_cbAlternateSymbol->GetValue();
282 
283  m_cbAlternateSymbol->SetValue( conversion && entry->HasConversion() );
284  m_cbAlternateSymbol->Enable( entry->HasConversion() );
285  }
286 }
287 
288 
290 {
291 #ifdef KICAD_SPICE
292  int diff = m_fields->size();
293 
294  DIALOG_SPICE_MODEL dialog( this, *m_cmp, m_fields );
295 
296  if( dialog.ShowModal() != wxID_OK )
297  return;
298 
299  diff = (int) m_fields->size() - diff;
300 
301  if( diff > 0 )
302  {
303  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, diff );
304  m_grid->ProcessTableMessage( msg );
305  }
306  else if( diff < 0 )
307  {
308  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, 0, -diff );
309  m_grid->ProcessTableMessage( msg );
310  }
311 
312  m_grid->ForceRefresh();
313 #endif /* KICAD_SPICE */
314 }
315 
316 
318 {
319  // Running the Footprint Browser gums up the works and causes the automatic cancel
320  // stuff to no longer work. So we do it here ourselves.
321  EndQuasiModal( wxID_CANCEL );
322 }
323 
324 
326 {
327  wxString msg;
328  LIB_ID id;
329 
330  if( !m_grid->CommitPendingChanges() || !m_grid->Validate() )
331  return false;
332 
333  if( !SCH_COMPONENT::IsReferenceStringValid( m_fields->at( REFERENCE ).GetText() ) )
334  {
335  DisplayErrorMessage( this, _( "References must start with a letter." ) );
336 
339 
340  return false;
341  }
342 
343  id.Parse( m_libraryNameTextCtrl->GetValue(), LIB_ID::ID_SCH );
344 
345  if( !id.IsValid() )
346  {
347  DisplayErrorMessage( this, _( "Library reference is not valid." ) );
348 
349  m_libraryNameTextCtrl->SetFocus();
350 
351  return false;
352  }
353  else if( id != m_cmp->GetLibId() )
354  {
355  LIB_PART* alias = nullptr;
356 
357  try
358  {
359  alias = Prj().SchSymbolLibTable()->LoadSymbol( id );
360  }
361  catch( ... )
362  {
363  }
364 
365  if( !alias )
366  {
367  msg.Printf( _( "Symbol \"%s\" not found in library \"%s\"." ),
368  id.GetLibItemName().wx_str(),
369  id.GetLibNickname().wx_str() );
370  DisplayErrorMessage( this, msg );
371 
372  m_libraryNameTextCtrl->SetFocus();
373 
374  return false;
375  }
376  }
377 
378  m_libraryNameTextCtrl->SetValue( id.Format() );
379 
380  // Check for missing field names.
381  for( size_t i = MANDATORY_FIELDS; i < m_fields->size(); ++i )
382  {
383  SCH_FIELD& field = m_fields->at( i );
384  wxString fieldName = field.GetName( false );
385 
386  if( fieldName.IsEmpty() )
387  {
388  DisplayErrorMessage( this, _( "Fields must have a name." ) );
389 
391  m_delayedFocusRow = i;
392 
393  return false;
394  }
395  }
396 
397  return true;
398 }
399 
400 
402 {
403  if( !wxDialog::TransferDataFromWindow() ) // Calls our Validate() method.
404  return false;
405 
406  SCH_SCREEN* currentScreen = GetParent()->GetScreen();
407 
408  wxCHECK( currentScreen, false );
409 
410  // This needs to be done before the LIB_ID is changed to prevent stale library symbols in
411  // the schematic file.
412  currentScreen->Remove( m_cmp );
413 
414  wxString msg;
415 
416  // save old cmp in undo list if not already in edit, or moving ...
417  if( m_cmp->GetEditFlags() == 0 )
419 
420  // Save current flags which could be modified by next change settings
421  STATUS_FLAGS flags = m_cmp->GetFlags();
422 
423  // Library symbol identifier
424  LIB_ID id;
425 
426  if( id.Parse( m_libraryNameTextCtrl->GetValue(), LIB_ID::ID_SCH, true ) >= 0 )
427  {
428  msg.Printf( _( "'%s' is not a valid library indentifier." ),
429  m_libraryNameTextCtrl->GetValue() );
430  DisplayError( this, msg );
431  return false;
432  }
433 
434  LIB_PART* libSymbol = Prj().SchSymbolLibTable()->LoadSymbol( id );
435 
436  if( !libSymbol )
437  {
438  msg.Printf( _( "Symbol '%s' not found in symbol library '%s'." ),
439  id.GetLibItemName().wx_str(), id.GetLibNickname().wx_str() );
440  DisplayError( this, msg );
441  return false;
442  }
443 
444  m_cmp->SetLibSymbol( libSymbol->Flatten().release() );
445  m_cmp->SetLibId( id );
446 
447  // For symbols with multiple shapes (De Morgan representation) Set the selected shape:
448  if( m_cbAlternateSymbol->IsEnabled() && m_cbAlternateSymbol->GetValue() )
449  m_cmp->SetConvert( LIB_ITEM::LIB_CONVERT::DEMORGAN );
450  else
451  m_cmp->SetConvert( LIB_ITEM::LIB_CONVERT::BASE );
452 
453  //Set the part selection in multiple part per package
454  int unit_selection = m_unitChoice->IsEnabled()
455  ? m_unitChoice->GetSelection() + 1
456  : 1;
457  m_cmp->SetUnitSelection( &GetParent()->GetCurrentSheet(), unit_selection );
458  m_cmp->SetUnit( unit_selection );
459 
460  switch( m_rbOrientation->GetSelection() )
461  {
462  case 0: m_cmp->SetOrientation( CMP_ORIENT_0 ); break;
463  case 1: m_cmp->SetOrientation( CMP_ORIENT_90 ); break;
464  case 2: m_cmp->SetOrientation( CMP_ORIENT_180 ); break;
465  case 3: m_cmp->SetOrientation( CMP_ORIENT_270 ); break;
466  }
467 
468  switch( m_rbMirror->GetSelection() )
469  {
470  case 0: break;
471  case 1: m_cmp->SetOrientation( CMP_MIRROR_X ); break;
472  case 2: m_cmp->SetOrientation( CMP_MIRROR_Y ); break;
473  }
474 
475  // Restore m_Flag modified by SetUnit() and other change settings
476  m_cmp->ClearFlags();
477  m_cmp->SetFlags( flags );
478 
479  // change all field positions from relative to absolute
480  for( unsigned i = 0; i < m_fields->size(); ++i )
481  m_fields->at( i ).Offset( m_cmp->GetPosition() );
482 
483  LIB_PART* entry = GetParent()->GetLibPart( m_cmp->GetLibId() );
484 
485  if( entry && entry->IsPower() )
486  m_fields->at( VALUE ).SetText( m_cmp->GetLibId().GetLibItemName() );
487 
488  // Push all fields to the component -except- for those which are TEMPLATE_FIELDNAMES
489  // with empty values.
490  TEMPLATE_FIELDNAMES templateFieldnames = GetParent()->GetTemplateFieldNames();
491  SCH_FIELDS& fields = m_cmp->GetFields();
492 
493  fields.clear();
494 
495  for( size_t i = 0; i < m_fields->size(); ++i )
496  {
497  SCH_FIELD& field = m_fields->at( i );
498  bool emptyTemplateField = false;
499 
500  if( i >= MANDATORY_FIELDS )
501  {
502  for( const auto& fieldname : templateFieldnames )
503  {
504  if( field.GetName() == fieldname.m_Name && field.GetText().IsEmpty() )
505  {
506  emptyTemplateField = true;
507  break;
508  }
509  }
510  }
511 
512  if( !emptyTemplateField )
513  fields.push_back( field );
514  }
515 
516  // Reference has a specific initialization, depending on the current active sheet
517  // because for a given component, in a complex hierarchy, there are more than one
518  // reference.
519  m_cmp->SetRef( &GetParent()->GetCurrentSheet(), m_fields->at( REFERENCE ).GetText() );
520 
521  m_cmp->SetIncludeInBom( !m_cbExcludeFromBom->IsChecked() );
522  m_cmp->SetIncludeOnBoard( !m_cbExcludeFromBoard->IsChecked() );
523 
524  // The value, footprint and datasheet fields and exclude from bill of materials setting
525  // should be kept in sync in multi-unit parts.
526  if( m_cmp->GetUnitCount() > 1 )
527  {
528  std::vector<SCH_COMPONENT*> otherUnits;
529 
530  CollectOtherUnits( GetParent()->GetCurrentSheet(), m_cmp, &otherUnits );
531 
532  for( SCH_COMPONENT* otherUnit : otherUnits )
533  {
534  GetParent()->SaveCopyInUndoList( otherUnit, UR_CHANGED, true /* append */);
535  otherUnit->GetField( VALUE )->SetText( m_fields->at( VALUE ).GetText() );
536  otherUnit->GetField( FOOTPRINT )->SetText( m_fields->at( FOOTPRINT ).GetText() );
537  otherUnit->GetField( DATASHEET )->SetText( m_fields->at( DATASHEET ).GetText() );
538  otherUnit->SetIncludeInBom( !m_cbExcludeFromBom->IsChecked() );
539  otherUnit->SetIncludeOnBoard( !m_cbExcludeFromBoard->IsChecked() );
540  GetParent()->RefreshItem( otherUnit );
541  }
542  }
543 
544  currentScreen->Append( m_cmp );
547  GetParent()->OnModify();
548 
549  return true;
550 }
551 
552 
554 {
555  wxGridCellEditor* editor = m_grid->GetCellEditor( event.GetRow(), event.GetCol() );
556  wxControl* control = editor->GetControl();
557 
558  if( control && control->GetValidator() && !control->GetValidator()->Validate( control ) )
559  {
560  event.Veto();
561  m_delayedFocusRow = event.GetRow();
562  m_delayedFocusColumn = event.GetCol();
563  }
564  else if( event.GetCol() == FDC_NAME )
565  {
566  wxString newName = event.GetString();
567 
568  for( int i = 0; i < m_grid->GetNumberRows(); ++i )
569  {
570  if( i == event.GetRow() )
571  continue;
572 
573  if( newName.CmpNoCase( m_grid->GetCellValue( i, FDC_NAME ) ) == 0 )
574  {
575  DisplayError( this, wxString::Format( _( "The name '%s' is already in use." ),
576  newName ) );
577  event.Veto();
578  m_delayedFocusRow = event.GetRow();
579  m_delayedFocusColumn = event.GetCol();
580  }
581  }
582  }
583 
584  editor->DecRef();
585 }
586 
587 
589 {
590  if( !m_grid->CommitPendingChanges() )
591  return;
592 
593  SCHEMATIC_SETTINGS& settings = m_cmp->Schematic()->Settings();
594  int fieldID = m_fields->size();
595  SCH_FIELD newField( wxPoint( 0, 0 ), fieldID, m_cmp,
597 
598  newField.SetTextAngle( m_fields->at( REFERENCE ).GetTextAngle() );
599  newField.SetTextSize( wxSize( settings.m_DefaultTextSize, settings.m_DefaultTextSize ) );
600 
601  m_fields->push_back( newField );
602 
603  // notify the grid
604  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
605  m_grid->ProcessTableMessage( msg );
606 
607  m_grid->MakeCellVisible( (int) m_fields->size() - 1, 0 );
608  m_grid->SetGridCursor( (int) m_fields->size() - 1, 0 );
609 
610  m_grid->EnableCellEditControl();
611  m_grid->ShowCellEditControl();
612 }
613 
614 
616 {
617  int curRow = m_grid->GetGridCursorRow();
618 
619  if( curRow < 0 )
620  {
621  return;
622  }
623  else if( curRow < MANDATORY_FIELDS )
624  {
625  DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ),
626  MANDATORY_FIELDS ) );
627  return;
628  }
629 
630  m_grid->CommitPendingChanges( true /* quiet mode */ );
631 
632  m_fields->erase( m_fields->begin() + curRow );
633 
634  // notify the grid
635  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, curRow, 1 );
636  m_grid->ProcessTableMessage( msg );
637 
638  if( m_grid->GetNumberRows() > 0 )
639  {
640  m_grid->MakeCellVisible( std::max( 0, curRow-1 ), m_grid->GetGridCursorCol() );
641  m_grid->SetGridCursor( std::max( 0, curRow-1 ), m_grid->GetGridCursorCol() );
642  }
643 }
644 
645 
646 void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnMoveUp( wxCommandEvent& event )
647 {
648  if( !m_grid->CommitPendingChanges() )
649  return;
650 
651  int i = m_grid->GetGridCursorRow();
652 
653  if( i > MANDATORY_FIELDS )
654  {
655  SCH_FIELD tmp = m_fields->at( (unsigned) i );
656  m_fields->erase( m_fields->begin() + i, m_fields->begin() + i + 1 );
657  m_fields->insert( m_fields->begin() + i - 1, tmp );
658  m_grid->ForceRefresh();
659 
660  m_grid->SetGridCursor( i - 1, m_grid->GetGridCursorCol() );
661  m_grid->MakeCellVisible( m_grid->GetGridCursorRow(), m_grid->GetGridCursorCol() );
662  }
663  else
664  {
665  wxBell();
666  }
667 }
668 
669 
671 {
672  if( !m_grid->CommitPendingChanges() )
673  return;
674 
675  int i = m_grid->GetGridCursorRow();
676 
677  if( i >= MANDATORY_FIELDS && i < m_grid->GetNumberRows() - 1 )
678  {
679  SCH_FIELD tmp = m_fields->at( (unsigned) i );
680  m_fields->erase( m_fields->begin() + i, m_fields->begin() + i + 1 );
681  m_fields->insert( m_fields->begin() + i + 1, tmp );
682  m_grid->ForceRefresh();
683 
684  m_grid->SetGridCursor( i + 1, m_grid->GetGridCursorCol() );
685  m_grid->MakeCellVisible( m_grid->GetGridCursorRow(), m_grid->GetGridCursorCol() );
686  }
687  else
688  {
689  wxBell();
690  }
691 }
692 
693 
695 {
696  if( !m_grid->CommitPendingChanges() )
697  return;
698 
699  LIB_ID id;
700  wxString msg;
701  SCH_COMPONENT copy( *m_cmp );
702 
703  copy.SetFields( *m_fields );
704 
705  id.Parse( m_libraryNameTextCtrl->GetValue(), LIB_ID::ID_SCH, true );
706 
707  if( id.Parse( m_libraryNameTextCtrl->GetValue(), LIB_ID::ID_SCH, true ) >= 0 )
708  {
709  msg.Printf( _( "'%s' is not a valid library indentifier." ),
710  m_libraryNameTextCtrl->GetValue() );
711  DisplayError( this, msg );
712  return;
713  }
714 
715  LIB_PART* libSymbol = Prj().SchSymbolLibTable()->LoadSymbol( id );
716 
717  if( !libSymbol )
718  {
719  msg.Printf( _( "Symbol '%s' not found in symbol library '%s'." ),
720  id.GetLibItemName().wx_str(), id.GetLibNickname().wx_str() );
721  DisplayError( this, msg );
722  return;
723  }
724 
725  copy.SetLibSymbol( libSymbol->Flatten().release() );
726 
727  // Update the requested fields in the component copy
728  std::list<SCH_COMPONENT*> components;
729  components.push_back( &copy );
730  InvokeDialogUpdateFields( GetParent(), components, false );
731 
732  wxGridTableMessage clear( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, 0, m_fields->size() );
733  m_grid->ProcessTableMessage( clear );
734 
735  // Copy fields from the component copy to the dialog buffer
736  m_fields->clear();
737  std::set<wxString> defined;
738 
739  for( int i = 0; i < copy.GetFieldCount(); ++i )
740  {
741  copy.GetField( i )->SetParent( m_cmp );
742 
743  defined.insert( copy.GetField( i )->GetName() );
744  m_fields->push_back( *copy.GetField( i ) );
745  }
746 
747  // Add in any template fieldnames not yet defined:
748  for( const TEMPLATE_FIELDNAME& templateFieldname : GetParent()->GetTemplateFieldNames() )
749  {
750  if( defined.count( templateFieldname.m_Name ) <= 0 )
751  {
752  SCH_FIELD field( wxPoint( 0, 0 ), -1, m_cmp, templateFieldname.m_Name );
753  field.SetVisible( templateFieldname.m_Visible );
754  m_fields->push_back( field );
755  }
756  }
757 
758  wxGridTableMessage refresh( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_fields->size() );
759  m_grid->ProcessTableMessage( refresh );
760 }
761 
762 
764 {
765  m_width = aWidth;
766  // Account for scroll bars
767  aWidth -= ( m_grid->GetSize().x - m_grid->GetClientSize().x );
768 
769  m_grid->AutoSizeColumn( 0 );
770 
771  int fixedColsWidth = m_grid->GetColSize( 0 );
772 
773  for( int i = 2; i < m_grid->GetNumberCols(); i++ )
774  fixedColsWidth += m_grid->GetColSize( i );
775 
776  m_grid->SetColSize( 1, aWidth - fixedColsWidth );
777 }
778 
779 
781 {
782  wxString shownColumns = m_grid->GetShownColumns();
783 
784  if( shownColumns != m_shownColumns )
785  {
786  m_shownColumns = shownColumns;
787 
788  if( !m_grid->IsCellEditControlShown() )
789  AdjustGridColumns( m_grid->GetRect().GetWidth() );
790  }
791 
792  // Handle a delayed focus
793  if( m_delayedFocusRow >= 0 )
794  {
795  m_grid->SetFocus();
796  m_grid->MakeCellVisible( m_delayedFocusRow, m_delayedFocusColumn );
797  m_grid->SetGridCursor( m_delayedFocusRow, m_delayedFocusColumn );
798 
799 
800  m_grid->EnableCellEditControl( true );
801  m_grid->ShowCellEditControl();
802 
803  m_delayedFocusRow = -1;
805  }
806 }
807 
808 
810 {
811  auto new_size = event.GetSize().GetX();
812 
813  if( m_width != new_size )
814  {
815  AdjustGridColumns( new_size );
816  }
817 
818  // Always propagate for a grid repaint (needed if the height changes, as well as width)
819  event.Skip();
820 }
821 
822 
823 void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnInitDlg( wxInitDialogEvent& event )
824 {
826 
827  // Now all widgets have the size fixed, call FinishDialogSettings
829 }
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:239
DIALOG_EDIT_COMPONENT_IN_SCHEMATIC(SCH_EDIT_FRAME *aParent, SCH_COMPONENT *aComponent)
const BITMAP_OPAQUE trash_xpm[1]
Definition: trash.cpp:46
SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:52
void Offset(const wxPoint &aOffset)
Definition: eda_text.h:252
void UpdateFieldsFromLibrary(wxCommandEvent &event) override
const UTF8 & GetLibItemName() const
Definition: lib_id.h:114
bool Remove(SCH_ITEM *aItem)
Remove aItem from the schematic associated with this screen.
Definition: sch_screen.cpp:245
void SetLibSymbol(LIB_PART *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
void SetLibId(const LIB_ID &aName)
name of datasheet
int GetOrientation()
Get the display symbol orientation.
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:252
void OnMoveDown(wxCommandEvent &event) override
void SetIncludeInBom(bool aIncludeInBom)
This file is part of the common library.
void Parse(void *yyp, int yymajor, ParseTOKENTYPE yyminor ParseARG_PDECL)
bool GetIncludeOnBoard() const
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:121
void OnAddField(wxCommandEvent &event) override
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:134
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
void OnEditSpiceModel(wxCommandEvent &event) override
void OnInitDlg(wxInitDialogEvent &event) override
void FinishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
SCHEMATIC * Schematic() const
Searches the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:113
int GetUnitCount() const
Return the number of units per package of the symbol.
void SetVisible(bool aVisible)
Definition: eda_text.h:184
void OnCancelButtonClick(wxCommandEvent &event) override
wxString AsString() const
Definition: common.cpp:165
static const wxString GetDefaultFieldName(int aFieldNdx)
Function GetDefaultFieldName returns a default symbol field name for field aFieldNdx for all componen...
Schematic editor (Eeschema) main window.
LIB_PART * GetLibPart(const LIB_ID &aLibId, bool aUseCacheLib=false, bool aShowErrorMsg=false)
Load symbol from symbol library table.
bool TestDanglingEnds()
Test all of the connectable objects in the schematic for unused connection points.
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:237
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:59
void SetIncludeOnBoard(bool aIncludeOnBoard)
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
Field Name Module PCB, i.e. "16DIP300".
Field Reference of part, i.e. "IC21".
bool IsDragging() const
Definition: base_struct.h:201
virtual void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:196
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populates a std::vector with SCH_FIELDs.
void SetConvert(int aConvert)
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:90
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Construct a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:80
#define VALUE
int GetUnit() const
void OnBrowseLibrary(wxCommandEvent &event) override
std::vector< TEMPLATE_FIELDNAME > TEMPLATE_FIELDNAMES
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:232
void SetFields(const SCH_FIELDS &aFields)
Set multiple schematic fields.
#define NULL
int GetUnitCount() const override
For items with units, return the number of units.
STATUS_FLAGS GetEditFlags() const
Definition: base_struct.h:237
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
std::vector< SCH_FIELD > SCH_FIELDS
A container for several SCH_FIELD items.
Definition: sch_component.h:77
const wxPoint GetPosition() const override
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
const BITMAP_OPAQUE small_down_xpm[1]
Definition: small_down.cpp:25
void SaveCopyInUndoList(SCH_ITEM *aItemToCopy, UNDO_REDO_T aTypeCommand, bool aAppend=false, const wxPoint &aTransformPoint=wxPoint(0, 0))
Create a copy of the current schematic item, and put it in the undo list.
Define a library symbol object.
void OnDeleteField(wxCommandEvent &event) override
unsigned STATUS_FLAGS
Definition: base_struct.h:152
void SetUnit(int aUnit)
Change the unit number to aUnit.
const BITMAP_OPAQUE small_library_xpm[1]
std::unique_ptr< LIB_PART > & GetPartRef()
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:174
bool GetIncludeInBom() const
COMPONENT_SELECTION SelectCompFromLibTree(const SCHLIB_FILTER *aFilter, std::vector< COMPONENT_SELECTION > &aHistoryList, bool aUseLibBrowser, int aUnit, int aConvert, bool aShowFootprints, const LIB_ID *aHighlight=nullptr, bool aAllowFields=true)
Function SelectComponentFromLib Calls the library viewer to select component to import into schematic...
Definition: getpart.cpp:89
std::unique_ptr< LIB_PART > Flatten() const
Return a flattened symbol inheritance to the caller.
const BITMAP_OPAQUE small_up_xpm[1]
Definition: small_up.cpp:26
int GetFieldCount() const
Return the number of fields in this symbol.
int InvokeDialogUpdateFields(SCH_EDIT_FRAME *aCaller, const list< SCH_COMPONENT * > aComponents, bool aCreateUndoEntry)
UTF8 Format() const
Definition: lib_id.cpp:237
Class DIALOG_EDIT_COMPONENT_IN_SCHEMATIC_BASE.
const KIID m_Uuid
Definition: base_struct.h:162
SCH_FIELD * GetField(int aFieldNdx)
Returns a field in this symbol.
wxString GetShownColumns()
Get a tokenized string containing the shown column indexes.
Definition: wx_grid.cpp:103
void SetRef(const SCH_SHEET_PATH *aSheet, const wxString &aReference)
Set the reference for the given sheet path for this symbol.
void EndQuasiModal(int retCode)
void SetUnitSelection(const SCH_SHEET_PATH *aSheet, int aUnitSelection)
bool IsPower() const
see class PGM_BASE
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 Append(SCH_ITEM *aItem)
Definition: sch_screen.cpp:133
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
void RefreshItem(EDA_ITEM *aItem, bool isAddOrDelete=false)
Mark an item for refresh.
#define _(s)
Definition: 3d_actions.cpp:33
wxString GetName(bool aUseDefaultName=true) const
Function GetName returns the field name.
Definition: sch_field.cpp:420
static wxString SubReference(int aUnit, bool aAddSeparator=true)
Schematic symbol object.
Definition: sch_component.h:88
These settings were stored in SCH_BASE_FRAME previously.
Struct TEMPLATE_FIELDNAME holds a name of a component's field, field value, and default visibility.
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: base_struct.h:233
int GetConvert() const
void CollectOtherUnits(SCH_SHEET_PATH &aSheet, SCH_COMPONENT *aUnit, std::vector< SCH_COMPONENT * > *otherUnits)
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag of the current screen and u...
virtual void SetTextAngle(double aAngle)
Definition: eda_text.h:166
Definition for part library class.
static bool IsReferenceStringValid(const wxString &aReferenceString)
Tests for an acceptable reference string.
int Parse(const UTF8 &aId, LIB_ID_TYPE aType, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition: lib_id.cpp:122
STATUS_FLAGS GetFlags() const
Definition: base_struct.h:234
const LIB_ID & GetLibId() const
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:126
const BITMAP_OPAQUE small_plus_xpm[1]
Definition: small_plus.cpp:20
void OnUpdateUI(wxUpdateUIEvent &event) override
const TEMPLATE_FIELDNAMES & GetTemplateFieldNames()
Return a template field names list for read only access.
void SetOrientation(int aOrientation)
Compute the new transform matrix based on aOrientation for the symbol which is applied to the current...