dialog_layers_setup.cpp 20 KB
Newer Older
dickelbeck's avatar
dickelbeck committed
1
/*
2
 * This program source code file is part of KiCad, a free EDA CAD application.
dickelbeck's avatar
dickelbeck committed
3 4 5
 *
 * Copyright (C) 2009 Isaac Marino Bavaresco, isaacbavaresco@yahoo.com.br
 * Copyright (C) 2009 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6
 * Copyright (C) 2009 KiCad Developers, see change_log.txt for contributors.
dickelbeck's avatar
dickelbeck committed
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 * 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
 */


27 28 29
#include <fctsys.h>
#include <class_drawpanel.h>
#include <macros.h>
dickelbeck's avatar
dickelbeck committed
30

31 32 33
#include <confirm.h>
#include <pcbnew.h>
#include <wxPcbStruct.h>
dickelbeck's avatar
dickelbeck committed
34

35
#include <class_board.h>
36

37
#include <dialog_layers_setup_base.h>
dickelbeck's avatar
dickelbeck committed
38 39


40 41
// some define to choose how copper layers widgets are shown

42
// if defined, display only active copper layers
43
// if not displays always 1=the full set (16 layers)
44
#define HIDE_INACTIVE_LAYERS
45

46 47
// if defined, use the layer manager copper layers order (from FRONT to BACK)
// to display inner layers.
48
// if not, use the default order (from BACK to FRONT)
49
#define USE_LAYER_MANAGER_COPPER_LAYERS_ORDER
50

dickelbeck's avatar
dickelbeck committed
51

dickelbeck's avatar
dickelbeck committed
52 53 54 55 56 57
/**
 * Struct CTLs
 * holds the 3 ui control pointers for a single board layer.
 */
struct CTLs
{
58
    CTLs( wxControl* aName, wxCheckBox* aCheckBox, wxControl* aChoiceOrDesc, wxPanel * aPanel = NULL)
dickelbeck's avatar
dickelbeck committed
59 60 61 62
    {
        name     = aName;
        checkbox = aCheckBox;
        choice   = aChoiceOrDesc;
63
        panel    = aPanel;
dickelbeck's avatar
dickelbeck committed
64
    }
dickelbeck's avatar
dickelbeck committed
65

dickelbeck's avatar
dickelbeck committed
66 67 68
    wxControl*      name;
    wxCheckBox*     checkbox;
    wxControl*      choice;
69
    wxPanel *       panel;
dickelbeck's avatar
dickelbeck committed
70
};
dickelbeck's avatar
dickelbeck committed
71 72


dickelbeck's avatar
dickelbeck committed
73 74 75
class DIALOG_LAYERS_SETUP : public DIALOG_LAYERS_SETUP_BASE
{
private:
76
    PCB_EDIT_FRAME*     m_Parent;
dickelbeck's avatar
dickelbeck committed
77

dickelbeck's avatar
dickelbeck committed
78
    int                 m_CopperLayerCount;
79
    LAYER_MSK           m_EnabledLayers;
dickelbeck's avatar
dickelbeck committed
80

dickelbeck's avatar
dickelbeck committed
81
    BOARD*              m_Pcb;
dickelbeck's avatar
dickelbeck committed
82

dickelbeck's avatar
dickelbeck committed
83 84 85 86
    wxStaticText*       m_NameStaticText;
    wxStaticText*       m_EnabledStaticText;
    wxStaticText*       m_TypeStaticText;

dickelbeck's avatar
dickelbeck committed
87

88
    void setLayerCheckBox( LAYER_NUM layer, bool isChecked );
dickelbeck's avatar
dickelbeck committed
89
    void setCopperLayerCheckBoxes( int copperCount );
dickelbeck's avatar
dickelbeck committed
90

dickelbeck's avatar
dickelbeck committed
91 92
    void showCopperChoice( int copperCount );
    void showBoardLayerNames();
93
    void showSelectedLayerCheckBoxes( LAYER_MSK enableLayerMask );
dickelbeck's avatar
dickelbeck committed
94
    void showLayerTypes();
95
    void showPresets( LAYER_MSK enabledLayerMask );
dickelbeck's avatar
dickelbeck committed
96

dickelbeck's avatar
dickelbeck committed
97
    /** return the selected layer mask within the UI checkboxes */
98
    LAYER_MSK getUILayerMask();
99 100
    wxString getLayerName( LAYER_NUM layer );
    int getLayerTypeIndex( LAYER_NUM layer );
dickelbeck's avatar
dickelbeck committed
101 102


dickelbeck's avatar
dickelbeck committed
103 104 105 106 107 108
    void OnCancelButtonClick( wxCommandEvent& event );
    void OnOkButtonClick( wxCommandEvent& event );
    void OnCheckBox( wxCommandEvent& event );
    void DenyChangeCheckBox( wxCommandEvent& event );
    void OnPresetsChoice( wxCommandEvent& event );
    void OnCopperLayersChoice( wxCommandEvent& event );
dickelbeck's avatar
dickelbeck committed
109

dickelbeck's avatar
dickelbeck committed
110
    bool testLayerNames();
dickelbeck's avatar
dickelbeck committed
111

dickelbeck's avatar
dickelbeck committed
112 113 114 115 116
    /**
     * Function getCTLs
     * maps \a aLayerNumber to the wx IDs for that layer which are
     * the layer name control ID, checkbox control ID, and choice control ID
     */
117
    CTLs getCTLs( LAYER_NUM aLayerNumber );
dickelbeck's avatar
dickelbeck committed
118

119
    wxControl* getName( LAYER_NUM aLayer )
dickelbeck's avatar
dickelbeck committed
120 121 122
    {
        return getCTLs( aLayer ).name;
    }
dickelbeck's avatar
dickelbeck committed
123

124
    wxCheckBox* getCheckBox( LAYER_NUM aLayer )
dickelbeck's avatar
dickelbeck committed
125 126 127
    {
        return getCTLs( aLayer ).checkbox;
    }
dickelbeck's avatar
dickelbeck committed
128

129
    wxChoice* getChoice( LAYER_NUM aLayer )
dickelbeck's avatar
dickelbeck committed
130 131 132
    {
        return (wxChoice*) getCTLs( aLayer ).choice;
    }
dickelbeck's avatar
dickelbeck committed
133

dickelbeck's avatar
dickelbeck committed
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
    void moveTitles()
    {
        wxArrayInt widths = m_LayerListFlexGridSizer->GetColWidths();

        int offset = 0;
        wxSize txtz;

        txtz = m_NameStaticText->GetSize();
        m_NameStaticText->Move( offset + (widths[0] - txtz.x)/2, 5 );
        offset += widths[0];

        txtz = m_EnabledStaticText->GetSize();
        m_EnabledStaticText->Move( offset + (widths[1] - txtz.x)/2, 5 );
        offset += widths[1];

        txtz = m_TypeStaticText->GetSize();
        m_TypeStaticText->Move( offset + (widths[2] - txtz.x)/2, 5 );
    }

dickelbeck's avatar
dickelbeck committed
153

dickelbeck's avatar
dickelbeck committed
154
public:
155
    DIALOG_LAYERS_SETUP( PCB_EDIT_FRAME* parent );
dickelbeck's avatar
dickelbeck committed
156
    ~DIALOG_LAYERS_SETUP( ) { };
dickelbeck's avatar
dickelbeck committed
157

dickelbeck's avatar
dickelbeck committed
158 159 160 161 162 163 164 165 166 167 168 169
    /**
     * Function Layout
     * overrides the standard Layout() function so that the column titles can
     * be positioned using information in the flexgridsizer.
     */
    bool Layout()
    {
        bool ret = DIALOG_LAYERS_SETUP_BASE::Layout();

        moveTitles();
        return ret;
    }
dickelbeck's avatar
dickelbeck committed
170 171 172
};


dickelbeck's avatar
dickelbeck committed
173
// Layer bit masks for each defined "Preset Layer Grouping"
174
static const LAYER_MSK presets[] =
dickelbeck's avatar
dickelbeck committed
175
{
176
    NO_LAYERS,  // shift the array index up by one, matches with "Custom".
dickelbeck's avatar
dickelbeck committed
177

dickelbeck's avatar
dickelbeck committed
178
    // "Two layers, parts on Front only"
179
    EDGE_LAYER | LAYER_FRONT | LAYER_BACK | FRONT_AUX_LAYERS,
dickelbeck's avatar
dickelbeck committed
180

dickelbeck's avatar
dickelbeck committed
181
    // "Two layers, parts on Back only",
182
    EDGE_LAYER | LAYER_FRONT | LAYER_BACK | BACK_AUX_LAYERS,
dickelbeck's avatar
dickelbeck committed
183

dickelbeck's avatar
dickelbeck committed
184
    // "Two layers, parts on Front and Back",
185
    EDGE_LAYER | LAYER_FRONT | LAYER_BACK | ALL_AUX_LAYERS,
dickelbeck's avatar
dickelbeck committed
186

dickelbeck's avatar
dickelbeck committed
187
    // "Four layers, parts on Front only"
188
    EDGE_LAYER | LAYER_FRONT | LAYER_BACK | LAYER_2 | LAYER_3 | FRONT_AUX_LAYERS,
dickelbeck's avatar
dickelbeck committed
189

dickelbeck's avatar
dickelbeck committed
190
    // "Four layers, parts on Front and Back"
191
    EDGE_LAYER | LAYER_FRONT | LAYER_BACK | LAYER_2 | LAYER_3 | ALL_AUX_LAYERS,
dickelbeck's avatar
dickelbeck committed
192

dickelbeck's avatar
dickelbeck committed
193 194
    //  "All layers on",
    ALL_LAYERS,
dickelbeck's avatar
dickelbeck committed
195 196 197
};


198
CTLs DIALOG_LAYERS_SETUP::getCTLs( LAYER_NUM aLayerNumber )
dickelbeck's avatar
dickelbeck committed
199
{
200 201
#define RETCOP(x)    return CTLs( x##Name, x##CheckBox, x##Choice, x##Panel );
#define RETAUX(x)    return CTLs( x##Name, x##CheckBox, x##StaticText, x##Panel );
dickelbeck's avatar
dickelbeck committed
202

dickelbeck's avatar
dickelbeck committed
203 204
    switch( aLayerNumber )
    {
dickelbeck's avatar
dickelbeck committed
205 206 207 208 209
    case ADHESIVE_N_FRONT:      RETAUX( m_AdhesFront );
    case SOLDERPASTE_N_FRONT:   RETAUX( m_SoldPFront );
    case SILKSCREEN_N_FRONT:    RETAUX( m_SilkSFront );
    case SOLDERMASK_N_FRONT:    RETAUX( m_MaskFront );
    case LAYER_N_FRONT:         RETCOP( m_Front );
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
#ifdef USE_LAYER_MANAGER_COPPER_LAYERS_ORDER
    case LAYER_N_15:            RETCOP( m_Inner2 );
    case LAYER_N_14:            RETCOP( m_Inner3 );
    case LAYER_N_13:            RETCOP( m_Inner4 );
    case LAYER_N_12:            RETCOP( m_Inner5 );
    case LAYER_N_11:            RETCOP( m_Inner6 );
    case LAYER_N_10:            RETCOP( m_Inner7 );
    case LAYER_N_9:             RETCOP( m_Inner8 );
    case LAYER_N_8:             RETCOP( m_Inner9 );
    case LAYER_N_7:             RETCOP( m_Inner10 );
    case LAYER_N_6:             RETCOP( m_Inner11 );
    case LAYER_N_5:             RETCOP( m_Inner12 );
    case LAYER_N_4:             RETCOP( m_Inner13 );
    case LAYER_N_3:             RETCOP( m_Inner14 );
    case LAYER_N_2:             RETCOP( m_Inner15 );
#else
dickelbeck's avatar
dickelbeck committed
226 227 228 229 230 231 232 233 234 235 236 237 238 239
    case LAYER_N_2:             RETCOP( m_Inner2 );
    case LAYER_N_3:             RETCOP( m_Inner3 );
    case LAYER_N_4:             RETCOP( m_Inner4 );
    case LAYER_N_5:             RETCOP( m_Inner5 );
    case LAYER_N_6:             RETCOP( m_Inner6 );
    case LAYER_N_7:             RETCOP( m_Inner7 );
    case LAYER_N_8:             RETCOP( m_Inner8 );
    case LAYER_N_9:             RETCOP( m_Inner9 );
    case LAYER_N_10:            RETCOP( m_Inner10 );
    case LAYER_N_11:            RETCOP( m_Inner11 );
    case LAYER_N_12:            RETCOP( m_Inner12 );
    case LAYER_N_13:            RETCOP( m_Inner13 );
    case LAYER_N_14:            RETCOP( m_Inner14 );
    case LAYER_N_15:            RETCOP( m_Inner15 );
240
#endif
dickelbeck's avatar
dickelbeck committed
241 242 243 244 245 246 247 248 249 250
    case LAYER_N_BACK:          RETCOP( m_Back );
    case SOLDERMASK_N_BACK:     RETAUX( m_MaskBack );
    case SILKSCREEN_N_BACK:     RETAUX( m_SilkSBack );
    case SOLDERPASTE_N_BACK:    RETAUX( m_SoldPBack );
    case ADHESIVE_N_BACK:       RETAUX( m_AdhesBack );
    case EDGE_N:                RETAUX( m_PCBEdges );
    case ECO2_N:                RETAUX( m_Eco2 );
    case ECO1_N:                RETAUX( m_Eco1 );
    case COMMENT_N:             RETAUX( m_Comments );
    case DRAW_N:                RETAUX( m_Drawings );
dickelbeck's avatar
dickelbeck committed
251 252 253 254
    default:
        // wxDEBUGMSG( "bad layer id" );
        return CTLs( 0, 0, 0 );
    }
dickelbeck's avatar
dickelbeck committed
255

dickelbeck's avatar
dickelbeck committed
256 257
#undef RETCOP
#undef RETAUX
dickelbeck's avatar
dickelbeck committed
258 259 260
}


dickelbeck's avatar
dickelbeck committed
261
/***********************************************************************************/
262
DIALOG_LAYERS_SETUP::DIALOG_LAYERS_SETUP( PCB_EDIT_FRAME* parent ) :
dickelbeck's avatar
dickelbeck committed
263 264
    DIALOG_LAYERS_SETUP_BASE( parent )
/***********************************************************************************/
dickelbeck's avatar
dickelbeck committed
265
{
dickelbeck's avatar
dickelbeck committed
266 267
    m_Parent    = parent;
    m_Pcb       = m_Parent->GetBoard();
dickelbeck's avatar
dickelbeck committed
268

dickelbeck's avatar
dickelbeck committed
269 270
    m_CopperLayerCount = m_Pcb->GetCopperLayerCount();
    showCopperChoice( m_CopperLayerCount );
271
    setCopperLayerCheckBoxes( m_CopperLayerCount );
dickelbeck's avatar
dickelbeck committed
272 273 274 275 276 277 278 279

    showBoardLayerNames();

    m_EnabledLayers = m_Pcb->GetEnabledLayers();
    showSelectedLayerCheckBoxes( m_EnabledLayers );
    showPresets( m_EnabledLayers );

    showLayerTypes();
dickelbeck's avatar
dickelbeck committed
280

dickelbeck's avatar
dickelbeck committed
281
    SetAutoLayout( true );
dickelbeck's avatar
dickelbeck committed
282 283 284

    // these 3 controls are handled outside wxformbuilder so that we can add
    // them without a sizer.  Then we position them manually based on the column
285
    // widths from m_LayerListFlexGridSizer->GetColWidths()
dickelbeck's avatar
dickelbeck committed
286
    m_NameStaticText = new wxStaticText( m_TitlePanel, wxID_ANY, _("Name"), wxDefaultPosition, wxDefaultSize, 0 );
dickelbeck's avatar
dickelbeck committed
287

dickelbeck's avatar
dickelbeck committed
288
    m_EnabledStaticText = new wxStaticText( m_TitlePanel, wxID_ANY, _("Enabled"), wxDefaultPosition, wxDefaultSize, 0 );
dickelbeck's avatar
dickelbeck committed
289

dickelbeck's avatar
dickelbeck committed
290
    m_TypeStaticText = new wxStaticText( m_TitlePanel, wxID_ANY, _("Type"), wxDefaultPosition, wxDefaultSize, 0 );
dickelbeck's avatar
dickelbeck committed
291

dickelbeck's avatar
dickelbeck committed
292 293
    // set the height of the title panel to be the size of any wxStaticText object
    // plus 10 so we can have a border of 5 on both top and bottom.
dickelbeck's avatar
dickelbeck committed
294 295
    m_TitlePanel->SetMinSize( wxSize( -1, m_AdhesFrontName->GetSize().y+10 ) );

dickelbeck's avatar
dickelbeck committed
296
    Layout();
dickelbeck's avatar
dickelbeck committed
297

dickelbeck's avatar
dickelbeck committed
298
    Center();
dickelbeck's avatar
dickelbeck committed
299

dickelbeck's avatar
dickelbeck committed
300
    m_sdbSizer2OK->SetFocus();
301
    m_sdbSizer2OK->SetDefault();
dickelbeck's avatar
dickelbeck committed
302 303 304
}


dickelbeck's avatar
dickelbeck committed
305
void DIALOG_LAYERS_SETUP::showCopperChoice( int copperCount )
dickelbeck's avatar
dickelbeck committed
306
{
dickelbeck's avatar
dickelbeck committed
307
    static const int copperCounts[] = { 2,4,6,8,10,12,14,16 };
dickelbeck's avatar
dickelbeck committed
308

dickelbeck's avatar
dickelbeck committed
309 310 311 312 313 314 315 316 317
    for( unsigned i = 0;  i<sizeof(copperCounts);  ++i )
    {
        // note this will change a one layer board to 2:
        if( copperCount <= copperCounts[i] )
        {
            m_CopperLayersChoice->SetSelection(i);
            break;
        }
    }
dickelbeck's avatar
dickelbeck committed
318 319 320
}


dickelbeck's avatar
dickelbeck committed
321 322 323 324
void DIALOG_LAYERS_SETUP::showBoardLayerNames()
{
    // Establish all the board's layer names into the dialog presentation, by
    // obtaining them from BOARD::GetLayerName() which calls
325
    // BOARD::GetStandardLayerName() for non-coppers.
dickelbeck's avatar
dickelbeck committed
326

327
    for( LAYER_NUM layer=FIRST_LAYER; layer<NB_PCB_LAYERS;  ++layer )
dickelbeck's avatar
dickelbeck committed
328
    {
dickelbeck's avatar
dickelbeck committed
329
        wxControl*  ctl = getName( layer );
dickelbeck's avatar
dickelbeck committed
330

dickelbeck's avatar
dickelbeck committed
331
        wxASSERT( ctl );
dickelbeck's avatar
dickelbeck committed
332

dickelbeck's avatar
dickelbeck committed
333
        if( ctl )
dickelbeck's avatar
dickelbeck committed
334
        {
dickelbeck's avatar
dickelbeck committed
335
            wxString lname = m_Pcb->GetLayerName( layer );
dickelbeck's avatar
dickelbeck committed
336

337
            //D(printf("layerName[%d]=%s\n", layer, TO_UTF8( lname ) );)
dickelbeck's avatar
dickelbeck committed
338

dickelbeck's avatar
dickelbeck committed
339 340 341 342
            if( ctl->IsKindOf( CLASSINFO(wxTextCtrl) ) )
                ((wxTextCtrl*)ctl)->SetValue( lname );     // wxTextCtrl
            else
                ctl->SetLabel( lname );     // wxStaticText
dickelbeck's avatar
dickelbeck committed
343 344
        }
    }
dickelbeck's avatar
dickelbeck committed
345
}
dickelbeck's avatar
dickelbeck committed
346 347


348
void DIALOG_LAYERS_SETUP::showSelectedLayerCheckBoxes( LAYER_MSK enabledLayers )
dickelbeck's avatar
dickelbeck committed
349
{
350
    for( LAYER_NUM layer=FIRST_LAYER; layer<NB_PCB_LAYERS; ++layer )
dickelbeck's avatar
dickelbeck committed
351
    {
352
        setLayerCheckBox( layer, GetLayerMask( layer ) & enabledLayers );
dickelbeck's avatar
dickelbeck committed
353
    }
dickelbeck's avatar
dickelbeck committed
354
}
dickelbeck's avatar
dickelbeck committed
355 356


357
void DIALOG_LAYERS_SETUP::showPresets( LAYER_MSK enabledLayers )
dickelbeck's avatar
dickelbeck committed
358 359
{
    int presetsNdx = 0;     // the "Custom" setting, matches nothing
dickelbeck's avatar
dickelbeck committed
360

dickelbeck's avatar
dickelbeck committed
361
    for( unsigned i=1; i<DIM(presets);  ++i )
dickelbeck's avatar
dickelbeck committed
362
    {
dickelbeck's avatar
dickelbeck committed
363
        if( enabledLayers == presets[i] )
dickelbeck's avatar
dickelbeck committed
364
        {
dickelbeck's avatar
dickelbeck committed
365 366
            presetsNdx = i;
            break;
dickelbeck's avatar
dickelbeck committed
367 368 369
        }
    }

dickelbeck's avatar
dickelbeck committed
370 371
    m_PresetsChoice->SetSelection( presetsNdx );
}
dickelbeck's avatar
dickelbeck committed
372 373


dickelbeck's avatar
dickelbeck committed
374 375
void DIALOG_LAYERS_SETUP::showLayerTypes()
{
376
    for( LAYER_NUM copperLayer = FIRST_COPPER_LAYER;
dickelbeck's avatar
dickelbeck committed
377 378 379 380 381 382
             copperLayer <= LAST_COPPER_LAYER; ++copperLayer )
    {
        wxChoice* ctl = getChoice( copperLayer );
        ctl->SetSelection( m_Pcb->GetLayerType( copperLayer ) );
    }
}
dickelbeck's avatar
dickelbeck committed
383 384


385
LAYER_MSK DIALOG_LAYERS_SETUP::getUILayerMask()
dickelbeck's avatar
dickelbeck committed
386
{
387
    LAYER_MSK layerMaskResult = NO_LAYERS;
dickelbeck's avatar
dickelbeck committed
388

389
    for( LAYER_NUM layer=FIRST_LAYER; layer<NB_PCB_LAYERS; ++layer )
dickelbeck's avatar
dickelbeck committed
390
    {
dickelbeck's avatar
dickelbeck committed
391 392 393
        wxCheckBox*  ctl = getCheckBox( layer );
        if( ctl->GetValue() )
        {
394
            layerMaskResult |= GetLayerMask( layer );
dickelbeck's avatar
dickelbeck committed
395
        }
dickelbeck's avatar
dickelbeck committed
396 397
    }

dickelbeck's avatar
dickelbeck committed
398
    return layerMaskResult;
dickelbeck's avatar
dickelbeck committed
399 400 401
}


402
void DIALOG_LAYERS_SETUP::setLayerCheckBox( LAYER_NUM aLayer, bool isChecked )
dickelbeck's avatar
dickelbeck committed
403
{
dickelbeck's avatar
dickelbeck committed
404 405 406
    wxCheckBox*  ctl = getCheckBox( aLayer );
    ctl->SetValue(  isChecked );
}
dickelbeck's avatar
dickelbeck committed
407 408


dickelbeck's avatar
dickelbeck committed
409 410 411
void DIALOG_LAYERS_SETUP::setCopperLayerCheckBoxes( int copperCount )
{
    if( copperCount > 0 )
dickelbeck's avatar
dickelbeck committed
412
    {
dickelbeck's avatar
dickelbeck committed
413 414
        setLayerCheckBox( LAYER_N_BACK, true );
        --copperCount;
dickelbeck's avatar
dickelbeck committed
415 416
    }

dickelbeck's avatar
dickelbeck committed
417
    if( copperCount > 0 )
dickelbeck's avatar
dickelbeck committed
418
    {
dickelbeck's avatar
dickelbeck committed
419 420
        setLayerCheckBox( LAYER_N_FRONT, true );
        --copperCount;
dickelbeck's avatar
dickelbeck committed
421 422 423
    }
    else
    {
dickelbeck's avatar
dickelbeck committed
424
        setLayerCheckBox( LAYER_N_FRONT, false );
dickelbeck's avatar
dickelbeck committed
425 426
    }

427
    for( LAYER_NUM layer=LAYER_N_2; layer < NB_COPPER_LAYERS-1; ++layer, --copperCount )
dickelbeck's avatar
dickelbeck committed
428
    {
429
        bool state = copperCount > 0;
430

431
#ifdef HIDE_INACTIVE_LAYERS
432 433 434 435
        // This code hides non-active copper layers, or redisplays hidden
        // layers which are now needed.
        CTLs ctl = getCTLs( layer );

436 437 438
        ctl.name->Show( state );
        ctl.checkbox->Show( state );
        ctl.choice->Show( state );
439

440 441 442
        if( ctl.panel )
            ctl.panel->Show( state );
#endif
dickelbeck's avatar
dickelbeck committed
443

444
        setLayerCheckBox( layer, state );
dickelbeck's avatar
dickelbeck committed
445
    }
446

447
#ifdef HIDE_INACTIVE_LAYERS
448 449 450 451
    // Send an size event to force sizers to be updated,
    // because the number of copper layers can have changed.
    wxSizeEvent evt_size(m_LayersListPanel->GetSize() );
    m_LayersListPanel->GetEventHandler()->ProcessEvent( evt_size );
452 453
#endif

dickelbeck's avatar
dickelbeck committed
454 455 456
}


dickelbeck's avatar
dickelbeck committed
457
void DIALOG_LAYERS_SETUP::OnCheckBox( wxCommandEvent& event )
dickelbeck's avatar
dickelbeck committed
458
{
dickelbeck's avatar
dickelbeck committed
459
    m_EnabledLayers = getUILayerMask();
dickelbeck's avatar
dickelbeck committed
460

dickelbeck's avatar
dickelbeck committed
461
    showPresets( m_EnabledLayers );
dickelbeck's avatar
dickelbeck committed
462 463 464
}


dickelbeck's avatar
dickelbeck committed
465
void DIALOG_LAYERS_SETUP::DenyChangeCheckBox( wxCommandEvent& event )
dickelbeck's avatar
dickelbeck committed
466
{
dickelbeck's avatar
dickelbeck committed
467
    // user may not change copper layer checkboxes from anything other than
468
    // either presets choice or the copper layer choice controls.
dickelbeck's avatar
dickelbeck committed
469

470
    // I tried to simply disable the copper CheckBoxes but they look like crap,
dickelbeck's avatar
dickelbeck committed
471
    // so leave them enabled and reverse the user's attempt to toggle them.
dickelbeck's avatar
dickelbeck committed
472

dickelbeck's avatar
dickelbeck committed
473
    setCopperLayerCheckBoxes( m_CopperLayerCount );
dickelbeck's avatar
dickelbeck committed
474 475 476
}


dickelbeck's avatar
dickelbeck committed
477
void DIALOG_LAYERS_SETUP::OnPresetsChoice( wxCommandEvent& event )
dickelbeck's avatar
dickelbeck committed
478
{
dickelbeck's avatar
dickelbeck committed
479
    unsigned presetNdx = m_PresetsChoice->GetCurrentSelection();
dickelbeck's avatar
dickelbeck committed
480

dickelbeck's avatar
dickelbeck committed
481
    if( presetNdx == 0 )        // the Custom setting controls nothing.
dickelbeck's avatar
dickelbeck committed
482 483
        return;

dickelbeck's avatar
dickelbeck committed
484 485 486
    if( presetNdx < DIM(presets) )
    {
        m_EnabledLayers = presets[ presetNdx ];
dickelbeck's avatar
dickelbeck committed
487

dickelbeck's avatar
dickelbeck committed
488
        int coppersMask = m_EnabledLayers & ALL_CU_LAYERS;
dickelbeck's avatar
dickelbeck committed
489

dickelbeck's avatar
dickelbeck committed
490 491 492 493 494
        int copperCount = 0;
        while( coppersMask )
        {
            if( coppersMask & 1 )
                ++copperCount;
dickelbeck's avatar
dickelbeck committed
495

dickelbeck's avatar
dickelbeck committed
496 497
            coppersMask >>= 1;
        }
dickelbeck's avatar
dickelbeck committed
498

dickelbeck's avatar
dickelbeck committed
499
        m_CopperLayerCount = copperCount;
500

dickelbeck's avatar
dickelbeck committed
501
        showCopperChoice( m_CopperLayerCount );
dickelbeck's avatar
dickelbeck committed
502

dickelbeck's avatar
dickelbeck committed
503
        showSelectedLayerCheckBoxes( m_EnabledLayers );
504 505

        setCopperLayerCheckBoxes( m_CopperLayerCount );
dickelbeck's avatar
dickelbeck committed
506
    }
dickelbeck's avatar
dickelbeck committed
507 508 509
}


dickelbeck's avatar
dickelbeck committed
510
void DIALOG_LAYERS_SETUP::OnCopperLayersChoice( wxCommandEvent& event )
dickelbeck's avatar
dickelbeck committed
511
{
dickelbeck's avatar
dickelbeck committed
512
    m_CopperLayerCount = m_CopperLayersChoice->GetCurrentSelection() * 2 + 2;
dickelbeck's avatar
dickelbeck committed
513

dickelbeck's avatar
dickelbeck committed
514
    setCopperLayerCheckBoxes( m_CopperLayerCount );
dickelbeck's avatar
dickelbeck committed
515

516
    m_EnabledLayers = getUILayerMask();
dickelbeck's avatar
dickelbeck committed
517

518 519
    showPresets( m_EnabledLayers );
}
dickelbeck's avatar
dickelbeck committed
520

dickelbeck's avatar
dickelbeck committed
521 522 523 524

/*****************************************************************/
void DIALOG_LAYERS_SETUP::OnCancelButtonClick( wxCommandEvent& event )
/*****************************************************************/
dickelbeck's avatar
dickelbeck committed
525
{
526
    EndModal( wxID_CANCEL );
dickelbeck's avatar
dickelbeck committed
527
}
dickelbeck's avatar
dickelbeck committed
528 529


dickelbeck's avatar
dickelbeck committed
530 531 532
/**************************************************************************/
void DIALOG_LAYERS_SETUP::OnOkButtonClick( wxCommandEvent& event )
/**************************************************************************/
dickelbeck's avatar
dickelbeck committed
533
{
dickelbeck's avatar
dickelbeck committed
534
    if( testLayerNames() )
dickelbeck's avatar
dickelbeck committed
535
    {
dickelbeck's avatar
dickelbeck committed
536
        wxString name;
dickelbeck's avatar
dickelbeck committed
537

dickelbeck's avatar
dickelbeck committed
538 539
        m_EnabledLayers = getUILayerMask();
        m_Pcb->SetEnabledLayers( m_EnabledLayers );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
540

541 542 543 544 545
        /* Ensure enabled layers are also visible
         * This is mainly to avoid mistakes if some enabled
         * layers are not visible when exiting this dialog
         */
        m_Pcb->SetVisibleLayers( m_EnabledLayers );
dickelbeck's avatar
dickelbeck committed
546

547
        for( LAYER_NUM layer = FIRST_COPPER_LAYER;
dickelbeck's avatar
dickelbeck committed
548 549
                 layer <= LAST_COPPER_LAYER; ++layer )
        {
550
            if( GetLayerMask( layer ) & m_EnabledLayers )
dickelbeck's avatar
dickelbeck committed
551 552
            {
                name = getLayerName( layer );
dickelbeck's avatar
dickelbeck committed
553

dickelbeck's avatar
dickelbeck committed
554
                m_Pcb->SetLayerName( layer, name );
dickelbeck's avatar
dickelbeck committed
555

dickelbeck's avatar
dickelbeck committed
556
                LAYER_T t = (LAYER_T) getLayerTypeIndex(layer);
dickelbeck's avatar
dickelbeck committed
557

dickelbeck's avatar
dickelbeck committed
558 559 560 561
                m_Pcb->SetLayerType( layer, t );
            }
        }

562
        m_Parent->OnModify();
dickelbeck's avatar
dickelbeck committed
563
        m_Parent->ReCreateLayerBox( NULL );
564
        m_Parent->ReFillLayerWidget();
dickelbeck's avatar
dickelbeck committed
565 566 567

        EndModal( wxID_OK );
    }
dickelbeck's avatar
dickelbeck committed
568
}
dickelbeck's avatar
dickelbeck committed
569

570
int DIALOG_LAYERS_SETUP::getLayerTypeIndex( LAYER_NUM aLayer )
dickelbeck's avatar
dickelbeck committed
571
{
dickelbeck's avatar
dickelbeck committed
572
    wxChoice*  ctl =  getChoice( aLayer );
dickelbeck's avatar
dickelbeck committed
573

dickelbeck's avatar
dickelbeck committed
574
    int ret = ctl->GetCurrentSelection();   // indices must have same sequence as LAYER_T
dickelbeck's avatar
dickelbeck committed
575

dickelbeck's avatar
dickelbeck committed
576
    return ret;
dickelbeck's avatar
dickelbeck committed
577
}
dickelbeck's avatar
dickelbeck committed
578

579
wxString DIALOG_LAYERS_SETUP::getLayerName( LAYER_NUM aLayer )
dickelbeck's avatar
dickelbeck committed
580
{
dickelbeck's avatar
dickelbeck committed
581
    wxString ret;
dickelbeck's avatar
dickelbeck committed
582

583
    wxASSERT( IsCopperLayer( aLayer ) );
dickelbeck's avatar
dickelbeck committed
584

dickelbeck's avatar
dickelbeck committed
585
    wxTextCtrl*  ctl = (wxTextCtrl*) getName( aLayer );
dickelbeck's avatar
dickelbeck committed
586

dickelbeck's avatar
dickelbeck committed
587
    ret = ctl->GetValue().Trim();
dickelbeck's avatar
dickelbeck committed
588

dickelbeck's avatar
dickelbeck committed
589
    return ret;
dickelbeck's avatar
dickelbeck committed
590 591
}

dickelbeck's avatar
dickelbeck committed
592 593 594 595 596 597 598
static bool hasOneOf( const wxString& str, const wxString& chars )
{
    for( unsigned i=0; i<chars.Len();  ++i )
        if( str.Find( chars[i] ) != wxNOT_FOUND )
            return true;
    return false;
}
dickelbeck's avatar
dickelbeck committed
599

dickelbeck's avatar
dickelbeck committed
600
bool DIALOG_LAYERS_SETUP::testLayerNames()
dickelbeck's avatar
dickelbeck committed
601
{
dickelbeck's avatar
dickelbeck committed
602 603 604
    std::vector<wxString>    names;

    wxTextCtrl*  ctl;
dickelbeck's avatar
dickelbeck committed
605

606
    for( LAYER_NUM layer=FIRST_LAYER; layer<=LAST_COPPER_LAYER; ++layer )
dickelbeck's avatar
dickelbeck committed
607
    {
dickelbeck's avatar
dickelbeck committed
608
        // we _can_ rely on m_EnabledLayers being current here:
609
        if( !(m_EnabledLayers & GetLayerMask( layer )) )
dickelbeck's avatar
dickelbeck committed
610
            continue;
611

dickelbeck's avatar
dickelbeck committed
612
        wxString name = getLayerName( layer );
dickelbeck's avatar
dickelbeck committed
613

614
        //D(printf("name[%d]=%s\n", layer, TO_UTF8(name) );)
dickelbeck's avatar
dickelbeck committed
615

dickelbeck's avatar
dickelbeck committed
616
        ctl = (wxTextCtrl*) getName( layer );
dickelbeck's avatar
dickelbeck committed
617

dickelbeck's avatar
dickelbeck committed
618 619 620 621 622 623
        // check name for legality.
        // 1) cannot be blank.
        // 2) cannot have blanks.
        // 3) cannot have " chars
        // 4) cannot be 'signal'
        // 5) must be unique.
624
        // 6) cannot have illegal chars in filenames ( some filenames are built from layer names )
Dick Hollenbeck's avatar
Dick Hollenbeck committed
625
        static const wxString badchars( wxT("%$\" /\\") );
dickelbeck's avatar
dickelbeck committed
626

dickelbeck's avatar
dickelbeck committed
627 628 629 630 631 632
        if( name == wxEmptyString )
        {
            DisplayError( this, _("Layer name may not be empty" ) );
            ctl->SetFocus();    // on the bad name
            return false;
        }
dickelbeck's avatar
dickelbeck committed
633

dickelbeck's avatar
dickelbeck committed
634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661
        if( hasOneOf( name, badchars ) )
        {
            DisplayError( this, _("Layer name has an illegal character, one of: '") + badchars + wxT("'") );
            ctl->SetFocus();    // on the bad name
            return false;
        }

        if( name == wxT("signal") )
        {
            DisplayError( this, _("'signal' is a reserved layer name") );
            ctl->SetFocus();    // on the bad name
            return false;
        }

        for( std::vector<wxString>::iterator it = names.begin();  it != names.end();  ++it )
        {
            if( name == *it )
            {
                DisplayError( this, _("Layer name is a duplicate of another") );
                ctl->SetFocus();    // on the bad name
                return false;
            }
        }

        names.push_back( name );
    }

    return true;
dickelbeck's avatar
dickelbeck committed
662 663
}

dickelbeck's avatar
dickelbeck committed
664

665
void PCB_EDIT_FRAME::InstallDialogLayerSetup()
dickelbeck's avatar
dickelbeck committed
666
{
jean-pierre charras's avatar
jean-pierre charras committed
667
    DIALOG_LAYERS_SETUP dlg( this );
668 669 670 671 672 673 674 675

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

    wxLogDebug( wxT( "Current layer selected %d." ), getActiveLayer() );

    // If the current active layer was removed, find the next avaiable layer to set as the
    // active layer.
676
    if( !( GetLayerMask( getActiveLayer() ) & GetBoard()->GetEnabledLayers() ) )
677
    {
678
        for( LAYER_NUM i = FIRST_LAYER; i < NB_LAYERS; ++i )
679
        {
680
            LAYER_NUM tmp = i;
681

682 683
            if( i >= NB_LAYERS )
                tmp = i - NB_LAYERS;
684

685
            if( GetLayerMask( tmp ) & GetBoard()->GetEnabledLayers() )
686 687 688 689 690 691 692 693 694 695 696
            {
                wxLogDebug( wxT( "Setting current layer to  %d." ), getActiveLayer() );
                setActiveLayer( tmp, true );
                break;
            }
        }
    }
    else
    {
        setActiveLayer( getActiveLayer(), true );
    }
dickelbeck's avatar
dickelbeck committed
697
}