dialog_layers_setup.cpp 20.7 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 76 77
class DIALOG_LAYERS_SETUP : public DIALOG_LAYERS_SETUP_BASE
{
private:
    static wxPoint      s_LastPos;
    static wxSize       s_LastSize;
dickelbeck's avatar
dickelbeck committed
78

79
    PCB_EDIT_FRAME*     m_Parent;
dickelbeck's avatar
dickelbeck committed
80

dickelbeck's avatar
dickelbeck committed
81 82
    int                 m_CopperLayerCount;
    int                 m_EnabledLayers;
dickelbeck's avatar
dickelbeck committed
83

dickelbeck's avatar
dickelbeck committed
84
    BOARD*              m_Pcb;
dickelbeck's avatar
dickelbeck committed
85

dickelbeck's avatar
dickelbeck committed
86 87 88 89
    wxStaticText*       m_NameStaticText;
    wxStaticText*       m_EnabledStaticText;
    wxStaticText*       m_TypeStaticText;

dickelbeck's avatar
dickelbeck committed
90

dickelbeck's avatar
dickelbeck committed
91 92
    void setLayerCheckBox( int layer, bool isChecked );
    void setCopperLayerCheckBoxes( int copperCount );
dickelbeck's avatar
dickelbeck committed
93

dickelbeck's avatar
dickelbeck committed
94 95 96 97 98
    void showCopperChoice( int copperCount );
    void showBoardLayerNames();
    void showSelectedLayerCheckBoxes( int enableLayerMask );
    void showLayerTypes();
    void showPresets( int enabledLayerMask );
dickelbeck's avatar
dickelbeck committed
99

dickelbeck's avatar
dickelbeck committed
100 101 102 103
    /** return the selected layer mask within the UI checkboxes */
    int getUILayerMask();
    wxString getLayerName( int layer );
    int getLayerTypeIndex( int layer );
dickelbeck's avatar
dickelbeck committed
104 105


dickelbeck's avatar
dickelbeck committed
106 107 108 109 110 111
    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
112

dickelbeck's avatar
dickelbeck committed
113
    bool testLayerNames();
dickelbeck's avatar
dickelbeck committed
114

dickelbeck's avatar
dickelbeck committed
115 116 117 118 119 120
    /**
     * 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
     */
    CTLs getCTLs( int aLayerNumber );
dickelbeck's avatar
dickelbeck committed
121

dickelbeck's avatar
dickelbeck committed
122 123 124 125
    wxControl* getName( int aLayer )
    {
        return getCTLs( aLayer ).name;
    }
dickelbeck's avatar
dickelbeck committed
126

dickelbeck's avatar
dickelbeck committed
127 128 129 130
    wxCheckBox* getCheckBox( int aLayer )
    {
        return getCTLs( aLayer ).checkbox;
    }
dickelbeck's avatar
dickelbeck committed
131

dickelbeck's avatar
dickelbeck committed
132 133 134 135
    wxChoice* getChoice( int aLayer )
    {
        return (wxChoice*) getCTLs( aLayer ).choice;
    }
dickelbeck's avatar
dickelbeck committed
136

dickelbeck's avatar
dickelbeck committed
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
    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
156

dickelbeck's avatar
dickelbeck committed
157
public:
158
    DIALOG_LAYERS_SETUP( PCB_EDIT_FRAME* parent );
dickelbeck's avatar
dickelbeck committed
159
    ~DIALOG_LAYERS_SETUP( ) { };
dickelbeck's avatar
dickelbeck committed
160

dickelbeck's avatar
dickelbeck committed
161
    bool Show( bool show );     // overload stock function
dickelbeck's avatar
dickelbeck committed
162

dickelbeck's avatar
dickelbeck committed
163 164 165 166 167 168 169 170 171 172 173 174
    /**
     * 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
175 176 177
};


dickelbeck's avatar
dickelbeck committed
178 179 180
// We want our dialog to remember its previous screen position
wxPoint DIALOG_LAYERS_SETUP::s_LastPos( -1, -1 );
wxSize  DIALOG_LAYERS_SETUP::s_LastSize;
dickelbeck's avatar
dickelbeck committed
181 182


dickelbeck's avatar
dickelbeck committed
183 184
// Layer bit masks for each defined "Preset Layer Grouping"
static const int presets[] =
dickelbeck's avatar
dickelbeck committed
185
{
186 187
#define FRONT_AUX   (SILKSCREEN_LAYER_FRONT | SOLDERMASK_LAYER_FRONT  | ADHESIVE_LAYER_FRONT | SOLDERPASTE_LAYER_FRONT)
#define BACK_AUX    (SILKSCREEN_LAYER_BACK  | SOLDERMASK_LAYER_BACK   | ADHESIVE_LAYER_BACK  | SOLDERPASTE_LAYER_BACK)
dickelbeck's avatar
dickelbeck committed
188

dickelbeck's avatar
dickelbeck committed
189
    0,  // shift the array index up by one, matches with "Custom".
dickelbeck's avatar
dickelbeck committed
190

dickelbeck's avatar
dickelbeck committed
191
    // "Two layers, parts on Front only"
192
    EDGE_LAYER | LAYER_FRONT | LAYER_BACK | FRONT_AUX,
dickelbeck's avatar
dickelbeck committed
193

dickelbeck's avatar
dickelbeck committed
194
    // "Two layers, parts on Back only",
195
    EDGE_LAYER | LAYER_FRONT | LAYER_BACK | BACK_AUX,
dickelbeck's avatar
dickelbeck committed
196

dickelbeck's avatar
dickelbeck committed
197
    // "Two layers, parts on Front and Back",
198
    EDGE_LAYER | LAYER_FRONT | LAYER_BACK | BACK_AUX | FRONT_AUX,
dickelbeck's avatar
dickelbeck committed
199

dickelbeck's avatar
dickelbeck committed
200
    // "Four layers, parts on Front only"
201
    EDGE_LAYER | LAYER_FRONT | LAYER_BACK | LAYER_2 | LAYER_3 | FRONT_AUX,
dickelbeck's avatar
dickelbeck committed
202

dickelbeck's avatar
dickelbeck committed
203
    // "Four layers, parts on Front and Back"
204
    EDGE_LAYER | LAYER_FRONT | LAYER_BACK | LAYER_2 | LAYER_3 | FRONT_AUX | BACK_AUX,
dickelbeck's avatar
dickelbeck committed
205

dickelbeck's avatar
dickelbeck committed
206 207
    //  "All layers on",
    ALL_LAYERS,
dickelbeck's avatar
dickelbeck committed
208 209 210
};


dickelbeck's avatar
dickelbeck committed
211
CTLs DIALOG_LAYERS_SETUP::getCTLs( int aLayerNumber )
dickelbeck's avatar
dickelbeck committed
212
{
213 214
#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
215

dickelbeck's avatar
dickelbeck committed
216 217
    switch( aLayerNumber )
    {
dickelbeck's avatar
dickelbeck committed
218 219 220 221 222
    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 );
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
#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
239 240 241 242 243 244 245 246 247 248 249 250 251 252
    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 );
253
#endif
dickelbeck's avatar
dickelbeck committed
254 255 256 257 258 259 260 261 262 263
    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
264 265 266 267
    default:
        // wxDEBUGMSG( "bad layer id" );
        return CTLs( 0, 0, 0 );
    }
dickelbeck's avatar
dickelbeck committed
268

dickelbeck's avatar
dickelbeck committed
269 270
#undef RETCOP
#undef RETAUX
dickelbeck's avatar
dickelbeck committed
271 272 273
}


dickelbeck's avatar
dickelbeck committed
274
/***********************************************************************************/
275
DIALOG_LAYERS_SETUP::DIALOG_LAYERS_SETUP( PCB_EDIT_FRAME* parent ) :
dickelbeck's avatar
dickelbeck committed
276 277
    DIALOG_LAYERS_SETUP_BASE( parent )
/***********************************************************************************/
dickelbeck's avatar
dickelbeck committed
278
{
dickelbeck's avatar
dickelbeck committed
279 280
    m_Parent    = parent;
    m_Pcb       = m_Parent->GetBoard();
dickelbeck's avatar
dickelbeck committed
281

dickelbeck's avatar
dickelbeck committed
282 283
    m_CopperLayerCount = m_Pcb->GetCopperLayerCount();
    showCopperChoice( m_CopperLayerCount );
284
    setCopperLayerCheckBoxes( m_CopperLayerCount );
dickelbeck's avatar
dickelbeck committed
285 286 287 288 289 290 291 292

    showBoardLayerNames();

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

    showLayerTypes();
dickelbeck's avatar
dickelbeck committed
293

dickelbeck's avatar
dickelbeck committed
294
    SetAutoLayout( true );
dickelbeck's avatar
dickelbeck committed
295 296 297

    // 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
298
    // widths from m_LayerListFlexGridSizer->GetColWidths()
dickelbeck's avatar
dickelbeck committed
299
    m_NameStaticText = new wxStaticText( m_TitlePanel, wxID_ANY, _("Name"), wxDefaultPosition, wxDefaultSize, 0 );
dickelbeck's avatar
dickelbeck committed
300

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

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

dickelbeck's avatar
dickelbeck committed
305 306
    // 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
307 308
    m_TitlePanel->SetMinSize( wxSize( -1, m_AdhesFrontName->GetSize().y+10 ) );

dickelbeck's avatar
dickelbeck committed
309
    Layout();
dickelbeck's avatar
dickelbeck committed
310

dickelbeck's avatar
dickelbeck committed
311
    Center();
dickelbeck's avatar
dickelbeck committed
312

dickelbeck's avatar
dickelbeck committed
313
    m_sdbSizer2OK->SetFocus();
314
    m_sdbSizer2OK->SetDefault();
dickelbeck's avatar
dickelbeck committed
315 316 317
}


dickelbeck's avatar
dickelbeck committed
318
bool DIALOG_LAYERS_SETUP::Show( bool show )
dickelbeck's avatar
dickelbeck committed
319
{
dickelbeck's avatar
dickelbeck committed
320
    bool ret;
dickelbeck's avatar
dickelbeck committed
321

dickelbeck's avatar
dickelbeck committed
322 323 324 325 326 327 328 329 330 331 332 333 334
    if( show )
    {
        if( s_LastPos.x != -1 )
        {
            SetSize( s_LastPos.x, s_LastPos.y, s_LastSize.x, s_LastSize.y, 0 );
        }
        ret = DIALOG_LAYERS_SETUP_BASE::Show( show );
    }
    else
    {
        // Save the dialog's position before hiding
        s_LastPos  = GetPosition();
        s_LastSize = GetSize();
dickelbeck's avatar
dickelbeck committed
335

dickelbeck's avatar
dickelbeck committed
336 337
        ret = DIALOG_LAYERS_SETUP_BASE::Show( show );
    }
dickelbeck's avatar
dickelbeck committed
338

dickelbeck's avatar
dickelbeck committed
339
    return ret;
dickelbeck's avatar
dickelbeck committed
340 341 342
}


dickelbeck's avatar
dickelbeck committed
343
void DIALOG_LAYERS_SETUP::showCopperChoice( int copperCount )
dickelbeck's avatar
dickelbeck committed
344
{
dickelbeck's avatar
dickelbeck committed
345
    static const int copperCounts[] = { 2,4,6,8,10,12,14,16 };
dickelbeck's avatar
dickelbeck committed
346

dickelbeck's avatar
dickelbeck committed
347 348 349 350 351 352 353 354 355
    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
356 357 358
}


dickelbeck's avatar
dickelbeck committed
359 360 361 362 363
void DIALOG_LAYERS_SETUP::showBoardLayerNames()
{
    // Establish all the board's layer names into the dialog presentation, by
    // obtaining them from BOARD::GetLayerName() which calls
    // BOARD::GetDefaultLayerName() for non-coppers.
dickelbeck's avatar
dickelbeck committed
364

dickelbeck's avatar
dickelbeck committed
365
    for( int layer=0; layer<NB_LAYERS;  ++layer )
dickelbeck's avatar
dickelbeck committed
366
    {
dickelbeck's avatar
dickelbeck committed
367
        wxControl*  ctl = getName( layer );
dickelbeck's avatar
dickelbeck committed
368

dickelbeck's avatar
dickelbeck committed
369
        wxASSERT( ctl );
dickelbeck's avatar
dickelbeck committed
370

dickelbeck's avatar
dickelbeck committed
371
        if( ctl )
dickelbeck's avatar
dickelbeck committed
372
        {
dickelbeck's avatar
dickelbeck committed
373
            wxString lname = m_Pcb->GetLayerName( layer );
dickelbeck's avatar
dickelbeck committed
374

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

dickelbeck's avatar
dickelbeck committed
377 378 379 380
            if( ctl->IsKindOf( CLASSINFO(wxTextCtrl) ) )
                ((wxTextCtrl*)ctl)->SetValue( lname );     // wxTextCtrl
            else
                ctl->SetLabel( lname );     // wxStaticText
dickelbeck's avatar
dickelbeck committed
381 382
        }
    }
dickelbeck's avatar
dickelbeck committed
383
}
dickelbeck's avatar
dickelbeck committed
384 385


dickelbeck's avatar
dickelbeck committed
386 387 388
void DIALOG_LAYERS_SETUP::showSelectedLayerCheckBoxes( int enabledLayers )
{
    for( int layer=0;  layer<NB_LAYERS;  ++layer )
dickelbeck's avatar
dickelbeck committed
389
    {
dickelbeck's avatar
dickelbeck committed
390
        setLayerCheckBox( layer, (1<<layer) & enabledLayers  );
dickelbeck's avatar
dickelbeck committed
391
    }
dickelbeck's avatar
dickelbeck committed
392
}
dickelbeck's avatar
dickelbeck committed
393 394


dickelbeck's avatar
dickelbeck committed
395 396 397
void DIALOG_LAYERS_SETUP::showPresets( int enabledLayers )
{
    int presetsNdx = 0;     // the "Custom" setting, matches nothing
dickelbeck's avatar
dickelbeck committed
398

dickelbeck's avatar
dickelbeck committed
399
    for( unsigned i=1; i<DIM(presets);  ++i )
dickelbeck's avatar
dickelbeck committed
400
    {
dickelbeck's avatar
dickelbeck committed
401
        if( enabledLayers == presets[i] )
dickelbeck's avatar
dickelbeck committed
402
        {
dickelbeck's avatar
dickelbeck committed
403 404
            presetsNdx = i;
            break;
dickelbeck's avatar
dickelbeck committed
405 406 407
        }
    }

dickelbeck's avatar
dickelbeck committed
408 409
    m_PresetsChoice->SetSelection( presetsNdx );
}
dickelbeck's avatar
dickelbeck committed
410 411


dickelbeck's avatar
dickelbeck committed
412 413 414 415 416 417 418 419 420
void DIALOG_LAYERS_SETUP::showLayerTypes()
{
    for( int copperLayer =  FIRST_COPPER_LAYER;
             copperLayer <= LAST_COPPER_LAYER; ++copperLayer )
    {
        wxChoice* ctl = getChoice( copperLayer );
        ctl->SetSelection( m_Pcb->GetLayerType( copperLayer ) );
    }
}
dickelbeck's avatar
dickelbeck committed
421 422


dickelbeck's avatar
dickelbeck committed
423
int DIALOG_LAYERS_SETUP::getUILayerMask()
dickelbeck's avatar
dickelbeck committed
424
{
dickelbeck's avatar
dickelbeck committed
425
    int layerMaskResult = 0;
dickelbeck's avatar
dickelbeck committed
426

dickelbeck's avatar
dickelbeck committed
427
    for( int layer=0;  layer<NB_LAYERS;  ++layer )
dickelbeck's avatar
dickelbeck committed
428
    {
dickelbeck's avatar
dickelbeck committed
429 430 431 432 433
        wxCheckBox*  ctl = getCheckBox( layer );
        if( ctl->GetValue() )
        {
            layerMaskResult |= (1 << layer);
        }
dickelbeck's avatar
dickelbeck committed
434 435
    }

dickelbeck's avatar
dickelbeck committed
436
    return layerMaskResult;
dickelbeck's avatar
dickelbeck committed
437 438 439
}


dickelbeck's avatar
dickelbeck committed
440
void DIALOG_LAYERS_SETUP::setLayerCheckBox( int aLayer, bool isChecked )
dickelbeck's avatar
dickelbeck committed
441
{
dickelbeck's avatar
dickelbeck committed
442 443 444
    wxCheckBox*  ctl = getCheckBox( aLayer );
    ctl->SetValue(  isChecked );
}
dickelbeck's avatar
dickelbeck committed
445 446


dickelbeck's avatar
dickelbeck committed
447 448 449
void DIALOG_LAYERS_SETUP::setCopperLayerCheckBoxes( int copperCount )
{
    if( copperCount > 0 )
dickelbeck's avatar
dickelbeck committed
450
    {
dickelbeck's avatar
dickelbeck committed
451 452
        setLayerCheckBox( LAYER_N_BACK, true );
        --copperCount;
dickelbeck's avatar
dickelbeck committed
453 454
    }

dickelbeck's avatar
dickelbeck committed
455
    if( copperCount > 0 )
dickelbeck's avatar
dickelbeck committed
456
    {
dickelbeck's avatar
dickelbeck committed
457 458
        setLayerCheckBox( LAYER_N_FRONT, true );
        --copperCount;
dickelbeck's avatar
dickelbeck committed
459 460 461
    }
    else
    {
dickelbeck's avatar
dickelbeck committed
462
        setLayerCheckBox( LAYER_N_FRONT, false );
dickelbeck's avatar
dickelbeck committed
463 464
    }

dickelbeck's avatar
dickelbeck committed
465
    int layer;
466
    for( layer=LAYER_N_2; layer < NB_COPPER_LAYERS-1;  ++layer, --copperCount )
dickelbeck's avatar
dickelbeck committed
467
    {
468
        bool state = copperCount > 0;
469

470
#ifdef HIDE_INACTIVE_LAYERS
471 472 473 474
        // This code hides non-active copper layers, or redisplays hidden
        // layers which are now needed.
        CTLs ctl = getCTLs( layer );

475 476 477
        ctl.name->Show( state );
        ctl.checkbox->Show( state );
        ctl.choice->Show( state );
478

479 480 481
        if( ctl.panel )
            ctl.panel->Show( state );
#endif
dickelbeck's avatar
dickelbeck committed
482

483
        setLayerCheckBox( layer, state );
dickelbeck's avatar
dickelbeck committed
484
    }
485

486
#ifdef HIDE_INACTIVE_LAYERS
487 488 489 490
    // 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 );
491 492
#endif

dickelbeck's avatar
dickelbeck committed
493 494 495
}


dickelbeck's avatar
dickelbeck committed
496
void DIALOG_LAYERS_SETUP::OnCheckBox( wxCommandEvent& event )
dickelbeck's avatar
dickelbeck committed
497
{
dickelbeck's avatar
dickelbeck committed
498
    m_EnabledLayers = getUILayerMask();
dickelbeck's avatar
dickelbeck committed
499

dickelbeck's avatar
dickelbeck committed
500
    showPresets( m_EnabledLayers );
dickelbeck's avatar
dickelbeck committed
501 502 503
}


dickelbeck's avatar
dickelbeck committed
504
void DIALOG_LAYERS_SETUP::DenyChangeCheckBox( wxCommandEvent& event )
dickelbeck's avatar
dickelbeck committed
505
{
dickelbeck's avatar
dickelbeck committed
506
    // user may not change copper layer checkboxes from anything other than
507
    // either presets choice or the copper layer choice controls.
dickelbeck's avatar
dickelbeck committed
508

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

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


dickelbeck's avatar
dickelbeck committed
516
void DIALOG_LAYERS_SETUP::OnPresetsChoice( wxCommandEvent& event )
dickelbeck's avatar
dickelbeck committed
517
{
dickelbeck's avatar
dickelbeck committed
518
    unsigned presetNdx = m_PresetsChoice->GetCurrentSelection();
dickelbeck's avatar
dickelbeck committed
519

dickelbeck's avatar
dickelbeck committed
520
    if( presetNdx == 0 )        // the Custom setting controls nothing.
dickelbeck's avatar
dickelbeck committed
521 522
        return;

dickelbeck's avatar
dickelbeck committed
523 524 525
    if( presetNdx < DIM(presets) )
    {
        m_EnabledLayers = presets[ presetNdx ];
dickelbeck's avatar
dickelbeck committed
526

dickelbeck's avatar
dickelbeck committed
527
        int coppersMask = m_EnabledLayers & ALL_CU_LAYERS;
dickelbeck's avatar
dickelbeck committed
528

dickelbeck's avatar
dickelbeck committed
529 530 531 532 533
        int copperCount = 0;
        while( coppersMask )
        {
            if( coppersMask & 1 )
                ++copperCount;
dickelbeck's avatar
dickelbeck committed
534

dickelbeck's avatar
dickelbeck committed
535 536
            coppersMask >>= 1;
        }
dickelbeck's avatar
dickelbeck committed
537

dickelbeck's avatar
dickelbeck committed
538
        m_CopperLayerCount = copperCount;
539

dickelbeck's avatar
dickelbeck committed
540
        showCopperChoice( m_CopperLayerCount );
dickelbeck's avatar
dickelbeck committed
541

dickelbeck's avatar
dickelbeck committed
542
        showSelectedLayerCheckBoxes( m_EnabledLayers );
543 544

        setCopperLayerCheckBoxes( m_CopperLayerCount );
dickelbeck's avatar
dickelbeck committed
545
    }
dickelbeck's avatar
dickelbeck committed
546 547 548
}


dickelbeck's avatar
dickelbeck committed
549
void DIALOG_LAYERS_SETUP::OnCopperLayersChoice( wxCommandEvent& event )
dickelbeck's avatar
dickelbeck committed
550
{
dickelbeck's avatar
dickelbeck committed
551
    m_CopperLayerCount = m_CopperLayersChoice->GetCurrentSelection() * 2 + 2;
dickelbeck's avatar
dickelbeck committed
552

dickelbeck's avatar
dickelbeck committed
553
    setCopperLayerCheckBoxes( m_CopperLayerCount );
dickelbeck's avatar
dickelbeck committed
554

555
    m_EnabledLayers = getUILayerMask();
dickelbeck's avatar
dickelbeck committed
556

557 558
    showPresets( m_EnabledLayers );
}
dickelbeck's avatar
dickelbeck committed
559

dickelbeck's avatar
dickelbeck committed
560 561 562 563

/*****************************************************************/
void DIALOG_LAYERS_SETUP::OnCancelButtonClick( wxCommandEvent& event )
/*****************************************************************/
dickelbeck's avatar
dickelbeck committed
564
{
565
    EndModal( wxID_CANCEL );
dickelbeck's avatar
dickelbeck committed
566
}
dickelbeck's avatar
dickelbeck committed
567 568


dickelbeck's avatar
dickelbeck committed
569 570 571
/**************************************************************************/
void DIALOG_LAYERS_SETUP::OnOkButtonClick( wxCommandEvent& event )
/**************************************************************************/
dickelbeck's avatar
dickelbeck committed
572
{
dickelbeck's avatar
dickelbeck committed
573
    if( testLayerNames() )
dickelbeck's avatar
dickelbeck committed
574
    {
dickelbeck's avatar
dickelbeck committed
575
        wxString name;
dickelbeck's avatar
dickelbeck committed
576

dickelbeck's avatar
dickelbeck committed
577 578
        m_EnabledLayers = getUILayerMask();
        m_Pcb->SetEnabledLayers( m_EnabledLayers );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
579

580 581 582 583 584
        /* 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
585

dickelbeck's avatar
dickelbeck committed
586 587 588 589 590 591
        for( int layer =  FIRST_COPPER_LAYER;
                 layer <= LAST_COPPER_LAYER; ++layer )
        {
            if( (1<<layer) & m_EnabledLayers )
            {
                name = getLayerName( layer );
dickelbeck's avatar
dickelbeck committed
592

dickelbeck's avatar
dickelbeck committed
593
                m_Pcb->SetLayerName( layer, name );
dickelbeck's avatar
dickelbeck committed
594

dickelbeck's avatar
dickelbeck committed
595
                LAYER_T t = (LAYER_T) getLayerTypeIndex(layer);
dickelbeck's avatar
dickelbeck committed
596

dickelbeck's avatar
dickelbeck committed
597 598 599 600
                m_Pcb->SetLayerType( layer, t );
            }
        }

601
        m_Parent->OnModify();
dickelbeck's avatar
dickelbeck committed
602
        m_Parent->ReCreateLayerBox( NULL );
603
        m_Parent->ReFillLayerWidget();
dickelbeck's avatar
dickelbeck committed
604 605 606

        EndModal( wxID_OK );
    }
dickelbeck's avatar
dickelbeck committed
607
}
dickelbeck's avatar
dickelbeck committed
608 609

int DIALOG_LAYERS_SETUP::getLayerTypeIndex( int aLayer )
dickelbeck's avatar
dickelbeck committed
610
{
dickelbeck's avatar
dickelbeck committed
611
    wxChoice*  ctl =  getChoice( aLayer );
dickelbeck's avatar
dickelbeck committed
612

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

dickelbeck's avatar
dickelbeck committed
615
    return ret;
dickelbeck's avatar
dickelbeck committed
616
}
dickelbeck's avatar
dickelbeck committed
617 618

wxString DIALOG_LAYERS_SETUP::getLayerName( int aLayer )
dickelbeck's avatar
dickelbeck committed
619
{
dickelbeck's avatar
dickelbeck committed
620
    wxString ret;
dickelbeck's avatar
dickelbeck committed
621

dickelbeck's avatar
dickelbeck committed
622
    wxASSERT( aLayer >= FIRST_COPPER_LAYER && aLayer <= LAST_COPPER_LAYER );
dickelbeck's avatar
dickelbeck committed
623

dickelbeck's avatar
dickelbeck committed
624
    wxTextCtrl*  ctl = (wxTextCtrl*) getName( aLayer );
dickelbeck's avatar
dickelbeck committed
625

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

dickelbeck's avatar
dickelbeck committed
628
    return ret;
dickelbeck's avatar
dickelbeck committed
629 630
}

dickelbeck's avatar
dickelbeck committed
631 632 633 634 635 636 637
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
638

dickelbeck's avatar
dickelbeck committed
639
bool DIALOG_LAYERS_SETUP::testLayerNames()
dickelbeck's avatar
dickelbeck committed
640
{
dickelbeck's avatar
dickelbeck committed
641 642 643
    std::vector<wxString>    names;

    wxTextCtrl*  ctl;
dickelbeck's avatar
dickelbeck committed
644

dickelbeck's avatar
dickelbeck committed
645
    for( int layer=0;  layer<=LAST_COPPER_LAYER;  ++layer )
dickelbeck's avatar
dickelbeck committed
646
    {
dickelbeck's avatar
dickelbeck committed
647 648 649
        // we _can_ rely on m_EnabledLayers being current here:
        if( !(m_EnabledLayers & (1<<layer)) )
            continue;
650

dickelbeck's avatar
dickelbeck committed
651
        wxString name = getLayerName( layer );
dickelbeck's avatar
dickelbeck committed
652

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

dickelbeck's avatar
dickelbeck committed
655
        ctl = (wxTextCtrl*) getName( layer );
dickelbeck's avatar
dickelbeck committed
656

dickelbeck's avatar
dickelbeck committed
657 658 659 660 661 662
        // check name for legality.
        // 1) cannot be blank.
        // 2) cannot have blanks.
        // 3) cannot have " chars
        // 4) cannot be 'signal'
        // 5) must be unique.
663 664
        // 6) cannot have illegal chars in filenames ( some filenames are built from layer names )
        static const wxString badchars( wxT("%$\" /\\.") );
dickelbeck's avatar
dickelbeck committed
665

dickelbeck's avatar
dickelbeck committed
666 667 668 669 670 671
        if( name == wxEmptyString )
        {
            DisplayError( this, _("Layer name may not be empty" ) );
            ctl->SetFocus();    // on the bad name
            return false;
        }
dickelbeck's avatar
dickelbeck committed
672

dickelbeck's avatar
dickelbeck committed
673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700
        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
701 702
}

dickelbeck's avatar
dickelbeck committed
703

704
void PCB_EDIT_FRAME::InstallDialogLayerSetup()
dickelbeck's avatar
dickelbeck committed
705
{
jean-pierre charras's avatar
jean-pierre charras committed
706
    DIALOG_LAYERS_SETUP dlg( this );
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

    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.
    if( ( ( 1 << getActiveLayer() ) & GetBoard()->GetEnabledLayers() ) == 0 )
    {
        for( int i = 0;  i < LAYER_COUNT;  i++ )
        {
            int tmp = i;

            if( i >= LAYER_COUNT )
                tmp = i - LAYER_COUNT;

            if( ( 1 << tmp ) & GetBoard()->GetEnabledLayers() )
            {
                wxLogDebug( wxT( "Setting current layer to  %d." ), getActiveLayer() );
                setActiveLayer( tmp, true );
                break;
            }
        }
    }
    else
    {
        setActiveLayer( getActiveLayer(), true );
    }
dickelbeck's avatar
dickelbeck committed
736
}