KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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-2023 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 <pcb_edit_frame.h>
31#include <board.h>
32#include <collectors.h>
33#include <footprint.h>
34#include <pad.h>
35#include <pcb_track.h>
36#include <panel_setup_layers.h>
38
39#include <wx/choicdlg.h>
40#include <eda_list_dialog.h>
41
42
43// some define to choose how copper layers widgets are shown
44
45// if defined, display only active copper layers
46// if not displays always 1=the full set (32 copper layers)
47#define HIDE_INACTIVE_LAYERS
48
49
51{
52 // Layers that are put out into the dialog UI, coordinate with wxformbuilder and
53 // getCTLs( int aLayerNumber )
54 static const PCB_LAYER_ID layers[] = {
55 F_CrtYd,
56 F_Fab,
57 F_Adhes,
58 F_Paste,
59 F_SilkS,
60 F_Mask,
61 F_Cu,
62
63 In1_Cu,
64 In2_Cu,
65 In3_Cu,
66 In4_Cu,
67 In5_Cu,
68 In6_Cu,
69 In7_Cu,
70 In8_Cu,
71 In9_Cu,
72 In10_Cu,
73 In11_Cu,
74 In12_Cu,
75 In13_Cu,
76 In14_Cu,
77 In15_Cu,
78
79 In16_Cu,
80 In17_Cu,
81 In18_Cu,
82 In19_Cu,
83 In20_Cu,
84 In21_Cu,
85 In22_Cu,
86 In23_Cu,
87 In24_Cu,
88 In25_Cu,
89 In26_Cu,
90 In27_Cu,
91 In28_Cu,
92 In29_Cu,
93 In30_Cu,
94
95 B_Cu,
96 B_Mask,
97 B_SilkS,
98 B_Paste,
99 B_Adhes,
100 B_Fab,
101 B_CrtYd,
102
103 Edge_Cuts,
104 Margin,
105 Eco2_User,
106 Eco1_User,
107 Cmts_User,
108 Dwgs_User,
109
110 User_1,
111 User_2,
112 User_3,
113 User_4,
114 User_5,
115 User_6,
116 User_7,
117 User_8,
118 User_9,
119 };
120
121 return LSEQ( layers, layers + arrayDim( layers ) );
122}
123
124
125PANEL_SETUP_LAYERS::PANEL_SETUP_LAYERS( wxWindow* aParentWindow, PCB_EDIT_FRAME* aFrame ) :
126 PANEL_SETUP_LAYERS_BASE( aParentWindow ),
127 m_frame( aFrame ),
128 m_physicalStackup( nullptr ),
129 m_initialized( false )
130{
131 m_pcb = aFrame->GetBoard();
132}
133
134
136{
137#define RETURN_COPPER( x ) return PANEL_SETUP_LAYERS_CTLs( x##Name, x##CheckBox, x##Choice )
138#define RETURN_AUX( x ) return PANEL_SETUP_LAYERS_CTLs( x##Name, x##CheckBox, x##StaticText )
139#define RETURN_MANDATORY( x ) return PANEL_SETUP_LAYERS_CTLs( x##Name, nullptr, x##StaticText )
140
141 switch( aLayerNumber )
142 {
143 case F_CrtYd: RETURN_MANDATORY( m_CrtYdFront );
144 case F_Fab: RETURN_AUX( m_FabFront );
145 case F_Adhes: RETURN_AUX( m_AdhesFront );
146 case F_Paste: RETURN_AUX( m_SoldPFront );
147 case F_SilkS: RETURN_AUX( m_SilkSFront );
148 case F_Mask: RETURN_AUX( m_MaskFront );
149 case F_Cu: RETURN_COPPER( m_Front );
150
151 case In1_Cu: RETURN_COPPER( m_In1 );
152 case In2_Cu: RETURN_COPPER( m_In2 );
153 case In3_Cu: RETURN_COPPER( m_In3 );
154 case In4_Cu: RETURN_COPPER( m_In4 );
155 case In5_Cu: RETURN_COPPER( m_In5 );
156 case In6_Cu: RETURN_COPPER( m_In6 );
157 case In7_Cu: RETURN_COPPER( m_In7 );
158 case In8_Cu: RETURN_COPPER( m_In8 );
159 case In9_Cu: RETURN_COPPER( m_In9 );
160 case In10_Cu: RETURN_COPPER( m_In10 );
161 case In11_Cu: RETURN_COPPER( m_In11 );
162 case In12_Cu: RETURN_COPPER( m_In12 );
163 case In13_Cu: RETURN_COPPER( m_In13 );
164 case In14_Cu: RETURN_COPPER( m_In14 );
165 case In15_Cu: RETURN_COPPER( m_In15 );
166
167 case In16_Cu: RETURN_COPPER( m_In16 );
168 case In17_Cu: RETURN_COPPER( m_In17 );
169 case In18_Cu: RETURN_COPPER( m_In18 );
170 case In19_Cu: RETURN_COPPER( m_In19 );
171 case In20_Cu: RETURN_COPPER( m_In20 );
172 case In21_Cu: RETURN_COPPER( m_In21 );
173 case In22_Cu: RETURN_COPPER( m_In22 );
174 case In23_Cu: RETURN_COPPER( m_In23 );
175 case In24_Cu: RETURN_COPPER( m_In24 );
176 case In25_Cu: RETURN_COPPER( m_In25 );
177 case In26_Cu: RETURN_COPPER( m_In26 );
178 case In27_Cu: RETURN_COPPER( m_In27 );
179 case In28_Cu: RETURN_COPPER( m_In28 );
180 case In29_Cu: RETURN_COPPER( m_In29 );
181 case In30_Cu: RETURN_COPPER( m_In30 );
182
183 case B_Cu: RETURN_COPPER( m_Back );
184 case B_Mask: RETURN_AUX( m_MaskBack );
185 case B_SilkS: RETURN_AUX( m_SilkSBack );
186 case B_Paste: RETURN_AUX( m_SoldPBack );
187 case B_Adhes: RETURN_AUX( m_AdhesBack );
188 case B_Fab: RETURN_AUX( m_FabBack );
189 case B_CrtYd: RETURN_MANDATORY( m_CrtYdBack );
190
191 case Edge_Cuts: RETURN_MANDATORY( m_PCBEdges );
192 case Margin: RETURN_MANDATORY( m_Margin );
193 case Eco2_User: RETURN_AUX( m_Eco2 );
194 case Eco1_User: RETURN_AUX( m_Eco1 );
195 case Cmts_User: RETURN_AUX( m_Comments );
196 case Dwgs_User: RETURN_AUX( m_Drawings );
197
198 case User_1: RETURN_AUX( m_User1 );
199 case User_2: RETURN_AUX( m_User2 );
200 case User_3: RETURN_AUX( m_User3 );
201 case User_4: RETURN_AUX( m_User4 );
202 case User_5: RETURN_AUX( m_User5 );
203 case User_6: RETURN_AUX( m_User6 );
204 case User_7: RETURN_AUX( m_User7 );
205 case User_8: RETURN_AUX( m_User8 );
206 case User_9: RETURN_AUX( m_User9 );
207
208 default:
209 wxASSERT_MSG( 0, wxT( "bad layer id" ) );
210 return PANEL_SETUP_LAYERS_CTLs( nullptr, nullptr, nullptr );
211 }
212}
213
214
215wxControl* PANEL_SETUP_LAYERS::getName( int aLayer )
216{
217 return getCTLs( aLayer ).name;
218}
219
220
221wxCheckBox* PANEL_SETUP_LAYERS::getCheckBox( int aLayer )
222{
223 return getCTLs( aLayer ).checkbox;
224}
225
226
227wxChoice* PANEL_SETUP_LAYERS::getChoice( int aLayer )
228{
229 return (wxChoice*) getCTLs( aLayer ).choice;
230}
231
232
234{
236
237 // Rescue may be enabled, but should not be shown in this dialog
238 m_enabledLayers.reset( Rescue );
239
241
244
248
249 m_initialized = true;
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 // Make sure we have the latest copper layer count
450
451 wxString msg;
452 bool modified = false;
453
454 // Check for removed layers with items which will get deleted from the board.
455 LSEQ removedLayers = getRemovedLayersWithItems();
456
457 // Check for non-copper layers in use in footprints, and therefore not removable.
458 LSEQ notremovableLayers = getNonRemovableLayers();
459
460 if( !notremovableLayers.empty() )
461 {
462 for( unsigned int ii = 0; ii < notremovableLayers.size(); ii++ )
463 msg << m_pcb->GetLayerName( notremovableLayers[ii] ) << wxT( "\n" );
464
465 if( !IsOK( this, wxString::Format( _( "Footprints have some items on removed layers:\n"
466 "%s\n"
467 "These items will be no longer accessible\n"
468 "Do you wish to continue?" ), msg ) ) )
469 {
470 return false;
471 }
472 }
473
474 if( !removedLayers.empty()
475 && !IsOK( this, _( "Items have been found on removed layers. This operation will "
476 "delete all items from removed layers and cannot be undone.\n"
477 "Do you wish to continue?" ) ) )
478 {
479 return false;
480 }
481
482 // Delete all objects on layers that have been removed. Leaving them in copper layers
483 // can (will?) result in DRC errors and it pollutes the board file with cruft.
484 bool hasRemovedBoardItems = false;
485
486 if( !removedLayers.empty() )
487 {
488 PCB_LAYER_COLLECTOR collector;
489
490 for( PCB_LAYER_ID layer_id : removedLayers )
491 {
492 collector.SetLayerId( layer_id );
494
495 // Bye-bye items on removed layer.
496 for( int i = 0; i < collector.GetCount(); i++ )
497 {
498 BOARD_ITEM* item = collector[i];
499 LSET layers = item->GetLayerSet();
500
501 layers.reset( layer_id );
502 hasRemovedBoardItems = true;
503 modified = true;
504
505 if( layers.any() )
506 {
507 item->SetLayerSet( layers );
508 }
509 else
510 {
511 m_pcb->Remove( item );
512 delete item;
513 }
514 }
515 }
516 }
517
519
520 LSET previousEnabled = m_pcb->GetEnabledLayers();
521
522 if( m_enabledLayers != previousEnabled )
523 {
525
526 LSET changedLayers = m_enabledLayers ^ previousEnabled;
527
528 /*
529 * Ensure enabled layers are also visible. This is mainly to avoid mistakes if some
530 * enabled layers are not visible when exiting this dialog.
531 */
532 m_pcb->SetVisibleLayers( m_pcb->GetVisibleLayers() | changedLayers );
533
534 /*
535 * Ensure items with through holes have all inner copper layers. (For historical reasons
536 * this is NOT trimmed to the currently-enabled inner layers.)
537 */
538 for( FOOTPRINT* fp : m_pcb->Footprints() )
539 {
540 for( PAD* pad : fp->Pads() )
541 {
542 if( pad->HasHole() && pad->IsOnCopperLayer() )
543 pad->SetLayerSet( pad->GetLayerSet() | LSET::InternalCuMask() );
544 }
545 }
546
547 for( PCB_TRACK* via : m_pcb->Tracks() )
548 {
549 if( via->HasHole() )
550 via->SetLayerSet( via->GetLayerSet() | LSET::InternalCuMask() );
551 }
552
553 modified = true;
554 }
555
556 for( LSEQ seq = LSET::AllLayersMask().Seq(); seq; ++seq )
557 {
558 PCB_LAYER_ID layer = *seq;
559
560 if( m_enabledLayers[layer] )
561 {
562 const wxString& newLayerName = GetLayerName( layer );
563
564 if( m_pcb->GetLayerName( layer ) != newLayerName )
565 {
566 m_pcb->SetLayerName( layer, newLayerName );
567 modified = true;
568 }
569
570 // Only copper layers have a definable type.
571 if( LSET::AllCuMask().Contains( layer ) )
572 {
573 LAYER_T t = (LAYER_T) getLayerTypeIndex( layer );
574
575 if( m_pcb->GetLayerType( layer ) != t )
576 {
577 m_pcb->SetLayerType( layer, t );
578 modified = true;
579 }
580 }
581 }
582 }
583
584 for( LSEQ seq = LSET::UserDefinedLayers().Seq(); seq; ++seq )
585 {
586 PCB_LAYER_ID layer = *seq;
587 const wxString& newLayerName = GetLayerName( layer );
588
589 if( m_enabledLayers[ layer ] && m_pcb->GetLayerName( layer ) != newLayerName )
590 {
591 m_pcb->SetLayerName( layer, newLayerName );
592 modified = true;
593 }
594 }
595
596 // If some board items are deleted: Rebuild the connectivity, because it is likely some
597 // tracks and vias were removed
598 if( hasRemovedBoardItems )
600
601 if( modified )
602 m_frame->OnModify();
603
604 return true;
605}
606
607
609{
610 wxChoice* ctl = getChoice( aLayer );
611 int ret = ctl->GetCurrentSelection(); // Indices must have same sequence as LAYER_T
612 return ret;
613}
614
615
617{
618 wxControl* control = getName( aLayer );
619
620 if( auto textCtl = dynamic_cast<wxTextCtrl*>( control ) )
621 return textCtl->GetValue().Trim();
622 else
623 return control->GetLabel();
624}
625
626
627static bool hasOneOf( const wxString& str, const wxString& chars )
628{
629 for( unsigned i=0; i<chars.Len(); ++i )
630 {
631 if( str.Find( chars[i] ) != wxNOT_FOUND )
632 return true;
633 }
634
635 return false;
636}
637
638
640{
641 std::vector<wxString> names;
642 wxTextCtrl* ctl;
643
644 for( LSEQ seq = LSET::AllLayersMask().Seq(); seq; ++seq )
645 {
646 PCB_LAYER_ID layer = *seq;
647
648 // we _can_ rely on m_enabledLayers being current here:
649
650 if( !m_enabledLayers[layer] )
651 continue;
652
653 wxString name = GetLayerName( layer );
654
655 ctl = (wxTextCtrl*) getName( layer );
656
657 // Check name for legality:
658 // 1) Cannot be blank.
659 // 2) Cannot have blanks.
660 // 3) Cannot have " chars
661 // 4) Cannot be 'signal'
662 // 5) Must be unique.
663 // 6) Cannot have illegal chars in filenames ( some filenames are built from layer names )
664 // like : % $ \ " / :
665 wxString badchars = wxFileName::GetForbiddenChars( wxPATH_DOS );
666 badchars.Append( '%' );
667
668 if( !name )
669 {
670 PAGED_DIALOG::GetDialog( this )->SetError( _( "Layer must have a name." ), this, ctl );
671 return false;
672 }
673
674 if( hasOneOf( name, badchars ) )
675 {
676 wxString msg = wxString::Format(_( "%s are forbidden in layer names." ), badchars );
677 PAGED_DIALOG::GetDialog( this )->SetError( msg, this, ctl );
678 return false;
679 }
680
681 if( name == wxT( "signal" ) )
682 {
683 PAGED_DIALOG::GetDialog( this )->SetError( _( "Layer name \"signal\" is reserved." ),
684 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 PAGED_DIALOG::GetDialog( this )->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( PAGED_DIALOG::GetDialog( this ), _( "Add User-defined Layer" ),
839 headers, list );
840 dlg.SetListLabel( _( "Select layer to add:" ) );
841 dlg.HideFilter();
842
843 if( dlg.ShowModal() == wxID_CANCEL || dlg.GetTextSelection().IsEmpty() )
844 return;
845
846 LSEQ seq;
847
848 for( seq = LSET::UserDefinedLayers().Seq(); seq; ++seq )
849 {
850 if( LayerName( *seq ) == dlg.GetTextSelection() )
851 break;
852 }
853
854 wxCHECK( *seq >= User_1 && *seq <= User_9, /* void */ );
855
856 LSET newLayer( *seq );
857
858 m_enabledLayers |= newLayer;
859
860 PANEL_SETUP_LAYERS_CTLs ctl = getCTLs( *seq );
861
862 // All user-defined layers should have a checkbox
863 wxASSERT( ctl.checkbox );
864
865 wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( ctl.name );
866
867 wxCHECK( textCtrl, /* void */ );
868 textCtrl->ChangeValue( LSET::Name( *seq ) );
869 ctl.name->Show( true );
870 ctl.checkbox->Show( true );
871 ctl.choice->Show( true );
872
873 wxSizeEvent evt_size( m_LayersListPanel->GetSize() );
874 m_LayersListPanel->GetEventHandler()->ProcessEvent( evt_size );
875
876 setLayerCheckBox( *seq, true );
877}
878
879
const char * name
Definition: DXF_plotter.cpp:57
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:148
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:77
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:209
virtual void SetLayerSet(LSET aLayers)
Definition: board_item.h:217
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:271
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:614
LSET GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:628
void SetEnabledLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:634
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:168
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:640
LAYER_T GetLayerType(PCB_LAYER_ID aLayer) const
Return the type of the copper layer given by aLayer.
Definition: board.cpp:535
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Changes the name of the layer given by aLayer.
Definition: board.cpp:517
FOOTPRINTS & Footprints()
Definition: board.h:313
int GetCopperLayerCount() const
Definition: board.cpp:590
TRACKS & Tracks()
Definition: board.h:310
void SetVisibleLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings changes the bit-mask of vis...
Definition: board.cpp:646
bool SetLayerType(PCB_LAYER_ID aLayer, LAYER_T aLayerType)
Change the type of the layer given by aLayer.
Definition: board.cpp:547
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:501
void Remove(BOARD_ITEM *aBoardItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition: board.cpp:930
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:513
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:552
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:58
static PAGED_DIALOG * GetDialog(wxWindow *aWindow)
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)
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
PANEL_SETUP_LAYERS(wxWindow *aParentWindow, PCB_EDIT_FRAME *aFrame)
void ImportSettingsFrom(BOARD *aBoard)
wxCheckBox * getCheckBox(int aLayer)
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:545
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:525
void SetLayerId(PCB_LAYER_ID aLayerId)
Definition: collectors.h:551
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:360
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:305
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:847
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ In22_Cu
Definition: layer_ids.h:87
@ In11_Cu
Definition: layer_ids.h:76
@ In29_Cu
Definition: layer_ids.h:94
@ In30_Cu
Definition: layer_ids.h:95
@ User_8
Definition: layer_ids.h:131
@ F_CrtYd
Definition: layer_ids.h:118
@ In17_Cu
Definition: layer_ids.h:82
@ B_Adhes
Definition: layer_ids.h:98
@ Edge_Cuts
Definition: layer_ids.h:114
@ Dwgs_User
Definition: layer_ids.h:110
@ F_Paste
Definition: layer_ids.h:102
@ In9_Cu
Definition: layer_ids.h:74
@ Cmts_User
Definition: layer_ids.h:111
@ User_6
Definition: layer_ids.h:129
@ User_7
Definition: layer_ids.h:130
@ In19_Cu
Definition: layer_ids.h:84
@ In7_Cu
Definition: layer_ids.h:72
@ In28_Cu
Definition: layer_ids.h:93
@ In26_Cu
Definition: layer_ids.h:91
@ F_Adhes
Definition: layer_ids.h:99
@ B_Mask
Definition: layer_ids.h:107
@ B_Cu
Definition: layer_ids.h:96
@ User_5
Definition: layer_ids.h:128
@ Eco1_User
Definition: layer_ids.h:112
@ F_Mask
Definition: layer_ids.h:108
@ In21_Cu
Definition: layer_ids.h:86
@ In23_Cu
Definition: layer_ids.h:88
@ B_Paste
Definition: layer_ids.h:101
@ In15_Cu
Definition: layer_ids.h:80
@ In2_Cu
Definition: layer_ids.h:67
@ User_9
Definition: layer_ids.h:132
@ F_Fab
Definition: layer_ids.h:121
@ In10_Cu
Definition: layer_ids.h:75
@ Margin
Definition: layer_ids.h:115
@ F_SilkS
Definition: layer_ids.h:105
@ In4_Cu
Definition: layer_ids.h:69
@ B_CrtYd
Definition: layer_ids.h:117
@ Eco2_User
Definition: layer_ids.h:113
@ In16_Cu
Definition: layer_ids.h:81
@ In24_Cu
Definition: layer_ids.h:89
@ In1_Cu
Definition: layer_ids.h:66
@ Rescue
Definition: layer_ids.h:134
@ User_3
Definition: layer_ids.h:126
@ User_1
Definition: layer_ids.h:124
@ B_SilkS
Definition: layer_ids.h:104
@ In13_Cu
Definition: layer_ids.h:78
@ User_4
Definition: layer_ids.h:127
@ In8_Cu
Definition: layer_ids.h:73
@ In14_Cu
Definition: layer_ids.h:79
@ User_2
Definition: layer_ids.h:125
@ In12_Cu
Definition: layer_ids.h:77
@ In27_Cu
Definition: layer_ids.h:92
@ In6_Cu
Definition: layer_ids.h:71
@ In5_Cu
Definition: layer_ids.h:70
@ In3_Cu
Definition: layer_ids.h:68
@ In20_Cu
Definition: layer_ids.h:85
@ F_Cu
Definition: layer_ids.h:65
@ In18_Cu
Definition: layer_ids.h:83
@ In25_Cu
Definition: layer_ids.h:90
@ B_Fab
Definition: layer_ids.h:120
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)
The 3 UI control pointers for a single board layer.