KiCad PCB EDA Suite
panel_setup_layers.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2009 Isaac Marino Bavaresco, [email protected]
5 * Copyright (C) 2009 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6 * Copyright (C) 2009-2021 KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26
27#include <confirm.h>
28#include <core/arraydim.h>
29#include <core/kicad_algo.h>
30#include <pcbnew.h>
31#include <pcb_edit_frame.h>
32#include <board.h>
33#include <collectors.h>
34#include <footprint.h>
35#include <pad.h>
36#include <pcb_track.h>
37#include <panel_setup_layers.h>
39
40#include <wx/choicdlg.h>
41#include <wx/treebook.h>
42#include <eda_list_dialog.h>
43
44
45// some define to choose how copper layers widgets are shown
46
47// if defined, display only active copper layers
48// if not displays always 1=the full set (32 copper layers)
49#define HIDE_INACTIVE_LAYERS
50
51
53{
54 // Layers that are put out into the dialog UI, coordinate with wxformbuilder and
55 // getCTLs( int aLayerNumber )
56 static const PCB_LAYER_ID layers[] = {
57 F_CrtYd,
58 F_Fab,
59 F_Adhes,
60 F_Paste,
61 F_SilkS,
62 F_Mask,
63 F_Cu,
64
65 In1_Cu,
66 In2_Cu,
67 In3_Cu,
68 In4_Cu,
69 In5_Cu,
70 In6_Cu,
71 In7_Cu,
72 In8_Cu,
73 In9_Cu,
74 In10_Cu,
75 In11_Cu,
76 In12_Cu,
77 In13_Cu,
78 In14_Cu,
79 In15_Cu,
80
81 In16_Cu,
82 In17_Cu,
83 In18_Cu,
84 In19_Cu,
85 In20_Cu,
86 In21_Cu,
87 In22_Cu,
88 In23_Cu,
89 In24_Cu,
90 In25_Cu,
91 In26_Cu,
92 In27_Cu,
93 In28_Cu,
94 In29_Cu,
95 In30_Cu,
96
97 B_Cu,
98 B_Mask,
99 B_SilkS,
100 B_Paste,
101 B_Adhes,
102 B_Fab,
103 B_CrtYd,
104
105 Edge_Cuts,
106 Margin,
107 Eco2_User,
108 Eco1_User,
109 Cmts_User,
110 Dwgs_User,
111
112 User_1,
113 User_2,
114 User_3,
115 User_4,
116 User_5,
117 User_6,
118 User_7,
119 User_8,
120 User_9,
121 };
122
123 return LSEQ( layers, layers + arrayDim( layers ) );
124}
125
126
128 PANEL_SETUP_LAYERS_BASE( aParent->GetTreebook() ),
129 m_parentDialog( aParent ),
130 m_frame( aFrame ),
131 m_physicalStackup( nullptr ),
132 m_initialized( false )
133{
134 m_pcb = aFrame->GetBoard();
135}
136
137
139{
140#define RETURN_COPPER( x ) return PANEL_SETUP_LAYERS_CTLs( x##Name, x##CheckBox, x##Choice )
141#define RETURN_AUX( x ) return PANEL_SETUP_LAYERS_CTLs( x##Name, x##CheckBox, x##StaticText )
142#define RETURN_MANDATORY( x ) return PANEL_SETUP_LAYERS_CTLs( x##Name, nullptr, x##StaticText )
143
144 switch( aLayerNumber )
145 {
146 case F_CrtYd: RETURN_MANDATORY( m_CrtYdFront );
147 case F_Fab: RETURN_AUX( m_FabFront );
148 case F_Adhes: RETURN_AUX( m_AdhesFront );
149 case F_Paste: RETURN_AUX( m_SoldPFront );
150 case F_SilkS: RETURN_AUX( m_SilkSFront );
151 case F_Mask: RETURN_AUX( m_MaskFront );
152 case F_Cu: RETURN_COPPER( m_Front );
153
154 case In1_Cu: RETURN_COPPER( m_In1 );
155 case In2_Cu: RETURN_COPPER( m_In2 );
156 case In3_Cu: RETURN_COPPER( m_In3 );
157 case In4_Cu: RETURN_COPPER( m_In4 );
158 case In5_Cu: RETURN_COPPER( m_In5 );
159 case In6_Cu: RETURN_COPPER( m_In6 );
160 case In7_Cu: RETURN_COPPER( m_In7 );
161 case In8_Cu: RETURN_COPPER( m_In8 );
162 case In9_Cu: RETURN_COPPER( m_In9 );
163 case In10_Cu: RETURN_COPPER( m_In10 );
164 case In11_Cu: RETURN_COPPER( m_In11 );
165 case In12_Cu: RETURN_COPPER( m_In12 );
166 case In13_Cu: RETURN_COPPER( m_In13 );
167 case In14_Cu: RETURN_COPPER( m_In14 );
168 case In15_Cu: RETURN_COPPER( m_In15 );
169
170 case In16_Cu: RETURN_COPPER( m_In16 );
171 case In17_Cu: RETURN_COPPER( m_In17 );
172 case In18_Cu: RETURN_COPPER( m_In18 );
173 case In19_Cu: RETURN_COPPER( m_In19 );
174 case In20_Cu: RETURN_COPPER( m_In20 );
175 case In21_Cu: RETURN_COPPER( m_In21 );
176 case In22_Cu: RETURN_COPPER( m_In22 );
177 case In23_Cu: RETURN_COPPER( m_In23 );
178 case In24_Cu: RETURN_COPPER( m_In24 );
179 case In25_Cu: RETURN_COPPER( m_In25 );
180 case In26_Cu: RETURN_COPPER( m_In26 );
181 case In27_Cu: RETURN_COPPER( m_In27 );
182 case In28_Cu: RETURN_COPPER( m_In28 );
183 case In29_Cu: RETURN_COPPER( m_In29 );
184 case In30_Cu: RETURN_COPPER( m_In30 );
185
186 case B_Cu: RETURN_COPPER( m_Back );
187 case B_Mask: RETURN_AUX( m_MaskBack );
188 case B_SilkS: RETURN_AUX( m_SilkSBack );
189 case B_Paste: RETURN_AUX( m_SoldPBack );
190 case B_Adhes: RETURN_AUX( m_AdhesBack );
191 case B_Fab: RETURN_AUX( m_FabBack );
192 case B_CrtYd: RETURN_MANDATORY( m_CrtYdBack );
193
194 case Edge_Cuts: RETURN_MANDATORY( m_PCBEdges );
195 case Margin: RETURN_MANDATORY( m_Margin );
196 case Eco2_User: RETURN_AUX( m_Eco2 );
197 case Eco1_User: RETURN_AUX( m_Eco1 );
198 case Cmts_User: RETURN_AUX( m_Comments );
199 case Dwgs_User: RETURN_AUX( m_Drawings );
200
201 case User_1: RETURN_AUX( m_User1 );
202 case User_2: RETURN_AUX( m_User2 );
203 case User_3: RETURN_AUX( m_User3 );
204 case User_4: RETURN_AUX( m_User4 );
205 case User_5: RETURN_AUX( m_User5 );
206 case User_6: RETURN_AUX( m_User6 );
207 case User_7: RETURN_AUX( m_User7 );
208 case User_8: RETURN_AUX( m_User8 );
209 case User_9: RETURN_AUX( m_User9 );
210
211 default:
212 wxASSERT_MSG( 0, wxT( "bad layer id" ) );
213 return PANEL_SETUP_LAYERS_CTLs( nullptr, nullptr, nullptr );
214 }
215}
216
217
218wxControl* PANEL_SETUP_LAYERS::getName( int aLayer )
219{
220 return getCTLs( aLayer ).name;
221}
222
223
224wxCheckBox* PANEL_SETUP_LAYERS::getCheckBox( int aLayer )
225{
226 return getCTLs( aLayer ).checkbox;
227}
228
229
230wxChoice* PANEL_SETUP_LAYERS::getChoice( int aLayer )
231{
232 return (wxChoice*) getCTLs( aLayer ).choice;
233}
234
235
237{
239
240 // Rescue may be enabled, but should not be shown in this dialog
241 m_enabledLayers.reset( Rescue );
242
244
247
251
252 m_initialized = true;
253
254 return true;
255}
256
257
258void PANEL_SETUP_LAYERS::SyncCopperLayers( int aNumCopperLayers )
259{
260 setCopperLayerCheckBoxes( aNumCopperLayers );
261}
262
263
265{
266 for( int layer : { F_CrtYd, B_CrtYd, Edge_Cuts, Margin } )
267 setLayerCheckBox( layer, true );
268}
269
270
272{
273 for( LSEQ seq = LSET::UserDefinedLayers().Seq(); seq; ++seq )
274 {
275 PCB_LAYER_ID layer = *seq;
276 bool state = m_pcb->IsLayerEnabled( layer );
277
278#ifdef HIDE_INACTIVE_LAYERS
279 // This code hides inactive copper layers, or redisplays hidden layers which are now needed.
280 PANEL_SETUP_LAYERS_CTLs ctl = getCTLs( layer );
281
282 // All user-defined layers should have a checkbox
283 wxASSERT( ctl.checkbox );
284
285 ctl.name->Show( state );
286 ctl.checkbox->Show( state );
287 ctl.choice->Show( state );
288#endif
289
290 setLayerCheckBox( layer, state );
291 }
292
293#ifdef HIDE_INACTIVE_LAYERS
294 // Send an size event to force sizers to be updated,
295 // because the number of copper layers can have changed.
296 wxSizeEvent evt_size( m_LayersListPanel->GetSize() );
297 m_LayersListPanel->GetEventHandler()->ProcessEvent( evt_size );
298#endif
299}
300
301
303{
304 // Set all the board's layer names into the dialog by calling BOARD::GetLayerName(),
305 // which will call BOARD::GetStandardLayerName() for non-coppers.
306
307 for( LSEQ seq = dlg_layers(); seq; ++seq )
308 {
309 PCB_LAYER_ID layer = *seq;
310 wxControl* ctl = getName( layer );
311
312 if( ctl )
313 {
314 wxString lname = m_pcb->GetLayerName( layer );
315
316 if( auto textCtl = dynamic_cast<wxTextCtrl*>( ctl ) )
317 textCtl->ChangeValue( lname ); // wxTextCtrl
318 else
319 ctl->SetLabel( lname ); // wxStaticText
320 }
321 }
322}
323
324
326{
327 // The check boxes
328 for( LSEQ seq = dlg_layers(); seq; ++seq )
329 {
330 PCB_LAYER_ID layer = *seq;
331 setLayerCheckBox( layer, enabledLayers[layer] );
332 }
333}
334
335
337{
338 for( LSEQ seq = LSET::AllCuMask().Seq(); seq; ++seq )
339 {
340 PCB_LAYER_ID cu_layer = *seq;
341
342 wxChoice* ctl = getChoice( cu_layer );
343 ctl->SetSelection( m_pcb->GetLayerType( cu_layer ) );
344 }
345}
346
347
349{
350 LSET layerMaskResult;
351
352 for( LSEQ seq = dlg_layers(); seq; ++seq )
353 {
354 PCB_LAYER_ID layer = *seq;
355 wxCheckBox* ctl = getCheckBox( layer );
356
357 if( !ctl || ctl->GetValue() )
358 layerMaskResult.set( layer );
359 }
360
361 return layerMaskResult;
362}
363
364
365void PANEL_SETUP_LAYERS::setLayerCheckBox( int aLayer, bool isChecked )
366{
367 PANEL_SETUP_LAYERS_CTLs ctl = getCTLs( aLayer );
368
369 if( !ctl.checkbox )
370 return;
371
372 ctl.checkbox->SetValue( isChecked );
373}
374
375
377{
378 if( copperCount > 0 )
379 {
380 setLayerCheckBox( F_Cu, true );
381 --copperCount;
382 }
383
384 if( copperCount > 0 )
385 {
386 setLayerCheckBox( B_Cu, true );
387 --copperCount;
388 }
389
390 for( LSEQ seq = LSET::InternalCuMask().Seq(); seq; ++seq, --copperCount )
391 {
392 PCB_LAYER_ID layer = *seq;
393 bool state = copperCount > 0;
394
395#ifdef HIDE_INACTIVE_LAYERS
396 // This code hides inactive copper layers, or redisplays hidden layers which are now needed.
397 PANEL_SETUP_LAYERS_CTLs ctl = getCTLs( layer );
398
399 // Inner layers should have a checkbox
400 wxASSERT( ctl.checkbox );
401
402 ctl.name->Show( state );
403 ctl.checkbox->Show( state );
404 ctl.choice->Show( state );
405#endif
406
407 setLayerCheckBox( layer, state );
408 }
409
410#ifdef HIDE_INACTIVE_LAYERS
411 // Send an size event to force sizers to be updated,
412 // because the number of copper layers can have changed.
413 wxSizeEvent evt_size( m_LayersListPanel->GetSize() );
414 m_LayersListPanel->GetEventHandler()->ProcessEvent( evt_size );
415#endif
416}
417
418
419void PANEL_SETUP_LAYERS::OnCheckBox( wxCommandEvent& event )
420{
422}
423
424
425void PANEL_SETUP_LAYERS::DenyChangeCheckBox( wxCommandEvent& event )
426{
427 wxObject* source = event.GetEventObject();
428
429 for( LSEQ seq = LSET::AllCuMask().Seq(); seq; ++seq )
430 {
431 wxCheckBox* copper = getCheckBox( *seq );
432
433 if( source == copper )
434 {
435 DisplayError( this, _( "Use the Physical Stackup page to change the number of "
436 "copper layers." ) );
437
438 copper->SetValue( true );
439 return;
440 }
441 }
442}
443
444
446{
447 if( !testLayerNames() )
448 return false;
449
450 wxASSERT( m_physicalStackup );
451
452 // Make sure we have the latest copper layer count
454
455 wxString msg;
456 bool modified = false;
457
458 // Check for removed layers with items which will get deleted from the board.
459 LSEQ removedLayers = getRemovedLayersWithItems();
460
461 // Check for non-copper layers in use in footprints, and therefore not removable.
462 LSEQ notremovableLayers = getNonRemovableLayers();
463
464 if( !notremovableLayers.empty() )
465 {
466 for( unsigned int ii = 0; ii < notremovableLayers.size(); ii++ )
467 msg << m_pcb->GetLayerName( notremovableLayers[ii] ) << wxT( "\n" );
468
469 if( !IsOK( this, wxString::Format( _( "Footprints have some items on removed layers:\n"
470 "%s\n"
471 "These items will be no longer accessible\n"
472 "Do you wish to continue?" ), msg ) ) )
473 {
474 return false;
475 }
476 }
477
478 if( !removedLayers.empty()
479 && !IsOK( this, _( "Items have been found on removed layers. This operation will "
480 "delete all items from removed layers and cannot be undone.\n"
481 "Do you wish to continue?" ) ) )
482 {
483 return false;
484 }
485
486 // Delete all objects on layers that have been removed. Leaving them in copper layers
487 // can (will?) result in DRC errors and it pollutes the board file with cruft.
488 bool hasRemovedBoardItems = false;
489
490 if( !removedLayers.empty() )
491 {
492 PCB_LAYER_COLLECTOR collector;
493
494 for( PCB_LAYER_ID layer_id : removedLayers )
495 {
496 collector.SetLayerId( layer_id );
498
499 // Bye-bye items on removed layer.
500 for( int i = 0; i < collector.GetCount(); i++ )
501 {
502 BOARD_ITEM* item = collector[i];
503 LSET layers = item->GetLayerSet();
504
505 layers.reset( layer_id );
506 hasRemovedBoardItems = true;
507 modified = true;
508
509 if( layers.any() )
510 {
511 item->SetLayerSet( layers );
512 }
513 else
514 {
515 m_pcb->Remove( item );
516 delete item;
517 }
518 }
519 }
520 }
521
523
524 LSET previousEnabled = m_pcb->GetEnabledLayers();
525
526 if( m_enabledLayers != previousEnabled )
527 {
529
530 LSET changedLayers = m_enabledLayers ^ previousEnabled;
531
532 /*
533 * Ensure enabled layers are also visible. This is mainly to avoid mistakes if some
534 * enabled layers are not visible when exiting this dialog.
535 */
536 m_pcb->SetVisibleLayers( m_pcb->GetVisibleLayers() | changedLayers );
537
538 /*
539 * Ensure items with through holes have all inner copper layers. (For historical reasons
540 * this is NOT trimmed to the currently-enabled inner layers.)
541 */
542 for( FOOTPRINT* fp : m_pcb->Footprints() )
543 {
544 for( PAD* pad : fp->Pads() )
545 {
546 if( pad->HasHole() && pad->IsOnCopperLayer() )
547 pad->SetLayerSet( pad->GetLayerSet() | LSET::InternalCuMask() );
548 }
549 }
550
551 for( PCB_TRACK* via : m_pcb->Tracks() )
552 {
553 if( via->HasHole() )
554 via->SetLayerSet( via->GetLayerSet() | LSET::InternalCuMask() );
555 }
556
557 modified = true;
558 }
559
560 for( LSEQ seq = LSET::AllLayersMask().Seq(); seq; ++seq )
561 {
562 PCB_LAYER_ID layer = *seq;
563
564 if( m_enabledLayers[layer] )
565 {
566 const wxString& newLayerName = GetLayerName( layer );
567
568 if( m_pcb->GetLayerName( layer ) != newLayerName )
569 {
570 m_pcb->SetLayerName( layer, newLayerName );
571 modified = true;
572 }
573
574 // Only copper layers have a definable type.
575 if( LSET::AllCuMask().Contains( layer ) )
576 {
577 LAYER_T t = (LAYER_T) getLayerTypeIndex( layer );
578
579 if( m_pcb->GetLayerType( layer ) != t )
580 {
581 m_pcb->SetLayerType( layer, t );
582 modified = true;
583 }
584 }
585 }
586 }
587
588 for( LSEQ seq = LSET::UserDefinedLayers().Seq(); seq; ++seq )
589 {
590 PCB_LAYER_ID layer = *seq;
591 const wxString& newLayerName = GetLayerName( layer );
592
593 if( m_enabledLayers[ layer ] && m_pcb->GetLayerName( layer ) != newLayerName )
594 {
595 m_pcb->SetLayerName( layer, newLayerName );
596 modified = true;
597 }
598 }
599
600 // If some board items are deleted: Rebuild the connectivity, because it is likely some
601 // tracks and vias were removed
602 if( hasRemovedBoardItems )
604
605 if( modified )
606 m_frame->OnModify();
607
608 return true;
609}
610
611
613{
614 wxChoice* ctl = getChoice( aLayer );
615 int ret = ctl->GetCurrentSelection(); // Indices must have same sequence as LAYER_T
616 return ret;
617}
618
619
621{
622 wxControl* control = getName( aLayer );
623
624 if( auto textCtl = dynamic_cast<wxTextCtrl*>( control ) )
625 return textCtl->GetValue().Trim();
626 else
627 return control->GetLabel();
628}
629
630
631static bool hasOneOf( const wxString& str, const wxString& chars )
632{
633 for( unsigned i=0; i<chars.Len(); ++i )
634 {
635 if( str.Find( chars[i] ) != wxNOT_FOUND )
636 return true;
637 }
638
639 return false;
640}
641
642
644{
645 std::vector<wxString> names;
646 wxTextCtrl* ctl;
647
648 for( LSEQ seq = LSET::AllLayersMask().Seq(); seq; ++seq )
649 {
650 PCB_LAYER_ID layer = *seq;
651
652 // we _can_ rely on m_enabledLayers being current here:
653
654 if( !m_enabledLayers[layer] )
655 continue;
656
657 wxString name = GetLayerName( layer );
658
659 ctl = (wxTextCtrl*) getName( layer );
660
661 // Check name for legality:
662 // 1) Cannot be blank.
663 // 2) Cannot have blanks.
664 // 3) Cannot have " chars
665 // 4) Cannot be 'signal'
666 // 5) Must be unique.
667 // 6) Cannot have illegal chars in filenames ( some filenames are built from layer names )
668 // like : % $ \ " / :
669 wxString badchars = wxFileName::GetForbiddenChars( wxPATH_DOS );
670 badchars.Append( '%' );
671
672 if( !name )
673 {
674 m_parentDialog->SetError( _( "Layer must have a name." ), this, ctl );
675 return false;
676 }
677
678 if( hasOneOf( name, badchars ) )
679 {
680 wxString msg = wxString::Format(_( "%s are forbidden in layer names." ), badchars );
681 m_parentDialog->SetError( msg, this, ctl );
682 return false;
683 }
684
685 if( name == wxT( "signal" ) )
686 {
687 m_parentDialog->SetError( _( "Layer name \"signal\" is reserved." ), this, ctl );
688 return false;
689 }
690
691 for( const wxString& existingName : names )
692 {
693 if( name == existingName )
694 {
695 wxString msg = wxString::Format(_( "Layer name '%s' already in use." ), name );
696 m_parentDialog->SetError( msg, this, ctl );
697 return false;
698 }
699 }
700
701 names.push_back( name );
702 }
703
704 return true;
705}
706
707
709{
710 LSEQ removedLayers;
711 LSET newLayers = GetUILayerMask();
712 LSET curLayers = m_pcb->GetEnabledLayers();
713
714 if( newLayers == curLayers ) // Return an empty list if no change
715 return removedLayers;
716
717 PCB_LAYER_COLLECTOR collector;
718 LSEQ newLayerSeq = newLayers.Seq();
719
720 for( PCB_LAYER_ID layer_id : curLayers.Seq() )
721 {
722 if( !alg::contains( newLayerSeq, layer_id ) )
723 {
724 collector.SetLayerId( layer_id );
726
727 if( collector.GetCount() != 0 )
728 removedLayers.push_back( layer_id );
729 }
730 }
731
732 return removedLayers;
733}
734
735
737{
738 // Build the list of non-copper layers in use in footprints.
739 LSEQ inUseLayers;
740 LSET newLayers = GetUILayerMask();
741 LSET curLayers = m_pcb->GetEnabledLayers();
742
743 if( newLayers == curLayers ) // Return an empty list if no change
744 return inUseLayers;
745
746 PCB_LAYER_COLLECTOR collector;
747 LSEQ newLayerSeq = newLayers.Seq();
748
749 for( PCB_LAYER_ID layer_id : curLayers.Seq() )
750 {
751 if( IsCopperLayer( layer_id ) ) // Copper layers are not taken into account here
752 continue;
753
754 if( !alg::contains( newLayerSeq, layer_id ) )
755 {
756 collector.SetLayerId( layer_id );
758
759 if( collector.GetCount() != 0 )
760 inUseLayers.push_back( layer_id );
761 }
762 }
763
764 return inUseLayers;
765}
766
767
769{
770 BOARD* savedBoard = m_pcb;
771
772 m_pcb = aBoard;
774
775 m_pcb = savedBoard;
776}
777
778
779bool PANEL_SETUP_LAYERS::CheckCopperLayerCount( BOARD* aWorkingBoard, BOARD* aImportedBoard )
780{
781 /*
782 * This function warns users if they are going to delete inner copper layers because
783 * they're importing settings from a board with less copper layers than the board
784 * already loaded. We want to return "true" as default on the assumption no layer will
785 * actually be deleted.
786 */
787 bool okToDeleteCopperLayers = true;
788
789 // Get the number of copper layers in the loaded board and the "import settings" board
790 int currNumLayers = aWorkingBoard->GetCopperLayerCount();
791 int newNumLayers = aImportedBoard->GetCopperLayerCount();
792
793 if( newNumLayers < currNumLayers )
794 {
795 wxString msg = wxString::Format( _( "Imported settings have fewer copper layers than "
796 "the current board (%i instead of %i).\n\n"
797 "Continue and delete the extra inner copper layers "
798 "from the current board?" ),
799 newNumLayers,
800 currNumLayers );
801
802 wxMessageDialog dlg( this, msg, _( "Inner Layers To Be Deleted" ),
803 wxICON_WARNING | wxSTAY_ON_TOP | wxYES | wxNO | wxNO_DEFAULT );
804
805 if( wxID_NO == dlg.ShowModal() )
806 okToDeleteCopperLayers = false;
807 }
808
809 return okToDeleteCopperLayers;
810}
811
812
813void PANEL_SETUP_LAYERS::addUserDefinedLayer( wxCommandEvent& aEvent )
814{
815 wxArrayString headers;
816 headers.Add( _( "Layers" ) );
817
818 // Build the available user-defined layers list:
819 std::vector<wxArrayString> list;
820
821 for( LSEQ seq = LSET::UserDefinedLayers().Seq(); seq; ++seq )
822 {
823 wxCheckBox* checkBox = getCheckBox( *seq );
824
825 if( checkBox && checkBox->IsShown() )
826 continue;
827
828 wxArrayString available_user_layer;
829 available_user_layer.Add( LayerName( *seq ) );
830
831 list.emplace_back( available_user_layer );
832 }
833
834 if( list.empty() )
835 {
837 _( "All user-defined layers have already been added." ) );
838 return;
839 }
840
841 EDA_LIST_DIALOG dlg( m_parentDialog, _( "Add User-defined Layer" ), headers, list );
842 dlg.SetListLabel( _( "Select layer to add:" ) );
843 dlg.HideFilter();
844
845 if( dlg.ShowModal() == wxID_CANCEL || dlg.GetTextSelection().IsEmpty() )
846 return;
847
848 LSEQ seq;
849
850 for( seq = LSET::UserDefinedLayers().Seq(); seq; ++seq )
851 {
852 if( LayerName( *seq ) == dlg.GetTextSelection() )
853 break;
854 }
855
856 wxCHECK( *seq >= User_1 && *seq <= User_9, /* void */ );
857
858 LSET newLayer( *seq );
859
860 m_enabledLayers |= newLayer;
861
862 PANEL_SETUP_LAYERS_CTLs ctl = getCTLs( *seq );
863
864 // All user-defined layers should have a checkbox
865 wxASSERT( ctl.checkbox );
866
867 wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( ctl.name );
868
869 wxCHECK( textCtrl, /* void */ );
870 textCtrl->ChangeValue( LSET::Name( *seq ) );
871 ctl.name->Show( true );
872 ctl.checkbox->Show( true );
873 ctl.choice->Show( true );
874
875 wxSizeEvent evt_size( m_LayersListPanel->GetSize() );
876 m_LayersListPanel->GetEventHandler()->ProcessEvent( evt_size );
877
878 setLayerCheckBox( *seq, true );
879}
880
881
const char * name
Definition: DXF_plotter.cpp:56
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
LAYER_T
The allowed types of layers, same as Specctra DSN spec.
Definition: board.h:147
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:70
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:197
virtual void SetLayerSet(LSET aLayers)
Definition: board_item.h:205
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:269
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:587
LSET GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:601
void SetEnabledLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:607
bool BuildConnectivity(PROGRESS_REPORTER *aReporter=nullptr)
Build or rebuild the board connectivity database for the board, especially the list of connected item...
Definition: board.cpp:166
bool IsLayerEnabled(PCB_LAYER_ID aLayer) const
A proxy function that calls the correspondent function in m_BoardSettings tests whether a given layer...
Definition: board.cpp:613
LAYER_T GetLayerType(PCB_LAYER_ID aLayer) const
Return the type of the copper layer given by aLayer.
Definition: board.cpp:508
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Changes the name of the layer given by aLayer.
Definition: board.cpp:490
FOOTPRINTS & Footprints()
Definition: board.h:311
int GetCopperLayerCount() const
Definition: board.cpp:563
TRACKS & Tracks()
Definition: board.h:308
void SetVisibleLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings changes the bit-mask of vis...
Definition: board.cpp:619
bool SetLayerType(PCB_LAYER_ID aLayer, LAYER_T aLayerType)
Change the type of the layer given by aLayer.
Definition: board.cpp:520
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:474
void Remove(BOARD_ITEM *aBoardItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition: board.cpp:881
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:81
A dialog which shows:
wxString GetTextSelection(int aColumn=0)
Return the selected text from aColumn in the wxListCtrl in the dialog.
void SetListLabel(const wxString &aLabel)
static const std::vector< KICAD_T > BoardLevelItems
A scan list for all primary board items, omitting items which are subordinate to a FOOTPRINT,...
Definition: collectors.h:235
static const std::vector< KICAD_T > FootprintItems
A scan list for primary footprint items.
Definition: collectors.h:250
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: layer_ids.h:493
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:532
static LSET AllLayersMask()
Definition: lset.cpp:808
static LSET UserDefinedLayers()
Return a mask with all of the allowable user defined layers.
Definition: lset.cpp:877
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:411
static LSET InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
Definition: lset.cpp:733
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:773
static const wxChar * Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Definition: lset.cpp:82
Definition: pad.h:60
void SetError(const wxString &aMessage, const wxString &aPageName, int aCtrlId, int aRow=-1, int aCol=-1)
Class PANEL_SETUP_LAYERS_BASE.
wxScrolledWindow * m_LayersListPanel
wxString GetLayerName(int layer)
PANEL_SETUP_LAYERS_CTLs getCTLs(int aLayerNumber)
void showSelectedLayerCheckBoxes(LSET enableLayerMask)
bool CheckCopperLayerCount(BOARD *aWorkingBoard, BOARD *aImportedBoard)
Check and warn if inner copper layers will be deleted.
void DenyChangeCheckBox(wxCommandEvent &event) override
bool TransferDataToWindow() override
int getLayerTypeIndex(int layer)
virtual void addUserDefinedLayer(wxCommandEvent &aEvent) override
void SyncCopperLayers(int aNumCopperLayers)
Called when switching to this tab to make sure that any changes to the copper layer count made on the...
void setLayerCheckBox(int layer, bool isChecked)
PANEL_SETUP_BOARD_STACKUP * m_physicalStackup
PCB_EDIT_FRAME * m_frame
LSEQ getNonRemovableLayers()
Return a list of layers in use in footprints, and therefore not removable.
void setCopperLayerCheckBoxes(int copperCount)
wxControl * getName(int aLayer)
PANEL_SETUP_LAYERS(PAGED_DIALOG *aParent, PCB_EDIT_FRAME *aFrame)
wxChoice * getChoice(int aLayer)
LSEQ getRemovedLayersWithItems()
Return a list of layers removed from the board that contain items.
bool TransferDataFromWindow() override
void OnCheckBox(wxCommandEvent &event) override
void ImportSettingsFrom(BOARD *aBoard)
wxCheckBox * getCheckBox(int aLayer)
PAGED_DIALOG * m_parentDialog
BOARD * GetBoard() const
The main frame for Pcbnew.
void OnModify() override
Must be called after a board change to set the modified flag.
Collect all BOARD_ITEM objects on a given layer.
Definition: collectors.h:550
void Collect(BOARD_ITEM *aBoard, const std::vector< KICAD_T > &aTypes)
Test a BOARD_ITEM using this class's Inspector method, which does the collection.
Definition: collectors.cpp:649
void SetLayerId(PCB_LAYER_ID aLayerId)
Definition: collectors.h:556
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:380
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:300
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:325
This file is part of the common library.
#define _(s)
wxString LayerName(int aLayer)
Returns the default display name for a given layer.
Definition: layer_id.cpp:30
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:827
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:59
@ In22_Cu
Definition: layer_ids.h:86
@ In11_Cu
Definition: layer_ids.h:75
@ In29_Cu
Definition: layer_ids.h:93
@ In30_Cu
Definition: layer_ids.h:94
@ User_8
Definition: layer_ids.h:130
@ F_CrtYd
Definition: layer_ids.h:117
@ In17_Cu
Definition: layer_ids.h:81
@ B_Adhes
Definition: layer_ids.h:97
@ Edge_Cuts
Definition: layer_ids.h:113
@ Dwgs_User
Definition: layer_ids.h:109
@ F_Paste
Definition: layer_ids.h:101
@ In9_Cu
Definition: layer_ids.h:73
@ Cmts_User
Definition: layer_ids.h:110
@ User_6
Definition: layer_ids.h:128
@ User_7
Definition: layer_ids.h:129
@ In19_Cu
Definition: layer_ids.h:83
@ In7_Cu
Definition: layer_ids.h:71
@ In28_Cu
Definition: layer_ids.h:92
@ In26_Cu
Definition: layer_ids.h:90
@ F_Adhes
Definition: layer_ids.h:98
@ B_Mask
Definition: layer_ids.h:106
@ B_Cu
Definition: layer_ids.h:95
@ User_5
Definition: layer_ids.h:127
@ Eco1_User
Definition: layer_ids.h:111
@ F_Mask
Definition: layer_ids.h:107
@ In21_Cu
Definition: layer_ids.h:85
@ In23_Cu
Definition: layer_ids.h:87
@ B_Paste
Definition: layer_ids.h:100
@ In15_Cu
Definition: layer_ids.h:79
@ In2_Cu
Definition: layer_ids.h:66
@ User_9
Definition: layer_ids.h:131
@ F_Fab
Definition: layer_ids.h:120
@ In10_Cu
Definition: layer_ids.h:74
@ Margin
Definition: layer_ids.h:114
@ F_SilkS
Definition: layer_ids.h:104
@ In4_Cu
Definition: layer_ids.h:68
@ B_CrtYd
Definition: layer_ids.h:116
@ Eco2_User
Definition: layer_ids.h:112
@ In16_Cu
Definition: layer_ids.h:80
@ In24_Cu
Definition: layer_ids.h:88
@ In1_Cu
Definition: layer_ids.h:65
@ Rescue
Definition: layer_ids.h:133
@ User_3
Definition: layer_ids.h:125
@ User_1
Definition: layer_ids.h:123
@ B_SilkS
Definition: layer_ids.h:103
@ In13_Cu
Definition: layer_ids.h:77
@ User_4
Definition: layer_ids.h:126
@ In8_Cu
Definition: layer_ids.h:72
@ In14_Cu
Definition: layer_ids.h:78
@ User_2
Definition: layer_ids.h:124
@ In12_Cu
Definition: layer_ids.h:76
@ In27_Cu
Definition: layer_ids.h:91
@ In6_Cu
Definition: layer_ids.h:70
@ In5_Cu
Definition: layer_ids.h:69
@ In3_Cu
Definition: layer_ids.h:67
@ In20_Cu
Definition: layer_ids.h:84
@ F_Cu
Definition: layer_ids.h:64
@ In18_Cu
Definition: layer_ids.h:82
@ In25_Cu
Definition: layer_ids.h:89
@ B_Fab
Definition: layer_ids.h:119
must_if< error >::control< Rule > control
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:99
#define RETURN_AUX(x)
#define RETURN_MANDATORY(x)
static LSEQ dlg_layers()
#define RETURN_COPPER(x)
static bool hasOneOf(const wxString &str, const wxString &chars)
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
The 3 UI control pointers for a single board layer.