KiCad PCB EDA Suite
sel_layer.cpp
Go to the documentation of this file.
1 
5 /*
6  * This program source code file is part of KiCad, a free EDA CAD application.
7  *
8  * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
9  * Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
10  *
11  * This program is free software: you can redistribute it and/or modify it
12  * under the terms of the GNU General Public License as published by the
13  * Free Software Foundation, either version 3 of the License, or (at your
14  * option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program. If not, see <http://www.gnu.org/licenses/>.
23  */
24 
25 
26 #include <confirm.h>
27 #include <pcb_base_frame.h>
29 #include <board.h>
31 #include <router/router_tool.h>
33 
34 
35 // Column position by function:
36 #define SELECT_COLNUM 0
37 #define COLOR_COLNUM 1
38 #define LAYERNAME_COLNUM 2
39 
40 
41 /* classes to display a layer list using a wxGrid.
42  */
44 {
45 public:
48  {
49  m_frame = aFrame;
50  }
51 
52 protected:
54 
55  // Returns true if the layer id is enabled (i.e. is it should be displayed)
56  bool isLayerEnabled( LAYER_NUM aLayer ) const override
57  {
58  return m_frame->GetBoard()->IsLayerEnabled( PCB_LAYER_ID( aLayer ) );
59  }
60 
61  // Returns a color index from the layer id
62  // Virtual function
63  COLOR4D getLayerColor( LAYER_NUM aLayer ) const override
64  {
65  return m_frame->GetColorSettings()->GetColor( aLayer );
66  }
67 
68  // Returns the name of the layer id
69  wxString getLayerName( LAYER_NUM aLayer ) const override
70  {
71  return m_frame->GetBoard()->GetLayerName( ToLAYER_ID( aLayer ) );
72  }
73 };
74 
75 
76 /*
77  * This class display a pcb layers list in a dialog,
78  * to select one layer from this list
79  */
82 {
86  std::vector<PCB_LAYER_ID> m_layersIdLeftColumn;
87  std::vector<PCB_LAYER_ID> m_layersIdRightColumn;
88 
89 public:
90  PCB_ONE_LAYER_SELECTOR( PCB_BASE_FRAME* aParent, BOARD * aBrd, PCB_LAYER_ID aDefaultLayer,
91  LSET aNotAllowedLayersMask );
92 
94 
95 private:
96  // Event handlers
97  void OnLeftGridCellClick( wxGridEvent& event ) override;
98  void OnRightGridCellClick( wxGridEvent& event ) override;
99 
100  void buildList();
101 };
102 
103 
105  PCB_LAYER_ID aDefaultLayer,
106  LSET aNotAllowedLayersMask ) :
107  PCB_LAYER_SELECTOR( aParent ),
108  DIALOG_LAYER_SELECTION_BASE( aParent )
109 {
110  m_layerSelected = aDefaultLayer;
111  m_notAllowedLayersMask = aNotAllowedLayersMask;
112  m_brd = aBrd;
113 
114  m_leftGridLayers->SetCellHighlightPenWidth( 0 );
115  m_rightGridLayers->SetCellHighlightPenWidth( 0 );
116  m_leftGridLayers->SetColFormatBool( SELECT_COLNUM );
117  m_rightGridLayers->SetColFormatBool( SELECT_COLNUM );
118  buildList();
119 
120  Layout();
121  GetSizer()->SetSizeHints( this );
122  SetFocus();
123 }
124 
125 
127 {
128  wxColour bg = getLayerColor( LAYER_PCB_BACKGROUND ).ToColour();
129  int left_row = 0;
130  int right_row = 0;
131  wxString layername;
132 
133  for( LSEQ ui_seq = m_brd->GetEnabledLayers().UIOrder(); ui_seq; ++ui_seq )
134  {
135  PCB_LAYER_ID layerid = *ui_seq;
136 
137  if( m_notAllowedLayersMask[layerid] )
138  continue;
139 
140  wxColour fg = getLayerColor( layerid ).ToColour();
141  wxColour color( wxColour::AlphaBlend( fg.Red(), bg.Red(), fg.Alpha() / 255.0 ),
142  wxColour::AlphaBlend( fg.Green(), bg.Green(), fg.Alpha() / 255.0 ),
143  wxColour::AlphaBlend( fg.Blue(), bg.Blue(), fg.Alpha() / 255.0 ) );
144 
145  layername = wxT( " " ) + getLayerName( layerid );
146 
147  if( IsCopperLayer( layerid ) )
148  {
149  if( left_row )
150  m_leftGridLayers->AppendRows( 1 );
151 
152  m_leftGridLayers->SetCellBackgroundColour ( left_row, COLOR_COLNUM, color );
153  m_leftGridLayers->SetCellValue( left_row, LAYERNAME_COLNUM, layername );
154 
155  if( m_layerSelected == layerid )
156  m_leftGridLayers->SetCellValue( left_row, SELECT_COLNUM, "1" );
157 
158  m_layersIdLeftColumn.push_back( layerid );
159  left_row++;
160  }
161  else
162  {
163  if( right_row )
164  m_rightGridLayers->AppendRows( 1 );
165 
166  m_rightGridLayers->SetCellBackgroundColour( right_row, COLOR_COLNUM, color );
167  m_rightGridLayers->SetCellValue( right_row, LAYERNAME_COLNUM, layername );
168 
169  if( m_layerSelected == layerid )
170  m_rightGridLayers->SetCellValue( right_row, SELECT_COLNUM, "1" );
171 
172  m_layersIdRightColumn.push_back( layerid );
173  right_row++;
174  }
175  }
176 
177  // Show only populated lists:
178  if( left_row <= 0 )
179  m_leftGridLayers->Show( false );
180 
181  if( right_row <= 0 )
182  m_rightGridLayers->Show( false );
183 
184  // Now fix min grid layer name column size (it also sets a minimal size)
185  m_leftGridLayers->AutoSizeColumn( LAYERNAME_COLNUM );
186  m_rightGridLayers->AutoSizeColumn( LAYERNAME_COLNUM );
187 }
188 
189 
191 {
192  m_layerSelected = m_layersIdLeftColumn[ event.GetRow() ];
193  EndModal( 1 );
194 }
195 
196 
198 {
199  m_layerSelected = m_layersIdRightColumn[ event.GetRow() ];
200  EndModal( 2 );
201 }
202 
203 
204 PCB_LAYER_ID PCB_BASE_FRAME::SelectLayer( PCB_LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask,
205  wxPoint aDlgPosition )
206 {
207  PCB_ONE_LAYER_SELECTOR dlg( this, GetBoard(), aDefaultLayer, aNotAllowedLayersMask );
208 
209  if( aDlgPosition != wxDefaultPosition )
210  {
211  wxSize dlgSize = dlg.GetSize();
212  aDlgPosition.x -= dlgSize.x/2;
213  aDlgPosition.y -= dlgSize.y/2;
214  dlg.SetPosition( aDlgPosition );
215  }
216 
217  dlg.ShowModal();
218 
219  PCB_LAYER_ID layer = ToLAYER_ID( dlg.GetLayerSelection() );
220  return layer;
221 }
222 
223 
231 {
232 private:
238 
239  std::vector<PCB_LAYER_ID> m_layersId;
240 
241 public:
243  PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer );
244 
245  void GetLayerPair( PCB_LAYER_ID& aFrontLayer, PCB_LAYER_ID& aBackLayer )
246  {
247  aFrontLayer = m_frontLayer;
248  aBackLayer = m_backLayer;
249  }
250 
251 private:
252  void OnLeftGridCellClick( wxGridEvent& event ) override;
253  void OnRightGridCellClick( wxGridEvent& event ) override;
254 
255  void buildList();
256 };
257 
258 
260 {
261  PCB_SCREEN* screen = frame()->GetScreen();
262 
264  screen->m_Route_Layer_BOTTOM );
265 
266  if( dlg.ShowModal() == wxID_OK )
267  {
268  dlg.GetLayerPair( screen->m_Route_Layer_TOP, screen->m_Route_Layer_BOTTOM );
269 
270  // select the same layer for both layers is allowed (normal in some boards)
271  // but could be a mistake. So display an info message
272  if( screen->m_Route_Layer_TOP == screen->m_Route_Layer_BOTTOM )
273  DisplayInfoMessage( frame(), _( "Warning: top and bottom layers are same." ) );
274  }
275 
276  return 0;
277 }
278 
279 
281  PCB_BASE_FRAME* aParent, BOARD * aPcb, PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer) :
282  PCB_LAYER_SELECTOR( aParent ),
284 {
285  m_frontLayer = aFrontLayer;
286  m_backLayer = aBackLayer;
287  m_leftRowSelected = 0;
288  m_rightRowSelected = 0;
289  m_brd = aPcb;
290 
291  m_leftGridLayers->SetCellHighlightPenWidth( 0 );
292  m_rightGridLayers->SetCellHighlightPenWidth( 0 );
293  m_leftGridLayers->SetColFormatBool( SELECT_COLNUM );
294  m_rightGridLayers->SetColFormatBool( SELECT_COLNUM );
295  buildList();
296 
297  SetFocus();
298 
299  GetSizer()->SetSizeHints( this );
300  Center();
301 }
302 
303 
305 {
306  wxColour bg = getLayerColor( LAYER_PCB_BACKGROUND ).ToColour();
307  int row = 0;
308  wxString layername;
309 
310  for( LSEQ ui_seq = m_brd->GetEnabledLayers().UIOrder(); ui_seq; ++ui_seq )
311  {
312  PCB_LAYER_ID layerid = *ui_seq;
313 
314  if( !IsCopperLayer( layerid ) )
315  continue;
316 
317  wxColour fg = getLayerColor( layerid ).ToColour();
318  wxColour color( wxColour::AlphaBlend( fg.Red(), bg.Red(), fg.Alpha() / 255.0 ),
319  wxColour::AlphaBlend( fg.Green(), bg.Green(), fg.Alpha() / 255.0 ),
320  wxColour::AlphaBlend( fg.Blue(), bg.Blue(), fg.Alpha() / 255.0 ) );
321 
322  layername = wxT( " " ) + getLayerName( layerid );
323 
324  if( row )
325  m_leftGridLayers->AppendRows( 1 );
326 
327  m_leftGridLayers->SetCellBackgroundColour( row, COLOR_COLNUM, color );
328  m_leftGridLayers->SetCellValue( row, LAYERNAME_COLNUM, layername );
329  m_layersId.push_back( layerid );
330 
331  if( m_frontLayer == layerid )
332  {
333  m_leftGridLayers->SetCellValue( row, SELECT_COLNUM, "1" );
334  m_leftGridLayers->SetGridCursor( row, COLOR_COLNUM );
335  m_leftRowSelected = row;
336  }
337 
338  if( row )
339  m_rightGridLayers->AppendRows( 1 );
340 
341  m_rightGridLayers->SetCellBackgroundColour( row, COLOR_COLNUM, color );
342  m_rightGridLayers->SetCellValue( row, LAYERNAME_COLNUM, layername );
343 
344  if( m_backLayer == layerid )
345  {
346  m_rightGridLayers->SetCellValue( row, SELECT_COLNUM, "1" );
347  m_rightRowSelected = row;
348  }
349 
350  row++;
351  }
352 
353  // Now fix min grid layer name column size (it also sets a minimal size)
354  m_leftGridLayers->AutoSizeColumn( LAYERNAME_COLNUM );
355  m_rightGridLayers->AutoSizeColumn( LAYERNAME_COLNUM );
356 }
357 
358 
360 {
361  int row = event.GetRow();
362  PCB_LAYER_ID layer = m_layersId[row];
363 
364  if( m_frontLayer == layer )
365  return;
366 
367  m_leftGridLayers->SetCellValue( m_leftRowSelected, SELECT_COLNUM, wxEmptyString );
368  m_frontLayer = layer;
369  m_leftRowSelected = row;
370  m_leftGridLayers->SetCellValue( m_leftRowSelected, SELECT_COLNUM, "1" );
371 }
372 
373 
375 {
376  int row = event.GetRow();
377  PCB_LAYER_ID layer = m_layersId[row];
378 
379  if( m_backLayer == layer )
380  return;
381 
382  m_rightGridLayers->SetCellValue( m_rightRowSelected, SELECT_COLNUM, wxEmptyString );
383  m_backLayer = layer;
384  m_rightRowSelected = row;
385  m_rightGridLayers->SetCellValue( m_rightRowSelected, SELECT_COLNUM, "1" );
386 }
Class DIALOG_LAYER_SELECTION_BASE.
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:332
SELECT_COPPER_LAYERS_PAIR_DIALOG(PCB_BASE_FRAME *aParent, BOARD *aPcb, PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer)
Definition: sel_layer.cpp:280
void OnLeftGridCellClick(wxGridEvent &event) override
Definition: sel_layer.cpp:190
PCB_BASE_FRAME * m_frame
Definition: sel_layer.cpp:53
This file is part of the common library.
#define SELECT_COLNUM
Definition: sel_layer.cpp:36
virtual COLOR_SETTINGS * GetColorSettings() override
Helper to retrieve the current color settings.
COLOR4D getLayerColor(LAYER_NUM aLayer) const override
Definition: sel_layer.cpp:63
int color
Definition: DXF_plotter.cpp:60
wxString getLayerName(LAYER_NUM aLayer) const override
Definition: sel_layer.cpp:69
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings Returns a bit-mask of all t...
Definition: board.cpp:437
void OnLeftGridCellClick(wxGridEvent &event) override
Definition: sel_layer.cpp:359
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.h:481
std::vector< PCB_LAYER_ID > m_layersId
Definition: sel_layer.cpp:239
Classes used in Pcbnew, CvPcb and GerbView.
PCB_BASE_EDIT_FRAME * frame() const
void GetLayerPair(PCB_LAYER_ID &aFrontLayer, PCB_LAYER_ID &aBackLayer)
Definition: sel_layer.cpp:245
PCB_LAYER_ID
A quick note on layer IDs:
LSET is a set of PCB_LAYER_IDs.
std::vector< PCB_LAYER_ID > m_layersIdRightColumn
Definition: sel_layer.cpp:87
TOOL_EVENT.
Definition: tool_event.h:171
LAYER_NUM GetLayerSelection()
Definition: sel_layer.cpp:93
PCB_LAYER_ID m_Route_Layer_BOTTOM
Definition: pcb_screen.h:39
std::vector< PCB_LAYER_ID > m_layersIdLeftColumn
Definition: sel_layer.cpp:86
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
int LAYER_NUM
This can be replaced with int and removed.
BOARD * GetBoard()
#define COLOR_COLNUM
Definition: sel_layer.cpp:37
COLOR4D GetColor(int aLayer) const
PCB_LAYER_ID m_layerSelected
Definition: sel_layer.cpp:83
PCB_LAYER_SELECTOR(PCB_BASE_FRAME *aFrame)
Definition: sel_layer.cpp:46
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:186
#define _(s)
Definition: 3d_actions.cpp:33
void OnRightGridCellClick(wxGridEvent &event) override
Definition: sel_layer.cpp:197
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
int SelectCopperLayerPair(const TOOL_EVENT &aEvent)
Definition: sel_layer.cpp:259
bool isLayerEnabled(LAYER_NUM aLayer) const override
Definition: sel_layer.cpp:56
#define LAYERNAME_COLNUM
Definition: sel_layer.cpp:38
BOARD * GetBoard() const
Class DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE.
void OnRightGridCellClick(wxGridEvent &event) override
Definition: sel_layer.cpp:374
LSEQ UIOrder() const
Definition: lset.cpp:888
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:268
PCB_LAYER_ID SelectLayer(PCB_LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask=LSET(), wxPoint aDlgPosition=wxDefaultPosition)
Install the dialog box for layer selection.
Definition: sel_layer.cpp:204
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:898
PCB_BASE_FRAME basic PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
PCB_LAYER_ID m_Route_Layer_TOP
Definition: pcb_screen.h:38
SELECT_COPPER_LAYERS_PAIR_DIALOG displays a double pcb copper layers list in a dialog,...
Definition: sel_layer.cpp:229
PCB_ONE_LAYER_SELECTOR(PCB_BASE_FRAME *aParent, BOARD *aBrd, PCB_LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask)
Definition: sel_layer.cpp:104
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:100