summaryrefslogtreecommitdiff
path: root/eeschema/dialogs/dialog_edit_libentry_fields_in_lib.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'eeschema/dialogs/dialog_edit_libentry_fields_in_lib.cpp')
-rw-r--r--eeschema/dialogs/dialog_edit_libentry_fields_in_lib.cpp796
1 files changed, 796 insertions, 0 deletions
diff --git a/eeschema/dialogs/dialog_edit_libentry_fields_in_lib.cpp b/eeschema/dialogs/dialog_edit_libentry_fields_in_lib.cpp
new file mode 100644
index 0000000..ce10190
--- /dev/null
+++ b/eeschema/dialogs/dialog_edit_libentry_fields_in_lib.cpp
@@ -0,0 +1,796 @@
+
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2011-2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
+ * Copyright (C) 2007-2016 KiCad Developers, see change_log.txt for contributors.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+
+#include <algorithm>
+
+#include <fctsys.h>
+#include <pgm_base.h>
+#include <kiway.h>
+#include <confirm.h>
+#include <class_drawpanel.h>
+#include <schframe.h>
+#include <id.h>
+#include <base_units.h>
+
+#include <general.h>
+#include <libeditframe.h>
+#include <class_library.h>
+#include <sch_component.h>
+#include <sch_field.h>
+#include <template_fieldnames.h>
+#include <dialog_helpers.h>
+#include <sch_validators.h>
+
+#include <dialog_edit_libentry_fields_in_lib_base.h>
+
+// Local variables:
+static int s_SelectedRow;
+
+#define COLUMN_FIELD_NAME 0
+#define COLUMN_TEXT 1
+
+class DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB : public DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB_BASE
+{
+public:
+ DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB( LIB_EDIT_FRAME* aParent, LIB_PART* aLibEntry );
+ //~DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB() {}
+
+private:
+ // Events handlers:
+ void OnInitDialog( wxInitDialogEvent& event );
+ void OnCloseDialog( wxCloseEvent& event );
+
+ void OnListItemDeselected( wxListEvent& event );
+ void OnListItemSelected( wxListEvent& event );
+ void addFieldButtonHandler( wxCommandEvent& event );
+
+ /**
+ * Function deleteFieldButtonHandler
+ * deletes a field.
+ * MANDATORY_FIELDS cannot be deleted.
+ * If a field is empty, it is removed.
+ * if not empty, the text is removed.
+ */
+ void deleteFieldButtonHandler( wxCommandEvent& event );
+
+ void moveUpButtonHandler( wxCommandEvent& event );
+ void OnCancelButtonClick( wxCommandEvent& event );
+ void OnOKButtonClick( wxCommandEvent& event );
+ void showButtonHandler( wxCommandEvent& event );
+
+ // internal functions:
+ void setSelectedFieldNdx( int aFieldNdx );
+
+ int getSelectedFieldNdx();
+
+ /**
+ * Function initBuffers
+ * sets up to edit the given component.
+ */
+ void initBuffers();
+
+ /**
+ * Function findField
+ * searches m_FieldsBuf and returns a LIB_FIELD with \a aFieldName or NULL if
+ * not found.
+ */
+ LIB_FIELD* findField( const wxString& aFieldName );
+
+ /**
+ * Function copySelectedFieldToPanel
+ * sets the values displayed on the panel according to
+ * the currently selected field row
+ */
+ void copySelectedFieldToPanel();
+
+ /**
+ * Function copyPanelToSelectedField
+ * copies the values displayed on the panel fields to the currently selected field
+ * @return bool - true if all fields are OK, else false if the user has put
+ * bad data into a field, and this value can be used to deny a row change.
+ */
+ bool copyPanelToSelectedField();
+
+ void setRowItem( int aFieldNdx, const wxString& aName, const wxString& aValue );
+ void setRowItem( int aFieldNdx, const LIB_FIELD& aField )
+ {
+ setRowItem( aFieldNdx, aField.GetName(), aField.GetText() );
+ }
+
+ /**
+ * Function updateDisplay
+ * update the listbox showing fields, according to the fields texts
+ * must be called after a text change in fields, if this change is not an edition
+ */
+ void updateDisplay( )
+ {
+ for( unsigned ii = MANDATORY_FIELDS; ii<m_FieldsBuf.size(); ii++ )
+ setRowItem( ii, m_FieldsBuf[ii] );
+ }
+
+ LIB_EDIT_FRAME* m_parent;
+ LIB_PART* m_libEntry;
+ bool m_skipCopyFromPanel;
+
+ /// a copy of the edited component's LIB_FIELDs
+ std::vector <LIB_FIELD> m_FieldsBuf;
+};
+
+
+void LIB_EDIT_FRAME::InstallFieldsEditorDialog( wxCommandEvent& event )
+{
+ if( !GetCurPart() )
+ return;
+
+ m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor() );
+
+ DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB dlg( this, GetCurPart() );
+
+ // This dialog itself subsequently can invoke a KIWAY_PLAYER as a quasimodal
+ // frame. Therefore this dialog as a modal frame parent, MUST be run under
+ // quasimodal mode for the quasimodal frame support to work. So don't use
+ // the QUASIMODAL macros here.
+ if( dlg.ShowQuasiModal() != wxID_OK )
+ return;
+
+ UpdateAliasSelectList();
+ UpdatePartSelectList();
+ DisplayLibInfos();
+ Refresh();
+}
+
+
+DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB(
+ LIB_EDIT_FRAME* aParent,
+ LIB_PART* aLibEntry ) :
+ DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB_BASE( aParent )
+{
+ m_parent = aParent;
+ m_libEntry = aLibEntry;
+ m_skipCopyFromPanel = false;
+}
+
+
+void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::OnInitDialog( wxInitDialogEvent& event )
+{
+ m_skipCopyFromPanel = false;
+ wxListItem columnLabel;
+
+ columnLabel.SetImage( -1 );
+
+ columnLabel.SetText( _( "Name" ) );
+ fieldListCtrl->InsertColumn( COLUMN_FIELD_NAME, columnLabel );
+
+ columnLabel.SetText( _( "Value" ) );
+ fieldListCtrl->InsertColumn( COLUMN_TEXT, columnLabel );
+
+ m_staticTextUnitSize->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
+ m_staticTextUnitPosX->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
+ m_staticTextUnitPosY->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
+
+ initBuffers();
+ copySelectedFieldToPanel();
+
+ stdDialogButtonSizerOK->SetDefault();
+
+ FixOSXCancelButtonIssue();
+
+ // Now all widgets have the size fixed, call FinishDialogSettings
+ FinishDialogSettings();
+}
+
+
+void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::OnListItemDeselected( wxListEvent& event )
+{
+ if( !m_skipCopyFromPanel )
+ {
+ if( !copyPanelToSelectedField() )
+ event.Skip(); // do not go to the next row
+ }
+}
+
+
+void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::OnListItemSelected( wxListEvent& event )
+{
+ // remember the selected row, statically
+ s_SelectedRow = event.GetIndex();
+
+ copySelectedFieldToPanel();
+}
+
+
+void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::OnCancelButtonClick( wxCommandEvent& event )
+{
+ EndQuasiModal( wxID_CANCEL );
+}
+
+
+void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::OnCloseDialog( wxCloseEvent& event )
+{
+ // On wxWidgets 2.8, and on Linux, call EndQuasiModal here is mandatory
+ // Otherwise, the main event loop is never restored, and Eeschema does not
+ // respond to any event, because the DIALOG_SHIM destructor is never called.
+ // on wxWidgets 3.0, or on Windows, the DIALOG_SHIM destructor is called,
+ // and calls EndQuasiModal.
+ // Therefore calling EndQuasiModal here is not mandatory but it creates no issues.
+ EndQuasiModal( wxID_CANCEL );
+}
+
+
+void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::OnOKButtonClick( wxCommandEvent& event )
+{
+ if( !copyPanelToSelectedField() )
+ return;
+
+ // test if reference prefix is acceptable
+ if( !SCH_COMPONENT::IsReferenceStringValid( m_FieldsBuf[REFERENCE].GetText() ) )
+ {
+ DisplayError( NULL, _( "Illegal reference. References must start with a letter." ) );
+ return;
+ }
+
+ /* Note: this code is now (2010-dec-04) not used, because the value field is no more editable
+ * because changing the value is equivalent to create a new component or alias.
+ * This is now handled in libedit main frame, and no more in this dialog
+ * but this code is not removed, just in case
+ */
+ /* If a new name entered in the VALUE field, that it not an existing alias name
+ * or root alias of the component */
+ wxString newvalue = m_FieldsBuf[VALUE].GetText();
+
+ if( m_libEntry->HasAlias( newvalue ) && !m_libEntry->GetAlias( newvalue )->IsRoot() )
+ {
+ wxString msg = wxString::Format(
+ _( "A new name is entered for this component\n"
+ "An alias %s already exists!\n"
+ "Cannot update this component" ),
+ GetChars( newvalue )
+ );
+ DisplayError( this, msg );
+ return;
+ }
+ /* End unused code */
+
+ // save old cmp in undo list
+ m_parent->SaveCopyInUndoList( m_libEntry );
+
+ // delete any fields with no name or no value before we copy all of m_FieldsBuf
+ // back into the component
+ for( unsigned i = MANDATORY_FIELDS; i < m_FieldsBuf.size(); )
+ {
+ if( m_FieldsBuf[i].GetName().IsEmpty() || m_FieldsBuf[i].GetText().IsEmpty() )
+ {
+ m_FieldsBuf.erase( m_FieldsBuf.begin() + i );
+ continue;
+ }
+
+ ++i;
+ }
+
+ // copy all the fields back, fully replacing any previous fields
+ m_libEntry->SetFields( m_FieldsBuf );
+
+ // We need to keep the name and the value the same at the moment!
+ SetName( m_libEntry->GetValueField().GetText() );
+
+ m_parent->OnModify();
+
+ EndQuasiModal( wxID_OK );
+}
+
+
+void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::addFieldButtonHandler( wxCommandEvent& event )
+{
+ // in case m_FieldsBuf[REFERENCE].m_Orient has changed on screen only, grab
+ // screen contents.
+ if( !copyPanelToSelectedField() )
+ return;
+
+ unsigned fieldNdx = m_FieldsBuf.size();
+
+ LIB_FIELD blank( fieldNdx );
+
+ m_FieldsBuf.push_back( blank );
+ m_FieldsBuf[fieldNdx].SetName( TEMPLATE_FIELDNAME::GetDefaultFieldName( fieldNdx ) );
+
+ setRowItem( fieldNdx, m_FieldsBuf[fieldNdx] );
+
+ m_skipCopyFromPanel = true;
+ setSelectedFieldNdx( fieldNdx );
+ m_skipCopyFromPanel = false;
+}
+
+
+void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::deleteFieldButtonHandler( wxCommandEvent& event )
+{
+ unsigned fieldNdx = getSelectedFieldNdx();
+
+ if( fieldNdx >= m_FieldsBuf.size() ) // traps the -1 case too
+ return;
+
+ if( fieldNdx < MANDATORY_FIELDS )
+ {
+ wxBell();
+ return;
+ }
+
+ m_skipCopyFromPanel = true;
+
+ if( m_FieldsBuf[fieldNdx].GetText().IsEmpty() )
+ {
+ m_FieldsBuf.erase( m_FieldsBuf.begin() + fieldNdx );
+ fieldListCtrl->DeleteItem( fieldNdx );
+
+ if( fieldNdx >= m_FieldsBuf.size() )
+ --fieldNdx;
+ }
+ else
+ {
+ m_FieldsBuf[fieldNdx].Empty();
+ copySelectedFieldToPanel();
+ }
+
+ updateDisplay( );
+
+ setRowItem( fieldNdx, m_FieldsBuf[fieldNdx] );
+ setSelectedFieldNdx( fieldNdx );
+ m_skipCopyFromPanel = false;
+}
+
+
+void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB:: moveUpButtonHandler( wxCommandEvent& event )
+{
+ unsigned fieldNdx = getSelectedFieldNdx();
+
+ if( fieldNdx >= m_FieldsBuf.size() ) // traps the -1 case too
+ return;
+
+ // The first field which can be moved up is the second user field
+ // so any field which id <= MANDATORY_FIELDS cannot be moved up
+ if( fieldNdx <= MANDATORY_FIELDS )
+ return;
+
+ if( !copyPanelToSelectedField() )
+ return;
+
+ // swap the fieldNdx field with the one before it, in both the vector
+ // and in the fieldListCtrl
+ LIB_FIELD tmp = m_FieldsBuf[fieldNdx - 1];
+
+ m_FieldsBuf[fieldNdx - 1] = m_FieldsBuf[fieldNdx];
+ setRowItem( fieldNdx - 1, m_FieldsBuf[fieldNdx] );
+ m_FieldsBuf[fieldNdx - 1].SetId(fieldNdx - 1);
+
+ m_FieldsBuf[fieldNdx] = tmp;
+ setRowItem( fieldNdx, tmp );
+ m_FieldsBuf[fieldNdx].SetId(fieldNdx);
+
+ updateDisplay( );
+
+ m_skipCopyFromPanel = true;
+ setSelectedFieldNdx( fieldNdx - 1 );
+ m_skipCopyFromPanel = false;
+}
+
+
+void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::showButtonHandler( wxCommandEvent& event )
+{
+ unsigned fieldNdx = getSelectedFieldNdx();
+
+ if( fieldNdx == DATASHEET )
+ {
+ wxString datasheet_uri = fieldValueTextCtrl->GetValue();
+ ::wxLaunchDefaultBrowser( datasheet_uri );
+ }
+ else if( fieldNdx == FOOTPRINT )
+ {
+ // pick a footprint using the footprint picker.
+ wxString fpid;
+
+ KIWAY_PLAYER* frame = Kiway().Player( FRAME_PCB_MODULE_VIEWER_MODAL, true );
+
+ if( frame->ShowModal( &fpid, this ) )
+ {
+ fieldValueTextCtrl->SetValue( fpid );
+ setRowItem( fieldNdx, m_FieldsBuf[fieldNdx].GetName( false ), fpid );
+ }
+
+ frame->Destroy();
+ }
+}
+
+
+void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::setSelectedFieldNdx( int aFieldNdx )
+{
+ // deselect old selection, but I think this is done by single selection
+ // flag within fieldListCtrl
+ // fieldListCtrl->SetItemState( s_SelectedRow, 0, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED);
+
+ if( aFieldNdx >= (int) m_FieldsBuf.size() )
+ aFieldNdx = m_FieldsBuf.size() - 1;
+
+ if( aFieldNdx < 0 )
+ aFieldNdx = 0;
+
+ fieldListCtrl->SetItemState( aFieldNdx, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
+ fieldListCtrl->EnsureVisible( aFieldNdx );
+
+ s_SelectedRow = aFieldNdx;
+}
+
+
+int DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::getSelectedFieldNdx()
+{
+ return s_SelectedRow;
+}
+
+
+/**
+ * Function findfield
+ * searches a LIB_FIELD_LIST for aFieldName.
+ */
+static LIB_FIELD* findfield( const LIB_FIELDS& aList, const wxString& aFieldName )
+{
+ const LIB_FIELD* field = NULL;
+
+ for( unsigned i=0; i<aList.size(); ++i )
+ {
+ if( aFieldName == aList[i].GetName() )
+ {
+ field = &aList[i]; // best to avoid casting here.
+ break;
+ }
+ }
+ return (LIB_FIELD*) field; // remove const-ness last
+}
+
+
+LIB_FIELD* DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::findField( const wxString& aFieldName )
+{
+ for( unsigned i=0; i<m_FieldsBuf.size(); ++i )
+ {
+ if( aFieldName == m_FieldsBuf[i].GetName() )
+ return &m_FieldsBuf[i];
+ }
+ return NULL;
+}
+
+
+void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::initBuffers()
+{
+ LIB_FIELDS cmpFields;
+
+ m_libEntry->GetFields( cmpFields );
+
+ /* We have 3 component related field lists to be aware of: 1) UI
+ presentation (m_FieldsBuf), 2) fields in component ram copy, and 3)
+ fields recorded with component on disk. m_FieldsBuf is the list of UI
+ fields, and this list is not the same as the list which is in the
+ component, which is also not the same as the list on disk. All 3 lists
+ are potentially different. In the UI we choose to preserve the order of
+ the first MANDATORY_FIELDS which are sometimes called fixed fields. Then
+ we append the template fieldnames in the exact same order as the
+ template fieldname editor shows them. Then we append any user defined
+ fieldnames which came from the component, and user can modify it during
+ editing, but cannot delete or move a fixed field.
+ */
+
+ m_FieldsBuf.clear();
+
+ /* When this code was written, all field constructors ensured that the
+ MANDATORY_FIELDS are all present within a component (in ram only). So we can
+ knowingly copy them over in the normal order. Copy only the fixed fields
+ at first. Please do not break the field constructors.
+ */
+
+ // fixed fields:
+ for( int i=0; i<MANDATORY_FIELDS; ++i )
+ {
+ m_FieldsBuf.push_back( cmpFields[i] );
+ }
+
+ // Add template fieldnames:
+ // Now copy in the template fields, in the order that they are present in the
+ // template field editor UI.
+ SCH_EDIT_FRAME* editor = (SCH_EDIT_FRAME*) Kiway().Player( FRAME_SCH, true );
+
+ const TEMPLATE_FIELDNAMES& tfnames = editor->GetTemplateFieldNames();
+
+ for( TEMPLATE_FIELDNAMES::const_iterator it = tfnames.begin(); it!=tfnames.end(); ++it )
+ {
+ // add a new field unconditionally to the UI only for this template fieldname
+
+ // field id must not be in range 0 - MANDATORY_FIELDS, set before saving to disk
+ LIB_FIELD fld( m_libEntry, -1 );
+
+ // See if field by same name already exists in component.
+ LIB_FIELD* libField = findfield( cmpFields, it->m_Name );
+
+ // If the field does not already exist in the component, then we
+ // use defaults from the template fieldname, otherwise the original
+ // values from the component will be set.
+ if( !libField )
+ {
+ fld.SetName( it->m_Name );
+ fld.SetText( it->m_Value ); // empty? ok too.
+
+ if( !it->m_Visible )
+ fld.SetVisible( false );
+ else
+ fld.SetVisible( true );
+ }
+ else
+ {
+ fld = *libField; // copy values from component, m_Name too
+ }
+
+ m_FieldsBuf.push_back( fld );
+ }
+
+ // Lastly, append any original fields from the component which were not added
+ // from the set of fixed fields nor from the set of template fields.
+ for( unsigned i=MANDATORY_FIELDS; i<cmpFields.size(); ++i )
+ {
+ LIB_FIELD* cmp = &cmpFields[i];
+ LIB_FIELD* buf = findField( cmp->GetName() );
+
+ if( !buf )
+ {
+ m_FieldsBuf.push_back( *cmp );
+ }
+ }
+
+ /* field names have become more important than field ids, so we cannot
+ mangle the names in the buffer, but can do so in the panel, see elsewhere.
+ m_FieldsBuf[VALUE].m_Name << wxT( "/" ) << _( "Chip Name" );
+ */
+
+ for( unsigned ii = 0; ii < m_FieldsBuf.size(); ++ii )
+ {
+ setRowItem( ii, m_FieldsBuf[ii] );
+ }
+
+ // put focus on the list ctrl
+ fieldListCtrl->SetFocus();
+
+ // resume editing at the last row edited, last time dialog was up.
+ if ( s_SelectedRow < (int) m_FieldsBuf.size() )
+ s_SelectedRow = 0;
+
+ setSelectedFieldNdx( s_SelectedRow );
+}
+
+
+void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::setRowItem( int aFieldNdx, const wxString& aName, const wxString& aValue )
+{
+ wxASSERT( aFieldNdx >= 0 );
+
+ // insert blanks if aFieldNdx is referencing a "yet to be defined" row
+ while( aFieldNdx >= fieldListCtrl->GetItemCount() )
+ {
+ long ndx = fieldListCtrl->InsertItem( fieldListCtrl->GetItemCount(), wxEmptyString );
+
+ wxASSERT( ndx >= 0 );
+
+ fieldListCtrl->SetItem( ndx, COLUMN_TEXT, wxEmptyString );
+ }
+
+ fieldListCtrl->SetItem( aFieldNdx, COLUMN_FIELD_NAME, aName );
+ fieldListCtrl->SetItem( aFieldNdx, COLUMN_TEXT, aValue );
+
+ // recompute the column widths here, after setting texts
+ fieldListCtrl->SetColumnWidth( COLUMN_FIELD_NAME, wxLIST_AUTOSIZE );
+ fieldListCtrl->SetColumnWidth( COLUMN_TEXT, wxLIST_AUTOSIZE );
+}
+
+
+void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::copySelectedFieldToPanel()
+{
+ unsigned fieldNdx = getSelectedFieldNdx();
+
+ if( fieldNdx >= m_FieldsBuf.size() ) // traps the -1 case too
+ return;
+
+ LIB_FIELD& field = m_FieldsBuf[fieldNdx];
+
+ showCheckBox->SetValue( field.IsVisible() );
+
+ rotateCheckBox->SetValue( field.GetOrientation() == TEXT_ORIENT_VERT );
+
+ int style = 0;
+
+ if( field.IsItalic() )
+ style = 1;
+
+ if( field.IsBold() )
+ style |= 2;
+
+ m_StyleRadioBox->SetSelection( style );
+
+ // Select the right text justification
+ if( field.GetHorizJustify() == GR_TEXT_HJUSTIFY_LEFT )
+ m_FieldHJustifyCtrl->SetSelection(0);
+ else if( field.GetHorizJustify() == GR_TEXT_HJUSTIFY_RIGHT )
+ m_FieldHJustifyCtrl->SetSelection(2);
+ else
+ m_FieldHJustifyCtrl->SetSelection(1);
+
+ if( field.GetVertJustify() == GR_TEXT_VJUSTIFY_BOTTOM )
+ m_FieldVJustifyCtrl->SetSelection(0);
+ else if( field.GetVertJustify() == GR_TEXT_VJUSTIFY_TOP )
+ m_FieldVJustifyCtrl->SetSelection(2);
+ else
+ m_FieldVJustifyCtrl->SetSelection(1);
+
+
+ // Field names have become more important than field ids, so we cannot
+ // mangle the names in the buffer but we can do so in the panel.
+ if( field.GetId() == VALUE )
+ {
+ // This field is the lib name and the default value when loading this component in
+ // schematic. The value is now not editable here (in this dialog) because changing
+ // it is equivalent to create a new component or alias. This is handles in libedir,
+ // not in this dialog.
+ fieldNameTextCtrl->SetValue( field.GetName() + wxT( " / " ) + _( "Chip Name" ) );
+ fieldValueTextCtrl->Enable( false );
+ }
+ else
+ {
+ fieldValueTextCtrl->Enable( true );
+ fieldNameTextCtrl->SetValue( field.GetName() );
+ }
+
+ // if fieldNdx == REFERENCE, VALUE, FOOTPRINT, or DATASHEET, then disable field name editing
+ fieldNameTextCtrl->Enable( fieldNdx >= MANDATORY_FIELDS );
+ fieldNameTextCtrl->SetEditable( fieldNdx >= MANDATORY_FIELDS );
+
+ // only user defined fields may be moved, and not the top most user defined
+ // field since it would be moving up into the fixed fields, > not >=
+ moveUpButton->Enable( fieldNdx > MANDATORY_FIELDS );
+
+ // if fieldNdx == REFERENCE, VALUE, then disable delete button
+ deleteFieldButton->Enable( fieldNdx >= MANDATORY_FIELDS );
+
+ fieldValueTextCtrl->SetValidator( SCH_FIELD_VALIDATOR( true, field.GetId() ) );
+ fieldValueTextCtrl->SetValue( field.GetText() );
+
+ textSizeTextCtrl->SetValue( EDA_GRAPHIC_TEXT_CTRL::FormatSize( g_UserUnit, field.GetSize().x ) );
+
+ m_show_datasheet_button->Enable( fieldNdx == DATASHEET || fieldNdx == FOOTPRINT );
+
+ if( fieldNdx == DATASHEET )
+ m_show_datasheet_button->SetLabel( _( "Show in Browser" ) );
+ else if( fieldNdx == FOOTPRINT )
+ m_show_datasheet_button->SetLabel( _( "Assign Footprint" ) );
+ else
+ m_show_datasheet_button->SetLabel( wxEmptyString );
+
+ wxPoint coord = field.GetTextPosition();
+ wxPoint zero;
+
+ // If the field value is empty and the position is at relative zero, we set the
+ // initial position as a small offset from the ref field, and orient
+ // it the same as the ref field. That is likely to put it at least
+ // close to the desired position.
+ if( coord == zero && field.GetText().IsEmpty() )
+ {
+ rotateCheckBox->SetValue( m_FieldsBuf[REFERENCE].GetOrientation() == TEXT_ORIENT_VERT );
+
+ coord.x = m_FieldsBuf[REFERENCE].GetTextPosition().x +
+ (fieldNdx - MANDATORY_FIELDS + 1) * 100;
+ coord.y = m_FieldsBuf[REFERENCE].GetTextPosition().y +
+ (fieldNdx - MANDATORY_FIELDS + 1) * 100;
+
+ // coord can compute negative if field is < MANDATORY_FIELDS, e.g. FOOTPRINT.
+ // That is ok, we basically don't want all the new empty fields on
+ // top of each other.
+ }
+
+ wxString coordText = StringFromValue( g_UserUnit, coord.x );
+ posXTextCtrl->SetValue( coordText );
+
+ // Note: the Y axis for components in lib is from bottom to top
+ // and the screen axis is top to bottom: we must change the y coord sign for editing
+ coord.y = -coord.y;
+ coordText = StringFromValue( g_UserUnit, coord.y );
+ posYTextCtrl->SetValue( coordText );
+}
+
+
+bool DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::copyPanelToSelectedField()
+{
+ unsigned fieldNdx = getSelectedFieldNdx();
+
+ if( fieldNdx >= m_FieldsBuf.size() ) // traps the -1 case too
+ return true;
+
+ // Check for illegal field text.
+ if( fieldValueTextCtrl->GetValidator()
+ && !fieldValueTextCtrl->GetValidator()->Validate( this ) )
+ return false;
+
+ LIB_FIELD& field = m_FieldsBuf[fieldNdx];
+
+ if( showCheckBox->GetValue() )
+ field.SetVisible( true );
+ else
+ field.SetVisible( false );
+
+ if( rotateCheckBox->GetValue() )
+ field.SetOrientation( TEXT_ORIENT_VERT );
+ else
+ field.SetOrientation( TEXT_ORIENT_HORIZ );
+
+ // Copy the text justification
+ static const EDA_TEXT_HJUSTIFY_T hjustify[3] = {
+ GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_HJUSTIFY_CENTER,
+ GR_TEXT_HJUSTIFY_RIGHT
+ };
+
+ static const EDA_TEXT_VJUSTIFY_T vjustify[3] = {
+ GR_TEXT_VJUSTIFY_BOTTOM, GR_TEXT_VJUSTIFY_CENTER,
+ GR_TEXT_VJUSTIFY_TOP
+ };
+
+ field.SetHorizJustify( hjustify[m_FieldHJustifyCtrl->GetSelection()] );
+ field.SetVertJustify( vjustify[m_FieldVJustifyCtrl->GetSelection()] );
+
+ // Blank/empty field texts for REFERENCE and VALUE are not allowed.
+ // (Value is the name of the component in lib!)
+ // Change them only if user provided a non blank value
+ if( !fieldValueTextCtrl->GetValue().IsEmpty() || fieldNdx > VALUE )
+ field.SetText( fieldValueTextCtrl->GetValue() );
+
+ // FieldNameTextCtrl has a tricked value in it for VALUE index, do not copy it back.
+ // It has the "Chip Name" appended.
+ if( field.GetId() >= MANDATORY_FIELDS )
+ {
+ wxString name = fieldNameTextCtrl->GetValue();
+ field.SetName( name );
+ }
+
+ setRowItem( fieldNdx, field ); // update fieldListCtrl
+
+ int tmp = EDA_GRAPHIC_TEXT_CTRL::ParseSize( textSizeTextCtrl->GetValue(), g_UserUnit );
+
+ field.SetSize( wxSize( tmp, tmp ) );
+
+ int style = m_StyleRadioBox->GetSelection();
+
+ field.SetItalic( (style & 1 ) != 0 );
+ field.SetBold( (style & 2 ) != 0 );
+
+ wxPoint pos( ValueFromString( g_UserUnit, posXTextCtrl->GetValue() ),
+ ValueFromString( g_UserUnit, posYTextCtrl->GetValue() ) );
+
+ // Note: the Y axis for components in lib is from bottom to top
+ // and the screen axis is top to bottom: we must change the y coord sign for editing
+ pos.y = -pos.y;
+
+ field.SetTextPosition( pos );
+
+ return true;
+}