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 );
93 
95 
96 private:
97  // Event handlers
98  void OnLeftGridCellClick( wxGridEvent& event ) override;
99  void OnRightGridCellClick( wxGridEvent& event ) override;
100 
101  // Will close the dialog on ESC key
102  void onCharHook( wxKeyEvent& event );
103 
104  void buildList();
105 };
106 
107 
109  PCB_LAYER_ID aDefaultLayer,
110  LSET aNotAllowedLayersMask ) :
111  PCB_LAYER_SELECTOR( aParent ),
112  DIALOG_LAYER_SELECTION_BASE( aParent )
113 {
114  m_useCalculatedSize = true;
115 
116  m_layerSelected = aDefaultLayer;
117  m_notAllowedLayersMask = aNotAllowedLayersMask;
118  m_brd = aBrd;
119 
120  m_leftGridLayers->SetCellHighlightPenWidth( 0 );
121  m_rightGridLayers->SetCellHighlightPenWidth( 0 );
122  m_leftGridLayers->SetColFormatBool( SELECT_COLNUM );
123  m_rightGridLayers->SetColFormatBool( SELECT_COLNUM );
124  buildList();
125 
126  Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( PCB_ONE_LAYER_SELECTOR::onCharHook ) );
127 
128  Layout();
129  GetSizer()->SetSizeHints( this );
130  SetFocus();
131 }
132 
133 
135 {
136  Disconnect( wxEVT_CHAR_HOOK, wxKeyEventHandler( PCB_ONE_LAYER_SELECTOR::onCharHook ) );
137 }
138 
139 
140 void PCB_ONE_LAYER_SELECTOR::onCharHook( wxKeyEvent& event )
141 {
142  if( event.GetKeyCode() == WXK_ESCAPE )
143  Close();
144 }
145 
146 
148 {
149  wxColour bg = getLayerColor( LAYER_PCB_BACKGROUND ).ToColour();
150  int left_row = 0;
151  int right_row = 0;
152  wxString layername;
153 
154  for( LSEQ ui_seq = m_brd->GetEnabledLayers().UIOrder(); ui_seq; ++ui_seq )
155  {
156  PCB_LAYER_ID layerid = *ui_seq;
157 
158  if( m_notAllowedLayersMask[layerid] )
159  continue;
160 
161  wxColour fg = getLayerColor( layerid ).ToColour();
162  wxColour color( wxColour::AlphaBlend( fg.Red(), bg.Red(), fg.Alpha() / 255.0 ),
163  wxColour::AlphaBlend( fg.Green(), bg.Green(), fg.Alpha() / 255.0 ),
164  wxColour::AlphaBlend( fg.Blue(), bg.Blue(), fg.Alpha() / 255.0 ) );
165 
166  layername = wxT( " " ) + getLayerName( layerid );
167 
168  if( IsCopperLayer( layerid ) )
169  {
170  if( left_row )
171  m_leftGridLayers->AppendRows( 1 );
172 
173  m_leftGridLayers->SetCellBackgroundColour ( left_row, COLOR_COLNUM, color );
174  m_leftGridLayers->SetCellValue( left_row, LAYERNAME_COLNUM, layername );
175 
176  if( m_layerSelected == layerid )
177  m_leftGridLayers->SetCellValue( left_row, SELECT_COLNUM, "1" );
178 
179  m_layersIdLeftColumn.push_back( layerid );
180  left_row++;
181  }
182  else
183  {
184  if( right_row )
185  m_rightGridLayers->AppendRows( 1 );
186 
187  m_rightGridLayers->SetCellBackgroundColour( right_row, COLOR_COLNUM, color );
188  m_rightGridLayers->SetCellValue( right_row, LAYERNAME_COLNUM, layername );
189 
190  if( m_layerSelected == layerid )
191  m_rightGridLayers->SetCellValue( right_row, SELECT_COLNUM, "1" );
192 
193  m_layersIdRightColumn.push_back( layerid );
194  right_row++;
195  }
196  }
197 
198  // Show only populated lists:
199  if( left_row <= 0 )
200  m_leftGridLayers->Show( false );
201 
202  if( right_row <= 0 )
203  m_rightGridLayers->Show( false );
204 
205  // Now fix min grid column size (it also sets a minimal size)
206  m_leftGridLayers->AutoSizeColumns();
207  m_rightGridLayers->AutoSizeColumns();
208 }
209 
210 
212 {
213  m_layerSelected = m_layersIdLeftColumn[ event.GetRow() ];
214  EndModal( 1 );
215 }
216 
217 
219 {
220  m_layerSelected = m_layersIdRightColumn[ event.GetRow() ];
221  EndModal( 2 );
222 }
223 
224 
225 PCB_LAYER_ID PCB_BASE_FRAME::SelectOneLayer( PCB_LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask,
226  wxPoint aDlgPosition )
227 {
228  PCB_ONE_LAYER_SELECTOR dlg( this, GetBoard(), aDefaultLayer, aNotAllowedLayersMask );
229 
230  if( aDlgPosition != wxDefaultPosition )
231  {
232  wxSize dlgSize = dlg.GetSize();
233  aDlgPosition.x -= dlgSize.x/2;
234  aDlgPosition.y -= dlgSize.y/2;
235  dlg.SetPosition( aDlgPosition );
236  }
237 
238  if( dlg.ShowModal() != wxID_CANCEL )
239  return ToLAYER_ID( dlg.GetLayerSelection() );
240  else
241  return UNDEFINED_LAYER;
242 }
243 
244 
252 {
253 private:
259 
260  std::vector<PCB_LAYER_ID> m_layersId;
261 
262 public:
264  PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer );
265 
266  void GetLayerPair( PCB_LAYER_ID& aFrontLayer, PCB_LAYER_ID& aBackLayer )
267  {
268  aFrontLayer = m_frontLayer;
269  aBackLayer = m_backLayer;
270  }
271 
272 private:
273  void OnLeftGridCellClick( wxGridEvent& event ) override;
274  void OnRightGridCellClick( wxGridEvent& event ) override;
275 
276  void buildList();
277 };
278 
279 
281 {
282  PCB_SCREEN* screen = frame()->GetScreen();
283 
285  screen->m_Route_Layer_BOTTOM );
286 
287  if( dlg.ShowModal() == wxID_OK )
288  {
289  dlg.GetLayerPair( screen->m_Route_Layer_TOP, screen->m_Route_Layer_BOTTOM );
290 
291  // select the same layer for both layers is allowed (normal in some boards)
292  // but could be a mistake. So display an info message
293  if( screen->m_Route_Layer_TOP == screen->m_Route_Layer_BOTTOM )
294  DisplayInfoMessage( frame(), _( "Warning: top and bottom layers are same." ) );
295  }
296 
297  return 0;
298 }
299 
300 
302  PCB_BASE_FRAME* aParent, BOARD * aPcb, PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer) :
303  PCB_LAYER_SELECTOR( aParent ),
305 {
306  m_frontLayer = aFrontLayer;
307  m_backLayer = aBackLayer;
308  m_leftRowSelected = 0;
309  m_rightRowSelected = 0;
310  m_brd = aPcb;
311 
312  m_leftGridLayers->SetCellHighlightPenWidth( 0 );
313  m_rightGridLayers->SetCellHighlightPenWidth( 0 );
314  m_leftGridLayers->SetColFormatBool( SELECT_COLNUM );
315  m_rightGridLayers->SetColFormatBool( SELECT_COLNUM );
316  buildList();
317 
318  SetFocus();
319 
320  GetSizer()->SetSizeHints( this );
321  Center();
322 }
323 
324 
326 {
327  wxColour bg = getLayerColor( LAYER_PCB_BACKGROUND ).ToColour();
328  int row = 0;
329  wxString layername;
330 
331  for( LSEQ ui_seq = m_brd->GetEnabledLayers().UIOrder(); ui_seq; ++ui_seq )
332  {
333  PCB_LAYER_ID layerid = *ui_seq;
334 
335  if( !IsCopperLayer( layerid ) )
336  continue;
337 
338  wxColour fg = getLayerColor( layerid ).ToColour();
339  wxColour color( wxColour::AlphaBlend( fg.Red(), bg.Red(), fg.Alpha() / 255.0 ),
340  wxColour::AlphaBlend( fg.Green(), bg.Green(), fg.Alpha() / 255.0 ),
341  wxColour::AlphaBlend( fg.Blue(), bg.Blue(), fg.Alpha() / 255.0 ) );
342 
343  layername = wxT( " " ) + getLayerName( layerid );
344 
345  if( row )
346  m_leftGridLayers->AppendRows( 1 );
347 
348  m_leftGridLayers->SetCellBackgroundColour( row, COLOR_COLNUM, color );
349  m_leftGridLayers->SetCellValue( row, LAYERNAME_COLNUM, layername );
350  m_layersId.push_back( layerid );
351 
352  if( m_frontLayer == layerid )
353  {
354  m_leftGridLayers->SetCellValue( row, SELECT_COLNUM, "1" );
355  m_leftGridLayers->SetGridCursor( row, COLOR_COLNUM );
356  m_leftRowSelected = row;
357  }
358 
359  if( row )
360  m_rightGridLayers->AppendRows( 1 );
361 
362  m_rightGridLayers->SetCellBackgroundColour( row, COLOR_COLNUM, color );
363  m_rightGridLayers->SetCellValue( row, LAYERNAME_COLNUM, layername );
364 
365  if( m_backLayer == layerid )
366  {
367  m_rightGridLayers->SetCellValue( row, SELECT_COLNUM, "1" );
368  m_rightRowSelected = row;
369  }
370 
371  row++;
372  }
373 
374  // Now fix min grid layer name column size (it also sets a minimal size)
375  m_leftGridLayers->AutoSizeColumn( LAYERNAME_COLNUM );
376  m_rightGridLayers->AutoSizeColumn( LAYERNAME_COLNUM );
377 }
378 
379 
381 {
382  int row = event.GetRow();
383  PCB_LAYER_ID layer = m_layersId[row];
384 
385  if( m_frontLayer == layer )
386  return;
387 
388  m_leftGridLayers->SetCellValue( m_leftRowSelected, SELECT_COLNUM, wxEmptyString );
389  m_frontLayer = layer;
390  m_leftRowSelected = row;
391  m_leftGridLayers->SetCellValue( m_leftRowSelected, SELECT_COLNUM, "1" );
392 }
393 
394 
396 {
397  int row = event.GetRow();
398  PCB_LAYER_ID layer = m_layersId[row];
399 
400  if( m_backLayer == layer )
401  return;
402 
403  m_rightGridLayers->SetCellValue( m_rightRowSelected, SELECT_COLNUM, wxEmptyString );
404  m_backLayer = layer;
405  m_rightRowSelected = row;
406  m_rightGridLayers->SetCellValue( m_rightRowSelected, SELECT_COLNUM, "1" );
407 }
PCB_LAYER_ID SelectOneLayer(PCB_LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask=LSET(), wxPoint aDlgPosition=wxDefaultPosition)
Show the dialog box for a layer selection.
Definition: sel_layer.cpp:225
Class DIALOG_LAYER_SELECTION_BASE.
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:342
SELECT_COPPER_LAYERS_PAIR_DIALOG(PCB_BASE_FRAME *aParent, BOARD *aPcb, PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer)
Definition: sel_layer.cpp:301
void OnLeftGridCellClick(wxGridEvent &event) override
Definition: sel_layer.cpp:211
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
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:447
void OnLeftGridCellClick(wxGridEvent &event) override
Definition: sel_layer.cpp:380
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:515
std::vector< PCB_LAYER_ID > m_layersId
Definition: sel_layer.cpp:260
Classes used in Pcbnew, CvPcb and GerbView.
PCB_BASE_EDIT_FRAME * frame() const
virtual COLOR_SETTINGS * GetColorSettings() const override
Helper to retrieve the current color settings.
void GetLayerPair(PCB_LAYER_ID &aFrontLayer, PCB_LAYER_ID &aBackLayer)
Definition: sel_layer.cpp:266
PCB_LAYER_ID
A quick note on layer IDs:
LSET is a set of PCB_LAYER_IDs.
void onCharHook(wxKeyEvent &event)
Definition: sel_layer.cpp:140
std::vector< PCB_LAYER_ID > m_layersIdRightColumn
Definition: sel_layer.cpp:87
void SetPosition(const wxPoint &aNewPosition)
Force the position of the dialog to a new position.
Generic, UI-independent tool event.
Definition: tool_event.h:173
LAYER_NUM GetLayerSelection()
Definition: sel_layer.cpp:94
PCB_LAYER_ID m_Route_Layer_BOTTOM
Definition: pcb_screen.h:44
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:190
#define _(s)
Definition: 3d_actions.cpp:33
void OnRightGridCellClick(wxGridEvent &event) override
Definition: sel_layer.cpp:218
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:280
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:395
LSEQ UIOrder() const
Definition: lset.cpp:895
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:280
bool m_useCalculatedSize
Definition: dialog_shim.h:204
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:905
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
PCB_LAYER_ID m_Route_Layer_TOP
Definition: pcb_screen.h:43
SELECT_COPPER_LAYERS_PAIR_DIALOG displays a double pcb copper layers list in a dialog,...
Definition: sel_layer.cpp:250
PCB_ONE_LAYER_SELECTOR(PCB_BASE_FRAME *aParent, BOARD *aBrd, PCB_LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask)
Definition: sel_layer.cpp:108
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:98