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-2021 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 /*
42  * Display a layer list using a wxGrid.
43  */
45 {
46 public:
49  {
50  m_frame = aFrame;
51  }
52 
53 protected:
55 
57  bool isLayerEnabled( LAYER_NUM aLayer ) const override
58  {
59  return m_frame->GetBoard()->IsLayerEnabled( PCB_LAYER_ID( aLayer ) );
60  }
61 
62  // Return the color index from the layer ID.
63  COLOR4D getLayerColor( LAYER_NUM aLayer ) const override
64  {
65  return m_frame->GetColorSettings()->GetColor( aLayer );
66  }
67 
68  // Return 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 
80 {
81 public:
82  PCB_ONE_LAYER_SELECTOR( PCB_BASE_FRAME* aParent, BOARD * aBrd, PCB_LAYER_ID aDefaultLayer,
83  LSET aNotAllowedLayersMask );
85 
87 
88 private:
89  // Event handlers
90  void OnLeftGridCellClick( wxGridEvent& event ) override;
91  void OnRightGridCellClick( wxGridEvent& event ) override;
92 
93  // Will close the dialog on ESC key
94  void onCharHook( wxKeyEvent& event );
95 
96  void buildList();
97 
101  std::vector<PCB_LAYER_ID> m_layersIdLeftColumn;
102  std::vector<PCB_LAYER_ID> m_layersIdRightColumn;
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_useCalculatedSize = true;
113 
114  m_layerSelected = aDefaultLayer;
115  m_notAllowedLayersMask = aNotAllowedLayersMask;
116  m_brd = aBrd;
117 
118  m_leftGridLayers->SetCellHighlightPenWidth( 0 );
119  m_rightGridLayers->SetCellHighlightPenWidth( 0 );
120  m_leftGridLayers->SetColFormatBool( SELECT_COLNUM );
121  m_rightGridLayers->SetColFormatBool( SELECT_COLNUM );
122  buildList();
123 
124  Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( PCB_ONE_LAYER_SELECTOR::onCharHook ) );
125 
126  Layout();
127  GetSizer()->SetSizeHints( this );
128  SetFocus();
129 }
130 
131 
133 {
134  Disconnect( wxEVT_CHAR_HOOK, wxKeyEventHandler( PCB_ONE_LAYER_SELECTOR::onCharHook ) );
135 }
136 
137 
138 void PCB_ONE_LAYER_SELECTOR::onCharHook( wxKeyEvent& event )
139 {
140  if( event.GetKeyCode() == WXK_ESCAPE )
141  Close();
142 }
143 
144 
146 {
147  wxColour bg = getLayerColor( LAYER_PCB_BACKGROUND ).ToColour();
148  int left_row = 0;
149  int right_row = 0;
150  wxString layername;
151 
152  for( LSEQ ui_seq = m_brd->GetEnabledLayers().UIOrder(); ui_seq; ++ui_seq )
153  {
154  PCB_LAYER_ID layerid = *ui_seq;
155 
156  if( m_notAllowedLayersMask[layerid] )
157  continue;
158 
159  wxColour fg = getLayerColor( layerid ).ToColour();
160  wxColour color( wxColour::AlphaBlend( fg.Red(), bg.Red(), fg.Alpha() / 255.0 ),
161  wxColour::AlphaBlend( fg.Green(), bg.Green(), fg.Alpha() / 255.0 ),
162  wxColour::AlphaBlend( fg.Blue(), bg.Blue(), fg.Alpha() / 255.0 ) );
163 
164  layername = wxT( " " ) + getLayerName( layerid );
165 
166  if( IsCopperLayer( layerid ) )
167  {
168  if( left_row )
169  m_leftGridLayers->AppendRows( 1 );
170 
171  m_leftGridLayers->SetCellBackgroundColour ( left_row, COLOR_COLNUM, color );
172  m_leftGridLayers->SetCellValue( left_row, LAYERNAME_COLNUM, layername );
173 
174  if( m_layerSelected == layerid )
175  m_leftGridLayers->SetCellValue( left_row, SELECT_COLNUM, "1" );
176 
177  m_layersIdLeftColumn.push_back( layerid );
178  left_row++;
179  }
180  else
181  {
182  if( right_row )
183  m_rightGridLayers->AppendRows( 1 );
184 
185  m_rightGridLayers->SetCellBackgroundColour( right_row, COLOR_COLNUM, color );
186  m_rightGridLayers->SetCellValue( right_row, LAYERNAME_COLNUM, layername );
187 
188  if( m_layerSelected == layerid )
189  m_rightGridLayers->SetCellValue( right_row, SELECT_COLNUM, "1" );
190 
191  m_layersIdRightColumn.push_back( layerid );
192  right_row++;
193  }
194  }
195 
196  // Show only populated lists:
197  if( left_row <= 0 )
198  m_leftGridLayers->Show( false );
199 
200  if( right_row <= 0 )
201  m_rightGridLayers->Show( false );
202 
203  // Now fix min grid column size (it also sets a minimal size)
204  m_leftGridLayers->AutoSizeColumns();
205  m_rightGridLayers->AutoSizeColumns();
206 }
207 
208 
210 {
211  m_layerSelected = m_layersIdLeftColumn[ event.GetRow() ];
212 
213  if( IsQuasiModal() )
214  EndQuasiModal( 1 );
215  else
216  EndDialog( 1 );
217 }
218 
219 
221 {
222  m_layerSelected = m_layersIdRightColumn[ event.GetRow() ];
223 
224  if( IsQuasiModal() )
225  EndQuasiModal( 2 );
226  else
227  EndDialog( 2 );
228 }
229 
230 
231 PCB_LAYER_ID PCB_BASE_FRAME::SelectOneLayer( PCB_LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask,
232  wxPoint aDlgPosition )
233 {
234  PCB_ONE_LAYER_SELECTOR dlg( this, GetBoard(), aDefaultLayer, aNotAllowedLayersMask );
235 
236  if( aDlgPosition != wxDefaultPosition )
237  {
238  wxSize dlgSize = dlg.GetSize();
239  aDlgPosition.x -= dlgSize.x/2;
240  aDlgPosition.y -= dlgSize.y/2;
241  dlg.SetPosition( aDlgPosition );
242  }
243 
244  if( dlg.ShowModal() != wxID_CANCEL )
245  return ToLAYER_ID( dlg.GetLayerSelection() );
246  else
247  return UNDEFINED_LAYER;
248 }
249 
250 
256 {
257 public:
259  PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer );
260 
261  void GetLayerPair( PCB_LAYER_ID& aFrontLayer, PCB_LAYER_ID& aBackLayer )
262  {
263  aFrontLayer = m_frontLayer;
264  aBackLayer = m_backLayer;
265  }
266 
267 private:
268  void OnLeftGridCellClick( wxGridEvent& event ) override;
269  void OnRightGridCellClick( wxGridEvent& event ) override;
270 
271  void buildList();
272 
278 
279  std::vector<PCB_LAYER_ID> m_layersId;
280 };
281 
282 
284 {
285  PCB_SCREEN* screen = frame()->GetScreen();
286 
288  screen->m_Route_Layer_BOTTOM );
289 
290  if( dlg.ShowModal() == wxID_OK )
291  {
292  dlg.GetLayerPair( screen->m_Route_Layer_TOP, screen->m_Route_Layer_BOTTOM );
293 
294  // select the same layer for both layers is allowed (normal in some boards)
295  // but could be a mistake. So display an info message
296  if( screen->m_Route_Layer_TOP == screen->m_Route_Layer_BOTTOM )
297  DisplayInfoMessage( frame(), _( "Warning: top and bottom layers are same." ) );
298  }
299 
300  return 0;
301 }
302 
303 
305  PCB_BASE_FRAME* aParent, BOARD * aPcb, PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer) :
306  PCB_LAYER_SELECTOR( aParent ),
308 {
309  m_frontLayer = aFrontLayer;
310  m_backLayer = aBackLayer;
311  m_leftRowSelected = 0;
312  m_rightRowSelected = 0;
313  m_brd = aPcb;
314 
315  m_leftGridLayers->SetCellHighlightPenWidth( 0 );
316  m_rightGridLayers->SetCellHighlightPenWidth( 0 );
317  m_leftGridLayers->SetColFormatBool( SELECT_COLNUM );
318  m_rightGridLayers->SetColFormatBool( SELECT_COLNUM );
319  buildList();
320 
321  SetFocus();
322 
323  GetSizer()->SetSizeHints( this );
324  Center();
325 }
326 
327 
329 {
330  wxColour bg = getLayerColor( LAYER_PCB_BACKGROUND ).ToColour();
331  int row = 0;
332  wxString layername;
333 
334  for( LSEQ ui_seq = m_brd->GetEnabledLayers().UIOrder(); ui_seq; ++ui_seq )
335  {
336  PCB_LAYER_ID layerid = *ui_seq;
337 
338  if( !IsCopperLayer( layerid ) )
339  continue;
340 
341  wxColour fg = getLayerColor( layerid ).ToColour();
342  wxColour color( wxColour::AlphaBlend( fg.Red(), bg.Red(), fg.Alpha() / 255.0 ),
343  wxColour::AlphaBlend( fg.Green(), bg.Green(), fg.Alpha() / 255.0 ),
344  wxColour::AlphaBlend( fg.Blue(), bg.Blue(), fg.Alpha() / 255.0 ) );
345 
346  layername = wxT( " " ) + getLayerName( layerid );
347 
348  if( row )
349  m_leftGridLayers->AppendRows( 1 );
350 
351  m_leftGridLayers->SetCellBackgroundColour( row, COLOR_COLNUM, color );
352  m_leftGridLayers->SetCellValue( row, LAYERNAME_COLNUM, layername );
353  m_layersId.push_back( layerid );
354 
355  if( m_frontLayer == layerid )
356  {
357  m_leftGridLayers->SetCellValue( row, SELECT_COLNUM, "1" );
358  m_leftGridLayers->SetGridCursor( row, COLOR_COLNUM );
359  m_leftRowSelected = row;
360  }
361 
362  if( row )
363  m_rightGridLayers->AppendRows( 1 );
364 
365  m_rightGridLayers->SetCellBackgroundColour( row, COLOR_COLNUM, color );
366  m_rightGridLayers->SetCellValue( row, LAYERNAME_COLNUM, layername );
367 
368  if( m_backLayer == layerid )
369  {
370  m_rightGridLayers->SetCellValue( row, SELECT_COLNUM, "1" );
371  m_rightRowSelected = row;
372  }
373 
374  row++;
375  }
376 
377  // Now fix min grid layer name column size (it also sets a minimal size)
378  m_leftGridLayers->AutoSizeColumn( LAYERNAME_COLNUM );
379  m_rightGridLayers->AutoSizeColumn( LAYERNAME_COLNUM );
380 }
381 
382 
384 {
385  int row = event.GetRow();
386  PCB_LAYER_ID layer = m_layersId[row];
387 
388  if( m_frontLayer == layer )
389  return;
390 
391  m_leftGridLayers->SetCellValue( m_leftRowSelected, SELECT_COLNUM, wxEmptyString );
392  m_frontLayer = layer;
393  m_leftRowSelected = row;
394  m_leftGridLayers->SetCellValue( m_leftRowSelected, SELECT_COLNUM, "1" );
395 }
396 
397 
399 {
400  int row = event.GetRow();
401  PCB_LAYER_ID layer = m_layersId[row];
402 
403  if( m_backLayer == layer )
404  return;
405 
406  m_rightGridLayers->SetCellValue( m_rightRowSelected, SELECT_COLNUM, wxEmptyString );
407  m_backLayer = layer;
408  m_rightRowSelected = row;
409  m_rightGridLayers->SetCellValue( m_rightRowSelected, SELECT_COLNUM, "1" );
410 }
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:231
Class DIALOG_LAYER_SELECTION_BASE.
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:360
SELECT_COPPER_LAYERS_PAIR_DIALOG(PCB_BASE_FRAME *aParent, BOARD *aPcb, PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer)
Definition: sel_layer.cpp:304
void OnLeftGridCellClick(wxGridEvent &event) override
Definition: sel_layer.cpp:209
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:36
COLOR4D getLayerColor(LAYER_NUM aLayer) const override
Definition: sel_layer.cpp:63
int color
Definition: DXF_plotter.cpp:60
bool IsQuasiModal() const
Definition: dialog_shim.h:106
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.
Definition: board.cpp:465
void OnLeftGridCellClick(wxGridEvent &event) override
Definition: sel_layer.cpp:383
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.cpp:491
std::vector< PCB_LAYER_ID > m_layersId
Definition: sel_layer.cpp:279
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:261
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:138
std::vector< PCB_LAYER_ID > m_layersIdRightColumn
Definition: sel_layer.cpp:102
void SetPosition(const wxPoint &aNewPosition)
Force the position of the dialog to a new position.
Generic, UI-independent tool event.
Definition: tool_event.h:152
Base class to build a layer list.
LAYER_NUM GetLayerSelection()
Definition: sel_layer.cpp:86
PCB_LAYER_ID m_Route_Layer_BOTTOM
Definition: pcb_screen.h:44
std::vector< PCB_LAYER_ID > m_layersIdLeftColumn
Definition: sel_layer.cpp:101
#define _(s)
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
void EndQuasiModal(int retCode)
COLOR4D GetColor(int aLayer) const
PCB_LAYER_ID m_layerSelected
Definition: sel_layer.cpp:98
PCB_LAYER_SELECTOR(PCB_BASE_FRAME *aFrame)
Definition: sel_layer.cpp:47
Display a PCB layers list in a dialog to select one layer from this list.
Definition: sel_layer.cpp:79
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
void OnRightGridCellClick(wxGridEvent &event) override
Definition: sel_layer.cpp:220
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:283
bool isLayerEnabled(LAYER_NUM aLayer) const override
Definition: sel_layer.cpp:57
#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:398
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:275
bool m_useCalculatedSize
Definition: dialog_shim.h:203
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
Display a pair PCB copper layers list in a dialog to select a layer pair from these lists.
Definition: sel_layer.cpp:254
PCB_ONE_LAYER_SELECTOR(PCB_BASE_FRAME *aParent, BOARD *aBrd, PCB_LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask)
Definition: sel_layer.cpp:106
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103