dialog_edit_libentry_fields_in_lib.cpp 23.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

/*
 * 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 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
 */

26 27 28

#include <algorithm>

29 30 31 32 33 34
#include <fctsys.h>
#include <appl_wxstruct.h>
#include <confirm.h>
#include <class_drawpanel.h>
#include <wxEeschemaStruct.h>
#include <id.h>
35
#include <base_units.h>
36

37 38 39 40 41 42 43 44
#include <general.h>
#include <protos.h>
#include <libeditframe.h>
#include <class_library.h>
#include <sch_component.h>
#include <sch_field.h>
#include <template_fieldnames.h>
#include <dialog_helpers.h>
45

46
#include <dialog_edit_libentry_fields_in_lib_base.h>
47 48 49 50

// Local variables:
static int s_SelectedRow;

51 52
#define COLUMN_FIELD_NAME   0
#define COLUMN_TEXT         1
53 54 55 56

class DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB : public DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB_BASE
{
public:
57
    DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB( LIB_EDIT_FRAME* aParent, LIB_COMPONENT* aLibEntry );
58
    //~DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB() {}
59 60 61 62 63 64 65 66

private:
    // Events handlers:
    void OnInitDialog( wxInitDialogEvent& event );

    void OnListItemDeselected( wxListEvent& event );
    void OnListItemSelected( wxListEvent& event );
    void addFieldButtonHandler( wxCommandEvent& event );
67 68 69 70 71 72 73 74

    /**
     * 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.
     */
75
    void deleteFieldButtonHandler( wxCommandEvent& event );
76

77 78 79
    void moveUpButtonHandler( wxCommandEvent& event );
    void OnCancelButtonClick( wxCommandEvent& event );
    void OnOKButtonClick( wxCommandEvent& event );
80
    void showButtonHandler( wxCommandEvent& event );
81 82 83 84 85 86 87

    // internal functions:
    void setSelectedFieldNdx( int aFieldNdx );

    int  getSelectedFieldNdx();

    /**
88
     * Function initBuffers
89 90
     * sets up to edit the given component.
     */
91
    void initBuffers();
92 93 94 95 96 97 98

    /**
     * Function findField
     * searches m_FieldsBuf and returns a LIB_FIELD with \a aFieldName or NULL if
     * not found.
     */
    LIB_FIELD* findField( const wxString& aFieldName );
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113

    /**
     * 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();
114
    void setRowItem( int aFieldNdx, const LIB_FIELD& aField );
115

116 117
    /**
     * Function updateDisplay
118 119 120 121 122
     * 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( )
    {
123
        for( unsigned ii = MANDATORY_FIELDS;  ii<m_FieldsBuf.size(); ii++ )
124 125
            setRowItem( ii, m_FieldsBuf[ii] );
    }
126 127 128 129 130 131 132

    LIB_EDIT_FRAME*    m_parent;
    LIB_COMPONENT*     m_libEntry;
    bool               m_skipCopyFromPanel;

    /// a copy of the edited component's LIB_FIELDs
    std::vector <LIB_FIELD> m_FieldsBuf;
133 134
};

135

136
void LIB_EDIT_FRAME::InstallFieldsEditorDialog( wxCommandEvent& event )
137
{
138
    if( m_component == NULL )
139 140
        return;

141
    m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor() );
142

143
    DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB dlg( this, m_component );
144

145 146 147 148
    int abort = dlg.ShowModal();

    if( abort )
        return;
149

150 151
    UpdateAliasSelectList();
    UpdatePartSelectList();
152
    DisplayLibInfos();
153
    Refresh();
154 155 156 157
}


DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB(
158 159
    LIB_EDIT_FRAME* aParent,
    LIB_COMPONENT*  aLibEntry ) :
160 161
    DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB_BASE( aParent )
{
162 163
    m_parent   = aParent;
    m_libEntry = aLibEntry;
jean-pierre charras's avatar
jean-pierre charras committed
164 165 166

    GetSizer()->SetSizeHints( this );
    Centre();
167 168 169 170 171 172 173 174 175 176 177
}


void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::OnInitDialog( wxInitDialogEvent& event )
{
    m_skipCopyFromPanel = false;
    wxListItem columnLabel;

    columnLabel.SetImage( -1 );

    columnLabel.SetText( _( "Name" ) );
charras's avatar
charras committed
178
    fieldListCtrl->InsertColumn( COLUMN_FIELD_NAME, columnLabel );
179 180

    columnLabel.SetText( _( "Value" ) );
charras's avatar
charras committed
181
    fieldListCtrl->InsertColumn( COLUMN_TEXT, columnLabel );
182

183 184 185
    m_staticTextUnitSize->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
    m_staticTextUnitPosX->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
    m_staticTextUnitPosY->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
186

187
    initBuffers();
188 189
    copySelectedFieldToPanel();

190
    stdDialogButtonSizerOK->SetDefault();
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
}


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 )
{
    EndModal( 1 );
}


void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::OnOKButtonClick( wxCommandEvent& event )
{
    if( !copyPanelToSelectedField() )
        return;

224
    // test if reference prefix is acceptable
225
    if( !SCH_COMPONENT::IsReferenceStringValid( m_FieldsBuf[REFERENCE].GetText() ) )
226 227 228 229 230
    {
        DisplayError( NULL, _( "Illegal reference prefix. A reference must start by a letter" ) );
        return;
    }

231 232 233 234 235
    /* 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
     */
236 237
    /* If a new name entered in the VALUE field, that it not an existing alias name
     * or root alias of the component */
238
    wxString newvalue = m_FieldsBuf[VALUE].GetText();
239

240
    if( m_libEntry->HasAlias( newvalue ) && !m_libEntry->GetAlias( newvalue )->IsRoot() )
241
    {
242 243 244 245 246 247
        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 )
            );
248 249
        DisplayError( this, msg );
        return;
250
    }
251
    /* End unused code */
252

253
    // save old cmp in undo list
254
    m_parent->SaveCopyInUndoList( m_libEntry, IS_CHANGED );
255

256 257 258
    // 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(); )
259
    {
260
        if( m_FieldsBuf[i].GetName().IsEmpty() || m_FieldsBuf[i].GetText().IsEmpty() )
261 262 263 264 265 266 267 268
        {
            m_FieldsBuf.erase( m_FieldsBuf.begin() + i );
            continue;
        }

        ++i;
    }

269
#if defined(DEBUG)
270
    for( unsigned i=0;  i<m_FieldsBuf.size();  ++i )
271 272
    {
        printf( "save[%d].name:'%s' value:'%s'\n", i,
273
                TO_UTF8( m_FieldsBuf[i].GetName() ),
274
                TO_UTF8( m_FieldsBuf[i].GetText() ) );
275 276 277 278
    }
#endif

    // copy all the fields back, fully replacing any previous fields
279
    m_libEntry->SetFields( m_FieldsBuf );
280

281
    // We need to keep the name and the value the same at the moment!
282
    SetName( m_libEntry->GetValueField().GetText() );
283

284
    m_parent->OnModify();
285 286 287 288 289 290 291 292 293 294 295 296

    EndModal( 0 );
}


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;

297
    unsigned fieldNdx = m_FieldsBuf.size();
298

299
    LIB_FIELD blank( fieldNdx );
300 301

    m_FieldsBuf.push_back( blank );
302
    m_FieldsBuf[fieldNdx].SetName( TEMPLATE_FIELDNAME::GetDefaultFieldName( fieldNdx ) );
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318

    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;

319
    if( fieldNdx < MANDATORY_FIELDS )
320 321 322 323 324
    {
        wxBell();
        return;
    }

325
    m_skipCopyFromPanel = true;
326

327
    if( m_FieldsBuf[fieldNdx].GetText().IsEmpty() )
charras's avatar
charras committed
328 329 330
    {
        m_FieldsBuf.erase( m_FieldsBuf.begin() + fieldNdx );
        fieldListCtrl->DeleteItem( fieldNdx );
331

charras's avatar
charras committed
332 333 334 335 336
        if( fieldNdx >= m_FieldsBuf.size() )
            --fieldNdx;
    }
    else
    {
337
        m_FieldsBuf[fieldNdx].Empty();
charras's avatar
charras committed
338 339
        copySelectedFieldToPanel();
    }
340

341 342 343
    updateDisplay( );

    setRowItem( fieldNdx, m_FieldsBuf[fieldNdx] );
344 345 346 347 348 349 350 351 352 353 354 355
    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;

356
    if( fieldNdx < MANDATORY_FIELDS )
357 358 359 360 361 362 363 364 365 366
    {
        wxBell();
        return;
    }

    if( !copyPanelToSelectedField() )
        return;

    // swap the fieldNdx field with the one before it, in both the vector
    // and in the fieldListCtrl
367
    LIB_FIELD tmp = m_FieldsBuf[fieldNdx - 1];
368 369 370 371 372 373 374

    m_FieldsBuf[fieldNdx - 1] = m_FieldsBuf[fieldNdx];
    setRowItem( fieldNdx - 1, m_FieldsBuf[fieldNdx] );

    m_FieldsBuf[fieldNdx] = tmp;
    setRowItem( fieldNdx, tmp );

375 376
    updateDisplay( );

377 378 379 380 381 382
    m_skipCopyFromPanel = true;
    setSelectedFieldNdx( fieldNdx - 1 );
    m_skipCopyFromPanel = false;
}


383 384 385 386 387 388 389
void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::showButtonHandler( wxCommandEvent& event )
{
    wxString datasheet_uri = fieldValueTextCtrl->GetValue();
    ::wxLaunchDefaultBrowser( datasheet_uri );
}


390 391
void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::setSelectedFieldNdx( int aFieldNdx )
{
392 393 394
    // 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);
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414

    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;
}


415 416 417 418
/**
 * Function findfield
 * searches a LIB_FIELD_LIST for aFieldName.
 */
419
static LIB_FIELD* findfield( const LIB_FIELDS& aList, const wxString& aFieldName )
420
{
421 422 423 424
    const LIB_FIELD*  field = NULL;

    for( unsigned i=0;  i<aList.size();  ++i )
    {
425
        if( aFieldName == aList[i].GetName() )
426 427 428 429 430 431
        {
            field = &aList[i];  // best to avoid casting here.
            break;
        }
    }
    return (LIB_FIELD*) field;  // remove const-ness last
432 433
}

434 435 436 437 438

LIB_FIELD* DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::findField( const wxString& aFieldName )
{
    for( unsigned i=0;  i<m_FieldsBuf.size();  ++i )
    {
439
        if( aFieldName == m_FieldsBuf[i].GetName() )
440 441 442 443 444 445
            return &m_FieldsBuf[i];
    }
    return NULL;
}


446
void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::initBuffers()
447
{
448
    LIB_FIELDS cmpFields;
449

450
    m_libEntry->GetFields( cmpFields );
451

452 453 454
#if defined(DEBUG)
    for( unsigned i=0; i<cmpFields.size();  ++i )
    {
455
        printf( "cmpFields[%d].name:%s\n", i, TO_UTF8( cmpFields[i].GetName() ) );
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470
    }
#endif

    /*  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.
    */
471

472
    m_FieldsBuf.clear();
473

474 475 476 477 478
    /*  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.
    */
479

480 481
    // fixed fields:
    for( int i=0; i<MANDATORY_FIELDS; ++i )
482
    {
483
        DBG( printf( "add fixed:%s\n", TO_UTF8( cmpFields[i].GetName() ) ); )
484
        m_FieldsBuf.push_back( cmpFields[i] );
485 486
    }

487 488 489 490
    // Add template fieldnames:
    // Now copy in the template fields, in the order that they are present in the
    // template field editor UI.
    const TEMPLATE_FIELDNAMES& tfnames =
491
        ((SCH_EDIT_FRAME*)m_parent->GetParent())->GetTemplateFieldNames();
492 493 494 495 496 497

    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
498
        LIB_FIELD fld( m_libEntry, -1 );
499 500 501

        // See if field by same name already exists in component.
        LIB_FIELD* libField = findfield( cmpFields, it->m_Name );
502

503 504 505 506 507
        // 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 )
        {
508
            DBG( printf( "add template:%s\n", TO_UTF8( it->m_Name ) ); )
509

Dick Hollenbeck's avatar
Dick Hollenbeck committed
510
            fld.SetName( it->m_Name );
511
            fld.SetText( it->m_Value );   // empty? ok too.
512 513

            if( !it->m_Visible )
514
                fld.SetVisible( false );
515
            else
516
                fld.SetVisible( true );;
517 518 519
        }
        else
        {
520
            DBG( printf( "match template:%s\n", TO_UTF8( libField->GetName() ) ); )
521 522 523 524 525
            fld = *libField;    // copy values from component, m_Name too
        }

        m_FieldsBuf.push_back( fld );
    }
526

527 528 529
    // 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 )
530
    {
531
        LIB_FIELD*  cmp = &cmpFields[i];
532
        LIB_FIELD*  buf = findField( cmp->GetName() );
533 534 535

        if( !buf )
        {
536
            DBG( printf( "add cmp:%s\n", TO_UTF8( cmp->GetName() ) ); )
537 538
            m_FieldsBuf.push_back( *cmp );
        }
539 540
    }

541 542 543 544 545
    /*  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" );
    */

546 547 548 549 550 551 552 553 554
    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.
555 556
    if ( s_SelectedRow < (int) m_FieldsBuf.size() )
        s_SelectedRow = 0;
557

558 559 560 561
    setSelectedFieldNdx( s_SelectedRow );
}


562
void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::setRowItem( int aFieldNdx, const LIB_FIELD& aField )
563 564 565 566 567 568 569 570 571 572
{
    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 );

charras's avatar
charras committed
573
        fieldListCtrl->SetItem( ndx, COLUMN_TEXT, wxEmptyString );
574 575
    }

576
    fieldListCtrl->SetItem( aFieldNdx, COLUMN_FIELD_NAME, aField.GetName() );
577
    fieldListCtrl->SetItem( aFieldNdx, COLUMN_TEXT, aField.GetText() );
578 579

    // recompute the column widths here, after setting texts
charras's avatar
charras committed
580 581
    fieldListCtrl->SetColumnWidth( COLUMN_FIELD_NAME, wxLIST_AUTOSIZE );
    fieldListCtrl->SetColumnWidth( COLUMN_TEXT, wxLIST_AUTOSIZE );
582 583 584 585 586 587 588 589 590 591
}


void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::copySelectedFieldToPanel()
{
    unsigned fieldNdx = getSelectedFieldNdx();

    if( fieldNdx >= m_FieldsBuf.size() )    // traps the -1 case too
        return;

592
    LIB_FIELD& field = m_FieldsBuf[fieldNdx];
593

594
    showCheckBox->SetValue( field.IsVisible() );
595

596
    rotateCheckBox->SetValue( field.GetOrientation() == TEXT_ORIENT_VERT );
597 598

    int style = 0;
599 600

    if( field.IsItalic() )
601
        style = 1;
602

603
    if( field.IsBold() )
604
        style |= 2;
605

606 607
    m_StyleRadioBox->SetSelection( style );

608
    // Select the right text justification
609
    if( field.GetHorizJustify() == GR_TEXT_HJUSTIFY_LEFT )
610
        m_FieldHJustifyCtrl->SetSelection(0);
611
    else if( field.GetHorizJustify() == GR_TEXT_HJUSTIFY_RIGHT )
612 613 614 615
        m_FieldHJustifyCtrl->SetSelection(2);
    else
        m_FieldHJustifyCtrl->SetSelection(1);

616
    if( field.GetVertJustify() == GR_TEXT_VJUSTIFY_BOTTOM )
617
        m_FieldVJustifyCtrl->SetSelection(0);
618
    else if( field.GetVertJustify() == GR_TEXT_VJUSTIFY_TOP )
619 620 621 622
        m_FieldVJustifyCtrl->SetSelection(2);
    else
        m_FieldVJustifyCtrl->SetSelection(1);

623 624 625

    // 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.
626 627 628 629 630 631 632
    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" ) );
633 634
        fieldValueTextCtrl->Enable( false );
    }
635
    else
636 637
    {
        fieldValueTextCtrl->Enable( true );
638
        fieldNameTextCtrl->SetValue( field.GetName() );
639
    }
640

641
    // if fieldNdx == REFERENCE, VALUE, FOOTPRINT, or DATASHEET, then disable field name editing
642 643 644 645 646
    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 >=
647
    moveUpButton->Enable( fieldNdx >= MANDATORY_FIELDS );
648

charras's avatar
charras committed
649
    // if fieldNdx == REFERENCE, VALUE, then disable delete button
650
    deleteFieldButton->Enable( fieldNdx >= MANDATORY_FIELDS );
651

652
    fieldValueTextCtrl->SetValue( field.GetText() );
653

654
    textSizeTextCtrl->SetValue( EDA_GRAPHIC_TEXT_CTRL::FormatSize( g_UserUnit, field.GetSize().x ) );
655

656 657
    m_show_datasheet_button->Enable( fieldNdx == DATASHEET );

658
    wxPoint coord = field.GetTextPosition();
659 660 661 662 663 664
    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.
665
    if( coord == zero && field.GetText().IsEmpty() )
666
    {
667
        rotateCheckBox->SetValue( m_FieldsBuf[REFERENCE].GetOrientation() == TEXT_ORIENT_VERT );
668

669 670 671 672
        coord.x = m_FieldsBuf[REFERENCE].GetTextPosition().x +
                  (fieldNdx - MANDATORY_FIELDS + 1) * 100;
        coord.y = m_FieldsBuf[REFERENCE].GetTextPosition().y +
                  (fieldNdx - MANDATORY_FIELDS + 1) * 100;
673

674
        // coord can compute negative if field is < MANDATORY_FIELDS, e.g. FOOTPRINT.
675 676 677 678
        // That is ok, we basically don't want all the new empty fields on
        // top of each other.
    }

679
    wxString coordText = ReturnStringFromValue( g_UserUnit, coord.x );
680 681 682 683 684
    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
    NEGATE( coord.y );
685
    coordText = ReturnStringFromValue( g_UserUnit, coord.y );
686 687 688 689 690 691 692 693 694 695 696
    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;

697
    LIB_FIELD& field = m_FieldsBuf[fieldNdx];
698 699

    if( showCheckBox->GetValue() )
700
        field.SetVisible( true );
701
    else
702
        field.SetVisible( false );
703 704

    if( rotateCheckBox->GetValue() )
705
        field.SetOrientation( TEXT_ORIENT_VERT );
706
    else
707
        field.SetOrientation( TEXT_ORIENT_HORIZ );
708

709
    // Copy the text justification
710
    static const EDA_TEXT_HJUSTIFY_T hjustify[3] = {
711 712 713
        GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_HJUSTIFY_CENTER,
        GR_TEXT_HJUSTIFY_RIGHT
    };
714

715
    static const EDA_TEXT_VJUSTIFY_T vjustify[3] = {
716 717 718
        GR_TEXT_VJUSTIFY_BOTTOM, GR_TEXT_VJUSTIFY_CENTER,
        GR_TEXT_VJUSTIFY_TOP
    };
719

720 721
    field.SetHorizJustify( hjustify[m_FieldHJustifyCtrl->GetSelection()] );
    field.SetVertJustify( vjustify[m_FieldVJustifyCtrl->GetSelection()] );
722

723 724 725
    // 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
726
    if( !fieldValueTextCtrl->GetValue().IsEmpty() || fieldNdx > VALUE )
727
        field.SetText( fieldValueTextCtrl->GetValue() );
728

729 730
    // FieldNameTextCtrl has a tricked value in it for VALUE index, do not copy it back.
    // It has the "Chip Name" appended.
731
    if( field.GetId() >= MANDATORY_FIELDS )
732 733
    {
        wxString name = fieldNameTextCtrl->GetValue();
734
        DBG( printf("name:%s\n", TO_UTF8( name ) ); )
735 736 737
        field.SetName( name );
    }

738
    DBG( printf("setname:%s\n", TO_UTF8( field.GetName() ) ); )
739 740 741

    setRowItem( fieldNdx, field );  // update fieldListCtrl

742
    int tmp = EDA_GRAPHIC_TEXT_CTRL::ParseSize( textSizeTextCtrl->GetValue(), g_UserUnit );
743

744
    field.SetSize( wxSize( tmp, tmp ) );
745 746 747

    int style = m_StyleRadioBox->GetSelection();

748 749
    field.SetItalic( (style & 1 ) != 0 );
    field.SetBold( (style & 2 ) != 0 );
750

751 752
    wxPoint pos( ReturnValueFromString( g_UserUnit, posXTextCtrl->GetValue() ),
                 ReturnValueFromString( g_UserUnit, posYTextCtrl->GetValue() ) );
753

754 755
    // 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
756 757
    NEGATE( pos.y );

758
    field.SetTextPosition( pos );
759 760 761

    return true;
}