KiCad PCB EDA Suite
select_layers_to_pcb.cpp
Go to the documentation of this file.
1 
6 /*
7  * This program source code file is part of KiCad, a free EDA CAD application.
8  *
9  * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, you may find one here:
23  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
24  * or you may search the http://www.gnu.org website for the version 2 license,
25  * or you may write to the Free Software Foundation, Inc.,
26  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
27  */
28 
29 #include <fctsys.h>
30 #include <kiface_i.h>
31 #include <gerbview.h>
32 #include <gerbview_frame.h>
33 #include <gerbview_id.h>
34 #include <gerber_file_image.h>
35 #include <gerber_file_image_list.h>
36 
37 #include <select_layers_to_pcb.h>
38 
39 // Imported function
40 extern const wxString GetPCBDefaultLayerName( LAYER_NUM aLayerNumber );
41 
46 };
47 
48 
49 /*
50  * This dialog shows the gerber files loaded, and allows user to choose:
51  * what gerber file and what board layer are used
52  * the number of copper layers
53  */
54 
56 
57 
58 BEGIN_EVENT_TABLE( LAYERS_MAP_DIALOG, LAYERS_MAP_DIALOG_BASE )
60  wxEVT_COMMAND_BUTTON_CLICKED,
61  LAYERS_MAP_DIALOG::OnSelectLayer )
62 END_EVENT_TABLE()
63 
64 
66  LAYERS_MAP_DIALOG_BASE( parent )
67 {
68  m_Parent = parent;
69  initDialog();
70 
71  // Resize the dialog
72  Layout();
73  GetSizer()->SetSizeHints( this );
74  Centre();
75 }
76 
77 
79 {
80  wxStaticText* label;
81  wxStaticText* text;
82  int item_ID;
83  wxString msg;
84  wxSize goodSize;
85 
86  for( int ii = 0; ii < GERBER_DRAWLAYERS_COUNT; ++ii )
87  {
88  // Specify the default value for each member of these arrays.
89  m_buttonTable[ii] = -1;
91  }
92 
93  // Ensure we have:
94  // at least 2 copper layers and less than max pacb copper layers count
95  // and even layers count because a board *must* have even layers count
97 
98  int idx = ( m_exportBoardCopperLayersCount / 2 ) - 1;
99  m_comboCopperLayersCount->SetSelection( idx );
100 
101  LAYER_NUM pcb_layer_num = 0;
104 
105  for( unsigned ii = 0; ii < GERBER_DRAWLAYERS_COUNT; ++ii )
106  {
107  if( images->GetGbrImage( ii ) == NULL )
108  break;
109 
110  if( (pcb_layer_num == m_exportBoardCopperLayersCount - 1)
112  pcb_layer_num = F_Cu;
113 
115  m_layersLookUpTable[ii] = pcb_layer_num;
117  ++pcb_layer_num;
118  }
119 
120  if( m_gerberActiveLayersCount <= GERBER_DRAWLAYERS_COUNT/2 ) // Only one list is enough
121  {
122  m_staticlineSep->Hide();
123  }
124 
125  wxFlexGridSizer* flexColumnBoxSizer = m_flexLeftColumnBoxSizer;
126 
127  for( int ii = 0; ii < m_gerberActiveLayersCount; ii++ )
128  {
129  // Each Gerber layer has an associated static text string (to
130  // identify that layer), a button (for invoking a child dialog
131  // box to change which Pcbnew layer that the Gerber layer is
132  // mapped to), and a second static text string (to depict which
133  // Pcbnew layer that the Gerber layer has been mapped to). Each
134  // of those items are placed into the left hand column, middle
135  // column, and right hand column (respectively) of the Flexgrid
136  // sizer, and the color of the second text string is set to
137  // fuchsia or blue (to respectively indicate whether the Gerber
138  // layer has been mapped to a Pcbnew layer or is not being
139  // exported at all). (Experimentation has shown that if a text
140  // control is used to depict which Pcbnew layer that each Gerber
141  // layer is mapped to (instead of a static text string), then
142  // those controls do not behave in a fully satisfactory manner
143  // in the Linux version. Even when the read-only attribute is
144  // specified for all of those controls, they can still be selected
145  // when the arrow keys or Tab key is used to step through all of
146  // the controls within the dialog box, and directives to set the
147  // foreground color of the text of each such control to blue (to
148  // indicate that the text is of a read-only nature) are disregarded.
149  // Specify a FlexGrid sizer with an appropriate number of rows
150  // and three columns. If nb_items < 16, then the number of rows
151  // is nb_items; otherwise, the number of rows is 16 (with two
152  // separate columns of controls being used if nb_items > 16).
153 
154  if( ii == GERBER_DRAWLAYERS_COUNT/2 )
155  flexColumnBoxSizer = m_flexRightColumnBoxSizer;
156 
157  // Provide a text string to identify the Gerber layer
158  msg.Printf( _( "Layer %d" ), m_buttonTable[ii] + 1 );
159 
160  label = new wxStaticText( this,
161  wxID_STATIC, msg, wxDefaultPosition,
162  wxDefaultSize, 0 );
163  flexColumnBoxSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
164 
165  /* Add file name and extension without path. */
166  wxFileName fn( images->GetGbrImage( ii )->m_FileName );
167  label = new wxStaticText( this,
168  wxID_STATIC, fn.GetFullName(),
169  wxDefaultPosition, wxDefaultSize );
170  flexColumnBoxSizer->Add( label, 0,
171  wxALIGN_CENTER_VERTICAL | wxALL, 5 );
172 
173  // Provide a button for this layer (which will invoke a child dialog box)
174  item_ID = ID_BUTTON_0 + ii;
175  wxButton * Button = new wxButton( this,
176  item_ID, wxT( "..." ),
177  wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT );
178 
179  flexColumnBoxSizer->Add( Button, 0, wxALIGN_CENTER_VERTICAL | wxALL );
180 
181  // Provide another text string to specify which Pcbnew layer that this
182  // Gerber layer is initially mapped to, and set the initial text to
183  // specify the appropriate Pcbnew layer, and set the foreground color
184  // of the text to fuchsia (to indicate that the layer is being exported).
185  item_ID = ID_TEXT_0 + ii;
186 
187  // When the first of these text strings is being added, determine what
188  // size is necessary to to be able to display any possible string
189  // without it being truncated. Then specify that size as the minimum
190  // size for all of these text strings. (If this minimum size is not
191  // determined in this fashion, then it is possible for the display of
192  // one or more of these strings to be truncated after different Pcbnew
193  // layers are selected.)
194  if( ii == 0 )
195  {
196  msg = _( "Do not export" );
197  text = new wxStaticText( this,
198  item_ID, msg, wxDefaultPosition,
199  wxDefaultSize, 0 );
200  goodSize = text->GetSize();
201 
202  for( LAYER_NUM jj = 0; jj < GERBER_DRAWLAYERS_COUNT; ++jj )
203  {
204  text->SetLabel( GetPCBDefaultLayerName( jj ) );
205  if( goodSize.x < text->GetSize().x )
206  goodSize.x = text->GetSize().x;
207  }
208 
210  text->SetLabel( msg );
211  }
212  else
213  {
215  text = new wxStaticText( this,
216  item_ID, msg, wxDefaultPosition,
217  wxDefaultSize, 0 );
218  }
219  text->SetMinSize( goodSize );
220  flexColumnBoxSizer->Add( text, 1, wxALIGN_CENTER_VERTICAL | wxALL,
221  5 );
222 
223  m_layersList[ii] = text;
224  }
225 }
226 
227 /* Ensure m_exportBoardCopperLayersCount = 2 to BOARD_COPPER_LAYERS_MAX_COUNT
228  * and it is an even value because Boards have always an even layer count
229  */
231 {
232  if( ( m_exportBoardCopperLayersCount & 1 ) )
234 
237 
240 
241 }
242 
243 /*
244  * Called when user change the current board copper layers count
245  */
246 void LAYERS_MAP_DIALOG::OnBrdLayersCountSelection( wxCommandEvent& event )
247 {
248  int id = event.GetSelection();
249  m_exportBoardCopperLayersCount = (id+1) * 2;
250 }
251 
252 /*
253  * reset pcb layers selection to the default value
254  */
255 void LAYERS_MAP_DIALOG::OnResetClick( wxCommandEvent& event )
256 {
257  wxString msg;
258  int ii;
259  LAYER_NUM layer;
260  for( ii = 0, layer = 0; ii < m_gerberActiveLayersCount; ii++, ++layer )
261  {
262  if( (layer == m_exportBoardCopperLayersCount - 1)
264  layer = F_Cu;
265  m_layersLookUpTable[ii] = layer;
266  msg = GetPCBDefaultLayerName( layer );
267  m_layersList[ii]->SetLabel( msg );
268  m_layersList[ii]->SetForegroundColour( wxNullColour );
269  m_buttonTable[ii] = ii;
270  }
271 }
272 
273 
274 /* Stores the current layers selection in config
275  */
276 void LAYERS_MAP_DIALOG::OnStoreSetup( wxCommandEvent& event )
277 {
278  wxConfigBase* config = Kiface().KifaceSettings();
279  config->Write( wxT("BrdLayersCount"), m_exportBoardCopperLayersCount );
280 
281  wxString key;
282  for( int ii = 0; ii < GERBER_DRAWLAYERS_COUNT; ++ii )
283  {
284  key.Printf( wxT("GbrLyr%dToPcb"), ii );
285  config->Write( key, m_layersLookUpTable[ii] );
286  }
287 }
288 
289 void LAYERS_MAP_DIALOG::OnGetSetup( wxCommandEvent& event )
290 {
291  wxConfigBase* config = Kiface().KifaceSettings();
292 
293  config->Read( wxT("BrdLayersCount"), &m_exportBoardCopperLayersCount );
295 
296  int idx = ( m_exportBoardCopperLayersCount / 2 ) - 1;
297  m_comboCopperLayersCount->SetSelection( idx );
298 
299  wxString key;
300  for( int ii = 0; ii < GERBER_DRAWLAYERS_COUNT; ++ii )
301  {
302  key.Printf( wxT("GbrLyr%dToPcb"), ii );
303  int ilayer;
304  config->Read( key, &ilayer);
305  m_layersLookUpTable[ii] = ilayer;
306  }
307 
308  for( int ii = 0; ii < m_gerberActiveLayersCount; ii++ )
309  {
310  LAYER_NUM layer = m_layersLookUpTable[ii];
311  if( layer == UNSELECTED_LAYER )
312  {
313  m_layersList[ii]->SetLabel( _( "Do not export" ) );
314  m_layersList[ii]->SetForegroundColour( *wxBLUE );
315  }
316  else
317  {
318  m_layersList[ii]->SetLabel( GetPCBDefaultLayerName( layer ) );
319  m_layersList[ii]->SetForegroundColour( wxColour( 255, 0, 128 ) );
320  }
321  }
322 }
323 
324 void LAYERS_MAP_DIALOG::OnSelectLayer( wxCommandEvent& event )
325 {
326  int ii;
327 
328  ii = event.GetId() - ID_BUTTON_0;
329 
330  if( (ii < 0) || (ii >= GERBER_DRAWLAYERS_COUNT) )
331  {
332  wxFAIL_MSG( wxT("Bad layer id") );
333  return;
334  }
335 
337 
338  if( jj != UNSELECTED_LAYER && !IsValidLayer( jj ) )
339  jj = B_Cu; // (Defaults to "Copper" layer.)
340 
342 
343  if( jj != UNSELECTED_LAYER && !IsValidLayer( jj ) )
344  return;
345 
346  if( jj != m_layersLookUpTable[m_buttonTable[ii]] )
347  {
348  m_layersLookUpTable[m_buttonTable[ii]] = jj;
349 
350  if( jj == UNSELECTED_LAYER )
351  {
352  m_layersList[ii]->SetLabel( _( "Do not export" ) );
353 
354  // Change the text color to blue (to highlight
355  // that this layer is *not* being exported)
356  m_layersList[ii]->SetForegroundColour( *wxBLUE );
357  }
358  else
359  {
360  m_layersList[ii]->SetLabel( GetPCBDefaultLayerName( jj ) );
361 
362  // Change the text color to fuchsia (to highlight
363  // that this layer *is* being exported)
364  m_layersList[ii]->SetForegroundColour( wxColour( 255, 0, 128 ) );
365  }
366  }
367 }
368 
369 
370 void LAYERS_MAP_DIALOG::OnOkClick( wxCommandEvent& event )
371 {
372  /* Make some test about copper layers:
373  * Board must have enough copper layers to handle selected internal layers
374  */
376 
377  int inner_layer_max = 0;
378  for( int ii = 0; ii < GERBER_DRAWLAYERS_COUNT; ++ii )
379  {
380  if( m_layersLookUpTable[ii] < F_Cu )
381  {
382  if( m_layersLookUpTable[ii ] > inner_layer_max )
383  inner_layer_max = m_layersLookUpTable[ii];
384  }
385  }
386 
387  // inner_layer_max must be less than (or equal to) the number of
388  // internal copper layers
389  // internal copper layers = m_exportBoardCopperLayersCount-2
390  if( inner_layer_max > m_exportBoardCopperLayersCount-2 )
391  {
392  wxMessageBox(
393  _("The exported board has not enough copper layers to handle selected inner layers") );
394  return;
395  }
396 
397  EndModal( wxID_OK );
398 }
GERBER_FILE_IMAGE_LIST is a helper class to handle a list of GERBER_FILE_IMAGE files which are loaded...
void OnResetClick(wxCommandEvent &event) override
int m_buttonTable[int(GERBER_DRAWLAYERS_COUNT)+1]
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
Definition: kicad.cpp:52
void OnOkClick(wxCommandEvent &event) override
bool IsValidLayer(LAYER_NUM aLayerId)
Function IsValidLayer tests whether a given integer is a valid layer index, i.e.
#define GERBER_DRAWLAYERS_COUNT
GERBER_FILE_IMAGE * GetGbrImage(int aIdx)
GERBVIEW_FRAME * m_Parent
EVT_COMMAND_RANGE(ID_BUTTON_0, ID_BUTTON_0+GERBER_DRAWLAYERS_COUNT-1, wxEVT_COMMAND_BUTTON_CLICKED, LAYERS_MAP_DIALOG::OnSelectLayer) LAYERS_MAP_DIALOG
Class LAYERS_MAP_DIALOG_BASE.
wxStaticText * m_layersList[int(GERBER_DRAWLAYERS_COUNT)+1]
wxConfigBase * KifaceSettings() const
Definition: kiface_i.h:103
GBR_LAYOUT * GetGerberLayout() const
LAYER_NUM m_layersLookUpTable[GERBER_DRAWLAYERS_COUNT]
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
const wxString GetPCBDefaultLayerName(LAYER_NUM aLayerNumber)
GERBER_FILE_IMAGE_LIST * GetImagesList() const
Definition: gbr_layout.cpp:50
void OnBrdLayersCountSelection(wxCommandEvent &event) override
void OnGetSetup(wxCommandEvent &event) override
static int m_exportBoardCopperLayersCount
void OnSelectLayer(wxCommandEvent &event)
int SelectPCBLayer(int aDefaultLayer, int aOpperLayerCount, bool aNullLayer=false)
Install the dialog box for layer selection.
void OnStoreSetup(wxCommandEvent &event) override