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