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