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 <fctsys.h>
27 #include <common.h>
28 #include <confirm.h>
29 #include <pcb_base_frame.h>
31 #include <class_board.h>
33 #include <router/router_tool.h>
34 
35 
36 // Column position by function:
37 #define SELECT_COLNUM 0
38 #define COLOR_COLNUM 1
39 #define LAYERNAME_COLNUM 2
40 
41 
42 /* classes to display a layer list using a wxGrid.
43  */
45 {
46 public:
49  {
50  m_frame = aFrame;
51  }
52 
53 protected:
55 
56  // Returns true if the layer id is enabled (i.e. is it should be displayed)
57  bool IsLayerEnabled( LAYER_NUM aLayer ) const override
58  {
59  return m_frame->GetBoard()->IsLayerEnabled( PCB_LAYER_ID( aLayer ) );
60  }
61 
62  // Returns a color index from the layer id
63  // Virtual function
64  COLOR4D GetLayerColor( LAYER_NUM aLayer ) const override
65  {
66  return m_frame->Settings().Colors().GetLayerColor( aLayer );
67  }
68 
69  // Returns the name of the layer id
70  wxString GetLayerName( LAYER_NUM aLayer ) const override
71  {
72  return m_frame->GetBoard()->GetLayerName( ToLAYER_ID( aLayer ) );
73  }
74 };
75 
76 
77 /*
78  * This class display a pcb layers list in a dialog,
79  * to select one layer from this list
80  */
83 {
87  std::vector<PCB_LAYER_ID> m_layersIdLeftColumn;
88  std::vector<PCB_LAYER_ID> m_layersIdRightColumn;
89 
90 public:
91  PCB_ONE_LAYER_SELECTOR( PCB_BASE_FRAME* aParent, BOARD * aBrd, PCB_LAYER_ID aDefaultLayer,
92  LSET aNotAllowedLayersMask );
93 
95 
96 private:
97  // Event handlers
98  void OnLeftGridCellClick( wxGridEvent& event ) override;
99  void OnRightGridCellClick( wxGridEvent& event ) override;
100 
101  void buildList();
102 };
103 
104 
106  PCB_LAYER_ID aDefaultLayer,
107  LSET aNotAllowedLayersMask ) :
108  PCB_LAYER_SELECTOR( aParent ),
109  DIALOG_LAYER_SELECTION_BASE( aParent )
110 {
111  m_layerSelected = aDefaultLayer;
112  m_notAllowedLayersMask = aNotAllowedLayersMask;
113  m_brd = aBrd;
114 
115  m_leftGridLayers->SetCellHighlightPenWidth( 0 );
116  m_rightGridLayers->SetCellHighlightPenWidth( 0 );
117  m_leftGridLayers->SetColFormatBool( SELECT_COLNUM );
118  m_rightGridLayers->SetColFormatBool( SELECT_COLNUM );
119  buildList();
120 
121  Layout();
122  GetSizer()->SetSizeHints( this );
123  SetFocus();
124 }
125 
126 
128 {
129  wxColour bg = GetLayerColor( LAYER_PCB_BACKGROUND ).ToColour();
130  int left_row = 0;
131  int right_row = 0;
132  wxString layername;
133 
134  for( LSEQ ui_seq = m_brd->GetEnabledLayers().UIOrder(); ui_seq; ++ui_seq )
135  {
136  PCB_LAYER_ID layerid = *ui_seq;
137 
138  if( m_notAllowedLayersMask[layerid] )
139  continue;
140 
141  wxColour fg = GetLayerColor( layerid ).ToColour();
142  wxColour color( wxColour::AlphaBlend( fg.Red(), bg.Red(), fg.Alpha() / 255.0 ),
143  wxColour::AlphaBlend( fg.Green(), bg.Green(), fg.Alpha() / 255.0 ),
144  wxColour::AlphaBlend( fg.Blue(), bg.Blue(), fg.Alpha() / 255.0 ) );
145 
146  layername = wxT( " " ) + GetLayerName( layerid );
147 
148  if( IsCopperLayer( layerid ) )
149  {
150  if( left_row )
151  m_leftGridLayers->AppendRows( 1 );
152 
153  m_leftGridLayers->SetCellBackgroundColour ( left_row, COLOR_COLNUM, color );
154  m_leftGridLayers->SetCellValue( left_row, LAYERNAME_COLNUM, layername );
155 
156  if( m_layerSelected == layerid )
157  m_leftGridLayers->SetCellValue( left_row, SELECT_COLNUM, "1" );
158 
159  m_layersIdLeftColumn.push_back( layerid );
160  left_row++;
161  }
162  else
163  {
164  if( right_row )
165  m_rightGridLayers->AppendRows( 1 );
166 
167  m_rightGridLayers->SetCellBackgroundColour( right_row, COLOR_COLNUM, color );
168  m_rightGridLayers->SetCellValue( right_row, LAYERNAME_COLNUM, layername );
169 
170  if( m_layerSelected == layerid )
171  m_rightGridLayers->SetCellValue( right_row, SELECT_COLNUM, "1" );
172 
173  m_layersIdRightColumn.push_back( layerid );
174  right_row++;
175  }
176  }
177 
178  // Show only populated lists:
179  if( left_row <= 0 )
180  m_leftGridLayers->Show( false );
181 
182  if( right_row <= 0 )
183  m_rightGridLayers->Show( false );
184 
185  // Now fix min grid layer name column size (it also sets a minimal size)
186  m_leftGridLayers->AutoSizeColumn( LAYERNAME_COLNUM );
187  m_rightGridLayers->AutoSizeColumn( LAYERNAME_COLNUM );
188 }
189 
190 
192 {
193  m_layerSelected = m_layersIdLeftColumn[ event.GetRow() ];
194  EndModal( 1 );
195 }
196 
197 
199 {
200  m_layerSelected = m_layersIdRightColumn[ event.GetRow() ];
201  EndModal( 2 );
202 }
203 
204 
205 PCB_LAYER_ID PCB_BASE_FRAME::SelectLayer( PCB_LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask,
206  wxPoint aDlgPosition )
207 {
208  PCB_ONE_LAYER_SELECTOR dlg( this, GetBoard(), aDefaultLayer, aNotAllowedLayersMask );
209 
210  if( aDlgPosition != wxDefaultPosition )
211  {
212  wxSize dlgSize = dlg.GetSize();
213  aDlgPosition.x -= dlgSize.x/2;
214  aDlgPosition.y -= dlgSize.y/2;
215  dlg.SetPosition( aDlgPosition );
216  }
217 
218  dlg.ShowModal();
219 
220  PCB_LAYER_ID layer = ToLAYER_ID( dlg.GetLayerSelection() );
221  return layer;
222 }
223 
224 
232 {
233 private:
239 
240  std::vector<PCB_LAYER_ID> m_layersId;
241 
242 public:
244  PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer );
245 
246  void GetLayerPair( PCB_LAYER_ID& aFrontLayer, PCB_LAYER_ID& aBackLayer )
247  {
248  aFrontLayer = m_frontLayer;
249  aBackLayer = m_backLayer;
250  }
251 
252 private:
253  void OnLeftGridCellClick( wxGridEvent& event ) override;
254  void OnRightGridCellClick( wxGridEvent& event ) override;
255 
256  void buildList();
257 };
258 
259 
261 {
262  PCB_SCREEN* screen = frame()->GetScreen();
263 
265  screen->m_Route_Layer_BOTTOM );
266 
267  if( dlg.ShowModal() == wxID_OK )
268  {
269  dlg.GetLayerPair( screen->m_Route_Layer_TOP, screen->m_Route_Layer_BOTTOM );
270 
271  // select the same layer for both layers is allowed (normal in some boards)
272  // but could be a mistake. So display an info message
273  if( screen->m_Route_Layer_TOP == screen->m_Route_Layer_BOTTOM )
274  DisplayInfoMessage( frame(), _( "Warning: top and bottom layers are same." ) );
275  }
276 
277  return 0;
278 }
279 
280 
282  PCB_BASE_FRAME* aParent, BOARD * aPcb, PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer) :
283  PCB_LAYER_SELECTOR( aParent ),
285 {
286  m_frontLayer = aFrontLayer;
287  m_backLayer = aBackLayer;
288  m_leftRowSelected = 0;
289  m_rightRowSelected = 0;
290  m_brd = aPcb;
291 
292  m_leftGridLayers->SetCellHighlightPenWidth( 0 );
293  m_rightGridLayers->SetCellHighlightPenWidth( 0 );
294  m_leftGridLayers->SetColFormatBool( SELECT_COLNUM );
295  m_rightGridLayers->SetColFormatBool( SELECT_COLNUM );
296  buildList();
297 
298  SetFocus();
299 
300  GetSizer()->SetSizeHints( this );
301  Center();
302 }
303 
304 
306 {
307  wxColour bg = GetLayerColor( LAYER_PCB_BACKGROUND ).ToColour();
308  int row = 0;
309  wxString layername;
310 
311  for( LSEQ ui_seq = m_brd->GetEnabledLayers().UIOrder(); ui_seq; ++ui_seq )
312  {
313  PCB_LAYER_ID layerid = *ui_seq;
314 
315  if( !IsCopperLayer( layerid ) )
316  continue;
317 
318  wxColour fg = GetLayerColor( layerid ).ToColour();
319  wxColour color( wxColour::AlphaBlend( fg.Red(), bg.Red(), fg.Alpha() / 255.0 ),
320  wxColour::AlphaBlend( fg.Green(), bg.Green(), fg.Alpha() / 255.0 ),
321  wxColour::AlphaBlend( fg.Blue(), bg.Blue(), fg.Alpha() / 255.0 ) );
322 
323  layername = wxT( " " ) + GetLayerName( layerid );
324 
325  if( row )
326  m_leftGridLayers->AppendRows( 1 );
327 
328  m_leftGridLayers->SetCellBackgroundColour( row, COLOR_COLNUM, color );
329  m_leftGridLayers->SetCellValue( row, LAYERNAME_COLNUM, layername );
330  m_layersId.push_back( layerid );
331 
332  if( m_frontLayer == layerid )
333  {
334  m_leftGridLayers->SetCellValue( row, SELECT_COLNUM, "1" );
335  m_leftGridLayers->SetGridCursor( row, COLOR_COLNUM );
336  m_leftRowSelected = row;
337  }
338 
339  if( row )
340  m_rightGridLayers->AppendRows( 1 );
341 
342  m_rightGridLayers->SetCellBackgroundColour( row, COLOR_COLNUM, color );
343  m_rightGridLayers->SetCellValue( row, LAYERNAME_COLNUM, layername );
344 
345  if( m_backLayer == layerid )
346  {
347  m_rightGridLayers->SetCellValue( row, SELECT_COLNUM, "1" );
348  m_rightRowSelected = row;
349  }
350 
351  row++;
352  }
353 
354  // Now fix min grid layer name column size (it also sets a minimal size)
355  m_leftGridLayers->AutoSizeColumn( LAYERNAME_COLNUM );
356  m_rightGridLayers->AutoSizeColumn( LAYERNAME_COLNUM );
357 }
358 
359 
361 {
362  int row = event.GetRow();
363  PCB_LAYER_ID layer = m_layersId[row];
364 
365  if( m_frontLayer == layer )
366  return;
367 
368  m_leftGridLayers->SetCellValue( m_leftRowSelected, SELECT_COLNUM, wxEmptyString );
369  m_frontLayer = layer;
370  m_leftRowSelected = row;
371  m_leftGridLayers->SetCellValue( m_leftRowSelected, SELECT_COLNUM, "1" );
372 }
373 
374 
376 {
377  int row = event.GetRow();
378  PCB_LAYER_ID layer = m_layersId[row];
379 
380  if( m_backLayer == layer )
381  return;
382 
383  m_rightGridLayers->SetCellValue( m_rightRowSelected, SELECT_COLNUM, wxEmptyString );
384  m_backLayer = layer;
385  m_rightRowSelected = row;
386  m_rightGridLayers->SetCellValue( m_rightRowSelected, SELECT_COLNUM, "1" );
387 }
Class DIALOG_LAYER_SELECTION_BASE.
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Function GetLayerName returns the name of a layer given by aLayer.
SELECT_COPPER_LAYERS_PAIR_DIALOG(PCB_BASE_FRAME *aParent, BOARD *aPcb, PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer)
Definition: sel_layer.cpp:281
void OnLeftGridCellClick(wxGridEvent &event) override
Definition: sel_layer.cpp:191
PCB_BASE_FRAME * m_frame
Definition: sel_layer.cpp:54
This file is part of the common library.
#define SELECT_COLNUM
Definition: sel_layer.cpp:37
int color
Definition: DXF_plotter.cpp:62
bool IsLayerEnabled(LAYER_NUM aLayer) const override
Definition: sel_layer.cpp:57
LSET GetEnabledLayers() const
Function GetEnabledLayers is a proxy function that calls the corresponding function in m_BoardSetting...
void OnLeftGridCellClick(wxGridEvent &event) override
Definition: sel_layer.cpp:360
bool IsLayerEnabled(PCB_LAYER_ID aLayer) const
Function IsLayerEnabled is a proxy function that calls the correspondent function in m_BoardSettings ...
Definition: class_board.h:447
std::vector< PCB_LAYER_ID > m_layersId
Definition: sel_layer.cpp:240
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:246
COLOR4D GetLayerColor(LAYER_NUM aLayer) const
Function GetLayerColor.
PCB_LAYER_ID
A quick note on layer IDs:
Class LSET is a set of PCB_LAYER_IDs.
std::vector< PCB_LAYER_ID > m_layersIdRightColumn
Definition: sel_layer.cpp:88
PCB_GENERAL_SETTINGS & Settings()
Class TOOL_EVENT.
Definition: tool_event.h:168
LAYER_NUM GetLayerSelection()
Definition: sel_layer.cpp:94
PCB_LAYER_ID m_Route_Layer_BOTTOM
Definition: pcb_screen.h:46
std::vector< PCB_LAYER_ID > m_layersIdLeftColumn
Definition: sel_layer.cpp:87
#define _(s)
Class LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
COLORS_DESIGN_SETTINGS & Colors()
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
BOARD * GetBoard()
#define COLOR_COLNUM
Definition: sel_layer.cpp:38
PCB_LAYER_ID m_layerSelected
Definition: sel_layer.cpp:84
PCB_LAYER_SELECTOR(PCB_BASE_FRAME *aFrame)
Definition: sel_layer.cpp:47
wxString GetLayerName(LAYER_NUM aLayer) const override
Definition: sel_layer.cpp:70
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:161
COLOR4D GetLayerColor(LAYER_NUM aLayer) const override
Definition: sel_layer.cpp:64
void OnRightGridCellClick(wxGridEvent &event) override
Definition: sel_layer.cpp:198
The common library.
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
int SelectCopperLayerPair(const TOOL_EVENT &aEvent)
Definition: sel_layer.cpp:260
#define LAYERNAME_COLNUM
Definition: sel_layer.cpp:39
BOARD * GetBoard() const
Class DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE.
void OnRightGridCellClick(wxGridEvent &event) override
Definition: sel_layer.cpp:375
LSEQ UIOrder() const
Definition: lset.cpp:803
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:276
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:205
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:813
class 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:45
Class SELECT_COPPER_LAYERS_PAIR_DIALOG displays a double pcb copper layers list in a dialog,...
Definition: sel_layer.cpp:230
PCB_ONE_LAYER_SELECTOR(PCB_BASE_FRAME *aParent, BOARD *aBrd, PCB_LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask)
Definition: sel_layer.cpp:105
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39