dialog_pad_properties.cpp 33.4 KB
Newer Older
1
/**
2 3
 * @file dialog_pad_properties.cpp
 * @brief Pad editing functions and dialog pad editor.
4
 */
5

6 7 8
/*
 * This program source code file is part of KiCad, a free EDA CAD application.
 *
9 10 11 12
 * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
 * Copyright (C) 2013 Dick Hollenbeck, dick@softplc.com
 * Copyright (C) 2008-2013 Wayne Stambaugh <stambaughw@verizon.net>
 * Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
 *
 * 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
 */

32 33 34 35 36 37 38 39 40 41
#include <fctsys.h>
#include <common.h>
#include <gr_basic.h>
#include <class_drawpanel.h>
#include <confirm.h>
#include <pcbnew.h>
#include <trigo.h>
#include <macros.h>
#include <wxBasePcbFrame.h>
#include <pcbcommon.h>
42
#include <base_units.h>
43

44
#include <wx/dcbuffer.h>
Dick Hollenbeck's avatar
Dick Hollenbeck committed
45
#include <protos.h>
46

47 48
#include <class_board.h>
#include <class_module.h>
49

50
#include <dialog_pad_properties_base.h>
51
#include <html_messagebox.h>
52 53


Dick Hollenbeck's avatar
Dick Hollenbeck committed
54 55
// list of pad shapes.
static PAD_SHAPE_T CodeShape[] = {
56 57 58 59
    PAD_CIRCLE, PAD_OVAL, PAD_RECT, PAD_TRAPEZOID
};


Dick Hollenbeck's avatar
Dick Hollenbeck committed
60
static PAD_ATTR_T CodeType[] = {
61 62 63
    PAD_STANDARD, PAD_SMD, PAD_CONN, PAD_HOLE_NOT_PLATED
};

Dick Hollenbeck's avatar
Dick Hollenbeck committed
64 65 66
#define NBTYPES     DIM(CodeType)


67
// Default mask layers setup for pads according to the pad type
68
static const LAYER_MSK Std_Pad_Layers[] = {
Dick Hollenbeck's avatar
Dick Hollenbeck committed
69

70
    // PAD_STANDARD:
charras's avatar
charras committed
71
    PAD_STANDARD_DEFAULT_LAYERS,
72 73

    // PAD_CONN:
charras's avatar
charras committed
74
    PAD_CONN_DEFAULT_LAYERS,
75 76

    // PAD_SMD:
charras's avatar
charras committed
77
    PAD_SMD_DEFAULT_LAYERS,
78 79

    //PAD_HOLE_NOT_PLATED:
charras's avatar
charras committed
80
    PAD_HOLE_NOT_PLATED_DEFAULT_LAYERS
81 82 83
};


84 85 86 87
/**
 * class DIALOG_PAD_PROPERTIES, derived from DIALOG_PAD_PROPERTIES_BASE,
 * created by wxFormBuilder
 */
88
 class DIALOG_PAD_PROPERTIES : public DIALOG_PAD_PROPERTIES_BASE
89 90
{
public:
Dick Hollenbeck's avatar
Dick Hollenbeck committed
91
    DIALOG_PAD_PROPERTIES( PCB_BASE_FRAME* aParent, D_PAD* aPad );
92 93 94 95 96
    ~DIALOG_PAD_PROPERTIES()
    {
        delete m_dummyPad;
    }

97
private:
98 99
    PCB_BASE_FRAME* m_parent;
    D_PAD*  m_currentPad;            // pad currently being edited
Dick Hollenbeck's avatar
Dick Hollenbeck committed
100
    D_PAD*  m_dummyPad;              // a working copy used to show changes
101 102
    BOARD*  m_board;
    D_PAD&  m_padMaster;
Dick Hollenbeck's avatar
Dick Hollenbeck committed
103 104 105 106
    bool    m_isFlipped;            // true if the parent footprint (therefore pads) is flipped (mirrored)
                                    // in this case, some Y coordinates values must be negated
    bool    m_canUpdate;

107
private:
108
    void initValues();
Dick Hollenbeck's avatar
Dick Hollenbeck committed
109

110
    bool padValuesOK();       ///< test if all values are acceptable for the pad
Dick Hollenbeck's avatar
Dick Hollenbeck committed
111 112

    /**
113
     * Function setPadLayersList
Dick Hollenbeck's avatar
Dick Hollenbeck committed
114 115 116
     * updates the CheckBox states in pad layers list,
     * @param layer_mask = pad layer mask (ORed layers bit mask)
     */
117
    void setPadLayersList( LAYER_MSK layer_mask );
118 119 120 121 122 123 124 125 126 127 128

    /// Copy values from dialog field to aPad's members
    bool transferDataToPad( D_PAD* aPad );

    // event handlers:

    void OnPadShapeSelection( wxCommandEvent& event );
    void OnDrillShapeSelected( wxCommandEvent& event );

    void PadOrientEvent( wxCommandEvent& event );
    void PadTypeSelected( wxCommandEvent& event );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
129

130
    void OnSetLayers( wxCommandEvent& event );
131 132
    void OnCancelButtonClick( wxCommandEvent& event );
    void OnPaintShowPanel( wxPaintEvent& event );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
133 134 135

    /// Called when a dimension has changed.
    /// Update the graphical pad shown in the panel.
136
    void OnValuesChanged( wxCommandEvent& event );
137 138

    /// Updates the different parameters for the component being edited.
Dick Hollenbeck's avatar
Dick Hollenbeck committed
139
    /// Fired from the OK button click.
140
    void PadPropertiesAccept( wxCommandEvent& event );
141 142 143
};


Dick Hollenbeck's avatar
Dick Hollenbeck committed
144
DIALOG_PAD_PROPERTIES::DIALOG_PAD_PROPERTIES( PCB_BASE_FRAME* aParent, D_PAD* aPad ) :
145
    DIALOG_PAD_PROPERTIES_BASE( aParent ),
146
    // use aParent's parent, which is the original BOARD, not the dummy module editor BOARD,
Dick Hollenbeck's avatar
Dick Hollenbeck committed
147
    // since FOOTPRINT_EDIT_FRAME::GetDesignSettings() is tricked out to use the PCB_EDIT_FRAME's
148
    // BOARD, not its own BOARD.
149
    m_padMaster( aParent->GetDesignSettings().m_Pad_Master )
Dick Hollenbeck's avatar
Dick Hollenbeck committed
150 151
{
    m_canUpdate  = false;
152 153 154
    m_parent     = aParent;
    m_currentPad = aPad;
    m_board      = m_parent->GetBoard();
Dick Hollenbeck's avatar
Dick Hollenbeck committed
155 156 157 158 159
    m_dummyPad   = new D_PAD( (MODULE*) NULL );

    if( aPad )
        m_dummyPad->Copy( aPad );
    else
160
        m_dummyPad->Copy( &m_padMaster );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
161 162 163 164 165

    initValues();

    m_sdbSizer1OK->SetDefault();
    GetSizer()->SetSizeHints( this );
166 167

    m_PadNumCtrl->SetFocus();
Dick Hollenbeck's avatar
Dick Hollenbeck committed
168 169 170 171
    m_canUpdate = true;
}


172 173 174 175 176
void DIALOG_PAD_PROPERTIES::OnPaintShowPanel( wxPaintEvent& event )
{
    wxPaintDC    dc( m_panelShowPad );
    PAD_DRAWINFO drawInfo;

177
    EDA_COLOR_T color = BLACK;
178

Dick Hollenbeck's avatar
Dick Hollenbeck committed
179
    if( m_dummyPad->GetLayerMask() & LAYER_FRONT )
180
    {
181
        color = m_board->GetVisibleElementColor( PAD_FR_VISIBLE );
182 183
    }

Dick Hollenbeck's avatar
Dick Hollenbeck committed
184
    if( m_dummyPad->GetLayerMask() & LAYER_BACK )
185
    {
186
        color = ColorMix( color, m_board->GetVisibleElementColor( PAD_BK_VISIBLE ) );
187 188
    }

189 190 191
    // What could happen: the pad color is *actually* black, or no
    // copper was selected
    if( color == BLACK )
192 193 194 195
        color = LIGHTGRAY;

    drawInfo.m_Color     = color;
    drawInfo.m_HoleColor = DARKGRAY;
Dick Hollenbeck's avatar
Dick Hollenbeck committed
196
    drawInfo.m_Offset    = m_dummyPad->GetPosition();
197 198
    drawInfo.m_Display_padnum  = true;
    drawInfo.m_Display_netname = true;
Dick Hollenbeck's avatar
Dick Hollenbeck committed
199

Dick Hollenbeck's avatar
Dick Hollenbeck committed
200
    if( m_dummyPad->GetAttribute() == PAD_HOLE_NOT_PLATED )
201
        drawInfo.m_ShowNotPlatedHole = true;
202 203

    // Shows the local pad clearance
Dick Hollenbeck's avatar
Dick Hollenbeck committed
204
    drawInfo.m_PadClearance = m_dummyPad->GetLocalClearance();
205 206 207 208 209

    wxSize dc_size = dc.GetSize();
    dc.SetDeviceOrigin( dc_size.x / 2, dc_size.y / 2 );

    // Calculate a suitable scale to fit the available draw area
210
    int dim = m_dummyPad->GetSize().x + std::abs( m_dummyPad->GetDelta().y);
Dick Hollenbeck's avatar
Dick Hollenbeck committed
211 212 213 214 215 216

    if( m_dummyPad->GetLocalClearance() > 0 )
        dim += m_dummyPad->GetLocalClearance() * 2;

    double scale = (double) dc_size.x / dim;

217
    dim = m_dummyPad->GetSize().y + std::abs( m_dummyPad->GetDelta().x);
Dick Hollenbeck's avatar
Dick Hollenbeck committed
218 219 220
    if( m_dummyPad->GetLocalClearance() > 0 )
        dim += m_dummyPad->GetLocalClearance() * 2;

221
    double altscale = (double) dc_size.y / dim;
222
    scale = std::min( scale, altscale );
223 224 225 226 227

    // Give a margin
    scale *= 0.7;
    dc.SetUserScale( scale, scale );

228
    GRResetPenAndBrush( &dc );
229 230
    m_dummyPad->DrawShape( NULL, &dc, drawInfo );

231 232 233
    // Draw X and Y axis.
    // this is particularly useful to show the reference position of pads
    // with offset and no hole
234 235
    GRLine( NULL, &dc, -dim, 0, dim, 0, 0, BLUE );   // X axis
    GRLine( NULL, &dc, 0, -dim, 0, dim, 0, BLUE );   // Y axis
236

237 238 239 240
    event.Skip();
}


Dick Hollenbeck's avatar
Dick Hollenbeck committed
241
void PCB_BASE_FRAME::InstallPadOptionsFrame( D_PAD* aPad )
242
{
Dick Hollenbeck's avatar
Dick Hollenbeck committed
243
    DIALOG_PAD_PROPERTIES dlg( this, aPad );
244

245
    dlg.ShowModal();
246 247 248
}


249
void DIALOG_PAD_PROPERTIES::initValues()
250
{
Dick Hollenbeck's avatar
Dick Hollenbeck committed
251 252
    wxString    msg;
    double      angle;
253

254 255
    // Setup layers names from board
    // Should be made first, before calling m_rbCopperLayersSel->SetSelection()
256 257 258 259 260 261 262 263 264 265 266 267 268 269
    m_rbCopperLayersSel->SetString( 0, m_board->GetLayerName( LAYER_N_FRONT ) );
    m_rbCopperLayersSel->SetString( 1, m_board->GetLayerName( LAYER_N_BACK ) );

    m_PadLayerAdhCmp->SetLabel( m_board->GetLayerName( ADHESIVE_N_FRONT ) );
    m_PadLayerAdhCu->SetLabel( m_board->GetLayerName( ADHESIVE_N_BACK ) );
    m_PadLayerPateCmp->SetLabel( m_board->GetLayerName( SOLDERPASTE_N_FRONT ) );
    m_PadLayerPateCu->SetLabel( m_board->GetLayerName( SOLDERPASTE_N_BACK ) );
    m_PadLayerSilkCmp->SetLabel( m_board->GetLayerName( SILKSCREEN_N_FRONT ) );
    m_PadLayerSilkCu->SetLabel( m_board->GetLayerName( SILKSCREEN_N_BACK ) );
    m_PadLayerMaskCmp->SetLabel( m_board->GetLayerName( SOLDERMASK_N_FRONT ) );
    m_PadLayerMaskCu->SetLabel( m_board->GetLayerName( SOLDERMASK_N_BACK ) );
    m_PadLayerECO1->SetLabel( m_board->GetLayerName( ECO1_N ) );
    m_PadLayerECO2->SetLabel( m_board->GetLayerName( ECO2_N ) );
    m_PadLayerDraft->SetLabel( m_board->GetLayerName( DRAW_N ) );
270

271
    m_isFlipped = false;
Dick Hollenbeck's avatar
Dick Hollenbeck committed
272

273
    if( m_currentPad )
274
    {
275
        MODULE* module = m_currentPad->GetParent();
Dick Hollenbeck's avatar
Dick Hollenbeck committed
276 277

        if( module->GetLayer() == LAYER_N_BACK )
278 279 280 281
        {
            m_isFlipped = true;
            m_staticModuleSideValue->SetLabel( _( "Back side (footprint is mirrored)" ) );
        }
Dick Hollenbeck's avatar
Dick Hollenbeck committed
282

283
        msg.Printf( wxT( "%.1f" ), module->GetOrientation() / 10.0 );
284 285
        m_staticModuleRotValue->SetLabel( msg );
    }
286

287 288
    if( m_isFlipped )
    {
Dick Hollenbeck's avatar
Dick Hollenbeck committed
289 290 291 292 293 294 295 296 297
        wxPoint pt = m_dummyPad->GetOffset();
        NEGATE( pt.y );
        m_dummyPad->SetOffset( pt );

        wxSize sz = m_dummyPad->GetDelta();
        NEGATE( sz.y );
        m_dummyPad->SetDelta( sz );

        // flip pad's layers
298
        m_dummyPad->SetLayerMask( FlipLayerMask( m_dummyPad->GetLayerMask() ) );
299
    }
Dick Hollenbeck's avatar
Dick Hollenbeck committed
300

301
    m_staticTextWarningPadFlipped->Show(m_isFlipped);
302

Dick Hollenbeck's avatar
Dick Hollenbeck committed
303
    m_PadNumCtrl->SetValue( m_dummyPad->GetPadName() );
304
    m_PadNetNameCtrl->SetValue( m_dummyPad->GetNetname() );
305

306
    // Display current unit name in dialog:
307 308 309 310 311 312 313 314 315 316
    m_PadPosX_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
    m_PadPosY_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
    m_PadDrill_X_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
    m_PadDrill_Y_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
    m_PadShapeSizeX_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
    m_PadShapeSizeY_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
    m_PadShapeOffsetX_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
    m_PadShapeOffsetY_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
    m_PadShapeDelta_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
    m_PadLengthDie_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
317

318
    // Display current pad masks clearances units
319 320 321 322 323
    m_NetClearanceUnits->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
    m_SolderMaskMarginUnits->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
    m_SolderPasteMarginUnits->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
    m_ThermalWidthUnits->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
    m_ThermalGapUnits->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
324 325

    // Display current pad parameters units:
326 327
    PutValueInLocalUnits( *m_PadPosition_X_Ctrl, m_dummyPad->GetPosition().x );
    PutValueInLocalUnits( *m_PadPosition_Y_Ctrl, m_dummyPad->GetPosition().y );
328

329 330
    PutValueInLocalUnits( *m_PadDrill_X_Ctrl, m_dummyPad->GetDrillSize().x );
    PutValueInLocalUnits( *m_PadDrill_Y_Ctrl, m_dummyPad->GetDrillSize().y );
331

332 333
    PutValueInLocalUnits( *m_ShapeSize_X_Ctrl, m_dummyPad->GetSize().x );
    PutValueInLocalUnits( *m_ShapeSize_Y_Ctrl, m_dummyPad->GetSize().y );
334

335 336
    PutValueInLocalUnits( *m_ShapeOffset_X_Ctrl, m_dummyPad->GetOffset().x );
    PutValueInLocalUnits( *m_ShapeOffset_Y_Ctrl, m_dummyPad->GetOffset().y );
337

Dick Hollenbeck's avatar
Dick Hollenbeck committed
338
    if( m_dummyPad->GetDelta().x )
339
    {
340
        PutValueInLocalUnits( *m_ShapeDelta_Ctrl, m_dummyPad->GetDelta().x );
341
        m_trapDeltaDirChoice->SetSelection( 0 );
342 343 344
    }
    else
    {
345
        PutValueInLocalUnits( *m_ShapeDelta_Ctrl, m_dummyPad->GetDelta().y );
346
        m_trapDeltaDirChoice->SetSelection( 1 );
347
    }
348

349
    PutValueInLocalUnits( *m_LengthPadToDieCtrl, m_dummyPad->GetPadToDieLength() );
350

351 352 353 354
    PutValueInLocalUnits( *m_NetClearanceValueCtrl, m_dummyPad->GetLocalClearance() );
    PutValueInLocalUnits( *m_SolderMaskMarginCtrl, m_dummyPad->GetLocalSolderMaskMargin() );
    PutValueInLocalUnits( *m_ThermalWidthCtrl, m_dummyPad->GetThermalWidth() );
    PutValueInLocalUnits( *m_ThermalGapCtrl, m_dummyPad->GetThermalGap() );
355

356
    // These 2 parameters are usually < 0, so prepare entering a negative value, if current is 0
357
    PutValueInLocalUnits( *m_SolderPasteMarginCtrl, m_dummyPad->GetLocalSolderPasteMargin() );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
358 359

    if( m_dummyPad->GetLocalSolderPasteMargin() == 0 )
360 361
        m_SolderPasteMarginCtrl->SetValue( wxT( "-" ) + m_SolderPasteMarginCtrl->GetValue() );

362
    msg.Printf( wxT( "%f" ), m_dummyPad->GetLocalSolderPasteMarginRatio() * 100.0 );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
363 364 365

    if( m_dummyPad->GetLocalSolderPasteMarginRatio() == 0.0 && msg[0] == '0' )
        // Sometimes Printf adds a sign if the value is small
366
        m_SolderPasteMarginRatioCtrl->SetValue( wxT( "-" ) + msg );
367
    else
368
        m_SolderPasteMarginRatioCtrl->SetValue( msg );
369

370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
    switch( m_dummyPad->GetZoneConnection() )
    {
    default:
    case UNDEFINED_CONNECTION:
        m_ZoneConnectionChoice->SetSelection( 0 );
        break;

    case PAD_IN_ZONE:
        m_ZoneConnectionChoice->SetSelection( 1 );
        break;

    case THERMAL_PAD:
        m_ZoneConnectionChoice->SetSelection( 2 );
        break;

    case PAD_NOT_IN_ZONE:
        m_ZoneConnectionChoice->SetSelection( 3 );
        break;
    }

390
    if( m_currentPad )
391
    {
392
        MODULE* module = m_currentPad->GetParent();
Dick Hollenbeck's avatar
Dick Hollenbeck committed
393

394
        angle = m_currentPad->GetOrientation() - module->GetOrientation();
Dick Hollenbeck's avatar
Dick Hollenbeck committed
395

396
        if( m_isFlipped )
Dick Hollenbeck's avatar
Dick Hollenbeck committed
397 398 399
            NEGATE( angle );

        m_dummyPad->SetOrientation( angle );
400
    }
401

Dick Hollenbeck's avatar
Dick Hollenbeck committed
402
    angle = m_dummyPad->GetOrientation();
403

Dick Hollenbeck's avatar
Dick Hollenbeck committed
404
    NORMALIZE_ANGLE_180( angle );    // ? normalizing is in D_PAD::SetOrientation()
405

Dick Hollenbeck's avatar
Dick Hollenbeck committed
406
    // Set layers used by this pad: :
407
    setPadLayersList( m_dummyPad->GetLayerMask() );
408 409

    // Pad Orient
Dick Hollenbeck's avatar
Dick Hollenbeck committed
410
    switch( int( angle ) )
411 412 413 414 415 416 417 418 419
    {
    case 0:
        m_PadOrient->SetSelection( 0 );
        break;

    case 900:
        m_PadOrient->SetSelection( 1 );
        break;

420
    case -900:
421 422 423 424
        m_PadOrient->SetSelection( 2 );
        break;

    case 1800:
425
    case -1800:
426 427 428 429 430 431 432 433
        m_PadOrient->SetSelection( 3 );
        break;

    default:
        m_PadOrient->SetSelection( 4 );
        break;
    }

Dick Hollenbeck's avatar
Dick Hollenbeck committed
434
    switch( m_dummyPad->GetShape() )
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453
    {
    default:
    case PAD_CIRCLE:
        m_PadShape->SetSelection( 0 );
        break;

    case PAD_OVAL:
        m_PadShape->SetSelection( 1 );
        break;

    case PAD_RECT:
        m_PadShape->SetSelection( 2 );
        break;

    case PAD_TRAPEZOID:
        m_PadShape->SetSelection( 3 );
        break;
    }

Dick Hollenbeck's avatar
Dick Hollenbeck committed
454
    msg.Printf( wxT( "%g" ), angle );
455
    m_PadOrientCtrl->SetValue( msg );
456

457
    // Type of pad selection
458
    m_PadType->SetSelection( 0 );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
459

460
    for( unsigned ii = 0; ii < NBTYPES; ii++ )
461
    {
Dick Hollenbeck's avatar
Dick Hollenbeck committed
462
        if( CodeType[ii] == m_dummyPad->GetAttribute() )
463
        {
464 465
            m_PadType->SetSelection( ii );
            break;
466 467 468
        }
    }

469 470
    // Enable/disable Pad name,and pad length die
    // (disable for NPTH pads (mechanical pads)
Dick Hollenbeck's avatar
Dick Hollenbeck committed
471 472
    bool enable = m_dummyPad->GetAttribute() != PAD_HOLE_NOT_PLATED;

473 474
    m_PadNumCtrl->Enable( enable );
    m_PadNetNameCtrl->Enable( enable );
475
    m_LengthPadToDieCtrl->Enable( enable );
476

Dick Hollenbeck's avatar
Dick Hollenbeck committed
477
    if( m_dummyPad->GetDrillShape() != PAD_OVAL )
478 479 480
        m_DrillShapeCtrl->SetSelection( 0 );
    else
        m_DrillShapeCtrl->SetSelection( 1 );
481

Dick Hollenbeck's avatar
Dick Hollenbeck committed
482
    // Update some dialog widgets state (Enable/disable options):
483
    wxCommandEvent cmd_event;
484
    setPadLayersList( m_dummyPad->GetLayerMask() );
485
    OnDrillShapeSelected( cmd_event );
486
    OnPadShapeSelection( cmd_event );
487 488 489
}


490
void DIALOG_PAD_PROPERTIES::OnPadShapeSelection( wxCommandEvent& event )
491 492 493
{
    switch( m_PadShape->GetSelection() )
    {
494
    case 0:     // CIRCLE:
495
        m_ShapeDelta_Ctrl->Enable( false );
496
        m_trapDeltaDirChoice->Enable( false );
497
        m_ShapeSize_Y_Ctrl->Enable( false );
498 499
        m_ShapeOffset_X_Ctrl->Enable( false );
        m_ShapeOffset_Y_Ctrl->Enable( false );
500 501
        break;

502
    case 1:     // OVAL:
503
        m_ShapeDelta_Ctrl->Enable( false );
504
        m_trapDeltaDirChoice->Enable( false );
505
        m_ShapeSize_Y_Ctrl->Enable( true );
506 507
        m_ShapeOffset_X_Ctrl->Enable( true );
        m_ShapeOffset_Y_Ctrl->Enable( true );
508 509 510
        break;

    case 2:     // PAD_RECT:
511
        m_ShapeDelta_Ctrl->Enable( false );
512
        m_trapDeltaDirChoice->Enable( false );
513
        m_ShapeSize_Y_Ctrl->Enable( true );
514 515
        m_ShapeOffset_X_Ctrl->Enable( true );
        m_ShapeOffset_Y_Ctrl->Enable( true );
516 517
        break;

518
    case 3:     // TRAPEZOID:
519
        m_ShapeDelta_Ctrl->Enable( true );
520
        m_trapDeltaDirChoice->Enable( true );
521
        m_ShapeSize_Y_Ctrl->Enable( true );
522 523
        m_ShapeOffset_X_Ctrl->Enable( true );
        m_ShapeOffset_Y_Ctrl->Enable( true );
524 525
        break;
    }
526

527
    transferDataToPad( m_dummyPad );
528
    m_panelShowPad->Refresh();
529 530 531
}


532
void DIALOG_PAD_PROPERTIES::OnDrillShapeSelected( wxCommandEvent& event )
533
{
Dick Hollenbeck's avatar
Dick Hollenbeck committed
534
    if( m_PadType->GetSelection() == 1 || m_PadType->GetSelection() == 2 )
535 536
    {
        // pad type = SMD or CONN: no hole allowed
537 538
        m_PadDrill_X_Ctrl->Enable( false );
        m_PadDrill_Y_Ctrl->Enable( false );
539
    }
540
    else
541
    {
542 543 544 545 546 547 548 549 550 551 552 553
        switch( m_DrillShapeCtrl->GetSelection() )
        {
        case 0:     //CIRCLE:
            m_PadDrill_X_Ctrl->Enable( true );
            m_PadDrill_Y_Ctrl->Enable( false );
            break;

        case 1:     //OVALE:
            m_PadDrill_X_Ctrl->Enable( true );
            m_PadDrill_Y_Ctrl->Enable( true );
            break;
        }
554
    }
555

556
    transferDataToPad( m_dummyPad );
557
    m_panelShowPad->Refresh();
558 559 560
}


561
void DIALOG_PAD_PROPERTIES::PadOrientEvent( wxCommandEvent& event )
562 563 564 565
{
    switch( m_PadOrient->GetSelection() )
    {
    case 0:
Dick Hollenbeck's avatar
Dick Hollenbeck committed
566
        m_dummyPad->SetOrientation( 0 );
567 568 569
        break;

    case 1:
Dick Hollenbeck's avatar
Dick Hollenbeck committed
570
        m_dummyPad->SetOrientation( 900 );
571 572 573
        break;

    case 2:
Dick Hollenbeck's avatar
Dick Hollenbeck committed
574
        m_dummyPad->SetOrientation( -900 );
575 576 577
        break;

    case 3:
Dick Hollenbeck's avatar
Dick Hollenbeck committed
578
        m_dummyPad->SetOrientation( 1800 );
579 580 581 582 583
        break;

    default:
        break;
    }
584 585

    wxString msg;
586
    msg.Printf( wxT( "%g" ), m_dummyPad->GetOrientation() );
587 588
    m_PadOrientCtrl->SetValue( msg );

589
    transferDataToPad( m_dummyPad );
590
    m_panelShowPad->Refresh();
591 592 593
}


594
void DIALOG_PAD_PROPERTIES::PadTypeSelected( wxCommandEvent& event )
595
{
596
    unsigned    ii = m_PadType->GetSelection();
597

598
    if( ii >= NBTYPES ) // catches < 0 also
599 600
        ii = 0;

601
    LAYER_MSK layer_mask = Std_Pad_Layers[ii];
602
    setPadLayersList( layer_mask );
603 604

    // Enable/disable drill dialog items:
605
    event.SetId( m_DrillShapeCtrl->GetSelection() );
606
    OnDrillShapeSelected( event );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
607

608 609 610 611
    if( ii == 0 || ii == NBTYPES-1 )
        m_DrillShapeCtrl->Enable( true );
    else
        m_DrillShapeCtrl->Enable( false );
612 613 614 615 616 617

    // Enable/disable Pad name,and pad length die
    // (disable for NPTH pads (mechanical pads)
    bool enable = ii != 3;
    m_PadNumCtrl->Enable( enable );
    m_PadNetNameCtrl->Enable( enable );
618
    m_LengthPadToDieCtrl->Enable( enable );
619 620 621
}


622
void DIALOG_PAD_PROPERTIES::setPadLayersList( LAYER_MSK layer_mask )
623
{
624
    if( ( layer_mask & ALL_CU_LAYERS ) == LAYER_FRONT )
625 626 627
        m_rbCopperLayersSel->SetSelection(0);
    else if( ( layer_mask & ALL_CU_LAYERS ) == LAYER_BACK)
        m_rbCopperLayersSel->SetSelection(1);
628
    else if( ( layer_mask & ALL_CU_LAYERS ) != 0 )
629 630 631
        m_rbCopperLayersSel->SetSelection(2);
    else
        m_rbCopperLayersSel->SetSelection(3);
632

Dick Hollenbeck's avatar
Dick Hollenbeck committed
633 634
    m_PadLayerAdhCmp->SetValue( bool( layer_mask & ADHESIVE_LAYER_FRONT ) );
    m_PadLayerAdhCu->SetValue( bool( layer_mask & ADHESIVE_LAYER_BACK ) );
635

Dick Hollenbeck's avatar
Dick Hollenbeck committed
636 637
    m_PadLayerPateCmp->SetValue( bool( layer_mask & SOLDERPASTE_LAYER_FRONT ) );
    m_PadLayerPateCu->SetValue( bool( layer_mask & SOLDERPASTE_LAYER_BACK ) );
638

Dick Hollenbeck's avatar
Dick Hollenbeck committed
639 640
    m_PadLayerSilkCmp->SetValue( bool( layer_mask & SILKSCREEN_LAYER_FRONT ) );
    m_PadLayerSilkCu->SetValue( bool( layer_mask & SILKSCREEN_LAYER_BACK ) );
641

Dick Hollenbeck's avatar
Dick Hollenbeck committed
642 643
    m_PadLayerMaskCmp->SetValue( bool( layer_mask & SOLDERMASK_LAYER_FRONT ) );
    m_PadLayerMaskCu->SetValue( bool( layer_mask & SOLDERMASK_LAYER_BACK ) );
644

Dick Hollenbeck's avatar
Dick Hollenbeck committed
645 646
    m_PadLayerECO1->SetValue( bool( layer_mask & ECO1_LAYER ) );
    m_PadLayerECO2->SetValue( bool( layer_mask & ECO2_LAYER ) );
647

Dick Hollenbeck's avatar
Dick Hollenbeck committed
648
    m_PadLayerDraft->SetValue( bool( layer_mask & DRAW_LAYER ) );
649 650 651
}


652
// Called when select/deselect a layer.
653
void DIALOG_PAD_PROPERTIES::OnSetLayers( wxCommandEvent& event )
654
{
655
    transferDataToPad( m_dummyPad );
656 657 658
    m_panelShowPad->Refresh();
}

Dick Hollenbeck's avatar
Dick Hollenbeck committed
659

660
// test if all values are acceptable for the pad
661
bool DIALOG_PAD_PROPERTIES::padValuesOK()
662
{
663
    bool error = transferDataToPad( m_dummyPad );
664 665 666 667 668 669 670 671 672 673 674

    wxArrayString error_msgs;
    wxString msg;

    // Test for incorrect values
    if( (m_dummyPad->GetSize().x < m_dummyPad->GetDrillSize().x) ||
        (m_dummyPad->GetSize().y < m_dummyPad->GetDrillSize().y) )
    {
        error_msgs.Add(  _( "Incorrect value for pad drill: pad drill bigger than pad size" ) );
    }

675
    LAYER_MSK padlayers_mask = m_dummyPad->GetLayerMask();
676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694
    if( ( padlayers_mask == 0 ) && ( m_dummyPad->GetAttribute() != PAD_HOLE_NOT_PLATED ) )
        error_msgs.Add( _( "Error: pad has no layer and is not a mechanical pad" ) );

    padlayers_mask &= (LAYER_BACK | LAYER_FRONT);
    if( padlayers_mask == 0 )
    {
        if( m_dummyPad->GetDrillSize().x || m_dummyPad->GetDrillSize().y )
        {
            msg = _( "Error: pad is not on a copper layer and has a hole" );
            if( m_dummyPad->GetAttribute() == PAD_HOLE_NOT_PLATED )
            {
                msg += wxT("\n");
                msg += _( "For NPTH pad, set pad drill value to pad size value,\n\
if you do not want this pad plotted in gerber files");
            }
            error_msgs.Add( msg );
        }
    }

695
    wxPoint max_size;
696 697
    max_size.x = std::abs( m_dummyPad->GetOffset().x );
    max_size.y = std::abs( m_dummyPad->GetOffset().y );
698 699
    max_size.x += m_dummyPad->GetDrillSize().x / 2;
    max_size.y += m_dummyPad->GetDrillSize().y / 2;
700 701
    if( ( m_dummyPad->GetSize().x / 2 < max_size.x ) ||
        ( m_dummyPad->GetSize().y / 2 < max_size.y ) )
702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735
    {
        error_msgs.Add( _( "Incorrect value for pad offset" ) );
    }

    if( error )
    {
        error_msgs.Add(  _( "Too large value for pad delta size" ) );
    }

    switch( m_dummyPad->GetAttribute() )
    {
        case PAD_STANDARD :     // Pad through hole, a hole is expected
            if( m_dummyPad->GetDrillSize().x <= 0 )
                error_msgs.Add( _( "Incorrect value for pad drill (too small value)" ) );
            break;

        case PAD_SMD:     // SMD and Connector pads (One external copper layer only)
        case PAD_CONN:
            if( (padlayers_mask & LAYER_BACK) && (padlayers_mask & LAYER_FRONT) )
                error_msgs.Add( _( "Error: only one copper layer allowed for this pad" ) );
            break;

        case PAD_HOLE_NOT_PLATED:     // Not plated
            break;
    }

    if( error_msgs.GetCount() )
    {
        HTML_MESSAGE_BOX dlg( this, _("Pad setup errors list" ) );
        dlg.ListSet( error_msgs );
        dlg.ShowModal();
    }
    return error_msgs.GetCount() == 0;
}
736

737

Dick Hollenbeck's avatar
Dick Hollenbeck committed
738
void DIALOG_PAD_PROPERTIES::PadPropertiesAccept( wxCommandEvent& event )
739
{
740
    if( !padValuesOK() )
741 742
        return;

743 744 745
    bool rastnestIsChanged = false;
    int  isign = m_isFlipped ? -1 : 1;

746
    transferDataToPad( &m_padMaster );
747

748
    if( m_currentPad )   // Set current Pad parameters
749
    {
Dick Hollenbeck's avatar
Dick Hollenbeck committed
750
        wxSize  size;
751
        MODULE* module = m_currentPad->GetParent();
Dick Hollenbeck's avatar
Dick Hollenbeck committed
752

753
        m_parent->SaveCopyInUndoList( module, UR_CHANGED );
754
        module->SetLastEditTime();
755 756

        // redraw the area where the pad was, without pad (delete pad on screen)
757 758 759
        m_currentPad->SetFlags( DO_NOT_DRAW );
        m_parent->GetCanvas()->RefreshDrawingRect( m_currentPad->GetBoundingBox() );
        m_currentPad->ClearFlags( DO_NOT_DRAW );
760 761

        // Update values
762 763
        m_currentPad->SetShape( m_padMaster.GetShape() );
        m_currentPad->SetAttribute( m_padMaster.GetAttribute() );
764

765
        if( m_currentPad->GetPosition() != m_padMaster.GetPosition() )
766
        {
767
            m_currentPad->SetPosition( m_padMaster.GetPosition() );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
768
            rastnestIsChanged = true;
769 770
        }

Dick Hollenbeck's avatar
Dick Hollenbeck committed
771 772
        // compute the pos 0 value, i.e. pad position for module with orientation = 0
        // i.e. relative to module origin (module position)
773
        wxPoint pt = m_currentPad->GetPosition() - module->GetPosition();
Dick Hollenbeck's avatar
Dick Hollenbeck committed
774 775 776

        RotatePoint( &pt, -module->GetOrientation() );

777
        m_currentPad->SetPos0( pt );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
778

779
        m_currentPad->SetOrientation( m_padMaster.GetOrientation() * isign + module->GetOrientation() );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
780

781
        m_currentPad->SetSize( m_padMaster.GetSize() );
782

783
        size = m_padMaster.GetDelta();
Dick Hollenbeck's avatar
Dick Hollenbeck committed
784
        size.y *= isign;
785
        m_currentPad->SetDelta( size );
786

787 788
        m_currentPad->SetDrillSize( m_padMaster.GetDrillSize() );
        m_currentPad->SetDrillShape( m_padMaster.GetDrillShape() );
789

790
        wxPoint offset = m_padMaster.GetOffset();
Dick Hollenbeck's avatar
Dick Hollenbeck committed
791
        offset.y *= isign;
792
        m_currentPad->SetOffset( offset );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
793

794
        m_currentPad->SetPadToDieLength( m_padMaster.GetPadToDieLength() );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
795

796
        if( m_currentPad->GetLayerMask() != m_padMaster.GetLayerMask() )
797 798
        {
            rastnestIsChanged = true;
799
            m_currentPad->SetLayerMask( m_padMaster.GetLayerMask() );
800
        }
Dick Hollenbeck's avatar
Dick Hollenbeck committed
801

802
        if( m_isFlipped )
803
            m_currentPad->SetLayerMask( FlipLayerMask( m_currentPad->GetLayerMask() ) );
804

805
        m_currentPad->SetPadName( m_padMaster.GetPadName() );
806

807
        if( m_currentPad->GetNetname() != m_padMaster.GetNetname() )
808
        {
809
            if( m_padMaster.GetNetname().IsEmpty() )
810 811
            {
                rastnestIsChanged = true;
812 813
                m_currentPad->SetNet( 0 );
                m_currentPad->SetNetname( wxEmptyString );
814 815 816
            }
            else
            {
817
                const NETINFO_ITEM* net = m_board->FindNet( m_padMaster.GetNetname() );
818 819 820
                if( net )
                {
                    rastnestIsChanged = true;
821 822
                    m_currentPad->SetNetname( m_padMaster.GetNetname() );
                    m_currentPad->SetNet( net->GetNet() );
823 824 825 826 827 828
                }
                else
                    DisplayError( NULL, _( "Unknown netname, netname not changed" ) );
            }
        }

829 830 831 832 833 834 835
        m_currentPad->SetLocalClearance( m_padMaster.GetLocalClearance() );
        m_currentPad->SetLocalSolderMaskMargin( m_padMaster.GetLocalSolderMaskMargin() );
        m_currentPad->SetLocalSolderPasteMargin( m_padMaster.GetLocalSolderPasteMargin() );
        m_currentPad->SetLocalSolderPasteMarginRatio( m_padMaster.GetLocalSolderPasteMarginRatio() );
        m_currentPad->SetZoneConnection( m_padMaster.GetZoneConnection() );
        m_currentPad->SetThermalWidth( m_padMaster.GetThermalWidth() );
        m_currentPad->SetThermalGap( m_padMaster.GetThermalGap() );
836

Dick Hollenbeck's avatar
Dick Hollenbeck committed
837
        module->CalculateBoundingBox();
838
        m_parent->SetMsgPanel( m_currentPad );
839 840

        // redraw the area where the pad was
841 842
        m_parent->GetCanvas()->RefreshDrawingRect( m_currentPad->GetBoundingBox() );
        m_parent->OnModify();
843 844 845 846 847
    }

    EndModal( wxID_OK );

    if( rastnestIsChanged )  // The net ratsnest must be recalculated
848
        m_board->m_Status_Pcb = 0;
849 850
}

Dick Hollenbeck's avatar
Dick Hollenbeck committed
851

852
bool DIALOG_PAD_PROPERTIES::transferDataToPad( D_PAD* aPad )
853
{
Dick Hollenbeck's avatar
Dick Hollenbeck committed
854 855
    wxString    msg;
    int         x, y;
856

Dick Hollenbeck's avatar
Dick Hollenbeck committed
857 858
    aPad->SetAttribute( CodeType[m_PadType->GetSelection()] );
    aPad->SetShape( CodeShape[m_PadShape->GetSelection()] );
859 860

    // Read pad clearances values:
861 862 863 864 865
    aPad->SetLocalClearance( ReturnValueFromTextCtrl( *m_NetClearanceValueCtrl ) );
    aPad->SetLocalSolderMaskMargin( ReturnValueFromTextCtrl( *m_SolderMaskMarginCtrl ) );
    aPad->SetLocalSolderPasteMargin( ReturnValueFromTextCtrl( *m_SolderPasteMarginCtrl ) );
    aPad->SetThermalWidth( ReturnValueFromTextCtrl( *m_ThermalWidthCtrl ) );
    aPad->SetThermalGap( ReturnValueFromTextCtrl( *m_ThermalGapCtrl ) );
866
    double dtmp = 0.0;
867 868
    msg = m_SolderPasteMarginRatioCtrl->GetValue();
    msg.ToDouble( &dtmp );
869

870 871 872 873 874 875 876
    // A -50% margin ratio means no paste on a pad, the ratio must be >= -50%
    if( dtmp < -50.0 )
        dtmp = -50.0;
    // A margin ratio is always <= 0
    // 0 means use full pad copper area
    if( dtmp > 0.0 )
        dtmp = 0.0;
Dick Hollenbeck's avatar
Dick Hollenbeck committed
877 878

    aPad->SetLocalSolderPasteMarginRatio( dtmp / 100 );
879

880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899
    switch( m_ZoneConnectionChoice->GetSelection() )
    {
    default:
    case 0:
        aPad->SetZoneConnection( UNDEFINED_CONNECTION );
        break;

    case 1:
        aPad->SetZoneConnection( PAD_IN_ZONE );
        break;

    case 2:
        aPad->SetZoneConnection( THERMAL_PAD );
        break;

    case 3:
        aPad->SetZoneConnection( PAD_NOT_IN_ZONE );
        break;
    }

900
    // Read pad position:
901 902
    x = ReturnValueFromTextCtrl( *m_PadPosition_X_Ctrl );
    y = ReturnValueFromTextCtrl( *m_PadPosition_Y_Ctrl );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
903 904 905

    aPad->SetPosition( wxPoint( x, y ) );
    aPad->SetPos0( wxPoint( x, y ) );
906 907

    // Read pad drill:
908 909
    x = ReturnValueFromTextCtrl( *m_PadDrill_X_Ctrl );
    y = ReturnValueFromTextCtrl( *m_PadDrill_Y_Ctrl );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
910

911 912
    if( m_DrillShapeCtrl->GetSelection() == 0 )
    {
Dick Hollenbeck's avatar
Dick Hollenbeck committed
913 914
        aPad->SetDrillShape( PAD_CIRCLE );
        y = x;
915 916
    }
    else
Dick Hollenbeck's avatar
Dick Hollenbeck committed
917 918 919
        aPad->SetDrillShape( PAD_OVAL );

    aPad->SetDrillSize( wxSize( x, y ) );
920 921

    // Read pad shape size:
922 923
    x = ReturnValueFromTextCtrl( *m_ShapeSize_X_Ctrl );
    y = ReturnValueFromTextCtrl( *m_ShapeSize_Y_Ctrl );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
924 925 926 927 928 929
    if( aPad->GetShape() == PAD_CIRCLE )
        y = x;

    aPad->SetSize( wxSize( x, y ) );

    // Read pad length die
930
    aPad->SetPadToDieLength( ReturnValueFromTextCtrl( *m_LengthPadToDieCtrl ) );
931 932

    // Read pad shape delta size:
933
    // m_DeltaSize.x or m_DeltaSize.y must be NULL. for a trapezoid.
934
    wxSize delta;
Dick Hollenbeck's avatar
Dick Hollenbeck committed
935

936
    if( m_trapDeltaDirChoice->GetSelection() == 0 )
937
        delta.x = ReturnValueFromTextCtrl( *m_ShapeDelta_Ctrl );
938
    else
939
        delta.y = ReturnValueFromTextCtrl( *m_ShapeDelta_Ctrl );
940

Dick Hollenbeck's avatar
Dick Hollenbeck committed
941
    // Test bad values (be sure delta values are not too large)
942
    // remember DeltaSize.x is the Y size variation
943
    bool   error    = false;
Dick Hollenbeck's avatar
Dick Hollenbeck committed
944 945

    if( delta.x < 0 && delta.x <= -aPad->GetSize().y )
946
    {
Dick Hollenbeck's avatar
Dick Hollenbeck committed
947
        delta.x = -aPad->GetSize().y + 2;
948 949
        error = true;
    }
Dick Hollenbeck's avatar
Dick Hollenbeck committed
950 951

    if( delta.x > 0 && delta.x >= aPad->GetSize().y )
952
    {
Dick Hollenbeck's avatar
Dick Hollenbeck committed
953
        delta.x = aPad->GetSize().y - 2;
954 955
        error = true;
    }
Dick Hollenbeck's avatar
Dick Hollenbeck committed
956 957

    if( delta.y < 0 && delta.y <= -aPad->GetSize().x )
958
    {
Dick Hollenbeck's avatar
Dick Hollenbeck committed
959
        delta.y = -aPad->GetSize().x + 2;
960 961
        error = true;
    }
Dick Hollenbeck's avatar
Dick Hollenbeck committed
962 963

    if( delta.y > 0 && delta.y >= aPad->GetSize().x )
964
    {
Dick Hollenbeck's avatar
Dick Hollenbeck committed
965
        delta.y = aPad->GetSize().x - 2;
966 967
        error = true;
    }
968

Dick Hollenbeck's avatar
Dick Hollenbeck committed
969 970
    aPad->SetDelta( delta );

971
    // Read pad shape offset:
972 973
    x = ReturnValueFromTextCtrl( *m_ShapeOffset_X_Ctrl );
    y = ReturnValueFromTextCtrl( *m_ShapeOffset_Y_Ctrl );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
974
    aPad->SetOffset( wxPoint( x, y ) );
975

976
    double orient_value = 0;
977
    msg = m_PadOrientCtrl->GetValue();
978 979 980
    msg.ToDouble( &orient_value );

    aPad->SetOrientation( orient_value );
981

982 983 984
    msg = m_PadNumCtrl->GetValue().Left( 4 );
    aPad->SetPadName( msg );
    aPad->SetNetname( m_PadNetNameCtrl->GetValue() );
985

charras's avatar
charras committed
986
    // Clear some values, according to the pad type and shape
Dick Hollenbeck's avatar
Dick Hollenbeck committed
987
    switch( aPad->GetShape() )
charras's avatar
charras committed
988 989
    {
    case PAD_CIRCLE:
Dick Hollenbeck's avatar
Dick Hollenbeck committed
990 991 992 993
        aPad->SetOffset( wxPoint( 0, 0 ) );
        aPad->SetDelta( wxSize( 0, 0 ) );
        x = aPad->GetSize().x;
        aPad->SetSize( wxSize( x, x ) );
charras's avatar
charras committed
994 995 996
        break;

    case PAD_RECT:
Dick Hollenbeck's avatar
Dick Hollenbeck committed
997
        aPad->SetDelta( wxSize( 0, 0 ) );
charras's avatar
charras committed
998 999 1000
        break;

    case PAD_OVAL:
Dick Hollenbeck's avatar
Dick Hollenbeck committed
1001
        aPad->SetDelta( wxSize( 0, 0 ) );
charras's avatar
charras committed
1002 1003 1004 1005
        break;

    case PAD_TRAPEZOID:
        break;
Dick Hollenbeck's avatar
Dick Hollenbeck committed
1006 1007 1008

    default:
        ;
charras's avatar
charras committed
1009 1010
    }

Dick Hollenbeck's avatar
Dick Hollenbeck committed
1011
    switch( aPad->GetAttribute() )
charras's avatar
charras committed
1012 1013 1014 1015 1016 1017
    {
    case PAD_STANDARD:
        break;

    case PAD_CONN:
    case PAD_SMD:
1018 1019
        // SMD and PAD_CONN has no hole.
        // basically, SMD and PAD_CONN are same type of pads
1020
        // PAD_CONN has just a default non technical layers that differs from SMD
1021 1022 1023
        // and are intended to be used in virtual edge board connectors
        // However we can accept a non null offset,
        // mainly to allow complex pads build from a set of from basic pad shapes
Dick Hollenbeck's avatar
Dick Hollenbeck committed
1024
        aPad->SetDrillSize( wxSize( 0, 0 ) );
charras's avatar
charras committed
1025 1026 1027
        break;

    case PAD_HOLE_NOT_PLATED:
1028 1029
        // Mechanical purpose only:
        // no offset, no net name, no pad name allowed
Dick Hollenbeck's avatar
Dick Hollenbeck committed
1030
        aPad->SetOffset( wxPoint( 0, 0 ) );
1031 1032
        aPad->SetPadName( wxEmptyString );
        aPad->SetNetname( wxEmptyString );
charras's avatar
charras committed
1033 1034 1035
        break;

    default:
1036
        DisplayError( NULL, wxT( "Error: unknown pad type" ) );
charras's avatar
charras committed
1037 1038 1039
        break;
    }

1040
    LAYER_MSK padLayerMask = NO_LAYERS;
Dick Hollenbeck's avatar
Dick Hollenbeck committed
1041

1042 1043
    switch( m_rbCopperLayersSel->GetSelection() )
    {
Dick Hollenbeck's avatar
Dick Hollenbeck committed
1044 1045 1046
    case 0:
        padLayerMask |= LAYER_FRONT;
        break;
1047

Dick Hollenbeck's avatar
Dick Hollenbeck committed
1048 1049 1050
    case 1:
        padLayerMask |= LAYER_BACK;
        break;
1051

Dick Hollenbeck's avatar
Dick Hollenbeck committed
1052 1053 1054
    case 2:
        padLayerMask |= ALL_CU_LAYERS;
        break;
1055

Dick Hollenbeck's avatar
Dick Hollenbeck committed
1056 1057
    case 3:     // No copper layers
        break;
1058 1059
    }

1060
    if( m_PadLayerAdhCmp->GetValue() )
Dick Hollenbeck's avatar
Dick Hollenbeck committed
1061
        padLayerMask |= ADHESIVE_LAYER_FRONT;
1062
    if( m_PadLayerAdhCu->GetValue() )
Dick Hollenbeck's avatar
Dick Hollenbeck committed
1063
        padLayerMask |= ADHESIVE_LAYER_BACK;
1064
    if( m_PadLayerPateCmp->GetValue() )
Dick Hollenbeck's avatar
Dick Hollenbeck committed
1065
        padLayerMask |= SOLDERPASTE_LAYER_FRONT;
1066
    if( m_PadLayerPateCu->GetValue() )
Dick Hollenbeck's avatar
Dick Hollenbeck committed
1067
        padLayerMask |= SOLDERPASTE_LAYER_BACK;
1068
    if( m_PadLayerSilkCmp->GetValue() )
Dick Hollenbeck's avatar
Dick Hollenbeck committed
1069
        padLayerMask |= SILKSCREEN_LAYER_FRONT;
1070
    if( m_PadLayerSilkCu->GetValue() )
Dick Hollenbeck's avatar
Dick Hollenbeck committed
1071
        padLayerMask |= SILKSCREEN_LAYER_BACK;
1072
    if( m_PadLayerMaskCmp->GetValue() )
Dick Hollenbeck's avatar
Dick Hollenbeck committed
1073
        padLayerMask |= SOLDERMASK_LAYER_FRONT;
1074
    if( m_PadLayerMaskCu->GetValue() )
Dick Hollenbeck's avatar
Dick Hollenbeck committed
1075
        padLayerMask |= SOLDERMASK_LAYER_BACK;
1076
    if( m_PadLayerECO1->GetValue() )
Dick Hollenbeck's avatar
Dick Hollenbeck committed
1077
        padLayerMask |= ECO1_LAYER;
1078
    if( m_PadLayerECO2->GetValue() )
Dick Hollenbeck's avatar
Dick Hollenbeck committed
1079
        padLayerMask |= ECO2_LAYER;
1080
    if( m_PadLayerDraft->GetValue() )
Dick Hollenbeck's avatar
Dick Hollenbeck committed
1081
        padLayerMask |= DRAW_LAYER;
1082

Dick Hollenbeck's avatar
Dick Hollenbeck committed
1083
    aPad->SetLayerMask( padLayerMask );
charras's avatar
charras committed
1084

1085
    return error;
1086
}
1087

1088

1089 1090 1091 1092
void DIALOG_PAD_PROPERTIES::OnValuesChanged( wxCommandEvent& event )
{
    if( m_canUpdate )
    {
1093
        transferDataToPad( m_dummyPad );
1094
        m_panelShowPad->Refresh();
1095 1096
    }
}
1097

1098

1099
void DIALOG_PAD_PROPERTIES::OnCancelButtonClick( wxCommandEvent& event )
1100
{
1101
    EndModal( wxID_CANCEL );
1102
}