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{
46public:
49 {
50 m_frame = aFrame;
51 }
52
53protected:
55
57 bool isLayerEnabled( int 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( int aLayer ) const override
64 {
65 return m_frame->GetColorSettings()->GetColor( aLayer );
66 }
67
68 // Return the name of the layer ID.
69 wxString getLayerName( int aLayer ) const override
70 {
71 return m_frame->GetBoard()->GetLayerName( ToLAYER_ID( aLayer ) );
72 }
73};
74
75
80{
81public:
82 PCB_ONE_LAYER_SELECTOR( PCB_BASE_FRAME* aParent, BOARD * aBrd, PCB_LAYER_ID aDefaultLayer,
83 LSET aNotAllowedLayersMask, bool aHideCheckBoxes = false );
85
87
88private:
89 // Event handlers
90 void OnLeftGridCellClick( wxGridEvent& aEvent ) override;
91 void OnRightGridCellClick( wxGridEvent& aEvent ) override;
92 void OnMouseMove( wxUpdateUIEvent& aEvent ) override;
93
94 // Will close the dialog on ESC key
95 void onCharHook( wxKeyEvent& event );
96
97 void buildList();
98
102 std::vector<PCB_LAYER_ID> m_layersIdLeftColumn;
103 std::vector<PCB_LAYER_ID> m_layersIdRightColumn;
104};
105
106
108 PCB_LAYER_ID aDefaultLayer,
109 LSET aNotAllowedLayersMask,
110 bool aHideCheckBoxes ) :
111 PCB_LAYER_SELECTOR( 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 if( aHideCheckBoxes )
127 {
130 }
131
132 Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( PCB_ONE_LAYER_SELECTOR::onCharHook ) );
133
134 Layout();
135 GetSizer()->SetSizeHints( this );
136 SetFocus();
137}
138
139
141{
142 Disconnect( wxEVT_CHAR_HOOK, wxKeyEventHandler( PCB_ONE_LAYER_SELECTOR::onCharHook ) );
143}
144
145
146void PCB_ONE_LAYER_SELECTOR::OnMouseMove( wxUpdateUIEvent& aEvent )
147{
151
152 wxPoint mouse_pos = wxGetMousePosition();
153 wxPoint left_pos = m_leftGridLayers->ScreenToClient( mouse_pos );
154 wxPoint right_pos = m_rightGridLayers->ScreenToClient( mouse_pos );
155
156 if( m_leftGridLayers->HitTest( left_pos ) == wxHT_WINDOW_INSIDE )
157 {
158 int row = m_leftGridLayers->YToRow( left_pos.y );
159
160 if( row != wxNOT_FOUND && row < static_cast<int>( m_layersIdLeftColumn.size() ) )
161 {
163 m_leftGridLayers->SelectBlock( row, LAYERNAME_COLNUM, row, LAYERNAME_COLNUM);
164 return;
165 }
166 }
167
168 if( m_rightGridLayers->HitTest( right_pos ) == wxHT_WINDOW_INSIDE )
169 {
170 int row = m_rightGridLayers->YToRow( right_pos.y );
171
172 if( row == wxNOT_FOUND || row >= static_cast<int>( m_layersIdRightColumn.size() ) )
173 return;
174
176 m_rightGridLayers->SelectBlock( row, LAYERNAME_COLNUM, row, LAYERNAME_COLNUM);
177 }
178}
179
180
181void PCB_ONE_LAYER_SELECTOR::onCharHook( wxKeyEvent& event )
182{
183 if( event.GetKeyCode() == WXK_ESCAPE )
184 Close();
185}
186
187
189{
190 wxColour bg = getLayerColor( LAYER_PCB_BACKGROUND ).ToColour();
191 int left_row = 0;
192 int right_row = 0;
193 wxString layername;
194
195 for( LSEQ ui_seq = m_brd->GetEnabledLayers().UIOrder(); ui_seq; ++ui_seq )
196 {
197 PCB_LAYER_ID layerid = *ui_seq;
198
199 if( m_notAllowedLayersMask[layerid] )
200 continue;
201
202 wxColour fg = getLayerColor( layerid ).ToColour();
203 wxColour color( wxColour::AlphaBlend( fg.Red(), bg.Red(), fg.Alpha() / 255.0 ),
204 wxColour::AlphaBlend( fg.Green(), bg.Green(), fg.Alpha() / 255.0 ),
205 wxColour::AlphaBlend( fg.Blue(), bg.Blue(), fg.Alpha() / 255.0 ) );
206
207 layername = wxT( " " ) + getLayerName( layerid );
208
209 if( IsCopperLayer( layerid ) )
210 {
211 if( left_row )
212 m_leftGridLayers->AppendRows( 1 );
213
214 m_leftGridLayers->SetCellBackgroundColour ( left_row, COLOR_COLNUM, color );
215 m_leftGridLayers->SetCellValue( left_row, LAYERNAME_COLNUM, layername );
216
217 if( m_layerSelected == layerid )
218 m_leftGridLayers->SetCellValue( left_row, SELECT_COLNUM, wxT( "1" ) );
219
220 m_layersIdLeftColumn.push_back( layerid );
221 left_row++;
222 }
223 else
224 {
225 if( right_row )
226 m_rightGridLayers->AppendRows( 1 );
227
228 m_rightGridLayers->SetCellBackgroundColour( right_row, COLOR_COLNUM, color );
229 m_rightGridLayers->SetCellValue( right_row, LAYERNAME_COLNUM, layername );
230
231 if( m_layerSelected == layerid )
232 m_rightGridLayers->SetCellValue( right_row, SELECT_COLNUM, wxT( "1" ) );
233
234 m_layersIdRightColumn.push_back( layerid );
235 right_row++;
236 }
237 }
238
239 // Show only populated lists:
240 if( left_row <= 0 )
241 m_leftGridLayers->Show( false );
242
243 if( right_row <= 0 )
244 m_rightGridLayers->Show( false );
245
246 // Now fix min grid column size (it also sets a minimal size)
247 m_leftGridLayers->AutoSizeColumns();
248 m_rightGridLayers->AutoSizeColumns();
249}
250
251
253{
254 m_layerSelected = m_layersIdLeftColumn[ event.GetRow() ];
255
256 if( IsQuasiModal() )
257 EndQuasiModal( 1 );
258 else
259 EndDialog( 1 );
260}
261
262
264{
265 m_layerSelected = m_layersIdRightColumn[ event.GetRow() ];
266
267 if( IsQuasiModal() )
268 EndQuasiModal( 2 );
269 else
270 EndDialog( 2 );
271}
272
273
274PCB_LAYER_ID PCB_BASE_FRAME::SelectOneLayer( PCB_LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask,
275 wxPoint aDlgPosition )
276{
277 PCB_ONE_LAYER_SELECTOR dlg( this, GetBoard(), aDefaultLayer, aNotAllowedLayersMask, true );
278
279 if( aDlgPosition != wxDefaultPosition )
280 {
281 wxSize dlgSize = dlg.GetSize();
282 aDlgPosition.x -= dlgSize.x/2;
283 aDlgPosition.y -= dlgSize.y/2;
284 dlg.SetPosition( aDlgPosition );
285 }
286
287 if( dlg.ShowModal() != wxID_CANCEL )
288 return ToLAYER_ID( dlg.GetLayerSelection() );
289 else
290 return UNDEFINED_LAYER;
291}
292
293
299{
300public:
302 PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer );
303
304 void GetLayerPair( PCB_LAYER_ID& aFrontLayer, PCB_LAYER_ID& aBackLayer )
305 {
306 aFrontLayer = m_frontLayer;
307 aBackLayer = m_backLayer;
308 }
309
310private:
311 void OnLeftGridCellClick( wxGridEvent& event ) override;
312 void OnRightGridCellClick( wxGridEvent& event ) override;
313
314 void buildList();
315
321
322 std::vector<PCB_LAYER_ID> m_layersId;
323};
324
325
327{
328 PCB_SCREEN* screen = frame()->GetScreen();
329
331 screen->m_Route_Layer_BOTTOM );
332
333 if( dlg.ShowModal() == wxID_OK )
334 {
336
337 // select the same layer for both layers is allowed (normal in some boards)
338 // but could be a mistake. So display an info message
339 if( screen->m_Route_Layer_TOP == screen->m_Route_Layer_BOTTOM )
340 DisplayInfoMessage( frame(), _( "Warning: top and bottom layers are same." ) );
341 }
342
343 return 0;
344}
345
346
348 PCB_BASE_FRAME* aParent, BOARD * aPcb, PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer) :
349 PCB_LAYER_SELECTOR( aParent ),
351{
352 m_frontLayer = aFrontLayer;
353 m_backLayer = aBackLayer;
356 m_brd = aPcb;
357
358 m_leftGridLayers->SetCellHighlightPenWidth( 0 );
359 m_rightGridLayers->SetCellHighlightPenWidth( 0 );
360 m_leftGridLayers->SetColFormatBool( SELECT_COLNUM );
361 m_rightGridLayers->SetColFormatBool( SELECT_COLNUM );
362 buildList();
363
364 SetFocus();
365
366 GetSizer()->SetSizeHints( this );
367 Center();
368}
369
370
372{
373 wxColour bg = getLayerColor( LAYER_PCB_BACKGROUND ).ToColour();
374 int row = 0;
375 wxString layername;
376
377 for( LSEQ ui_seq = m_brd->GetEnabledLayers().UIOrder(); ui_seq; ++ui_seq )
378 {
379 PCB_LAYER_ID layerid = *ui_seq;
380
381 if( !IsCopperLayer( layerid ) )
382 continue;
383
384 wxColour fg = getLayerColor( layerid ).ToColour();
385 wxColour color( wxColour::AlphaBlend( fg.Red(), bg.Red(), fg.Alpha() / 255.0 ),
386 wxColour::AlphaBlend( fg.Green(), bg.Green(), fg.Alpha() / 255.0 ),
387 wxColour::AlphaBlend( fg.Blue(), bg.Blue(), fg.Alpha() / 255.0 ) );
388
389 layername = wxT( " " ) + getLayerName( layerid );
390
391 if( row )
392 m_leftGridLayers->AppendRows( 1 );
393
394 m_leftGridLayers->SetCellBackgroundColour( row, COLOR_COLNUM, color );
395 m_leftGridLayers->SetCellValue( row, LAYERNAME_COLNUM, layername );
396 m_layersId.push_back( layerid );
397
398 if( m_frontLayer == layerid )
399 {
400 m_leftGridLayers->SetCellValue( row, SELECT_COLNUM, wxT( "1" ) );
401 m_leftGridLayers->SetGridCursor( row, COLOR_COLNUM );
402 m_leftRowSelected = row;
403 }
404
405 if( row )
406 m_rightGridLayers->AppendRows( 1 );
407
408 m_rightGridLayers->SetCellBackgroundColour( row, COLOR_COLNUM, color );
409 m_rightGridLayers->SetCellValue( row, LAYERNAME_COLNUM, layername );
410
411 if( m_backLayer == layerid )
412 {
413 m_rightGridLayers->SetCellValue( row, SELECT_COLNUM, wxT( "1" ) );
414 m_rightRowSelected = row;
415 }
416
417 row++;
418 }
419
420 // Now fix min grid layer name column size (it also sets a minimal size)
421 m_leftGridLayers->AutoSizeColumn( LAYERNAME_COLNUM );
422 m_rightGridLayers->AutoSizeColumn( LAYERNAME_COLNUM );
423}
424
425
427{
428 int row = event.GetRow();
429 PCB_LAYER_ID layer = m_layersId[row];
430
431 if( m_frontLayer == layer )
432 return;
433
434 m_leftGridLayers->SetCellValue( m_leftRowSelected, SELECT_COLNUM, wxEmptyString );
435 m_frontLayer = layer;
436 m_leftRowSelected = row;
437 m_leftGridLayers->SetCellValue( m_leftRowSelected, SELECT_COLNUM, wxT( "1" ) );
438}
439
440
442{
443 int row = event.GetRow();
444 PCB_LAYER_ID layer = m_layersId[row];
445
446 if( m_backLayer == layer )
447 return;
448
449 m_rightGridLayers->SetCellValue( m_rightRowSelected, SELECT_COLNUM, wxEmptyString );
450 m_backLayer = layer;
451 m_rightRowSelected = row;
452 m_rightGridLayers->SetCellValue( m_rightRowSelected, SELECT_COLNUM, wxT( "1" ) );
453}
int color
Definition: DXF_plotter.cpp:57
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:265
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:501
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:527
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:400
COLOR4D GetColor(int aLayer) const
Class DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE.
Class DIALOG_LAYER_SELECTION_BASE.
bool IsQuasiModal() const
Definition: dialog_shim.h:106
bool m_useCalculatedSize
Definition: dialog_shim.h:207
void EndQuasiModal(int retCode)
void SetPosition(const wxPoint &aNewPosition)
Force the position of the dialog to a new position.
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
Base class to build a layer list.
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: layer_ids.h:491
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:530
LSEQ UIOrder() const
Definition: lset.cpp:916
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
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:274
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
BOARD * GetBoard() const
virtual COLOR_SETTINGS * GetColorSettings(bool aForceRefresh=false) const override
Helper to retrieve the current color settings.
PCB_BASE_FRAME * m_frame
Definition: sel_layer.cpp:54
bool isLayerEnabled(int aLayer) const override
Definition: sel_layer.cpp:57
COLOR4D getLayerColor(int aLayer) const override
Definition: sel_layer.cpp:63
PCB_LAYER_SELECTOR(PCB_BASE_FRAME *aFrame)
Definition: sel_layer.cpp:47
wxString getLayerName(int aLayer) const override
Definition: sel_layer.cpp:69
Display a PCB layers list in a dialog to select one layer from this list.
Definition: sel_layer.cpp:80
void OnLeftGridCellClick(wxGridEvent &aEvent) override
Definition: sel_layer.cpp:252
void OnRightGridCellClick(wxGridEvent &aEvent) override
Definition: sel_layer.cpp:263
void onCharHook(wxKeyEvent &event)
Definition: sel_layer.cpp:181
std::vector< PCB_LAYER_ID > m_layersIdLeftColumn
Definition: sel_layer.cpp:102
PCB_ONE_LAYER_SELECTOR(PCB_BASE_FRAME *aParent, BOARD *aBrd, PCB_LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask, bool aHideCheckBoxes=false)
Definition: sel_layer.cpp:107
std::vector< PCB_LAYER_ID > m_layersIdRightColumn
Definition: sel_layer.cpp:103
void OnMouseMove(wxUpdateUIEvent &aEvent) override
Definition: sel_layer.cpp:146
PCB_LAYER_ID m_layerSelected
Definition: sel_layer.cpp:99
PCB_LAYER_ID m_Route_Layer_TOP
Definition: pcb_screen.h:43
PCB_LAYER_ID m_Route_Layer_BOTTOM
Definition: pcb_screen.h:44
PCB_BASE_EDIT_FRAME * frame() const
int SelectCopperLayerPair(const TOOL_EVENT &aEvent)
Definition: sel_layer.cpp:326
Display a pair PCB copper layers list in a dialog to select a layer pair from these lists.
Definition: sel_layer.cpp:299
std::vector< PCB_LAYER_ID > m_layersId
Definition: sel_layer.cpp:322
void GetLayerPair(PCB_LAYER_ID &aFrontLayer, PCB_LAYER_ID &aBackLayer)
Definition: sel_layer.cpp:304
void OnRightGridCellClick(wxGridEvent &event) override
Definition: sel_layer.cpp:441
void OnLeftGridCellClick(wxGridEvent &event) override
Definition: sel_layer.cpp:426
SELECT_COPPER_LAYERS_PAIR_DIALOG(PCB_BASE_FRAME *aParent, BOARD *aPcb, PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer)
Definition: sel_layer.cpp:347
Generic, UI-independent tool event.
Definition: tool_event.h:156
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:320
This file is part of the common library.
#define _(s)
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:823
@ LAYER_PCB_BACKGROUND
PCB background color.
Definition: layer_ids.h:220
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:59
@ UNDEFINED_LAYER
Definition: layer_ids.h:60
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:926
BOARD * GetBoard()
#define LAYERNAME_COLNUM
Definition: sel_layer.cpp:38
#define SELECT_COLNUM
Definition: sel_layer.cpp:36
#define COLOR_COLNUM
Definition: sel_layer.cpp:37