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-2016 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>
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 
87 
88  // Experimentation has shown that buttons in the Windows version can be 20
89  // pixels wide and 20 pixels high, but that they need to be 26 pixels wide
90  // and 26 pixels high in the Linux version. (And although the dimensions
91  // of those buttons could be set to 26 pixels wide and 26 pixels high in
92  // both of those versions, that would result in a dialog box which would
93  // be excessively high in the Windows version.)
94 #ifdef __WINDOWS__
95  int w = 20;
96  int h = 20;
97 #else
98  int w = 26;
99  int h = 26;
100 #endif
101 
102  // As currently implemented, the dimensions of the buttons in the Mac
103  // version are also 26 pixels wide and 26 pixels high. If appropriate,
104  // the above code should be modified as required in the event that those
105  // buttons should be some other size in that version.
106  for( int ii = 0; ii < GERBER_DRAWLAYERS_COUNT; ++ii )
107  {
108  // Specify the default value for each member of these arrays.
109  m_buttonTable[ii] = -1;
111  }
112 
113  // Ensure we have:
114  // at least 2 copper layers and less than max pacb copper layers count
115  // and even layers count because a board *must* have even layers count
117 
118  int idx = ( m_exportBoardCopperLayersCount / 2 ) - 1;
119  m_comboCopperLayersCount->SetSelection( idx );
120 
121  LAYER_NUM pcb_layer_num = 0;
124 
125  for( unsigned ii = 0; ii < GERBER_DRAWLAYERS_COUNT; ++ii )
126  {
127  if( images->GetGbrImage( ii ) == NULL )
128  break;
129 
130  if( (pcb_layer_num == m_exportBoardCopperLayersCount - 1)
132  pcb_layer_num = F_Cu;
133 
135  m_layersLookUpTable[ii] = pcb_layer_num;
137  ++pcb_layer_num;
138  }
139 
140  if( m_gerberActiveLayersCount <= GERBER_DRAWLAYERS_COUNT/2 ) // Only one list is enough
141  {
142  m_staticlineSep->Hide();
143  }
144  else // Add the second list of gerber files
145  {
146  m_flexRightColumnBoxSizer = new wxFlexGridSizer( 16, 4, 0, 0 );
147  for( int ii = 0; ii < 4; ii++ )
148  m_flexRightColumnBoxSizer->AddGrowableCol( ii );
149  m_flexRightColumnBoxSizer->SetFlexibleDirection( wxBOTH );
150  m_flexRightColumnBoxSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
151  sbSizerLayersTable->Add( m_flexRightColumnBoxSizer, 1, wxEXPAND, 5 );
152  }
153 
154  wxFlexGridSizer* flexColumnBoxSizer = m_flexLeftColumnBoxSizer;
155  for( int ii = 0; ii < m_gerberActiveLayersCount; ii++ )
156  {
157  // Each Gerber layer has an associated static text string (to
158  // identify that layer), a button (for invoking a child dialog
159  // box to change which Pcbnew layer that the Gerber layer is
160  // mapped to), and a second static text string (to depict which
161  // Pcbnew layer that the Gerber layer has been mapped to). Each
162  // of those items are placed into the left hand column, middle
163  // column, and right hand column (respectively) of the Flexgrid
164  // sizer, and the color of the second text string is set to
165  // fuchsia or blue (to respectively indicate whether the Gerber
166  // layer has been mapped to a Pcbnew layer or is not being
167  // exported at all). (Experimentation has shown that if a text
168  // control is used to depict which Pcbnew layer that each Gerber
169  // layer is mapped to (instead of a static text string), then
170  // those controls do not behave in a fully satisfactory manner
171  // in the Linux version. Even when the read-only attribute is
172  // specified for all of those controls, they can still be selected
173  // when the arrow keys or Tab key is used to step through all of
174  // the controls within the dialog box, and directives to set the
175  // foreground color of the text of each such control to blue (to
176  // indicate that the text is of a read-only nature) are disregarded.
177  // Specify a FlexGrid sizer with an appropriate number of rows
178  // and three columns. If nb_items < 16, then the number of rows
179  // is nb_items; otherwise, the number of rows is 16 (with two
180  // separate columns of controls being used if nb_items > 16).
181 
182  if( ii == GERBER_DRAWLAYERS_COUNT/2 )
183  flexColumnBoxSizer = m_flexRightColumnBoxSizer;
184 
185  // Provide a text string to identify the Gerber layer
186  msg.Printf( _( "Layer %d" ), m_buttonTable[ii] + 1 );
187 
188  label = new wxStaticText( this, wxID_STATIC, msg, wxDefaultPosition,
189  wxDefaultSize, wxALIGN_RIGHT );
190  flexColumnBoxSizer->Add( label, 0,
191  wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL |
192  wxRIGHT | wxLEFT, 5 );
193 
194  /* Add file name and extension without path. */
195  wxFileName fn( images->GetGbrImage( ii )->m_FileName );
196  label = new wxStaticText( this, wxID_STATIC, fn.GetFullName(),
197  wxDefaultPosition, wxDefaultSize );
198  flexColumnBoxSizer->Add( label, 0,
199  wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL |
200  wxRIGHT | wxLEFT, 5 );
201 
202  // Provide a button for this layer (which will invoke a child dialog box)
203  item_ID = ID_BUTTON_0 + ii;
204  wxButton * Button = new wxButton( this, item_ID, wxT( "..." ),
205  wxDefaultPosition, wxSize( w, h ), 0 );
206 
207  flexColumnBoxSizer->Add( Button, 0,
208  wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
209 
210  // Provide another text string to specify which Pcbnew layer that this
211  // Gerber layer is initially mapped to, and set the initial text to
212  // specify the appropriate Pcbnew layer, and set the foreground color
213  // of the text to fuchsia (to indicate that the layer is being exported).
214  item_ID = ID_TEXT_0 + ii;
215 
216  // When the first of these text strings is being added, determine what
217  // size is necessary to to be able to display any possible string
218  // without it being truncated. Then specify that size as the minimum
219  // size for all of these text strings. (If this minimum size is not
220  // determined in this fashion, then it is possible for the display of
221  // one or more of these strings to be truncated after different Pcbnew
222  // layers are selected.)
223  if( ii == 0 )
224  {
225  msg = _( "Do not export" );
226  text = new wxStaticText( this, item_ID, msg, wxDefaultPosition,
227  wxDefaultSize, 0 );
228  goodSize = text->GetSize();
229 
230  for( LAYER_NUM jj = 0; jj < GERBER_DRAWLAYERS_COUNT; ++jj )
231  {
232  text->SetLabel( GetPCBDefaultLayerName( jj ) );
233  if( goodSize.x < text->GetSize().x )
234  goodSize.x = text->GetSize().x;
235  }
236 
238  text->SetLabel( msg );
239  }
240  else
241  {
243  text = new wxStaticText( this, item_ID, msg, wxDefaultPosition,
244  wxDefaultSize, 0 );
245  }
246  text->SetMinSize( goodSize );
247  flexColumnBoxSizer->Add( text, 1,
248  wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxRIGHT | wxLEFT,
249  5 );
250 
251  m_layersList[ii] = text;
252  }
253 }
254 
255 /* Ensure m_exportBoardCopperLayersCount = 2 to BOARD_COPPER_LAYERS_MAX_COUNT
256  * and it is an even value because Boards have always an even layer count
257  */
259 {
260  if( ( m_exportBoardCopperLayersCount & 1 ) )
262 
265 
268 
269 }
270 
271 /*
272  * Called when user change the current board copper layers count
273  */
274 void LAYERS_MAP_DIALOG::OnBrdLayersCountSelection( wxCommandEvent& event )
275 {
276  int id = event.GetSelection();
277  m_exportBoardCopperLayersCount = (id+1) * 2;
278 }
279 
280 /*
281  * reset pcb layers selection to the default value
282  */
283 void LAYERS_MAP_DIALOG::OnResetClick( wxCommandEvent& event )
284 {
285  wxString msg;
286  int ii;
287  LAYER_NUM layer;
288  for( ii = 0, layer = 0; ii < m_gerberActiveLayersCount; ii++, ++layer )
289  {
290  if( (layer == m_exportBoardCopperLayersCount - 1)
292  layer = F_Cu;
293  m_layersLookUpTable[ii] = layer;
294  msg = GetPCBDefaultLayerName( layer );
295  m_layersList[ii]->SetLabel( msg );
296  m_layersList[ii]->SetForegroundColour( wxNullColour );
297  m_buttonTable[ii] = ii;
298  }
299 }
300 
301 
302 /* Stores the current layers selection in config
303  */
304 void LAYERS_MAP_DIALOG::OnStoreSetup( wxCommandEvent& event )
305 {
306  wxConfigBase* config = Kiface().KifaceSettings();
307  config->Write( wxT("BrdLayersCount"), m_exportBoardCopperLayersCount );
308 
309  wxString key;
310  for( int ii = 0; ii < GERBER_DRAWLAYERS_COUNT; ++ii )
311  {
312  key.Printf( wxT("GbrLyr%dToPcb"), ii );
313  config->Write( key, m_layersLookUpTable[ii] );
314  }
315 }
316 
317 void LAYERS_MAP_DIALOG::OnGetSetup( wxCommandEvent& event )
318 {
319  wxConfigBase* config = Kiface().KifaceSettings();
320 
321  config->Read( wxT("BrdLayersCount"), &m_exportBoardCopperLayersCount );
323 
324  int idx = ( m_exportBoardCopperLayersCount / 2 ) - 1;
325  m_comboCopperLayersCount->SetSelection( idx );
326 
327  wxString key;
328  for( int ii = 0; ii < GERBER_DRAWLAYERS_COUNT; ++ii )
329  {
330  key.Printf( wxT("GbrLyr%dToPcb"), ii );
331  int ilayer;
332  config->Read( key, &ilayer);
333  m_layersLookUpTable[ii] = ilayer;
334  }
335 
336  for( int ii = 0; ii < m_gerberActiveLayersCount; ii++ )
337  {
338  LAYER_NUM layer = m_layersLookUpTable[ii];
339  if( layer == UNSELECTED_LAYER )
340  {
341  m_layersList[ii]->SetLabel( _( "Do not export" ) );
342  m_layersList[ii]->SetForegroundColour( *wxBLUE );
343  }
344  else
345  {
346  m_layersList[ii]->SetLabel( GetPCBDefaultLayerName( layer ) );
347  m_layersList[ii]->SetForegroundColour( wxColour( 255, 0, 128 ) );
348  }
349  }
350 }
351 
352 void LAYERS_MAP_DIALOG::OnSelectLayer( wxCommandEvent& event )
353 {
354  int ii;
355 
356  ii = event.GetId() - ID_BUTTON_0;
357 
358  if( (ii < 0) || (ii >= GERBER_DRAWLAYERS_COUNT) )
359  {
360  wxFAIL_MSG( wxT("Bad layer id") );
361  return;
362  }
363 
365 
366  if( jj != UNSELECTED_LAYER && !IsValidLayer( jj ) )
367  jj = B_Cu; // (Defaults to "Copper" layer.)
368 
370 
371  if( jj != UNSELECTED_LAYER && !IsValidLayer( jj ) )
372  return;
373 
374  if( jj != m_layersLookUpTable[m_buttonTable[ii]] )
375  {
376  m_layersLookUpTable[m_buttonTable[ii]] = jj;
377 
378  if( jj == UNSELECTED_LAYER )
379  {
380  m_layersList[ii]->SetLabel( _( "Do not export" ) );
381 
382  // Change the text color to blue (to highlight
383  // that this layer is *not* being exported)
384  m_layersList[ii]->SetForegroundColour( *wxBLUE );
385  }
386  else
387  {
388  m_layersList[ii]->SetLabel( GetPCBDefaultLayerName( jj ) );
389 
390  // Change the text color to fuchsia (to highlight
391  // that this layer *is* being exported)
392  m_layersList[ii]->SetForegroundColour( wxColour( 255, 0, 128 ) );
393  }
394  }
395 }
396 
397 
398 void LAYERS_MAP_DIALOG::OnOkClick( wxCommandEvent& event )
399 {
400  /* Make some test about copper layers:
401  * Board must have enough copper layers to handle selected internal layers
402  */
404 
405  int inner_layer_max = 0;
406  for( int ii = 0; ii < GERBER_DRAWLAYERS_COUNT; ++ii )
407  {
408  if( m_layersLookUpTable[ii] < F_Cu )
409  {
410  if( m_layersLookUpTable[ii ] > inner_layer_max )
411  inner_layer_max = m_layersLookUpTable[ii];
412  }
413  }
414 
415  // inner_layer_max must be less than (or equal to) the number of
416  // internal copper layers
417  // internal copper layers = m_exportBoardCopperLayersCount-2
418  if( inner_layer_max > m_exportBoardCopperLayersCount-2 )
419  {
420  wxMessageBox(
421  _("The exported board has not enough copper layers to handle selected inner layers") );
422  return;
423  }
424 
425  EndModal( wxID_OK );
426 }
GERBER_FILE_IMAGE_LIST * GetImagesList()
wxFlexGridSizer * m_flexRightColumnBoxSizer
swap_layer_id
Definition: swap_layers.cpp:47
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.
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:101
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)
void OnBrdLayersCountSelection(wxCommandEvent &event) override
void OnGetSetup(wxCommandEvent &event) override
static int m_exportBoardCopperLayersCount
#define GERBER_DRAWLAYERS_COUNT
Definition: gerbview.h:45
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