KiCad PCB EDA Suite
dialog_edit_libentry_fields_in_lib.cpp
Go to the documentation of this file.
1 
2 /*
3  * This program source code file is part of KiCad, a free EDA CAD application.
4  *
5  * Copyright (C) 2011-2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6  * Copyright (C) 2007-2017 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 
27 #include <algorithm>
28 
29 #include <fctsys.h>
30 #include <pgm_base.h>
31 #include <kiway.h>
32 #include <confirm.h>
33 #include <class_drawpanel.h>
34 #include <sch_edit_frame.h>
35 #include <id.h>
36 #include <base_units.h>
37 
38 #include <general.h>
39 #include <lib_edit_frame.h>
40 #include <class_library.h>
41 #include <sch_component.h>
42 #include <sch_field.h>
43 #include <template_fieldnames.h>
44 #include <dialog_helpers.h>
45 #include <sch_validators.h>
46 
47 #include <bitmaps.h>
48 #include "eda_doc.h"
49 
51 #ifdef KICAD_SPICE
52 #include <dialog_spice_model.h>
54 #endif /* KICAD_SPICE */
55 
56 // Local variables:
57 static int s_SelectedRow;
58 
59 #define COLUMN_FIELD_NAME 0
60 #define COLUMN_TEXT 1
61 
63 {
64 public:
66  //~DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB() {}
67 
68 private:
69  // Events handlers:
70  void OnInitDialog( wxInitDialogEvent& event ) override;
71  void OnCloseDialog( wxCloseEvent& event ) override;
72 
73  void OnListItemDeselected( wxListEvent& event ) override;
74  void OnListItemSelected( wxListEvent& event ) override;
75  void addFieldButtonHandler( wxCommandEvent& event ) override;
76  void EditSpiceModel( wxCommandEvent& event ) override;
77 
85  void deleteFieldButtonHandler( wxCommandEvent& event ) override;
86 
87  void moveUpButtonHandler( wxCommandEvent& event ) override;
88  void moveDownButtonHandler( wxCommandEvent& event ) override;
89  void OnCancelButtonClick( wxCommandEvent& event ) override;
90  void OnOKButtonClick( wxCommandEvent& event ) override;
91  void showButtonHandler( wxCommandEvent& event ) override;
92 
93  // internal functions:
94  void setSelectedFieldNdx( int aFieldNdx );
95 
96  int getSelectedFieldNdx();
97 
102  void initBuffers();
103 
109  LIB_FIELD* findField( const wxString& aFieldName );
110 
117 
125 
126  void setRowItem( int aFieldNdx, const wxString& aName, const wxString& aValue );
127  void setRowItem( int aFieldNdx, const LIB_FIELD& aField )
128  {
129  setRowItem( aFieldNdx, aField.GetName(), aField.GetText() );
130  }
131 
138  {
139  for( unsigned ii = MANDATORY_FIELDS; ii<m_FieldsBuf.size(); ii++ )
140  setRowItem( ii, m_FieldsBuf[ii] );
141  }
142 
146 
148  std::vector <LIB_FIELD> m_FieldsBuf;
149 };
150 
151 
152 void LIB_EDIT_FRAME::InstallFieldsEditorDialog( wxCommandEvent& event )
153 {
154  if( !GetCurPart() )
155  return;
156 
157  m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor() );
158 
159  DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB dlg( this, GetCurPart() );
160 
161  if( GetDrawItem() && GetDrawItem()->Type() == LIB_FIELD_T )
162  SetDrawItem( nullptr ); // selected LIB_FIELD might be deleted
163 
164  // This dialog itself subsequently can invoke a KIWAY_PLAYER as a quasimodal
165  // frame. Therefore this dialog as a modal frame parent, MUST be run under
166  // quasimodal mode for the quasimodal frame support to work. So don't use
167  // the QUASIMODAL macros here.
168  if( dlg.ShowQuasiModal() != wxID_OK )
169  return;
170 
171  UpdateAliasSelectList();
172  UpdatePartSelectList();
173  DisplayLibInfos();
174  Refresh();
175 }
176 
177 
179  LIB_EDIT_FRAME* aParent,
180  LIB_PART* aLibEntry ) :
182 {
183  m_parent = aParent;
184  m_libEntry = aLibEntry;
185  m_skipCopyFromPanel = false;
186 
187 #ifndef KICAD_SPICE
188  m_spiceFieldsButton->Show(false);
189 #endif
190 
191  // Configure button logos
192  addFieldButton->SetBitmap( KiBitmap( plus_xpm ) );
193  deleteFieldButton->SetBitmap( KiBitmap( minus_xpm ) );
194  moveUpButton->SetBitmap( KiBitmap( go_up_xpm ) );
195  moveDownButton->SetBitmap( KiBitmap( go_down_xpm ) );
196 }
197 
198 
199 void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::OnInitDialog( wxInitDialogEvent& event )
200 {
201  m_skipCopyFromPanel = false;
202  wxListItem columnLabel;
203 
204  columnLabel.SetImage( -1 );
205 
206  columnLabel.SetText( _( "Name" ) );
207  fieldListCtrl->InsertColumn( COLUMN_FIELD_NAME, columnLabel );
208 
209  columnLabel.SetText( _( "Value" ) );
210  fieldListCtrl->InsertColumn( COLUMN_TEXT, columnLabel );
211 
215 
216  initBuffers();
218 
219  stdDialogButtonSizerOK->SetDefault();
220 
221  // Now all widgets have the size fixed, call FinishDialogSettings
223 }
224 
225 
227 {
228  if( !m_skipCopyFromPanel )
229  {
230  if( !copyPanelToSelectedField() )
231  event.Skip(); // do not go to the next row
232  }
233 }
234 
235 
237 {
238  // remember the selected row, statically
239  s_SelectedRow = event.GetIndex();
240 
242 }
243 
244 
246 {
247  EndQuasiModal( wxID_CANCEL );
248 }
249 
250 
252 {
253  // On wxWidgets 2.8, and on Linux, call EndQuasiModal here is mandatory
254  // Otherwise, the main event loop is never restored, and Eeschema does not
255  // respond to any event, because the DIALOG_SHIM destructor is never called.
256  // on wxWidgets 3.0, or on Windows, the DIALOG_SHIM destructor is called,
257  // and calls EndQuasiModal.
258  // Therefore calling EndQuasiModal here is not mandatory but it creates no issues.
259  EndQuasiModal( wxID_CANCEL );
260 }
261 
262 
264 {
265  if( !copyPanelToSelectedField() )
266  return;
267 
268  // test if reference prefix is acceptable
270  {
271  DisplayError( NULL, _( "Illegal reference. References must start with a letter." ) );
272  return;
273  }
274 
275  /* Note: this code is now (2010-dec-04) not used, because the value field is no more editable
276  * because changing the value is equivalent to create a new component or alias.
277  * This is now handled in libedit main frame, and no more in this dialog
278  * but this code is not removed, just in case
279  */
280  /* If a new name entered in the VALUE field, that it not an existing alias name
281  * or root alias of the component */
282  wxString newvalue = m_FieldsBuf[VALUE].GetText();
283 
284  if( m_libEntry->HasAlias( newvalue ) && !m_libEntry->GetAlias( newvalue )->IsRoot() )
285  {
286  wxString msg = wxString::Format(
287  _( "A new name is entered for this component\n"
288  "An alias %s already exists!\n"
289  "Cannot update this component" ),
290  GetChars( newvalue )
291  );
292  DisplayError( this, msg );
293  return;
294  }
295  /* End unused code */
296 
297  // save old cmp in undo list
299 
300  // delete any fields with no name or no value before we copy all of m_FieldsBuf
301  // back into the component
302  for( unsigned i = MANDATORY_FIELDS; i < m_FieldsBuf.size(); )
303  {
304  if( m_FieldsBuf[i].GetName().IsEmpty() || m_FieldsBuf[i].GetText().IsEmpty() )
305  {
306  m_FieldsBuf.erase( m_FieldsBuf.begin() + i );
307  continue;
308  }
309 
310  ++i;
311  }
312 
313  // copy all the fields back, fully replacing any previous fields
315 
316  // We need to keep the name and the value the same at the moment!
317  SetName( m_libEntry->GetValueField().GetText() );
318 
319  m_parent->OnModify();
320 
321  EndQuasiModal( wxID_OK );
322 }
323 
324 
326 {
327 #ifdef KICAD_SPICE
328  // DIALOG_SPICE_MODEL expects a SCH_COMPONENT,
329  // and a list of SCH_FIELDS to create/edit/delete Spice fields.
330  SCH_COMPONENT component; // This dummy component
331 
332  // Build fields list from the m_FieldsBuf fields buffer dialog
333  // to be sure to use the current fields.
334  SCH_FIELDS schfields;
335 
336  for( unsigned ii = 0; ii < m_FieldsBuf.size(); ++ii )
337  {
338  LIB_FIELD& libfield = m_FieldsBuf[ii];
339  SCH_FIELD schfield( libfield.GetTextPos(), libfield.GetId(),
340  &component, libfield.GetName() );
341  schfield.ImportValues( m_FieldsBuf[ii] );
342  schfield.SetText( m_FieldsBuf[ii].GetText() );
343 
344  schfields.push_back( schfield );
345  }
346 
347  component.SetFields( schfields );
348 
349  DIALOG_SPICE_MODEL dialog( this, component, schfields );
350 
351  if( dialog.ShowModal() != wxID_OK )
352  return;
353 
354  // Transfert sch fields to the m_FieldsBuf fields buffer dialog:
355  m_FieldsBuf.clear();
356 
357  for( unsigned ii = 0; ii < schfields.size(); ii++ )
358  {
359  LIB_FIELD libfield;
360  schfields[ii].ExportValues( libfield );
361  m_FieldsBuf.push_back( libfield );
362  }
363 
364  updateDisplay();
365 #endif /* KICAD_SPICE */
366 }
367 
368 
370 {
371  // in case m_FieldsBuf[REFERENCE].m_Orient has changed on screen only, grab
372  // screen contents.
373  if( !copyPanelToSelectedField() )
374  return;
375 
376  unsigned fieldNdx = m_FieldsBuf.size();
377 
378  LIB_FIELD blank( fieldNdx );
379 
380  m_FieldsBuf.push_back( blank );
381  m_FieldsBuf[fieldNdx].SetName( TEMPLATE_FIELDNAME::GetDefaultFieldName( fieldNdx ) );
382 
383  setRowItem( fieldNdx, m_FieldsBuf[fieldNdx] );
384 
385  m_skipCopyFromPanel = true;
386  setSelectedFieldNdx( fieldNdx );
387  m_skipCopyFromPanel = false;
388 }
389 
390 
392 {
393  unsigned fieldNdx = getSelectedFieldNdx();
394 
395  if( fieldNdx >= m_FieldsBuf.size() ) // traps the -1 case too
396  return;
397 
398  if( fieldNdx < MANDATORY_FIELDS )
399  {
400  wxBell();
401  return;
402  }
403 
404  m_skipCopyFromPanel = true;
405 
406  if( m_FieldsBuf[fieldNdx].GetText().IsEmpty() )
407  {
408  m_FieldsBuf.erase( m_FieldsBuf.begin() + fieldNdx );
409  fieldListCtrl->DeleteItem( fieldNdx );
410 
411  if( fieldNdx >= m_FieldsBuf.size() )
412  --fieldNdx;
413  }
414  else
415  {
416  m_FieldsBuf[fieldNdx].Empty();
418  }
419 
420  updateDisplay( );
421 
422  setRowItem( fieldNdx, m_FieldsBuf[fieldNdx] );
423  setSelectedFieldNdx( fieldNdx );
424  m_skipCopyFromPanel = false;
425 }
426 
427 
429 {
430  unsigned int fieldNdx = getSelectedFieldNdx();
431 
432  // Ensure there is at least one field after this one
433  if( fieldNdx >= ( m_FieldsBuf.size() - 1 ) )
434  {
435  return;
436  }
437 
438  // The first field which can be moved up is the second user field
439  // so any field which id < MANDATORY_FIELDS cannot be moved down
440  if( fieldNdx < MANDATORY_FIELDS )
441  return;
442 
443  if( !copyPanelToSelectedField() )
444  return;
445 
446  // swap the fieldNdx field with the one before it, in both the vector
447  // and in the fieldListCtrl
448  LIB_FIELD tmp = m_FieldsBuf[fieldNdx + 1];
449 
450  m_FieldsBuf[fieldNdx + 1] = m_FieldsBuf[fieldNdx];
451  setRowItem( fieldNdx + 1, m_FieldsBuf[fieldNdx] );
452  m_FieldsBuf[fieldNdx + 1].SetId( fieldNdx + 1 );
453 
454  m_FieldsBuf[fieldNdx] = tmp;
455  setRowItem( fieldNdx, tmp );
456  m_FieldsBuf[fieldNdx].SetId( fieldNdx );
457 
458  updateDisplay( );
459 
460  m_skipCopyFromPanel = true;
461  setSelectedFieldNdx( fieldNdx + 1 );
462  m_skipCopyFromPanel = false;
463 }
464 
465 
467 {
468  unsigned fieldNdx = getSelectedFieldNdx();
469 
470  if( fieldNdx >= m_FieldsBuf.size() ) // traps the -1 case too
471  return;
472 
473  // The first field which can be moved up is the second user field
474  // so any field which id <= MANDATORY_FIELDS cannot be moved up
475  if( fieldNdx <= MANDATORY_FIELDS )
476  return;
477 
478  if( !copyPanelToSelectedField() )
479  return;
480 
481  // swap the fieldNdx field with the one before it, in both the vector
482  // and in the fieldListCtrl
483  LIB_FIELD tmp = m_FieldsBuf[fieldNdx - 1];
484 
485  m_FieldsBuf[fieldNdx - 1] = m_FieldsBuf[fieldNdx];
486  setRowItem( fieldNdx - 1, m_FieldsBuf[fieldNdx] );
487  m_FieldsBuf[fieldNdx - 1].SetId(fieldNdx - 1);
488 
489  m_FieldsBuf[fieldNdx] = tmp;
490  setRowItem( fieldNdx, tmp );
491  m_FieldsBuf[fieldNdx].SetId(fieldNdx);
492 
493  updateDisplay( );
494 
495  m_skipCopyFromPanel = true;
496  setSelectedFieldNdx( fieldNdx - 1 );
497  m_skipCopyFromPanel = false;
498 }
499 
500 
502 {
503  unsigned fieldNdx = getSelectedFieldNdx();
504 
505  if( fieldNdx == DATASHEET )
506  {
507  wxString datasheet_uri = fieldValueTextCtrl->GetValue();
508  datasheet_uri = ResolveUriByEnvVars( datasheet_uri );
509  GetAssociatedDocument( this, datasheet_uri );
510  }
511  else if( fieldNdx == FOOTPRINT )
512  {
513  // pick a footprint using the footprint picker.
514  wxString fpid;
515 
516  KIWAY_PLAYER* frame = Kiway().Player( FRAME_PCB_MODULE_VIEWER_MODAL, true, this );
517 
518  if( frame->ShowModal( &fpid, this ) )
519  {
520  fieldValueTextCtrl->SetValue( fpid );
521  setRowItem( fieldNdx, m_FieldsBuf[fieldNdx].GetName( false ), fpid );
522  }
523 
524  frame->Destroy();
525  }
526 }
527 
528 
530 {
531  // deselect old selection, but I think this is done by single selection
532  // flag within fieldListCtrl
533  // fieldListCtrl->SetItemState( s_SelectedRow, 0, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED);
534 
535  if( aFieldNdx >= (int) m_FieldsBuf.size() )
536  aFieldNdx = m_FieldsBuf.size() - 1;
537 
538  if( aFieldNdx < 0 )
539  aFieldNdx = 0;
540 
541  fieldListCtrl->SetItemState( aFieldNdx, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
542  fieldListCtrl->EnsureVisible( aFieldNdx );
543 
544  s_SelectedRow = aFieldNdx;
545 }
546 
547 
549 {
550  return s_SelectedRow;
551 }
552 
553 
558 static LIB_FIELD* findfield( const LIB_FIELDS& aList, const wxString& aFieldName )
559 {
560  const LIB_FIELD* field = NULL;
561 
562  for( unsigned i=0; i<aList.size(); ++i )
563  {
564  if( aFieldName == aList[i].GetName() )
565  {
566  field = &aList[i]; // best to avoid casting here.
567  break;
568  }
569  }
570  return (LIB_FIELD*) field; // remove const-ness last
571 }
572 
573 
575 {
576  for( unsigned i=0; i<m_FieldsBuf.size(); ++i )
577  {
578  if( aFieldName == m_FieldsBuf[i].GetName() )
579  return &m_FieldsBuf[i];
580  }
581  return NULL;
582 }
583 
584 
586 {
587  LIB_FIELDS cmpFields;
588 
589  m_libEntry->GetFields( cmpFields );
590 
591  /* We have 3 component related field lists to be aware of: 1) UI
592  presentation (m_FieldsBuf), 2) fields in component ram copy, and 3)
593  fields recorded with component on disk. m_FieldsBuf is the list of UI
594  fields, and this list is not the same as the list which is in the
595  component, which is also not the same as the list on disk. All 3 lists
596  are potentially different. In the UI we choose to preserve the order of
597  the first MANDATORY_FIELDS which are sometimes called fixed fields. Then
598  we append the template fieldnames in the exact same order as the
599  template fieldname editor shows them. Then we append any user defined
600  fieldnames which came from the component, and user can modify it during
601  editing, but cannot delete or move a fixed field.
602  */
603 
604  m_FieldsBuf.clear();
605 
606  /* When this code was written, all field constructors ensured that the
607  MANDATORY_FIELDS are all present within a component (in ram only). So we can
608  knowingly copy them over in the normal order. Copy only the fixed fields
609  at first. Please do not break the field constructors.
610  */
611 
612  // fixed fields:
613  for( int i=0; i<MANDATORY_FIELDS; ++i )
614  {
615  m_FieldsBuf.push_back( cmpFields[i] );
616  }
617 
618  // Add template fieldnames:
619  // Now copy in the template fields, in the order that they are present in the
620  // template field editor UI.
621  SCH_EDIT_FRAME* editor = (SCH_EDIT_FRAME*) Kiway().Player( FRAME_SCH, true );
622 
623  const TEMPLATE_FIELDNAMES& tfnames = editor->GetTemplateFieldNames();
624 
625  for( TEMPLATE_FIELDNAMES::const_iterator it = tfnames.begin(); it!=tfnames.end(); ++it )
626  {
627  // add a new field unconditionally to the UI only for this template fieldname
628 
629  // field id must not be in range 0 - MANDATORY_FIELDS, set before saving to disk
630  LIB_FIELD fld( m_libEntry, -1 );
631 
632  // See if field by same name already exists in component.
633  LIB_FIELD* libField = findfield( cmpFields, it->m_Name );
634 
635  // If the field does not already exist in the component, then we
636  // use defaults from the template fieldname, otherwise the original
637  // values from the component will be set.
638  if( !libField )
639  {
640  fld.SetName( it->m_Name );
641  fld.SetText( it->m_Value ); // empty? ok too.
642 
643  if( !it->m_Visible )
644  fld.SetVisible( false );
645  else
646  fld.SetVisible( true );
647  }
648  else
649  {
650  fld = *libField; // copy values from component, m_Name too
651  }
652 
653  m_FieldsBuf.push_back( fld );
654  }
655 
656  // Lastly, append any original fields from the component which were not added
657  // from the set of fixed fields nor from the set of template fields.
658  for( unsigned i=MANDATORY_FIELDS; i<cmpFields.size(); ++i )
659  {
660  LIB_FIELD* cmp = &cmpFields[i];
661  LIB_FIELD* buf = findField( cmp->GetName() );
662 
663  if( !buf )
664  {
665  m_FieldsBuf.push_back( *cmp );
666  }
667  }
668 
669  /* field names have become more important than field ids, so we cannot
670  mangle the names in the buffer, but can do so in the panel, see elsewhere.
671  m_FieldsBuf[VALUE].m_Name << wxT( "/" ) << _( "Chip Name" );
672  */
673 
674  for( unsigned ii = 0; ii < m_FieldsBuf.size(); ++ii )
675  {
676  setRowItem( ii, m_FieldsBuf[ii] );
677  }
678 
679  // put focus on the list ctrl
680  fieldListCtrl->SetFocus();
681 
682  // resume editing at the last row edited, last time dialog was up.
683  if ( s_SelectedRow < (int) m_FieldsBuf.size() )
684  s_SelectedRow = 0;
685 
687 }
688 
689 
690 void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::setRowItem( int aFieldNdx, const wxString& aName, const wxString& aValue )
691 {
692  wxASSERT( aFieldNdx >= 0 );
693 
694  // insert blanks if aFieldNdx is referencing a "yet to be defined" row
695  while( aFieldNdx >= fieldListCtrl->GetItemCount() )
696  {
697  long ndx = fieldListCtrl->InsertItem( fieldListCtrl->GetItemCount(), wxEmptyString );
698 
699  wxASSERT( ndx >= 0 );
700 
701  fieldListCtrl->SetItem( ndx, COLUMN_TEXT, wxEmptyString );
702  }
703 
704  fieldListCtrl->SetItem( aFieldNdx, COLUMN_FIELD_NAME, aName );
705  fieldListCtrl->SetItem( aFieldNdx, COLUMN_TEXT, aValue );
706 
707  // recompute the column widths here, after setting texts
708  fieldListCtrl->SetColumnWidth( COLUMN_FIELD_NAME, wxLIST_AUTOSIZE );
709  fieldListCtrl->SetColumnWidth( COLUMN_TEXT, wxLIST_AUTOSIZE );
710 }
711 
712 
714 {
715  unsigned fieldNdx = getSelectedFieldNdx();
716 
717  if( fieldNdx >= m_FieldsBuf.size() ) // traps the -1 case too
718  return;
719 
720  LIB_FIELD& field = m_FieldsBuf[fieldNdx];
721 
722  showCheckBox->SetValue( field.IsVisible() );
723 
724  rotateCheckBox->SetValue( field.GetTextAngle() == TEXT_ANGLE_VERT );
725 
726  int style = 0;
727 
728  if( field.IsItalic() )
729  style = 1;
730 
731  if( field.IsBold() )
732  style |= 2;
733 
734  m_StyleRadioBox->SetSelection( style );
735 
736  // Select the right text justification
737  if( field.GetHorizJustify() == GR_TEXT_HJUSTIFY_LEFT )
738  m_FieldHJustifyCtrl->SetSelection(0);
739  else if( field.GetHorizJustify() == GR_TEXT_HJUSTIFY_RIGHT )
740  m_FieldHJustifyCtrl->SetSelection(2);
741  else
742  m_FieldHJustifyCtrl->SetSelection(1);
743 
744  if( field.GetVertJustify() == GR_TEXT_VJUSTIFY_BOTTOM )
745  m_FieldVJustifyCtrl->SetSelection(0);
746  else if( field.GetVertJustify() == GR_TEXT_VJUSTIFY_TOP )
747  m_FieldVJustifyCtrl->SetSelection(2);
748  else
749  m_FieldVJustifyCtrl->SetSelection(1);
750 
751 
752  // Field names have become more important than field ids, so we cannot
753  // mangle the names in the buffer but we can do so in the panel.
754  if( field.GetId() == VALUE )
755  {
756  // This field is the lib name and the default value when loading this component in
757  // schematic. The value is now not editable here (in this dialog) because changing
758  // it is equivalent to create a new component or alias. This is handles in libedir,
759  // not in this dialog.
760  fieldNameTextCtrl->SetValue( field.GetName() + wxT( " / " ) + _( "Chip Name" ) );
761  fieldValueTextCtrl->Enable( false );
762  }
763  else
764  {
765  fieldValueTextCtrl->Enable( true );
766  fieldNameTextCtrl->SetValue( field.GetName() );
767  }
768 
769  // if fieldNdx == REFERENCE, VALUE, FOOTPRINT, or DATASHEET, then disable field name editing
770  fieldNameTextCtrl->Enable( fieldNdx >= MANDATORY_FIELDS );
771  fieldNameTextCtrl->SetEditable( fieldNdx >= MANDATORY_FIELDS );
772 
773  // only user defined fields may be moved, and not the top most user defined
774  // field since it would be moving up into the fixed fields, > not >=
775  moveUpButton->Enable( fieldNdx > MANDATORY_FIELDS );
776  moveDownButton->Enable( ( fieldNdx >= MANDATORY_FIELDS ) && ( fieldNdx < ( m_FieldsBuf.size() - 1 ) ) );
777 
778  // if fieldNdx == REFERENCE, VALUE, then disable delete button
779  deleteFieldButton->Enable( fieldNdx >= MANDATORY_FIELDS );
780 
781  fieldValueTextCtrl->SetValidator( SCH_FIELD_VALIDATOR( true, field.GetId() ) );
782  fieldValueTextCtrl->SetValue( field.GetText() );
783 
785 
786  m_show_datasheet_button->Enable( fieldNdx == DATASHEET || fieldNdx == FOOTPRINT );
787 
788  if( fieldNdx == DATASHEET )
789  {
790  m_show_datasheet_button->SetLabel( _( "Show Datasheet" ) );
791  m_show_datasheet_button->SetToolTip(
792  _("If your datasheet is given as an http:// link,"
793  " then pressing this button should bring it up in your webbrowser.") );
794  }
795  else if( fieldNdx == FOOTPRINT )
796  {
797  m_show_datasheet_button->SetLabel( _( "Browse Footprints" ) );
798  m_show_datasheet_button->SetToolTip(
799  _("Open the footprint browser to choose a footprint and assign it.") );
800  }
801  else
802  {
803  m_show_datasheet_button->SetLabel( wxEmptyString );
804  m_show_datasheet_button->SetToolTip(
805  _("Used only for fields Footprint and Datasheet.") );
806  }
807 
808  wxPoint coord = field.GetTextPos();
809  wxPoint zero;
810 
811  // If the field value is empty and the position is at relative zero, we set the
812  // initial position as a small offset from the ref field, and orient
813  // it the same as the ref field. That is likely to put it at least
814  // close to the desired position.
815  if( coord == zero && field.GetText().IsEmpty() )
816  {
817  rotateCheckBox->SetValue( m_FieldsBuf[REFERENCE].GetTextAngle() == TEXT_ANGLE_VERT );
818 
819  coord.x = m_FieldsBuf[REFERENCE].GetTextPos().x +
820  (fieldNdx - MANDATORY_FIELDS + 1) * 100;
821  coord.y = m_FieldsBuf[REFERENCE].GetTextPos().y +
822  (fieldNdx - MANDATORY_FIELDS + 1) * 100;
823 
824  // coord can compute negative if field is < MANDATORY_FIELDS, e.g. FOOTPRINT.
825  // That is ok, we basically don't want all the new empty fields on
826  // top of each other.
827  }
828 
829  wxString coordText = StringFromValue( g_UserUnit, coord.x );
830  posXTextCtrl->SetValue( coordText );
831 
832  // Note: the Y axis for components in lib is from bottom to top
833  // and the screen axis is top to bottom: we must change the y coord sign for editing
834  coord.y = -coord.y;
835  coordText = StringFromValue( g_UserUnit, coord.y );
836  posYTextCtrl->SetValue( coordText );
837 }
838 
839 
841 {
842  unsigned fieldNdx = getSelectedFieldNdx();
843 
844  if( fieldNdx >= m_FieldsBuf.size() ) // traps the -1 case too
845  return true;
846 
847  // Check for illegal field text.
848  if( fieldValueTextCtrl->GetValidator()
849  && !fieldValueTextCtrl->GetValidator()->Validate( this ) )
850  return false;
851 
852  LIB_FIELD& field = m_FieldsBuf[fieldNdx];
853 
854  if( showCheckBox->GetValue() )
855  field.SetVisible( true );
856  else
857  field.SetVisible( false );
858 
859  if( rotateCheckBox->GetValue() )
860  field.SetTextAngle( TEXT_ANGLE_VERT );
861  else
863 
864  // Copy the text justification
865  static const EDA_TEXT_HJUSTIFY_T hjustify[3] = {
868  };
869 
870  static const EDA_TEXT_VJUSTIFY_T vjustify[3] = {
873  };
874 
875  field.SetHorizJustify( hjustify[m_FieldHJustifyCtrl->GetSelection()] );
876  field.SetVertJustify( vjustify[m_FieldVJustifyCtrl->GetSelection()] );
877 
878  // Blank/empty field texts for REFERENCE and VALUE are not allowed.
879  // (Value is the name of the component in lib!)
880  // Change them only if user provided a non blank value
881  if( !fieldValueTextCtrl->GetValue().IsEmpty() || fieldNdx > VALUE )
882  field.SetText( fieldValueTextCtrl->GetValue() );
883 
884  // FieldNameTextCtrl has a tricked value in it for VALUE index, do not copy it back.
885  // It has the "Chip Name" appended.
886  if( field.GetId() >= MANDATORY_FIELDS )
887  {
888  wxString name = fieldNameTextCtrl->GetValue();
889  field.SetName( name );
890  }
891 
892  setRowItem( fieldNdx, field ); // update fieldListCtrl
893 
895 
896  field.SetTextSize( wxSize( tmp, tmp ) );
897 
898  int style = m_StyleRadioBox->GetSelection();
899 
900  field.SetItalic( (style & 1 ) != 0 );
901  field.SetBold( (style & 2 ) != 0 );
902 
903  wxPoint pos( ValueFromString( g_UserUnit, posXTextCtrl->GetValue() ),
904  ValueFromString( g_UserUnit, posYTextCtrl->GetValue() ) );
905 
906  // Note: the Y axis for components in lib is from bottom to top
907  // and the screen axis is top to bottom: we must change the y coord sign for editing
908  pos.y = -pos.y;
909 
910  field.SetTextPos( pos );
911 
912  return true;
913 }
void SetTextAngle(double aAngle)
Definition: eda_text.h:154
#define TEXT_ANGLE_HORIZ
Frequent text rotations, used with {Set,Get}TextAngle(), in 0.1 degrees for now, hoping to migrate to...
Definition: common.h:91
LIB_FIELD * findField(const wxString &aFieldName)
Function findField searches m_FieldsBuf and returns a LIB_FIELD with aFieldName or NULL if not found...
Class SCH_FIELD instances are attached to a component and provide a place for the component&#39;s value...
Definition: sch_field.h:56
Class KIWAY_PLAYER is a wxFrame capable of the OpenProjectFiles function, meaning it can load a porti...
Definition: kiway_player.h:111
EDA_TEXT_HJUSTIFY_T
Definition: eda_text.h:47
KIWAY & Kiway() const
Function Kiway returns a reference to the KIWAY that this object has an opportunity to participate in...
Definition: kiway_player.h:60
name of datasheet
bool copyPanelToSelectedField()
Function copyPanelToSelectedField copies the values displayed on the panel fields to the currently se...
void setRowItem(int aFieldNdx, const wxString &aName, const wxString &aValue)
const wxPoint & GetTextPos() const
Definition: eda_text.h:222
bool IsItalic() const
Definition: eda_text.h:168
const wxString ResolveUriByEnvVars(const wxString &aUri)
Function ResolveUriByEnvVars replaces any environment variables in file-path uris (leaving network-pa...
Definition: common.cpp:269
LIB_ALIAS * GetAlias(size_t aIndex)
Implementation of conversion functions that require both schematic and board internal units...
This file is part of the common library.
This file is part of the common library.
void ImportValues(const LIB_FIELD &aSource)
Function ImportValues copy parameters from a LIB_FIELD source.
Definition: sch_field.cpp:222
wxString StringFromValue(EDA_UNITS_T aUnit, int aValue, bool aAddUnitSymbol)
Function StringFromValue returns the string from aValue according to units (inch, mm ...
Definition: base_units.cpp:205
void SetItalic(bool isItalic)
Definition: eda_text.h:167
void setRowItem(int aFieldNdx, const LIB_FIELD &aField)
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
void FinishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
bool HasAlias(const wxString &aName) const
Test if alias aName is in part alias list.
void SetTextPos(const wxPoint &aPoint)
Definition: eda_text.h:221
void OnInitDialog(wxInitDialogEvent &event) override
void SetVisible(bool aVisible)
Definition: eda_text.h:173
LIB_FIELD & GetValueField()
Return reference to the value field.
static int ParseSize(const wxString &sizeText, EDA_UNITS_T user_unit)
bool GetAssociatedDocument(wxWindow *aParent, const wxString &aDocName, const wxPathList *aPaths)
Function GetAssociatedDocument open a document (file) with the suitable browser.
Definition: eda_doc.cpp:87
void OnModify()
Must be called after a schematic change in order to set the "modify" flag of the current screen...
void deleteFieldButtonHandler(wxCommandEvent &event) override
Function deleteFieldButtonHandler deletes a field.
void OnListItemSelected(wxListEvent &event) override
static LIB_FIELD * findfield(const LIB_FIELDS &aList, const wxString &aFieldName)
Function findfield searches a LIB_FIELD_LIST for aFieldName.
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.
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:212
std::vector< LIB_FIELD > m_FieldsBuf
a copy of the edited component&#39;s LIB_FIELDs
void SetName(const wxString &aName)
Set a user definable field name to aName.
Definition: lib_field.cpp:482
EDA_TEXT_HJUSTIFY_T GetHorizJustify() const
Definition: eda_text.h:188
#define TEXT_ANGLE_VERT
Definition: common.h:92
Field Name Module PCB, i.e. "16DIP300".
Field Reference of part, i.e. "IC21".
bool IsBold() const
Definition: eda_text.h:171
double GetTextAngle() const
Definition: eda_text.h:162
DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB(LIB_EDIT_FRAME *aParent, LIB_PART *aLibEntry)
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Function KiBitmap constructs a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:78
bool IsRoot() const
void updateDisplay()
Function updateDisplay update the listbox showing fields, according to the fields texts must be calle...
std::vector< TEMPLATE_FIELDNAME > TEMPLATE_FIELDNAMES
void SetFields(const SCH_FIELDS &aFields)
Set multiple schematic fields.
VTBL_ENTRY KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=NULL)
Function Player returns the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:300
void SetText(const wxString &aText) override
Sets the field text to aText.
Definition: lib_field.cpp:502
void Refresh()
Update the board display after modifying it bu a python script (note: it is automatically called by a...
int GetId() const
Definition: lib_field.h:138
int ShowQuasiModal()
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:128
std::vector< SCH_FIELD > SCH_FIELDS
A container for several SCH_FIELD items.
Definition: sch_component.h:53
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:192
wxString GetAbbreviatedUnitsLabel(EDA_UNITS_T aUnit)
Definition: base_units.cpp:485
Defintions of control validators for schematic dialogs.
int ValueFromString(EDA_UNITS_T aUnits, const wxString &aTextValue)
Function ValueFromString converts aTextValue in aUnits to internal units used by the application...
Definition: base_units.cpp:370
Define a library symbol object.
Helper dialog and control classes.
wxString GetText(GRAPHIC_PINSHAPE shape)
Definition: pin_shape.cpp:33
void addFieldButtonHandler(wxCommandEvent &event) override
void InstallFieldsEditorDialog(wxCommandEvent &event)
void EditSpiceModel(wxCommandEvent &event) override
void initBuffers()
Function initBuffers sets up to edit the given component.
wxString GetName(bool aTranslate=true) const
Returns the field name.
Definition: lib_field.cpp:432
void showButtonHandler(wxCommandEvent &event) override
EDA_TEXT_VJUSTIFY_T
Definition: eda_text.h:54
EDA_UNITS_T g_UserUnit
Global variables definitions.
Definition: common.cpp:57
EDA_TEXT_VJUSTIFY_T GetVertJustify() const
Definition: eda_text.h:189
void moveDownButtonHandler(wxCommandEvent &event) override
void EndQuasiModal(int retCode)
Definition the SCH_COMPONENT class for Eeschema.
The symbol library editor main window.
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
const TEMPLATE_FIELDNAMES & GetTemplateFieldNames()
Return a template field names list for read only access.
see class PGM_BASE
void OnListItemDeselected(wxListEvent &event) override
const char * name
Definition: DXF_plotter.cpp:61
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
bool IsVisible() const
Definition: lib_field.h:164
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:191
void OnOKButtonClick(wxCommandEvent &event) override
void moveUpButtonHandler(wxCommandEvent &event) override
std::vector< LIB_FIELD > LIB_FIELDS
Definition: lib_field.h:257
void SaveCopyInUndoList(EDA_ITEM *ItemToCopy, UNDO_REDO_T undoType=UR_LIBEDIT)
Create a copy of the current component, and save it in the undo list.
size_t i
Definition: json11.cpp:597
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:69
bool Destroy() override
Our version of Destroy() which is virtual from wxWidgets.
Definition of class LIB_EDIT_FRAME.
const wxSize & GetTextSize() const
Definition: eda_text.h:213
class SCH_FILED_VALIDATOR
Definition for part library class.
Definition of the SCH_FIELD class for Eeschema.
static bool IsReferenceStringValid(const wxString &aReferenceString)
Tests for an acceptable reference string.
void SetFields(const std::vector< LIB_FIELD > &aFieldsList)
Overwrite all the existing fields in this symbol with fields supplied in aFieldsList.
#define VALUE
void SetBold(bool aBold)
Definition: eda_text.h:170
static wxString FormatSize(EDA_UNITS_T user_unit, int textSize)
Function FormatSize formats a string containing the size in the desired units.
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:185
VTBL_ENTRY bool ShowModal(wxString *aResult=NULL, wxWindow *aResultantFocusWindow=NULL)
Function ShowModal puts up this wxFrame as if it were a modal dialog, with all other instantiated wxF...
Class DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB_BASE.
static int s_SelectedRow
void OnCancelButtonClick(wxCommandEvent &event) override
void GetFields(LIB_FIELDS &aList)
Return a list of fields withing this part.
void copySelectedFieldToPanel()
Function copySelectedFieldToPanel sets the values displayed on the panel according to the currently s...