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{
133 m_pcb = aFrame->GetBoard();
134}
135
136
138{
139#define RETURN_COPPER( x ) return PANEL_SETUP_LAYERS_CTLs( x##Name, x##CheckBox, x##Choice )
140#define RETURN_AUX( x ) return PANEL_SETUP_LAYERS_CTLs( x##Name, x##CheckBox, x##StaticText )
141#define RETURN_MANDATORY( x ) return PANEL_SETUP_LAYERS_CTLs( x##Name, nullptr, x##StaticText )
142
143 switch( aLayerNumber )
144 {
145 case F_CrtYd: RETURN_MANDATORY( m_CrtYdFront );
146 case F_Fab: RETURN_AUX( m_FabFront );
147 case F_Adhes: RETURN_AUX( m_AdhesFront );
148 case F_Paste: RETURN_AUX( m_SoldPFront );
149 case F_SilkS: RETURN_AUX( m_SilkSFront );
150 case F_Mask: RETURN_AUX( m_MaskFront );
151 case F_Cu: RETURN_COPPER( m_Front );
152
153 case In1_Cu: RETURN_COPPER( m_In1 );
154 case In2_Cu: RETURN_COPPER( m_In2 );
155 case In3_Cu: RETURN_COPPER( m_In3 );
156 case In4_Cu: RETURN_COPPER( m_In4 );
157 case In5_Cu: RETURN_COPPER( m_In5 );
158 case In6_Cu: RETURN_COPPER( m_In6 );
159 case In7_Cu: RETURN_COPPER( m_In7 );
160 case In8_Cu: RETURN_COPPER( m_In8 );
161 case In9_Cu: RETURN_COPPER( m_In9 );
162 case In10_Cu: RETURN_COPPER( m_In10 );
163 case In11_Cu: RETURN_COPPER( m_In11 );
164 case In12_Cu: RETURN_COPPER( m_In12 );
165 case In13_Cu: RETURN_COPPER( m_In13 );
166 case In14_Cu: RETURN_COPPER( m_In14 );
167 case In15_Cu: RETURN_COPPER( m_In15 );
168
169 case In16_Cu: RETURN_COPPER( m_In16 );
170 case In17_Cu: RETURN_COPPER( m_In17 );
171 case In18_Cu: RETURN_COPPER( m_In18 );
172 case In19_Cu: RETURN_COPPER( m_In19 );
173 case In20_Cu: RETURN_COPPER( m_In20 );
174 case In21_Cu: RETURN_COPPER( m_In21 );
175 case In22_Cu: RETURN_COPPER( m_In22 );
176 case In23_Cu: RETURN_COPPER( m_In23 );
177 case In24_Cu: RETURN_COPPER( m_In24 );
178 case In25_Cu: RETURN_COPPER( m_In25 );
179 case In26_Cu: RETURN_COPPER( m_In26 );
180 case In27_Cu: RETURN_COPPER( m_In27 );
181 case In28_Cu: RETURN_COPPER( m_In28 );
182 case In29_Cu: RETURN_COPPER( m_In29 );
183 case In30_Cu: RETURN_COPPER( m_In30 );
184
185 case B_Cu: RETURN_COPPER( m_Back );
186 case B_Mask: RETURN_AUX( m_MaskBack );
187 case B_SilkS: RETURN_AUX( m_SilkSBack );
188 case B_Paste: RETURN_AUX( m_SoldPBack );
189 case B_Adhes: RETURN_AUX( m_AdhesBack );
190 case B_Fab: RETURN_AUX( m_FabBack );
191 case B_CrtYd: RETURN_MANDATORY( m_CrtYdBack );
192
193 case Edge_Cuts: RETURN_MANDATORY( m_PCBEdges );
194 case Margin: RETURN_MANDATORY( m_Margin );
195 case Eco2_User: RETURN_AUX( m_Eco2 );
196 case Eco1_User: RETURN_AUX( m_Eco1 );
197 case Cmts_User: RETURN_AUX( m_Comments );
198 case Dwgs_User: RETURN_AUX( m_Drawings );
199
200 case User_1: RETURN_AUX( m_User1 );
201 case User_2: RETURN_AUX( m_User2 );
202 case User_3: RETURN_AUX( m_User3 );
203 case User_4: RETURN_AUX( m_User4 );
204 case User_5: RETURN_AUX( m_User5 );
205 case User_6: RETURN_AUX( m_User6 );
206 case User_7: RETURN_AUX( m_User7 );
207 case User_8: RETURN_AUX( m_User8 );
208 case User_9: RETURN_AUX( m_User9 );
209
210 default:
211 wxASSERT_MSG( 0, wxT( "bad layer id" ) );
212 return PANEL_SETUP_LAYERS_CTLs( nullptr, nullptr, nullptr );
213 }
214}
215
216
217wxControl* PANEL_SETUP_LAYERS::getName( int aLayer )
218{
219 return getCTLs( aLayer ).name;
220}
221
222
223wxCheckBox* PANEL_SETUP_LAYERS::getCheckBox( int aLayer )
224{
225 return getCTLs( aLayer ).checkbox;
226}
227
228
229wxChoice* PANEL_SETUP_LAYERS::getChoice( int aLayer )
230{
231 return (wxChoice*) getCTLs( aLayer ).choice;
232}
233
234
236{
238
239 // Rescue may be enabled, but should not be shown in this dialog
240 m_enabledLayers.reset( Rescue );
241
243
246
250
251 return true;
252}
253
254
255void PANEL_SETUP_LAYERS::SyncCopperLayers( int aNumCopperLayers )
256{
257 setCopperLayerCheckBoxes( aNumCopperLayers );
258}
259
260
262{
263 for( int layer : { F_CrtYd, B_CrtYd, Edge_Cuts, Margin } )
264 setLayerCheckBox( layer, true );
265}
266
267
269{
270 for( LSEQ seq = LSET::UserDefinedLayers().Seq(); seq; ++seq )
271 {
272 PCB_LAYER_ID layer = *seq;
273 bool state = m_pcb->IsLayerEnabled( layer );
274
275#ifdef HIDE_INACTIVE_LAYERS
276 // This code hides inactive copper layers, or redisplays hidden layers which are now needed.
277 PANEL_SETUP_LAYERS_CTLs ctl = getCTLs( layer );
278
279 // All user-defined layers should have a checkbox
280 wxASSERT( ctl.checkbox );
281
282 ctl.name->Show( state );
283 ctl.checkbox->Show( state );
284 ctl.choice->Show( state );
285#endif
286
287 setLayerCheckBox( layer, state );
288 }
289
290#ifdef HIDE_INACTIVE_LAYERS
291 // Send an size event to force sizers to be updated,
292 // because the number of copper layers can have changed.
293 wxSizeEvent evt_size( m_LayersListPanel->GetSize() );
294 m_LayersListPanel->GetEventHandler()->ProcessEvent( evt_size );
295#endif
296}
297
298
300{
301 // Set all the board's layer names into the dialog by calling BOARD::GetLayerName(),
302 // which will call BOARD::GetStandardLayerName() for non-coppers.
303
304 for( LSEQ seq = dlg_layers(); seq; ++seq )
305 {
306 PCB_LAYER_ID layer = *seq;
307 wxControl* ctl = getName( layer );
308
309 if( ctl )
310 {
311 wxString lname = m_pcb->GetLayerName( layer );
312
313 if( auto textCtl = dynamic_cast<wxTextCtrl*>( ctl ) )
314 textCtl->ChangeValue( lname ); // wxTextCtrl
315 else
316 ctl->SetLabel( lname ); // wxStaticText
317 }
318 }
319}
320
321
323{
324 // The check boxes
325 for( LSEQ seq = dlg_layers(); seq; ++seq )
326 {
327 PCB_LAYER_ID layer = *seq;
328 setLayerCheckBox( layer, enabledLayers[layer] );
329 }
330}
331
332
334{
335 for( LSEQ seq = LSET::AllCuMask().Seq(); seq; ++seq )
336 {
337 PCB_LAYER_ID cu_layer = *seq;
338
339 wxChoice* ctl = getChoice( cu_layer );
340 ctl->SetSelection( m_pcb->GetLayerType( cu_layer ) );
341 }
342}
343
344
346{
347 LSET layerMaskResult;
348
349 for( LSEQ seq = dlg_layers(); seq; ++seq )
350 {
351 PCB_LAYER_ID layer = *seq;
352 wxCheckBox* ctl = getCheckBox( layer );
353
354 if( !ctl || ctl->GetValue() )
355 layerMaskResult.set( layer );
356 }
357
358 return layerMaskResult;
359}
360
361
362void PANEL_SETUP_LAYERS::setLayerCheckBox( int aLayer, bool isChecked )
363{
364 PANEL_SETUP_LAYERS_CTLs ctl = getCTLs( aLayer );
365
366 if( !ctl.checkbox )
367 return;
368
369 ctl.checkbox->SetValue( isChecked );
370}
371
372
374{
375 if( copperCount > 0 )
376 {
377 setLayerCheckBox( F_Cu, true );
378 --copperCount;
379 }
380
381 if( copperCount > 0 )
382 {
383 setLayerCheckBox( B_Cu, true );
384 --copperCount;
385 }
386
387 for( LSEQ seq = LSET::InternalCuMask().Seq(); seq; ++seq, --copperCount )
388 {
389 PCB_LAYER_ID layer = *seq;
390 bool state = copperCount > 0;
391
392#ifdef HIDE_INACTIVE_LAYERS
393 // This code hides inactive copper layers, or redisplays hidden layers which are now needed.
394 PANEL_SETUP_LAYERS_CTLs ctl = getCTLs( layer );
395
396 // Inner layers should have a checkbox
397 wxASSERT( ctl.checkbox );
398
399 ctl.name->Show( state );
400 ctl.checkbox->Show( state );
401 ctl.choice->Show( state );
402#endif
403
404 setLayerCheckBox( layer, state );
405 }
406
407#ifdef HIDE_INACTIVE_LAYERS
408 // Send an size event to force sizers to be updated,
409 // because the number of copper layers can have changed.
410 wxSizeEvent evt_size( m_LayersListPanel->GetSize() );
411 m_LayersListPanel->GetEventHandler()->ProcessEvent( evt_size );
412#endif
413}
414
415
416void PANEL_SETUP_LAYERS::OnCheckBox( wxCommandEvent& event )
417{
419}
420
421
422void PANEL_SETUP_LAYERS::DenyChangeCheckBox( wxCommandEvent& event )
423{
424 wxObject* source = event.GetEventObject();
425
426 for( LSEQ seq = LSET::AllCuMask().Seq(); seq; ++seq )
427 {
428 wxCheckBox* copper = getCheckBox( *seq );
429
430 if( source == copper )
431 {
432 DisplayError( this, _( "Use the Physical Stackup page to change the number of "
433 "copper layers." ) );
434
435 copper->SetValue( true );
436 return;
437 }
438 }
439}
440
441
443{
444 if( !testLayerNames() )
445 return false;
446
447 wxASSERT( m_physicalStackup );
448
449 // Make sure we have the latest copper layer count
451
452 wxString msg;
453 bool modified = false;
454
455 // Check for removed layers with items which will get deleted from the board.
456 LSEQ removedLayers = getRemovedLayersWithItems();
457
458 // Check for non-copper layers in use in footprints, and therefore not removable.
459 LSEQ notremovableLayers = getNonRemovableLayers();
460
461 if( !notremovableLayers.empty() )
462 {
463 for( unsigned int ii = 0; ii < notremovableLayers.size(); ii++ )
464 msg << m_pcb->GetLayerName( notremovableLayers[ii] ) << wxT( "\n" );
465
466 if( !IsOK( this, wxString::Format( _( "Footprints have some items on removed layers:\n"
467 "%s\n"
468 "These items will be no longer accessible\n"
469 "Do you wish to continue?" ), msg ) ) )
470 {
471 return false;
472 }
473 }
474
475 if( !removedLayers.empty()
476 && !IsOK( this, _( "Items have been found on removed layers. This operation will "
477 "delete all items from removed layers and cannot be undone.\n"
478 "Do you wish to continue?" ) ) )
479 {
480 return false;
481 }
482
483 // Delete all objects on layers that have been removed. Leaving them in copper layers
484 // can (will?) result in DRC errors and it pollutes the board file with cruft.
485 bool hasRemovedBoardItems = false;
486
487 if( !removedLayers.empty() )
488 {
489 PCB_LAYER_COLLECTOR collector;
490
491 for( PCB_LAYER_ID layer_id : removedLayers )
492 {
493 collector.SetLayerId( layer_id );
495
496 // Bye-bye items on removed layer.
497 for( int i = 0; i < collector.GetCount(); i++ )
498 {
499 BOARD_ITEM* item = collector[i];
500 LSET layers = item->GetLayerSet();
501
502 layers.reset( layer_id );
503 hasRemovedBoardItems = true;
504 modified = true;
505
506 if( layers.any() )
507 {
508 item->SetLayerSet( layers );
509 }
510 else
511 {
512 m_pcb->Remove( item );
513 delete item;
514 }
515 }
516 }
517 }
518
520
521 LSET previousEnabled = m_pcb->GetEnabledLayers();
522
523 if( m_enabledLayers != previousEnabled )
524 {
526
527 LSET changedLayers = m_enabledLayers ^ previousEnabled;
528
529 /*
530 * Ensure enabled layers are also visible. This is mainly to avoid mistakes if some
531 * enabled layers are not visible when exiting this dialog.
532 */
533 m_pcb->SetVisibleLayers( m_pcb->GetVisibleLayers() | changedLayers );
534
535 /*
536 * Ensure items with through holes have all inner copper layers. (For historical reasons
537 * this is NOT trimmed to the currently-enabled inner layers.)
538 */
539 for( FOOTPRINT* fp : m_pcb->Footprints() )
540 {
541 for( PAD* pad : fp->Pads() )
542 {
543 if( pad->HasHole() && pad->IsOnCopperLayer() )
544 pad->SetLayerSet( pad->GetLayerSet() | LSET::InternalCuMask() );
545 }
546 }
547
548 for( PCB_TRACK* via : m_pcb->Tracks() )
549 {
550 if( via->HasHole() )
551 via->SetLayerSet( via->GetLayerSet() | LSET::InternalCuMask() );
552 }
553
554 modified = true;
555 }
556
557 for( LSEQ seq = LSET::AllLayersMask().Seq(); seq; ++seq )
558 {
559 PCB_LAYER_ID layer = *seq;
560
561 if( m_enabledLayers[layer] )
562 {
563 const wxString& newLayerName = GetLayerName( layer );
564
565 if( m_pcb->GetLayerName( layer ) != newLayerName )
566 {
567 m_pcb->SetLayerName( layer, newLayerName );
568 modified = true;
569 }
570
571 // Only copper layers have a definable type.
572 if( LSET::AllCuMask().Contains( layer ) )
573 {
574 LAYER_T t = (LAYER_T) getLayerTypeIndex( layer );
575
576 if( m_pcb->GetLayerType( layer ) != t )
577 {
578 m_pcb->SetLayerType( layer, t );
579 modified = true;
580 }
581 }
582 }
583 }
584
585 for( LSEQ seq = LSET::UserDefinedLayers().Seq(); seq; ++seq )
586 {
587 PCB_LAYER_ID layer = *seq;
588 const wxString& newLayerName = GetLayerName( layer );
589
590 if( m_enabledLayers[ layer ] && m_pcb->GetLayerName( layer ) != newLayerName )
591 {
592 m_pcb->SetLayerName( layer, newLayerName );
593 modified = true;
594 }
595 }
596
597 // If some board items are deleted: Rebuild the connectivity, because it is likely some
598 // tracks and vias were removed
599 if( hasRemovedBoardItems )
601
602 if( modified )
603 m_frame->OnModify();
604
605 return true;
606}
607
608
610{
611 wxChoice* ctl = getChoice( aLayer );
612 int ret = ctl->GetCurrentSelection(); // Indices must have same sequence as LAYER_T
613 return ret;
614}
615
616
618{
619 wxControl* control = getName( aLayer );
620
621 if( auto textCtl = dynamic_cast<wxTextCtrl*>( control ) )
622 return textCtl->GetValue().Trim();
623 else
624 return control->GetLabel();
625}
626
627
628static bool hasOneOf( const wxString& str, const wxString& chars )
629{
630 for( unsigned i=0; i<chars.Len(); ++i )
631 {
632 if( str.Find( chars[i] ) != wxNOT_FOUND )
633 return true;
634 }
635
636 return false;
637}
638
639
641{
642 std::vector<wxString> names;
643 wxTextCtrl* ctl;
644
645 for( LSEQ seq = LSET::AllLayersMask().Seq(); seq; ++seq )
646 {
647 PCB_LAYER_ID layer = *seq;
648
649 // we _can_ rely on m_enabledLayers being current here:
650
651 if( !m_enabledLayers[layer] )
652 continue;
653
654 wxString name = GetLayerName( layer );
655
656 ctl = (wxTextCtrl*) getName( layer );
657
658 // Check name for legality:
659 // 1) Cannot be blank.
660 // 2) Cannot have blanks.
661 // 3) Cannot have " chars
662 // 4) Cannot be 'signal'
663 // 5) Must be unique.
664 // 6) Cannot have illegal chars in filenames ( some filenames are built from layer names )
665 // like : % $ \ " / :
666 wxString badchars = wxFileName::GetForbiddenChars( wxPATH_DOS );
667 badchars.Append( '%' );
668
669 if( !name )
670 {
671 m_parentDialog->SetError( _( "Layer must have a name." ), this, ctl );
672 return false;
673 }
674
675 if( hasOneOf( name, badchars ) )
676 {
677 wxString msg = wxString::Format(_( "%s are forbidden in layer names." ), badchars );
678 m_parentDialog->SetError( msg, this, ctl );
679 return false;
680 }
681
682 if( name == wxT( "signal" ) )
683 {
684 m_parentDialog->SetError( _( "Layer name \"signal\" is reserved." ), this, ctl );
685 return false;
686 }
687
688 for( const wxString& existingName : names )
689 {
690 if( name == existingName )
691 {
692 wxString msg = wxString::Format(_( "Layer name '%s' already in use." ), name );
693 m_parentDialog->SetError( msg, this, ctl );
694 return false;
695 }
696 }
697
698 names.push_back( name );
699 }
700
701 return true;
702}
703
704
706{
707 LSEQ removedLayers;
708 LSET newLayers = GetUILayerMask();
709 LSET curLayers = m_pcb->GetEnabledLayers();
710
711 if( newLayers == curLayers ) // Return an empty list if no change
712 return removedLayers;
713
714 PCB_LAYER_COLLECTOR collector;
715 LSEQ newLayerSeq = newLayers.Seq();
716
717 for( PCB_LAYER_ID layer_id : curLayers.Seq() )
718 {
719 if( !alg::contains( newLayerSeq, layer_id ) )
720 {
721 collector.SetLayerId( layer_id );
723
724 if( collector.GetCount() != 0 )
725 removedLayers.push_back( layer_id );
726 }
727 }
728
729 return removedLayers;
730}
731
732
734{
735 // Build the list of non-copper layers in use in footprints.
736 LSEQ inUseLayers;
737 LSET newLayers = GetUILayerMask();
738 LSET curLayers = m_pcb->GetEnabledLayers();
739
740 if( newLayers == curLayers ) // Return an empty list if no change
741 return inUseLayers;
742
743 PCB_LAYER_COLLECTOR collector;
744 LSEQ newLayerSeq = newLayers.Seq();
745
746 for( PCB_LAYER_ID layer_id : curLayers.Seq() )
747 {
748 if( IsCopperLayer( layer_id ) ) // Copper layers are not taken into account here
749 continue;
750
751 if( !alg::contains( newLayerSeq, layer_id ) )
752 {
753 collector.SetLayerId( layer_id );
755
756 if( collector.GetCount() != 0 )
757 inUseLayers.push_back( layer_id );
758 }
759 }
760
761 return inUseLayers;
762}
763
764
766{
767 BOARD* savedBoard = m_pcb;
768
769 m_pcb = aBoard;
771
772 m_pcb = savedBoard;
773}
774
775
776bool PANEL_SETUP_LAYERS::CheckCopperLayerCount( BOARD* aWorkingBoard, BOARD* aImportedBoard )
777{
778 /*
779 * This function warns users if they are going to delete inner copper layers because
780 * they're importing settings from a board with less copper layers than the board
781 * already loaded. We want to return "true" as default on the assumption no layer will
782 * actually be deleted.
783 */
784 bool okToDeleteCopperLayers = true;
785
786 // Get the number of copper layers in the loaded board and the "import settings" board
787 int currNumLayers = aWorkingBoard->GetCopperLayerCount();
788 int newNumLayers = aImportedBoard->GetCopperLayerCount();
789
790 if( newNumLayers < currNumLayers )
791 {
792 wxString msg = wxString::Format( _( "Imported settings have fewer copper layers than "
793 "the current board (%i instead of %i).\n\n"
794 "Continue and delete the extra inner copper layers "
795 "from the current board?" ),
796 newNumLayers,
797 currNumLayers );
798
799 wxMessageDialog dlg( this, msg, _( "Inner Layers To Be Deleted" ),
800 wxICON_WARNING | wxSTAY_ON_TOP | wxYES | wxNO | wxNO_DEFAULT );
801
802 if( wxID_NO == dlg.ShowModal() )
803 okToDeleteCopperLayers = false;
804 }
805
806 return okToDeleteCopperLayers;
807}
808
809
810void PANEL_SETUP_LAYERS::addUserDefinedLayer( wxCommandEvent& aEvent )
811{
812 wxArrayString headers;
813 headers.Add( _( "Layers" ) );
814
815 // Build the available user-defined layers list:
816 std::vector<wxArrayString> list;
817
818 for( LSEQ seq = LSET::UserDefinedLayers().Seq(); seq; ++seq )
819 {
820 wxCheckBox* checkBox = getCheckBox( *seq );
821
822 if( checkBox && checkBox->IsShown() )
823 continue;
824
825 wxArrayString available_user_layer;
826 available_user_layer.Add( LayerName( *seq ) );
827
828 list.emplace_back( available_user_layer );
829 }
830
831 if( list.empty() )
832 {
834 _( "All user-defined layers have already been added." ) );
835 return;
836 }
837
838 EDA_LIST_DIALOG dlg( m_parentDialog, _( "Add User-defined Layer" ), headers, list );
839 dlg.SetListLabel( _( "Select layer to add:" ) );
840 dlg.HideFilter();
841
842 if( dlg.ShowModal() == wxID_CANCEL || dlg.GetTextSelection().IsEmpty() )
843 return;
844
845 LSEQ seq;
846
847 for( seq = LSET::UserDefinedLayers().Seq(); seq; ++seq )
848 {
849 if( LayerName( *seq ) == dlg.GetTextSelection() )
850 break;
851 }
852
853 wxCHECK( *seq >= User_1 && *seq <= User_9, /* void */ );
854
855 LSET newLayer( *seq );
856
857 m_enabledLayers |= newLayer;
858
859 PANEL_SETUP_LAYERS_CTLs ctl = getCTLs( *seq );
860
861 // All user-defined layers should have a checkbox
862 wxASSERT( ctl.checkbox );
863
864 wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( ctl.name );
865
866 wxCHECK( textCtrl, /* void */ );
867 textCtrl->ChangeValue( LSET::Name( *seq ) );
868 ctl.name->Show( true );
869 ctl.checkbox->Show( true );
870 ctl.choice->Show( true );
871
872 wxSizeEvent evt_size( m_LayersListPanel->GetSize() );
873 m_LayersListPanel->GetEventHandler()->ProcessEvent( evt_size );
874
875 setLayerCheckBox( *seq, true );
876}
877
878
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:143
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:58
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:185
virtual void SetLayerSet(LSET aLayers)
Definition: board_item.h:193
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:265
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:526
LSET GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:540
void SetEnabledLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:546
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:552
LAYER_T GetLayerType(PCB_LAYER_ID aLayer) const
Return the type of the copper layer given by aLayer.
Definition: board.cpp:447
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Changes the name of the layer given by aLayer.
Definition: board.cpp:429
FOOTPRINTS & Footprints()
Definition: board.h:307
int GetCopperLayerCount() const
Definition: board.cpp:502
TRACKS & Tracks()
Definition: board.h:304
void SetVisibleLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings changes the bit-mask of vis...
Definition: board.cpp:558
bool SetLayerType(PCB_LAYER_ID aLayer, LAYER_T aLayerType)
Change the type of the layer given by aLayer.
Definition: board.cpp:459
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:413
void Remove(BOARD_ITEM *aBoardItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition: board.cpp:820
void BuildConnectivity(PROGRESS_REPORTER *aReporter=nullptr)
Build or rebuild the board connectivity database for the board, especially the list of connected item...
Definition: board.cpp:162
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:491
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:530
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:59
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:342
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:280
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:299
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:825
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
Definition: sim_serde.h:107
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.