KiCad PCB EDA Suite
dialog_layers_setup.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, isaacbavaresco@yahoo.com.br
5  * Copyright (C) 2009 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6  * Copyright (C) 2009-2018 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 <fctsys.h>
28 #include <macros.h>
29 
30 #include <confirm.h>
31 #include <pcbnew.h>
32 #include <pcb_edit_frame.h>
33 #include <view/view.h>
34 
35 #include <invoke_pcb_dialog.h>
36 
37 #include <class_board.h>
38 #include <collectors.h>
39 
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 
53 struct CTLs
54 {
55  CTLs( wxControl* aName, wxCheckBox* aCheckBox, wxControl* aChoiceOrDesc,
56  wxPanel* aPanel = NULL )
57  {
58  name = aName;
59  checkbox = aCheckBox;
60  choice = aChoiceOrDesc;
61  panel = aPanel;
62  }
63 
64  wxControl* name;
65  wxCheckBox* checkbox;
66  wxControl* choice;
67  wxPanel * panel;
68 };
69 
70 
71 static LSEQ dlg_layers()
72 {
73  // layers that are put out into the dialog UI, coordinate with wxformbuilder and
74  // getCTLs( LAYER_NUM aLayerNumber )
75  static const PCB_LAYER_ID layers[] = {
76  F_CrtYd,
77  F_Fab,
78  F_Adhes,
79  F_Paste,
80  F_SilkS,
81  F_Mask,
82  F_Cu,
83 
84  In1_Cu,
85  In2_Cu,
86  In3_Cu,
87  In4_Cu,
88  In5_Cu,
89  In6_Cu,
90  In7_Cu,
91  In8_Cu,
92  In9_Cu,
93  In10_Cu,
94  In11_Cu,
95  In12_Cu,
96  In13_Cu,
97  In14_Cu,
98  In15_Cu,
99 
100  In16_Cu,
101  In17_Cu,
102  In18_Cu,
103  In19_Cu,
104  In20_Cu,
105  In21_Cu,
106  In22_Cu,
107  In23_Cu,
108  In24_Cu,
109  In25_Cu,
110  In26_Cu,
111  In27_Cu,
112  In28_Cu,
113  In29_Cu,
114  In30_Cu,
115 
116  B_Cu,
117  B_Mask,
118  B_SilkS,
119  B_Paste,
120  B_Adhes,
121  B_Fab,
122  B_CrtYd,
123 
124  Edge_Cuts,
125  Margin,
126  Eco2_User,
127  Eco1_User,
128  Cmts_User,
129  Dwgs_User,
130  };
131 
132  return LSEQ( layers, layers + DIM( layers ) );
133 }
134 
135 
137 {
138 public:
139  DIALOG_LAYERS_SETUP( PCB_EDIT_FRAME* aCaller, BOARD* aBoard );
140 
141 private:
144 
146 
147  wxStaticText* m_nameStaticText;
148  wxStaticText* m_enabledStaticText;
149  wxStaticText* m_typeStaticText;
150 
151  void setLayerCheckBox( LAYER_NUM layer, bool isChecked );
152  void setCopperLayerCheckBoxes( int copperCount );
153  // Force mandatory non copper layers enabled
154  void setStateMandatoryLayerCheckBoxes();
155 
156  void showCopperChoice( int copperCount );
157  void showBoardLayerNames();
158  void showSelectedLayerCheckBoxes( LSET enableLayerMask );
159  void showLayerTypes();
160  void showPresets( LSET enabledLayerMask );
161 
163  LSET getUILayerMask();
164  wxString getLayerName( LAYER_NUM layer );
165  int getLayerTypeIndex( LAYER_NUM layer );
166 
167  void OnInitDialog( wxInitDialogEvent& aEvent ) override;
168  void OnCheckBox( wxCommandEvent& event ) override;
169  void DenyChangeCheckBox( wxCommandEvent& event ) override;
170  void OnPresetsChoice( wxCommandEvent& event ) override;
171  void OnCopperLayersChoice( wxCommandEvent& event ) override;
172  bool TransferDataToWindow() override;
173  bool TransferDataFromWindow() override;
174 
175  bool testLayerNames();
176 
180  LSEQ getRemovedLayersWithItems();
181 
185  LSEQ getNonRemovableLayers();
186 
191  CTLs getCTLs( LAYER_NUM aLayerNumber );
192 
193  wxControl* getName( LAYER_NUM aLayer )
194  {
195  return getCTLs( aLayer ).name;
196  }
197 
198  wxCheckBox* getCheckBox( LAYER_NUM aLayer )
199  {
200  return getCTLs( aLayer ).checkbox;
201  }
202 
203  wxChoice* getChoice( LAYER_NUM aLayer )
204  {
205  return (wxChoice*) getCTLs( aLayer ).choice;
206  }
207 
208  void moveTitles()
209  {
210  wxArrayInt widths = m_LayerListFlexGridSizer->GetColWidths();
211 
212  int offset = 0;
213  wxSize txtz;
214 
215  wxSize panel_sz = m_TitlePanel->GetSize();
216  int voffset = panel_sz.y/2 - VertPixelsFromDU( 4 );
217 
218  txtz = m_nameStaticText->GetSize();
219  m_nameStaticText->Move( offset + (widths[0] - txtz.x)/2, voffset );
220  offset += widths[0];
221 
222  txtz = m_enabledStaticText->GetSize();
223  m_enabledStaticText->Move( offset + (widths[1] - txtz.x)/2, voffset );
224  offset += widths[1];
225 
226  txtz = m_typeStaticText->GetSize();
227  m_typeStaticText->Move( offset + (widths[2] - txtz.x)/2, voffset );
228  }
229 
230  void OnSize( wxSizeEvent& event ) override;
231 };
232 
233 
234 // Layer bit masks for each defined "Preset Layer Grouping"
235 static const LSET presets[] =
236 {
237  LSET(), // shift the array index up by one, matches with "Custom".
238 
239  // "Two layers, parts on Front only"
241 
242  // "Two layers, parts on Back only",
244 
245  // "Two layers, parts on Front and Back",
247 
248  // "Four layers, parts on Front only"
250 
251  // "Four layers, parts on Front and Back"
253  LSET::UserMask(),
254 
255  // "All layers on",
256  LSET().set(),
257 };
258 
259 
261 {
262 #define RETCOP(x) return CTLs( x##Name, x##CheckBox, x##Choice, x##Panel );
263 #define RETAUX(x) return CTLs( x##Name, x##CheckBox, x##StaticText, x##Panel );
264 
265  switch( aLayerNumber )
266  {
267  case F_CrtYd: RETAUX( m_CrtYdFront );
268  case F_Fab: RETAUX( m_FabFront );
269  case F_Adhes: RETAUX( m_AdhesFront );
270  case F_Paste: RETAUX( m_SoldPFront );
271  case F_SilkS: RETAUX( m_SilkSFront );
272  case F_Mask: RETAUX( m_MaskFront );
273  case F_Cu: RETCOP( m_Front );
274 
275  case In1_Cu: RETCOP( m_In1 );
276  case In2_Cu: RETCOP( m_In2 );
277  case In3_Cu: RETCOP( m_In3 );
278  case In4_Cu: RETCOP( m_In4 );
279  case In5_Cu: RETCOP( m_In5 );
280  case In6_Cu: RETCOP( m_In6 );
281  case In7_Cu: RETCOP( m_In7 );
282  case In8_Cu: RETCOP( m_In8 );
283  case In9_Cu: RETCOP( m_In9 );
284  case In10_Cu: RETCOP( m_In10 );
285  case In11_Cu: RETCOP( m_In11 );
286  case In12_Cu: RETCOP( m_In12 );
287  case In13_Cu: RETCOP( m_In13 );
288  case In14_Cu: RETCOP( m_In14 );
289  case In15_Cu: RETCOP( m_In15 );
290 
291  case In16_Cu: RETCOP( m_In16 );
292  case In17_Cu: RETCOP( m_In17 );
293  case In18_Cu: RETCOP( m_In18 );
294  case In19_Cu: RETCOP( m_In19 );
295  case In20_Cu: RETCOP( m_In20 );
296  case In21_Cu: RETCOP( m_In21 );
297  case In22_Cu: RETCOP( m_In22 );
298  case In23_Cu: RETCOP( m_In23 );
299  case In24_Cu: RETCOP( m_In24 );
300  case In25_Cu: RETCOP( m_In25 );
301  case In26_Cu: RETCOP( m_In26 );
302  case In27_Cu: RETCOP( m_In27 );
303  case In28_Cu: RETCOP( m_In28 );
304  case In29_Cu: RETCOP( m_In29 );
305  case In30_Cu: RETCOP( m_In30 );
306 
307  case B_Cu: RETCOP( m_Back );
308  case B_Mask: RETAUX( m_MaskBack );
309  case B_SilkS: RETAUX( m_SilkSBack );
310  case B_Paste: RETAUX( m_SoldPBack );
311  case B_Adhes: RETAUX( m_AdhesBack );
312  case B_Fab: RETAUX( m_FabBack );
313  case B_CrtYd: RETAUX( m_CrtYdBack );
314 
315  case Edge_Cuts: RETAUX( m_PCBEdges );
316  case Margin: RETAUX( m_Margin );
317  case Eco2_User: RETAUX( m_Eco2 );
318  case Eco1_User: RETAUX( m_Eco1 );
319  case Cmts_User: RETAUX( m_Comments );
320  case Dwgs_User: RETAUX( m_Drawings );
321  default:
322  wxASSERT_MSG( 0, wxT( "bad layer id" ) );
323  return CTLs( 0, 0, 0 );
324  }
325 
326 #undef RETCOP
327 #undef RETAUX
328 }
329 
330 
332  DIALOG_LAYERS_SETUP_BASE( aParent )
333 {
334  m_pcb = aBoard;
335 
338 
339  SetAutoLayout( true );
340 
341  // these 3 controls are handled outside wxformbuilder so that we can add
342  // them without a sizer. Then we position them manually based on the column
343  // widths from m_LayerListFlexGridSizer->GetColWidths()
344  m_nameStaticText = new wxStaticText( m_TitlePanel, wxID_ANY, _( "Name" ),
345  wxDefaultPosition, wxDefaultSize, 0 );
346 
347  m_enabledStaticText = new wxStaticText( m_TitlePanel, wxID_ANY, _( "Enabled" ),
348  wxDefaultPosition, wxDefaultSize, 0 );
349 
350  m_typeStaticText = new wxStaticText( m_TitlePanel, wxID_ANY, _( "Type" ),
351  wxDefaultPosition, wxDefaultSize, 0 );
352 }
353 
354 
355 void DIALOG_LAYERS_SETUP::OnInitDialog( wxInitDialogEvent& aEvent )
356 {
357  wxWindowBase::OnInitDialog( aEvent );
358 
359  m_TitlePanel->SetMinSize( wxSize( -1, VertPixelsFromDU( 10 ) ) );
360 
361  m_LayersListPanel->ShowScrollbars( wxSHOW_SB_ALWAYS, wxSHOW_SB_ALWAYS );
362 
363  Layout();
364  SetSizeInDU( 240, 240 );
365  Center();
366 
367  m_sdbSizerOK->SetFocus();
368  m_sdbSizerOK->SetDefault();
369 
370  // OnSize() will fix the title spacing.
371  QueueEvent( new wxSizeEvent( GetSize() ) );
372 }
373 
374 
376 {
377  if( !wxDialog::TransferDataToWindow() )
378  return false;
379 
385 
389  showLayerTypes();
391 
392  // All widgets are now initialized. Fix the min sizes:
393  GetSizer()->SetSizeHints( this );
394 
395  return true;
396 }
397 
398 
400 {
401  int layerList[4] =
402  {
404  };
405 
406  for( int ii = 0; ii < 4; ii++ )
407  {
408  setLayerCheckBox( layerList[ii], true );
409  getCheckBox( layerList[ii] )->Enable( false ); // do not allow changes
410  }
411 }
412 
413 
414 void DIALOG_LAYERS_SETUP::OnSize( wxSizeEvent& event )
415 {
416  moveTitles();
417  event.Skip();
418  Refresh();
419 }
420 
421 
423 {
424  if( copperCount > MAX_CU_LAYERS )
425  copperCount = MAX_CU_LAYERS;
426 
427  if( copperCount < 2 )
428  copperCount = 2;
429 
430  for( int lyrCnt = 2; lyrCnt <= MAX_CU_LAYERS; lyrCnt += 2 )
431  {
432  // note this will change a one layer board to 2:
433  if( copperCount <= lyrCnt )
434  {
435  int idx = lyrCnt/2 - 1;
436  m_CopperLayersChoice->SetSelection(idx);
437  break;
438  }
439  }
440 }
441 
442 
444 {
445  // Establish all the board's layer names into the dialog presentation, by
446  // obtaining them from BOARD::GetLayerName() which calls
447  // BOARD::GetStandardLayerName() for non-coppers.
448 
449  for( LSEQ seq = dlg_layers(); seq; ++seq )
450  {
451  PCB_LAYER_ID layer = *seq;
452 
453  wxControl* ctl = getName( layer );
454 
455  wxASSERT( ctl );
456 
457  if( ctl )
458  {
459  wxString lname = m_pcb->GetLayerName( layer );
460 
461  if( ctl->IsKindOf( CLASSINFO( wxTextCtrl ) ) )
462  ((wxTextCtrl*)ctl)->SetValue( lname ); // wxTextCtrl
463  else
464  ctl->SetLabel( lname ); // wxStaticText
465  }
466  }
467 }
468 
469 
471 {
472  // the check boxes
473  for( LSEQ seq = dlg_layers(); seq; ++seq )
474  {
475  PCB_LAYER_ID layer = *seq;
476  setLayerCheckBox( layer, enabledLayers[layer] );
477  }
478 }
479 
480 
482 {
483  int presetsNdx = 0; // the "Custom" setting, matches nothing
484 
485  for( unsigned i=1; i<DIM( presets ); ++i )
486  {
487  if( enabledLayers == presets[i] )
488  {
489  presetsNdx = i;
490  break;
491  }
492  }
493 
494  m_PresetsChoice->SetSelection( presetsNdx );
495 }
496 
497 
499 {
500  for( LSEQ seq = LSET::AllCuMask().Seq(); seq; ++seq )
501  {
502  PCB_LAYER_ID cu_layer = *seq;
503 
504  wxChoice* ctl = getChoice( cu_layer );
505  ctl->SetSelection( m_pcb->GetLayerType( cu_layer ) );
506  }
507 }
508 
509 
511 {
512  LSET layerMaskResult;
513 
514  for( LSEQ seq = dlg_layers(); seq; ++seq )
515  {
516  PCB_LAYER_ID layer = *seq;
517  wxCheckBox* ctl = getCheckBox( layer );
518 
519  if( ctl->GetValue() )
520  {
521  layerMaskResult.set( layer );
522  }
523  }
524 
525  return layerMaskResult;
526 }
527 
528 
529 void DIALOG_LAYERS_SETUP::setLayerCheckBox( LAYER_NUM aLayer, bool isChecked )
530 {
531  wxCheckBox* ctl = getCheckBox( aLayer );
532  ctl->SetValue( isChecked );
533 }
534 
535 
537 {
538  if( copperCount > 0 )
539  {
540  setLayerCheckBox( F_Cu, true );
541  --copperCount;
542  }
543 
544  if( copperCount > 0 )
545  {
546  setLayerCheckBox( B_Cu, true );
547  --copperCount;
548  }
549 
550  for( LSEQ seq = LSET::InternalCuMask().Seq(); seq; ++seq, --copperCount )
551  {
552  PCB_LAYER_ID layer = *seq;
553  bool state = copperCount > 0;
554 
555 #ifdef HIDE_INACTIVE_LAYERS
556  // This code hides non-active copper layers, or redisplays hidden
557  // layers which are now needed.
558  CTLs ctl = getCTLs( layer );
559 
560  ctl.name->Show( state );
561  ctl.checkbox->Show( state );
562  ctl.choice->Show( state );
563 
564  if( ctl.panel )
565  ctl.panel->Show( state );
566 #endif
567 
568  setLayerCheckBox( layer, state );
569  }
570 
571 #ifdef HIDE_INACTIVE_LAYERS
572  // Send an size event to force sizers to be updated,
573  // because the number of copper layers can have changed.
574  wxSizeEvent evt_size( m_LayersListPanel->GetSize() );
575  m_LayersListPanel->GetEventHandler()->ProcessEvent( evt_size );
576 #endif
577 }
578 
579 
580 void DIALOG_LAYERS_SETUP::OnCheckBox( wxCommandEvent& event )
581 {
583 
585 }
586 
587 
588 void DIALOG_LAYERS_SETUP::DenyChangeCheckBox( wxCommandEvent& event )
589 {
590  // user may not change copper layer checkboxes from anything other than
591  // either presets choice or the copper layer choice controls.
592 
593  // I tried to simply disable the copper CheckBoxes but they look like crap,
594  // so leave them enabled and reverse the user's attempt to toggle them.
595 
597 }
598 
599 
600 void DIALOG_LAYERS_SETUP::OnPresetsChoice( wxCommandEvent& event )
601 {
602  unsigned presetNdx = m_PresetsChoice->GetCurrentSelection();
603 
604  if( presetNdx == 0 ) // the Custom setting controls nothing.
605  return;
606 
607  if( presetNdx < DIM(presets) )
608  {
609  m_enabledLayers = presets[ presetNdx ];
610  LSET copperSet = m_enabledLayers & LSET::AllCuMask();
611  int copperCount = copperSet.count();
612 
613  m_copperLayerCount = copperCount;
617  }
618 
619  // Ensure mandatory layers are activated
621 }
622 
623 
624 void DIALOG_LAYERS_SETUP::OnCopperLayersChoice( wxCommandEvent& event )
625 {
626  m_copperLayerCount = m_CopperLayersChoice->GetCurrentSelection() * 2 + 2;
630 }
631 
632 
634 {
635  if( !wxWindow::TransferDataFromWindow() || !testLayerNames() )
636  return false;
637 
638  wxString msg;
639 
640  // Make sure the board thickness is sane.
641  int thickness = ValueFromTextCtrl( *m_textCtrlBrdThickness );
642 
643  if( thickness < Millimeter2iu( 0.1 ) || thickness > Millimeter2iu( 10.0 ) )
644  {
645  msg.Printf( _( "Board thickness %s is out of range." ),
646  StringFromValue( g_UserUnit, thickness, true ) );
647  DisplayError( this, msg );
648  return false;
649  }
650 
651  // Check for removed layers with items which will get deleted from the board.
652  LSEQ removedLayers = getRemovedLayersWithItems();
653 
654  // Check for non copper layers in use in footprints, and therefore not removable.
655  LSEQ notremovableLayers = getNonRemovableLayers();
656 
657  if( !notremovableLayers.empty() )
658  {
659  for( unsigned int ii = 0; ii < notremovableLayers.size(); ii++ )
660  msg << m_pcb->GetLayerName( notremovableLayers[ii] ) << "\n";
661 
662  if( !IsOK( this, wxString::Format( _( "Footprints have some items on removed layers:\n"
663  "%s\n"
664  "These items will be no longer accessible\n"
665  "Do you wish to continue?" ), msg ) ) )
666  return false;
667  }
668 
669  if( !removedLayers.empty() &&
670  !IsOK( this, _( "Items have been found on removed layers. This operation will delete "
671  "all items from removed layers and cannot be undone. Do you wish to "
672  "continue?" ) ) )
673  return false;
674 
675  // Delete all objects on layers that have been removed. Leaving them in copper layers
676  // can (will?) result in DRC errors and it pollutes the board file with cruft.
677  bool hasRemovedBoardItems = false;
678 
679  if( !removedLayers.empty() )
680  {
681  PCB_LAYER_COLLECTOR collector;
682 
683  for( auto layer_id : removedLayers )
684  {
685  collector.SetLayerId( layer_id );
687 
688  // Bye-bye items on on removed layer.
689  if( collector.GetCount() != 0 )
690  {
691  hasRemovedBoardItems = true;
692 
693  for( int i = 0; i < collector.GetCount(); i++ )
694  {
695  BOARD_ITEM* item = collector[i];
696  m_pcb->Remove( item );
697  delete item;
698  }
699  }
700  }
701  }
702 
703  wxString name;
704 
707 
708  /* Ensure enabled layers are also visible
709  * This is mainly to avoid mistakes if some enabled
710  * layers are not visible when exiting this dialog
711  */
713 
714  for( LSEQ seq = LSET::AllCuMask().Seq(); seq; ++seq )
715  {
716  PCB_LAYER_ID layer = *seq;
717 
718  if( m_enabledLayers[layer] )
719  {
720  name = getLayerName( layer );
721  m_pcb->SetLayerName( layer, name );
722  LAYER_T t = (LAYER_T) getLayerTypeIndex( layer );
723  m_pcb->SetLayerType( layer, t );
724  }
725  }
726 
727  m_pcb->GetDesignSettings().SetBoardThickness( thickness );
728 
729  // If some board items are deleted: rebuild the connectivity,
730  // because it is likely some tracks and vias where removed
731  if( hasRemovedBoardItems )
732  {
733  PCB_EDIT_FRAME* editFrame = static_cast<PCB_EDIT_FRAME*>( GetParent() );
734  // Rebuild list of nets (full ratsnest rebuild)
735  editFrame->Compile_Ratsnest( NULL, true );
737  }
738 
739  return true;
740 }
741 
742 
744 {
745  wxChoice* ctl = getChoice( aLayer );
746  int ret = ctl->GetCurrentSelection(); // indices must have same sequence as LAYER_T
747  return ret;
748 }
749 
750 
752 {
753  wxString ret;
754  wxASSERT( IsCopperLayer( aLayer ) );
755  wxTextCtrl* ctl = (wxTextCtrl*) getName( aLayer );
756  ret = ctl->GetValue().Trim();
757 
758  return ret;
759 }
760 
761 
762 static bool hasOneOf( const wxString& str, const wxString& chars )
763 {
764  for( unsigned i=0; i<chars.Len(); ++i )
765  {
766  if( str.Find( chars[i] ) != wxNOT_FOUND )
767  return true;
768  }
769 
770  return false;
771 }
772 
773 
775 {
776  std::vector<wxString> names;
777  wxTextCtrl* ctl;
778 
779  for( LSEQ seq = LSET::AllCuMask().Seq(); seq; ++seq )
780  {
781  PCB_LAYER_ID layer = *seq;
782 
783  // we _can_ rely on m_enabledLayers being current here:
784  if( !m_enabledLayers[layer] )
785  continue;
786 
787  wxString name = getLayerName( layer );
788 
789  ctl = (wxTextCtrl*) getName( layer );
790 
791  // check name for legality.
792  // 1) cannot be blank.
793  // 2) cannot have blanks.
794  // 3) cannot have " chars
795  // 4) cannot be 'signal'
796  // 5) must be unique.
797  // 6) cannot have illegal chars in filenames ( some filenames are built from layer names )
798  // like : % $ \ " / :
799  wxString badchars = wxFileName::GetForbiddenChars( wxPATH_DOS );
800  badchars.Append( '%' );
801 
802  if( !name )
803  {
804  DisplayError( this, _( "Layer name may not be empty." ) );
805  ctl->SetFocus(); // on the bad name
806  return false;
807  }
808 
809  if( hasOneOf( name, badchars ) )
810  {
811  DisplayError( this, _( "Layer name has an illegal character, one of: '" ) +
812  badchars + wxT( "'" ) );
813  ctl->SetFocus(); // on the bad name
814  return false;
815  }
816 
817  if( name == wxT( "signal" ) )
818  {
819  DisplayError( this, _( "Layer name 'signal' is reserved." ) );
820  ctl->SetFocus(); // on the bad name
821  return false;
822  }
823 
824  for( std::vector<wxString>::iterator it = names.begin(); it != names.end(); ++it )
825  {
826  if( name == *it )
827  {
828  DisplayError( this, _( "Duplicate layer names are not permitted." ) );
829  ctl->SetFocus(); // on the bad name
830  return false;
831  }
832  }
833 
834  names.push_back( name );
835  }
836 
837  return true;
838 }
839 
840 
842 {
843  LSEQ removedLayers;
844  LSET newLayers = getUILayerMask();
845  LSET curLayers = m_pcb->GetEnabledLayers();
846 
847  if( newLayers == curLayers ) // return a empty list if no change
848  return removedLayers;
849 
850  PCB_LAYER_COLLECTOR collector;
851  LSEQ newLayerSeq = newLayers.Seq();
852  std::vector< PCB_LAYER_ID >::iterator it;
853 
854  for( auto layer_id : curLayers.Seq() )
855  {
856  if( std::find( newLayerSeq.begin(), newLayerSeq.end(), layer_id ) == newLayerSeq.end() )
857  {
858  collector.SetLayerId( layer_id );
860 
861  if( collector.GetCount() != 0 )
862  removedLayers.push_back( layer_id );
863  }
864  }
865 
866  return removedLayers;
867 }
868 
869 
871 {
872  //Build the list of non copper layers in use in footprints.
873  LSEQ inUseLayers;
874  LSET newLayers = getUILayerMask();
875  LSET curLayers = m_pcb->GetEnabledLayers();
876 
877  if( newLayers == curLayers ) // return a empty list if no change
878  return inUseLayers;
879 
880  PCB_LAYER_COLLECTOR collector;
881  LSEQ newLayerSeq = newLayers.Seq();
882  std::vector< PCB_LAYER_ID >::iterator it;
883 
884  for( auto layer_id : curLayers.Seq() )
885  {
886  if( IsCopperLayer( layer_id ) ) // Copper layers are not taken in account here
887  continue;
888 
889  if( std::find( newLayerSeq.begin(), newLayerSeq.end(), layer_id ) == newLayerSeq.end() )
890  {
891  collector.SetLayerId( layer_id );
893 
894  if( collector.GetCount() != 0 )
895  inUseLayers.push_back( layer_id );
896  }
897  }
898 
899  return inUseLayers;
900 }
901 
902 
903 bool InvokeLayerSetup( PCB_EDIT_FRAME* aCaller, BOARD* aBoard )
904 {
905  DIALOG_LAYERS_SETUP dlg( aCaller, aBoard );
906 
907  return dlg.ShowModal() == wxID_OK;
908 }
wxCheckBox * getCheckBox(LAYER_NUM aLayer)
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:673
int GetCount() const
Function GetCount returns the number of objects in the list.
Definition: collector.h:106
#define DIM(x)
of elements in an array
Definition: macros.h:98
static LSEQ dlg_layers()
static const KICAD_T BoardLevelItems[]
A scan list for all primary board items, omitting items which are subordinate to a MODULE...
Definition: collectors.h:275
Holds the 3 UI control pointers for a single board layer.
wxControl * getName(LAYER_NUM aLayer)
bool InvokeLayerSetup(PCB_EDIT_FRAME *aCaller, BOARD *aBoard)
Function InvokeLayerSetup shows the layer setup dialog.
This file is part of the common library.
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class...
static LSET BackTechMask()
Function BackTechMask returns a mask holding all technical layers (no CU layer) on back side...
Definition: lset.cpp:717
void setLayerCheckBox(LAYER_NUM layer, bool isChecked)
Class BOARD to handle a board.
wxString StringFromValue(EDA_UNITS_T aUnit, int aValue, bool aAddUnitSymbol)
Function StringFromValue returns the string from aValue according to units (inch, mm ...
Definition: base_units.cpp:205
int GetCopperLayerCount() const
Function GetCopperLayerCount.
wxStaticText * m_typeStaticText
CTLs(wxControl *aName, wxCheckBox *aCheckBox, wxControl *aChoiceOrDesc, wxPanel *aPanel=NULL)
void showPresets(LSET enabledLayerMask)
void Collect(BOARD_ITEM *aBoard, const KICAD_T aScanList[])
Tests a BOARD_ITEM using this class&#39;s Inspector method, which does the collection.
Definition: collectors.cpp:522
static LSET FrontTechMask()
Function FrontTechMask returns a mask holding all technical layers (no CU layer) on front side...
Definition: lset.cpp:729
wxStaticText * m_enabledStaticText
CTLs getCTLs(LAYER_NUM aLayerNumber)
Map aLayerNumber to the wx IDs for that layer which are the layer name control ID, checkbox control ID, and choice control ID.
Collect all BOARD_ITEM objects on a given layer.
Definition: collectors.h:619
bool SetLayerType(PCB_LAYER_ID aLayer, LAYER_T aLayerType)
Function SetLayerType changes the type of the layer given by aLayer.
void OnSize(wxSizeEvent &event) override
void SetBoardThickness(int aThickness)
LSET GetEnabledLayers() const
Function GetEnabledLayers is a proxy function that calls the corresponding function in m_BoardSetting...
LSEQ getNonRemovableLayers()
Return a list of layers in use in footprints, and therefore not removable.
const string & str
Definition: json11.cpp:596
bool TransferDataToWindow() override
void SetLayerId(PCB_LAYER_ID aLayerId)
Definition: collectors.h:629
Class DIALOG_LAYERS_SETUP_BASE.
void OnCheckBox(wxCommandEvent &event) override
This file contains miscellaneous commonly used macros and functions.
wxStaticText * m_nameStaticText
wxControl * choice
static const LSET presets[]
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Function Seq returns an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:364
wxPanel * panel
PCB_LAYER_ID
A quick note on layer IDs:
Class LSET is a set of PCB_LAYER_IDs.
void OnInitDialog(wxInitDialogEvent &aEvent) override
void showCopperChoice(int copperCount)
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
#define RETCOP(x)
void SetVisibleLayers(LSET aLayerMask)
Function SetVisibleLayers is a proxy function that calls the correspondent function in m_BoardSetting...
void OnPresetsChoice(wxCommandEvent &event) override
LAYER_T
Enum LAYER_T gives the allowed types of layers, same as Specctra DSN spec.
Definition: class_board.h:71
bool TransferDataFromWindow() override
wxString GetAbbreviatedUnitsLabel(EDA_UNITS_T aUnit)
Definition: base_units.cpp:485
void setCopperLayerCheckBoxes(int copperCount)
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Function GetLayerName returns the name of a layer given by aLayer.
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Function SetLayerName changes the name of the layer given by aLayer.
void SetSizeInDU(int x, int y)
Set the dialog to the given dimensions in "dialog units".
static LSET InternalCuMask()
Function InternalCuMask() returns a complete set of internal copper layers, which is all Cu layers ex...
Definition: lset.cpp:633
DIALOG_LAYERS_SETUP(PCB_EDIT_FRAME *aCaller, BOARD *aBoard)
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:535
#define RETAUX(x)
void BuildConnectivity()
Builds or rebuilds the board connectivity database for the board, especially the list of connected it...
int ValueFromTextCtrl(const wxTextCtrl &aTextCtr)
Convert the number Value in a string according to the internal units and the selected unit (g_UserUni...
Definition: base_units.cpp:386
Class LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
void OnCopperLayersChoice(wxCommandEvent &event) override
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
wxChoice * getChoice(LAYER_NUM aLayer)
void Compile_Ratsnest(wxDC *aDC, bool aDisplayStatus)
Function Compile_Ratsnest Create the entire board ratsnest.
Definition: ratsnest.cpp:54
int VertPixelsFromDU(int y)
Convert an integer number of dialog units to pixels, vertically.
EDA_UNITS_T g_UserUnit
Global variables definitions.
Definition: common.cpp:57
void showSelectedLayerCheckBoxes(LSET enableLayerMask)
LSET getUILayerMask()
Return the selected layer mask within the UI checkboxes.
void PutValueInLocalUnits(wxTextCtrl &aTextCtr, int aValue)
Function PutValueInLocalUnits converts aValue from internal units to user units and append the units ...
Definition: base_units.cpp:267
LSEQ getRemovedLayersWithItems()
Return a list of layers removed from the board that contain items.
const char * name
Definition: DXF_plotter.cpp:61
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:169
static const KICAD_T ModuleItems[]
A scan list for primary module items.
Definition: collectors.h:300
wxString getLayerName(LAYER_NUM layer)
size_t i
Definition: json11.cpp:597
Class PCB_EDIT_FRAME is the main frame for Pcbnew.
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
wxCheckBox * checkbox
static bool hasOneOf(const wxString &str, const wxString &chars)
int getLayerTypeIndex(LAYER_NUM layer)
void DenyChangeCheckBox(wxCommandEvent &event) override
static LSET UserMask()
Definition: lset.cpp:757
wxControl * name
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:185
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Function IsOK displays a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:233
LAYER_T GetLayerType(PCB_LAYER_ID aLayer) const
Function GetLayerType returns the type of the copper layer given by aLayer.
void SetEnabledLayers(LSET aLayerMask)
Function SetEnabledLayers is a proxy function that calls the correspondent function in m_BoardSetting...
void Remove(BOARD_ITEM *aBoardItem) override
Removes an item from the container.