dialog_edit_component_in_schematic.cpp 26.1 KB
Newer Older
1 2 3
/**
 * @file dialog_edit_component_in_schematic.cpp
 */
4

5
#include <wx/tooltip.h>
6

7 8 9 10 11 12 13
#include <fctsys.h>
#include <appl_wxstruct.h>
#include <gr_basic.h>
#include <class_drawpanel.h>
#include <confirm.h>
#include <class_sch_screen.h>
#include <wxEeschemaStruct.h>
14
#include <base_units.h>
15

16 17 18 19
#include <general.h>
#include <class_library.h>
#include <sch_component.h>
#include <dialog_helpers.h>
20

21
#include <dialog_edit_component_in_schematic.h>
22 23


24
int DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_SelectedRow;
25
wxSize DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_LastSize = wxDefaultSize;
26 27


28
void SCH_EDIT_FRAME::EditComponent( SCH_COMPONENT* aComponent )
29
{
30 31
    wxCHECK_RET( aComponent != NULL && aComponent->Type() == SCH_COMPONENT_T,
                 wxT( "Invalid component object pointer.  Bad Programmer!" )  );
32

33
    m_canvas->SetIgnoreMouseEvents( true );
34

35
    DIALOG_EDIT_COMPONENT_IN_SCHEMATIC* dlg = new DIALOG_EDIT_COMPONENT_IN_SCHEMATIC( this );
36

jean-pierre charras's avatar
jean-pierre charras committed
37
    dlg->InitBuffers( aComponent );
38

jean-pierre charras's avatar
jean-pierre charras committed
39
    wxSize sizeNow = dlg->GetSize();
40

41 42 43 44
    // this relies on wxDefaultSize being -1,-1, be careful here.
    if( sizeNow.GetWidth() < DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_LastSize.GetWidth()
        || sizeNow.GetHeight() < DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_LastSize.GetHeight() )
    {
jean-pierre charras's avatar
jean-pierre charras committed
45
        dlg->SetSize( DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_LastSize );
46
    }
47

48
    // make sure the chipnameTextCtrl is wide enough to hold any unusually long chip names:
jean-pierre charras's avatar
jean-pierre charras committed
49
    EnsureTextCtrlWidth( dlg->chipnameTextCtrl );
dickelbeck's avatar
dickelbeck committed
50

jean-pierre charras's avatar
jean-pierre charras committed
51
    dlg->ShowModal();
52

53 54 55
    // Some of the field values are long and are not always fully visible because the
    // window comes up too narrow.  Remember user's manual window resizing efforts here
    // so it comes up wide enough next time.
jean-pierre charras's avatar
jean-pierre charras committed
56
    DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::s_LastSize = dlg->GetSize();
57

58
    m_canvas->MoveCursorToCrossHair();
59
    m_canvas->SetIgnoreMouseEvents( false );
jean-pierre charras's avatar
jean-pierre charras committed
60
    dlg->Destroy();
61
}
62

63

64 65
DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::DIALOG_EDIT_COMPONENT_IN_SCHEMATIC( wxWindow* parent ) :
    DIALOG_EDIT_COMPONENT_IN_SCHEMATIC_FBP( parent )
66
{
67
    m_Parent = (SCH_EDIT_FRAME*) parent;
68

69
    m_LibEntry = NULL;
70
    m_skipCopyFromPanel = false;
dickelbeck's avatar
dickelbeck committed
71

72
    wxListItem columnLabel;
73

74
    columnLabel.SetImage( -1 );
75

76
    columnLabel.SetText( _( "Name" ) );
dickelbeck's avatar
dickelbeck committed
77
    fieldListCtrl->InsertColumn( 0, columnLabel );
78

79
    columnLabel.SetText( _( "Value" ) );
dickelbeck's avatar
dickelbeck committed
80
    fieldListCtrl->InsertColumn( 1, columnLabel );
81

82
    wxString label = _( "Size" ) + ReturnUnitSymbol( g_UserUnit );
83 84
    textSizeLabel->SetLabel( label );

85
    label  = _( "Pos " );
86
    label += _( "X" );
87
    label += ReturnUnitSymbol( g_UserUnit );
88 89
    posXLabel->SetLabel( label );

90
    label  = _( "Pos " );
91
    label += _( "Y" );
92
    label += ReturnUnitSymbol( g_UserUnit );
93
    posYLabel->SetLabel( label );
dickelbeck's avatar
dickelbeck committed
94 95

    copySelectedFieldToPanel();
96 97

    wxToolTip::Enable( true );
98

99 100
    GetSizer()->SetSizeHints( this );
    Center();
101 102

    stdDialogButtonSizerOK->SetDefault();
103 104 105
}


dickelbeck's avatar
dickelbeck committed
106
void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnListItemDeselected( wxListEvent& event )
107
{
108
    D( printf( "OnListItemDeselected()\n" ); )
109

110 111 112 113 114
    if( !m_skipCopyFromPanel )
    {
        if( !copyPanelToSelectedField() )
            event.Skip();   // do not go to the next row
    }
115
}
dickelbeck's avatar
dickelbeck committed
116 117 118 119


void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnListItemSelected( wxListEvent& event )
{
120
    D( printf( "OnListItemSelected()\n" ); )
dickelbeck's avatar
dickelbeck committed
121

122 123
    // remember the selected row, statically
    s_SelectedRow = event.GetIndex();
dickelbeck's avatar
dickelbeck committed
124 125 126 127

    copySelectedFieldToPanel();
}

128

129
void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnCancelButtonClick( wxCommandEvent& event )
130
{
131
    EndModal( 1 );
132 133 134
}


135
void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyPanelToOptions()
136
{
137 138
    wxString newname = chipnameTextCtrl->GetValue();

139
#ifndef KICAD_KEEPCASE
140
    newname.MakeUpper();
141
#endif
142
    newname.Replace( wxT( " " ), wxT( "_" ) );
143

144
    if( newname.IsEmpty() )
jean-pierre charras's avatar
jean-pierre charras committed
145
        DisplayError( NULL, _( "No Component Name!" ) );
146

147 148
    else if( newname.CmpNoCase( m_Cmp->m_ChipName ) )
    {
149
        if( CMP_LIBRARY::FindLibraryEntry( newname ) == NULL )
150 151
        {
            wxString message;
jean-pierre charras's avatar
jean-pierre charras committed
152 153
            message.Printf( _( "Component [%s] not found!" ), GetChars( newname ) );
            DisplayError( NULL, message );
154
        }
155
        else    // Change component from lib!
156 157 158 159
        {
            m_Cmp->m_ChipName = newname;
        }
    }
160

161
    // For components with multiple shapes (De Morgan representation) Set the selected shape:
162 163
    if( convertCheckBox->IsEnabled() )
    {
164
        m_Cmp->SetConvert( convertCheckBox->GetValue() ? 2 : 1 );
165
    }
166

167
    //Set the part selection in multiple part per package
168
    if( m_Cmp->GetUnit() )
169 170
    {
        int unit_selection = unitChoice->GetCurrentSelection() + 1;
171
        m_Cmp->SetUnitSelection( &m_Parent->GetCurrentSheet(), unit_selection );
172
        m_Cmp->SetUnit( unit_selection );
173
    }
174

175 176 177
    switch( orientationRadioBox->GetSelection() )
    {
    case 0:
178
        m_Cmp->SetOrientation( CMP_ORIENT_0 );
179
        break;
180

181
    case 1:
182
        m_Cmp->SetOrientation( CMP_ORIENT_90 );
183
        break;
184

185
    case 2:
186
        m_Cmp->SetOrientation( CMP_ORIENT_180 );
187
        break;
188

189
    case 3:
190
        m_Cmp->SetOrientation( CMP_ORIENT_270 );
191 192
        break;
    }
193

194
    int mirror = mirrorRadioBox->GetSelection();
195

196 197 198 199
    switch( mirror )
    {
    case 0:
        break;
200

201
    case 1:
202
        m_Cmp->SetOrientation( CMP_MIRROR_X );
203
        break;
204

205
    case 2:
206
        m_Cmp->SetOrientation( CMP_MIRROR_Y );
207 208 209
        break;
    }
}
210 211


212 213
void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnOKButtonClick( wxCommandEvent& event )
{
214 215
    bool removeRemainingFields = false;

216 217
    if( !copyPanelToSelectedField() )
        return;
218

219
    if( ! SCH_COMPONENT::IsReferenceStringValid( m_FieldsBuf[REFERENCE].GetText() ) )
220
    {
221
        DisplayError( NULL, _( "Illegal reference. A reference must start with a letter" ) );
222 223 224
        return;
    }

225
    // save old cmp in undo list if not already in edit, or moving ...
226 227 228
    // or the component to be edited is part of a block
    if( m_Cmp->m_Flags == 0 ||
        m_Parent->GetScreen()->m_BlockLocate.GetState() != STATE_NO_BLOCK )
229
        m_Parent->SaveCopyInUndoList( m_Cmp, UR_CHANGED );
230

231 232
    copyPanelToOptions();

233
    // change all field positions from relative to absolute
234
    for( unsigned i = 0;  i<m_FieldsBuf.size();  ++i )
235
    {
236
        m_FieldsBuf[i].SetTextPosition( m_FieldsBuf[i].GetTextPosition() + m_Cmp->m_Pos );
237 238
    }

239
    // Delete any fields with no name before we copy all of m_FieldsBuf back into the component.
240
    for( unsigned i = MANDATORY_FIELDS;  i<m_FieldsBuf.size(); )
241
    {
242
        if( m_FieldsBuf[i].GetName( false ).IsEmpty() || m_FieldsBuf[i].GetText().IsEmpty() )
243
        {
244 245 246 247
            // If a field has no value and is not it the field template list, warn the user
            // that it will be remove from the component.  This gives the user a chance to
            // correct the problem before removing the undefined fields.  It should also
            // resolve most of the bug reports and questions regarding missing fields.
248 249
            if( !m_FieldsBuf[i].GetName( false ).IsEmpty() && m_FieldsBuf[i].GetText().IsEmpty()
                && !m_Parent->GetTemplates().HasFieldName( m_FieldsBuf[i].GetName( false ) )
250 251 252 253 254 255 256
                && !removeRemainingFields )
            {
                wxString msg;

                msg.Printf( _( "The field name <%s> does not have a value and is not defined in \
the field template list.  Empty field values are invalid an will be removed from the component.  \
Do you wish to remove this and all remaining undefined fields?" ),
257
                            GetChars( m_FieldsBuf[i].GetName( false ) ) );
258 259 260 261 262 263 264 265 266

                wxMessageDialog dlg( this, msg, _( "Remove Fields" ), wxYES_NO | wxNO_DEFAULT );

                if( dlg.ShowModal() == wxID_NO )
                    return;

                removeRemainingFields = true;
            }

267 268 269 270 271 272 273
            m_FieldsBuf.erase( m_FieldsBuf.begin() + i );
            continue;
        }

        ++i;
    }

274
    LIB_COMPONENT* entry = CMP_LIBRARY::FindLibraryComponent( m_Cmp->m_ChipName );
275

276
    if( entry &&  entry->IsPower() )
277
        m_FieldsBuf[VALUE].SetText( m_Cmp->m_ChipName );
278 279 280

    // copy all the fields back, and change the length of m_Fields.
    m_Cmp->SetFields( m_FieldsBuf );
281

282 283
    // Reference has a specific initialization, depending on the current active sheet
    // because for a given component, in a complex hierarchy, there are more than one
284
    // reference.
285
    m_Cmp->SetRef( &m_Parent->GetCurrentSheet(), m_FieldsBuf[REFERENCE].GetText() );
286

287
    m_Parent->OnModify();
288
    m_Parent->GetScreen()->TestDanglingEnds();
289
    m_Parent->GetCanvas()->Refresh( true );
290 291 292 293 294

    EndModal( 0 );
}


295 296
void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::addFieldButtonHandler( wxCommandEvent& event )
{
297 298
    // in case m_FieldsBuf[REFERENCE].m_Orient has changed on screen only, grab
    // screen contents.
299 300 301
    if( !copyPanelToSelectedField() )
        return;

302
    unsigned  fieldNdx = m_FieldsBuf.size();
303

304
    SCH_FIELD blank( wxPoint(), fieldNdx, m_Cmp );
305

306
    blank.SetOrientation( m_FieldsBuf[REFERENCE].GetOrientation() );
307 308

    m_FieldsBuf.push_back( blank );
309
    m_FieldsBuf[fieldNdx].SetName( TEMPLATE_FIELDNAME::GetDefaultFieldName( fieldNdx ) );
310

311
    m_skipCopyFromPanel = true;
312 313 314 315 316 317 318 319 320 321 322 323 324 325
    setRowItem( fieldNdx, m_FieldsBuf[fieldNdx] );

    setSelectedFieldNdx( fieldNdx );
    m_skipCopyFromPanel = false;
}


void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::deleteFieldButtonHandler( wxCommandEvent& event )
{
    unsigned fieldNdx = getSelectedFieldNdx();

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

326
    if( fieldNdx < MANDATORY_FIELDS )
327 328 329 330 331
    {
        wxBell();
        return;
    }

332
    m_skipCopyFromPanel = true;
333 334 335 336 337 338
    m_FieldsBuf.erase( m_FieldsBuf.begin() + fieldNdx );
    fieldListCtrl->DeleteItem( fieldNdx );

    if( fieldNdx >= m_FieldsBuf.size() )
        --fieldNdx;

339
    updateDisplay();
340

341 342 343 344 345
    setSelectedFieldNdx( fieldNdx );
    m_skipCopyFromPanel = false;
}


346
void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::moveUpButtonHandler( wxCommandEvent& event )
347 348 349 350 351 352
{
    unsigned fieldNdx = getSelectedFieldNdx();

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

353
    if( fieldNdx <= MANDATORY_FIELDS )
354 355 356 357 358 359 360 361 362 363
    {
        wxBell();
        return;
    }

    if( !copyPanelToSelectedField() )
        return;

    // swap the fieldNdx field with the one before it, in both the vector
    // and in the fieldListCtrl
364
    SCH_FIELD tmp = m_FieldsBuf[fieldNdx - 1];
365

366
    D( printf( "tmp.m_Text=\"%s\" tmp.m_Name=\"%s\"\n",
367
               TO_UTF8( tmp.GetText() ), TO_UTF8( tmp.GetName( false ) ) ); )
368

369 370
    m_FieldsBuf[fieldNdx - 1] = m_FieldsBuf[fieldNdx];
    setRowItem( fieldNdx - 1, m_FieldsBuf[fieldNdx] );
371 372 373 374

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

375
    updateDisplay();
376

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


383 384
void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::setSelectedFieldNdx( int aFieldNdx )
{
385 386 387 388
    /* 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);
389
     */
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406

    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_COMPONENT_IN_SCHEMATIC::getSelectedFieldNdx()
{
    return s_SelectedRow;
407 408 409
}


410
SCH_FIELD* DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::findField( const wxString& aFieldName )
411
{
412 413
    for( unsigned i=0;  i<m_FieldsBuf.size();  ++i )
    {
414
        if( aFieldName == m_FieldsBuf[i].GetName( false ) )
415 416
            return &m_FieldsBuf[i];
    }
417

418
    return NULL;
419 420
}

421

422
void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::InitBuffers( SCH_COMPONENT* aComponent )
423
{
424 425
    m_Cmp = aComponent;

426 427 428 429 430 431 432 433 434 435 436 437
    /*  We have 3 component related field lists to be aware of: 1) UI
        presentation, 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.
    */

438
    m_LibEntry = CMP_LIBRARY::FindLibraryComponent( m_Cmp->m_ChipName );
439 440

#if 0 && defined(DEBUG)
441
    for( int i = 0;  i<aComponent->GetFieldCount();  ++i )
442
    {
443 444
        printf( "Orig[%d] (x=%d, y=%d)\n", i, aComponent->m_Fields[i].m_Pos.x,
                aComponent->m_Fields[i].m_Pos.y );
445
    }
446

447 448
#endif

449 450 451 452 453 454
    // When this code was written, all field constructors ensure that the fixed fields
    // are all present within a component.  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.

    m_FieldsBuf.clear();
455

456 457 458 459 460
    for( int i=0;  i<MANDATORY_FIELDS;  ++i )
    {
        m_FieldsBuf.push_back(  aComponent->m_Fields[i] );

        // make the editable field position relative to the component
461
        m_FieldsBuf[i].SetTextPosition( m_FieldsBuf[i].GetTextPosition() - m_Cmp->m_Pos );
462 463 464 465 466 467
    }

    // 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 = m_Parent->GetTemplateFieldNames();
468

469 470 471
    for( TEMPLATE_FIELDNAMES::const_iterator it = tfnames.begin();  it!=tfnames.end();  ++it )
    {
        // add a new field unconditionally to the UI only
472
        SCH_FIELD   fld( wxPoint(0,0), -1 /* id is a relic */, m_Cmp, it->m_Name );
473 474 475 476 477 478 479 480 481 482

        // See if field by same name already exists in component.
        SCH_FIELD* schField = aComponent->FindField( 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( !schField )
        {
            if( !it->m_Visible )
483
                fld.SetVisible( false );
484
            else
485
                fld.SetVisible( true );
486

487
            fld.SetText( it->m_Value );   // empty? ok too.
488 489 490 491 492 493
        }
        else
        {
            fld = *schField;

            // make the editable field position relative to the component
494
            fld.SetTextPosition( fld.GetTextPosition() - m_Cmp->m_Pos );
495 496 497 498 499 500 501 502 503 504
        }

        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<aComponent->m_Fields.size();  ++i )
    {
        SCH_FIELD*  cmp = &aComponent->m_Fields[i];
505
        SCH_FIELD*  buf = findField( cmp->GetName( false ) );
506 507 508 509 510 511 512

        if( !buf )
        {
            int newNdx = m_FieldsBuf.size();
            m_FieldsBuf.push_back( *cmp );

            // make the editable field position relative to the component
513 514
            m_FieldsBuf[newNdx].SetTextPosition( m_FieldsBuf[newNdx].GetTextPosition() -
                                                 m_Cmp->m_Pos );
515 516
        }
    }
517

518

519
#if 0 && defined(DEBUG)
520
    for( unsigned i = 0;  i<m_FieldsBuf.size();  ++i )
521
    {
522
        printf( "m_FieldsBuf[%d] (x=%-3d, y=%-3d) name:%s\n", i, m_FieldsBuf[i].m_Pos.x,
523
                m_FieldsBuf[i].m_Pos.y, TO_UTF8(m_FieldsBuf[i].GetName( false ) ) );
524 525 526
    }
#endif

527
    m_FieldsBuf[REFERENCE].SetText( m_Cmp->GetRef( &m_Parent->GetCurrentSheet() ) );
528

529
    for( unsigned i = 0;  i<m_FieldsBuf.size();  ++i )
530
    {
531
        setRowItem( i, m_FieldsBuf[i] );
532
    }
dickelbeck's avatar
dickelbeck committed
533

534
#if 0 && defined(DEBUG)
535
    for( unsigned i = 0;  i<m_FieldsBuf.size();  ++i )
536
    {
537 538
        printf( "after[%d] (x=%d, y=%d)\n", i, m_FieldsBuf[i].m_Pos.x,
                m_FieldsBuf[i].m_Pos.y );
539
    }
540

541 542 543 544
#endif

    copyOptionsToPanel();

545 546 547 548 549 550 551 552 553
    // disable some options inside the edit dialog
    // which can cause problems while dragging
    if( m_Cmp->IsDragging() )
    {
        orientationRadioBox->Disable();
        mirrorRadioBox->Disable();
        chipnameTextCtrl->Disable();
    }

554 555 556 557 558
    // put focus on the list ctrl
    fieldListCtrl->SetFocus();

    // resume editing at the last row edited, last time dialog was up.
    setSelectedFieldNdx( s_SelectedRow );
dickelbeck's avatar
dickelbeck committed
559 560 561
}


562
void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::setRowItem( int aFieldNdx, const SCH_FIELD& aField )
dickelbeck's avatar
dickelbeck committed
563 564 565
{
    wxASSERT( aFieldNdx >= 0 );

566
    // insert blanks if aFieldNdx is referencing a "yet to be defined" row
dickelbeck's avatar
dickelbeck committed
567 568
    while( aFieldNdx >= fieldListCtrl->GetItemCount() )
    {
569
        long ndx = fieldListCtrl->InsertItem( fieldListCtrl->GetItemCount(), wxEmptyString );
dickelbeck's avatar
dickelbeck committed
570 571 572 573 574 575

        wxASSERT( ndx >= 0 );

        fieldListCtrl->SetItem( ndx, 1, wxEmptyString );
    }

576 577
    fieldListCtrl->SetItem( aFieldNdx, 0, aField.GetName( false ) );
    fieldListCtrl->SetItem( aFieldNdx, 1, aField.GetText() );
dickelbeck's avatar
dickelbeck committed
578 579 580 581

    // recompute the column widths here, after setting texts
    fieldListCtrl->SetColumnWidth( 0, wxLIST_AUTOSIZE );
    fieldListCtrl->SetColumnWidth( 1, wxLIST_AUTOSIZE );
582 583 584
}


dickelbeck's avatar
dickelbeck committed
585
void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copySelectedFieldToPanel()
586
{
dickelbeck's avatar
dickelbeck committed
587
    unsigned fieldNdx = getSelectedFieldNdx();
588

dickelbeck's avatar
dickelbeck committed
589
    if( fieldNdx >= m_FieldsBuf.size() )    // traps the -1 case too
590 591
        return;

592
    SCH_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
    m_StyleRadioBox->SetSelection( style );
607

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 623
        m_FieldVJustifyCtrl->SetSelection(2);
    else
        m_FieldVJustifyCtrl->SetSelection(1);


624
    fieldNameTextCtrl->SetValue( field.GetName( false ) );
dickelbeck's avatar
dickelbeck committed
625

626 627 628 629 630 631 632 633 634 635
    // the names of the fixed fields are not editable, others are.
    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 );

    // may only delete user defined fields
    deleteFieldButton->Enable( fieldNdx >= MANDATORY_FIELDS );
dickelbeck's avatar
dickelbeck committed
636

637
    fieldValueTextCtrl->SetValue( field.GetText() );
dickelbeck's avatar
dickelbeck committed
638

639 640
    // For power symbols, the value is NOR editable, because value and pin
    // name must be same and can be edited only in library editor
641
    if( fieldNdx == VALUE && m_LibEntry && m_LibEntry->IsPower() )
642 643 644
        fieldValueTextCtrl->Enable( false );
    else
        fieldValueTextCtrl->Enable( true );
645

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

648
    wxPoint coord = field.GetTextPosition();
649 650
    wxPoint zero  = -m_Cmp->m_Pos;  // relative zero

651 652 653
    // 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
654
    // close to the desired position.
655
    if( coord == zero && field.GetText().IsEmpty() )
656
    {
657
        rotateCheckBox->SetValue( m_FieldsBuf[REFERENCE].GetOrientation() == TEXT_ORIENT_VERT );
dickelbeck's avatar
dickelbeck committed
658

659
        coord.x = m_FieldsBuf[REFERENCE].GetTextPosition().x
660 661
            + ( fieldNdx - MANDATORY_FIELDS + 1 ) * 100;

662
        coord.y = m_FieldsBuf[REFERENCE].GetTextPosition().y
663
            + ( fieldNdx - MANDATORY_FIELDS + 1 ) * 100;
dickelbeck's avatar
dickelbeck committed
664

665
        // coord can compute negative if field is < MANDATORY_FIELDS, e.g. FOOTPRINT.
666 667
        // That is ok, we basically don't want all the new empty fields on
        // top of each other.
668 669
    }

670
    wxString coordText = ReturnStringFromValue( g_UserUnit, coord.x );
671
    posXTextCtrl->SetValue( coordText );
672

673
    coordText = ReturnStringFromValue( g_UserUnit, coord.y );
674
    posYTextCtrl->SetValue( coordText );
675
}
676 677


678
bool DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyPanelToSelectedField()
dickelbeck's avatar
dickelbeck committed
679 680
{
    unsigned fieldNdx = getSelectedFieldNdx();
681

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

685
    SCH_FIELD& field = m_FieldsBuf[fieldNdx];
dickelbeck's avatar
dickelbeck committed
686

687
    field.SetVisible( showCheckBox->GetValue() );
688 689

    if( rotateCheckBox->GetValue() )
690
        field.SetOrientation( TEXT_ORIENT_VERT );
691
    else
692
        field.SetOrientation( TEXT_ORIENT_HORIZ );
693

694
    rotateCheckBox->SetValue( field.GetOrientation() == TEXT_ORIENT_VERT );
695

696
    // Copy the text justification
697
    EDA_TEXT_HJUSTIFY_T hjustify[3] = {
698 699 700 701
        GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_HJUSTIFY_CENTER,
        GR_TEXT_HJUSTIFY_RIGHT
    };

702
    EDA_TEXT_VJUSTIFY_T vjustify[3] = {
703 704 705 706
        GR_TEXT_VJUSTIFY_BOTTOM, GR_TEXT_VJUSTIFY_CENTER,
        GR_TEXT_VJUSTIFY_TOP
    };

707 708
    field.SetHorizJustify( hjustify[m_FieldHJustifyCtrl->GetSelection()] );
    field.SetVertJustify( vjustify[m_FieldVJustifyCtrl->GetSelection()] );
709

710
    field.SetName( fieldNameTextCtrl->GetValue() );
711

712
    /* Void fields texts for REFERENCE and VALUE (value is the name of the
713
     * component in lib ! ) are not allowed
714
     * change them only for a new non void value
715
     * When void, usually netlists are broken
716 717
     */
    if( !fieldValueTextCtrl->GetValue().IsEmpty() || fieldNdx > VALUE )
718
        field.SetText( fieldValueTextCtrl->GetValue() );
dickelbeck's avatar
dickelbeck committed
719

720
    setRowItem( fieldNdx, field );  // update fieldListCtrl
dickelbeck's avatar
dickelbeck committed
721

722 723
    int tmp = EDA_GRAPHIC_TEXT_CTRL::ParseSize( textSizeTextCtrl->GetValue(), g_UserUnit );
    field.SetSize( wxSize( tmp, tmp ) );
724
    int style = m_StyleRadioBox->GetSelection();
725

726 727
    field.SetItalic( (style & 1 ) != 0 );
    field.SetBold( (style & 2 ) != 0 );
728

729 730 731 732
    wxPoint pos;
    pos.x = ReturnValueFromString( g_UserUnit, posXTextCtrl->GetValue() );
    pos.y = ReturnValueFromString( g_UserUnit, posYTextCtrl->GetValue() );
    field.SetPosition( pos );
733

734 735
    return true;
}
736

737

738
void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyOptionsToPanel()
739
{
740
    int choiceCount = unitChoice->GetCount();
741

742
    // Remove non existing choices (choiceCount must be <= number for parts)
743
    int unitcount = m_LibEntry ? m_LibEntry->GetPartCount() : 1;
744 745

    if( unitcount < 1 )
746
        unitcount = 1;
747

748
    if( unitcount < choiceCount )
749
    {
750
        while( unitcount < choiceCount )
751 752
        {
            choiceCount--;
753
            unitChoice->Delete( choiceCount );
754 755 756 757 758
        }
    }

    // For components with multiple parts per package, set the unit selection
    choiceCount = unitChoice->GetCount();
759

760 761
    if( m_Cmp->GetUnit() <= choiceCount )
        unitChoice->SetSelection( m_Cmp->GetUnit() - 1 );
762

763
    // Disable unit selection if only one unit exists:
764 765
    if( choiceCount <= 1 )
        unitChoice->Enable( false );
766

767 768
    int orientation = m_Cmp->GetOrientation()
        & ~( CMP_MIRROR_X | CMP_MIRROR_Y );
769

770 771 772 773 774 775
    if( orientation == CMP_ORIENT_90 )
        orientationRadioBox->SetSelection( 1 );
    else if( orientation == CMP_ORIENT_180 )
        orientationRadioBox->SetSelection( 2 );
    else if( orientation == CMP_ORIENT_270 )
        orientationRadioBox->SetSelection( 3 );
776 777
    else
        orientationRadioBox->SetSelection( 0 );
778

779
    int mirror = m_Cmp->GetOrientation() & ( CMP_MIRROR_X | CMP_MIRROR_Y );
780

781
    if( mirror == CMP_MIRROR_X )
782 783
    {
        mirrorRadioBox->SetSelection( 1 );
784
        D( printf( "mirror=X,1\n" ); )
785
    }
786
    else if( mirror == CMP_MIRROR_Y )
787 788
    {
        mirrorRadioBox->SetSelection( 2 );
789
        D( printf( "mirror=Y,2\n" ); )
790
    }
791 792
    else
        mirrorRadioBox->SetSelection( 0 );
793

794 795
    // Activate/Desactivate the normal/convert option ? (activated only if
    // the component has more than one shape)
796
    if( m_Cmp->GetConvert() > 1 )
797
    {
798
        convertCheckBox->SetValue( true );
799
    }
800

801
    if( m_LibEntry == NULL || !m_LibEntry->HasConversion() )
802
    {
803
        convertCheckBox->Enable( false );
804 805
    }

806
    // Show the "Parts Locked" option?
807
    if( !m_LibEntry || !m_LibEntry->UnitsLocked() )
808
    {
809
        D( printf( "partsAreLocked->false\n" ); )
810
        partsAreLockedLabel->Show( false );
811 812
    }

813
    // Set the component's library name.
814
    chipnameTextCtrl->SetValue( m_Cmp->m_ChipName );
815 816
}

817

818
#include <kicad_device_context.h>
819

820
/* reinitialize components parameters to default values found in lib
821
 */
822
void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::SetInitCmp( wxCommandEvent& event )
823
{
824
    LIB_COMPONENT* entry;
825

826 827
    if( m_Cmp == NULL )
        return;
828

829
    entry = CMP_LIBRARY::FindLibraryComponent( m_Cmp->m_ChipName );
830

831 832
    if( entry == NULL )
        return;
833

834 835 836 837
    // save old cmp in undo list if not already in edit, or moving ...
    if( m_Cmp->m_Flags == 0 )
        m_Parent->SaveCopyInUndoList( m_Cmp, UR_CHANGED );

838 839
    INSTALL_UNBUFFERED_DC( dc, m_Parent->GetCanvas() );
    m_Cmp->Draw( m_Parent->GetCanvas(), &dc, wxPoint( 0, 0 ), g_XorMode );
840

841 842 843 844 845 846
    // Initialize fixed field values to default values found in library
    // Note: the field texts are not modified because they are set in schematic,
    // the text from libraries is most of time a dummy text
    // Only VALUE and REFERENCE are re-initialized
    // Perhaps the FOOTPRINT field should also be considered,
    // but for most of components it is not set in library
847
    LIB_FIELD& refField = entry->GetReferenceField();
848
    m_Cmp->GetField( REFERENCE )->SetTextPosition( refField.GetTextPosition() + m_Cmp->m_Pos );
849
    m_Cmp->GetField( REFERENCE )->ImportValues( refField );
850

851
    LIB_FIELD& valField = entry->GetValueField();
852
    m_Cmp->GetField( VALUE )->SetTextPosition( valField.GetTextPosition() + m_Cmp->m_Pos );
853
    m_Cmp->GetField( VALUE )->ImportValues( valField );
854

855
    m_Cmp->SetOrientation( CMP_NORMAL );
856

857
    m_Parent->OnModify();
858

859
    m_Cmp->Draw( m_Parent->GetCanvas(), &dc, wxPoint( 0, 0 ), GR_DEFAULT_DRAWMODE );
860
    EndModal( 1 );
861
}