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#include <tools/pcb_actions.h>
35
36// Column position by function:
37#define SELECT_COLNUM 0
38#define COLOR_COLNUM 1
39#define LAYERNAME_COLNUM 2
40#define LAYER_HK_COLUMN 3
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 wxString getLayerHotKey( PCB_LAYER_ID aLayer ) const
99 {
100 int code = PCB_ACTIONS::LayerIDToAction( aLayer )->GetHotKey();
101 return AddHotkeyName( wxS( "" ), code, IS_COMMENT );
102 }
103
104 void buildList();
105
109 std::vector<PCB_LAYER_ID> m_layersIdLeftColumn;
110 std::vector<PCB_LAYER_ID> m_layersIdRightColumn;
111};
112
113
115 PCB_LAYER_ID aDefaultLayer,
116 LSET aNotAllowedLayersMask,
117 bool aHideCheckBoxes ) :
118 PCB_LAYER_SELECTOR( aParent ),
120{
121 m_useCalculatedSize = true;
122
123 m_layerSelected = aDefaultLayer;
124 m_notAllowedLayersMask = aNotAllowedLayersMask;
125 m_brd = aBrd;
126
127 m_leftGridLayers->SetCellHighlightPenWidth( 0 );
128 m_rightGridLayers->SetCellHighlightPenWidth( 0 );
129 m_leftGridLayers->SetColFormatBool( SELECT_COLNUM );
130 m_rightGridLayers->SetColFormatBool( SELECT_COLNUM );
131
132 m_leftGridLayers->AppendCols( 1 );
133
134 buildList();
135
136 if( aHideCheckBoxes )
137 {
140 }
141
142 Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( PCB_ONE_LAYER_SELECTOR::onCharHook ) );
143
144 Layout();
145 GetSizer()->SetSizeHints( this );
146 SetFocus();
147}
148
149
151{
152 Disconnect( wxEVT_CHAR_HOOK, wxKeyEventHandler( PCB_ONE_LAYER_SELECTOR::onCharHook ) );
153}
154
155
156void PCB_ONE_LAYER_SELECTOR::OnMouseMove( wxUpdateUIEvent& aEvent )
157{
161
162 wxPoint mouse_pos = KIPLATFORM::UI::GetMousePosition();
163 wxPoint left_pos = m_leftGridLayers->ScreenToClient( mouse_pos );
164 wxPoint right_pos = m_rightGridLayers->ScreenToClient( mouse_pos );
165
166 if( m_leftGridLayers->HitTest( left_pos ) == wxHT_WINDOW_INSIDE )
167 {
168 int row = m_leftGridLayers->YToRow( left_pos.y );
169
170 if( row != wxNOT_FOUND && row < static_cast<int>( m_layersIdLeftColumn.size() ) )
171 {
173 m_leftGridLayers->SelectBlock( row, LAYERNAME_COLNUM, row, LAYER_HK_COLUMN );
174 return;
175 }
176 }
177
178 if( m_rightGridLayers->HitTest( right_pos ) == wxHT_WINDOW_INSIDE )
179 {
180 int row = m_rightGridLayers->YToRow( right_pos.y );
181
182 if( row == wxNOT_FOUND || row >= static_cast<int>( m_layersIdRightColumn.size() ) )
183 return;
184
186 m_rightGridLayers->SelectBlock( row, LAYERNAME_COLNUM, row, LAYERNAME_COLNUM);
187 }
188}
189
190
191void PCB_ONE_LAYER_SELECTOR::onCharHook( wxKeyEvent& event )
192{
193 if( event.GetKeyCode() == WXK_ESCAPE )
194 Close();
195}
196
197
199{
201 int left_row = 0;
202 int right_row = 0;
203 wxString layername;
204
205 for( LSEQ ui_seq = m_brd->GetEnabledLayers().UIOrder(); ui_seq; ++ui_seq )
206 {
207 PCB_LAYER_ID layerid = *ui_seq;
208
209 if( m_notAllowedLayersMask[layerid] )
210 continue;
211
212 wxColour fg = getLayerColor( layerid ).ToColour();
213 wxColour color( wxColour::AlphaBlend( fg.Red(), bg.Red(), fg.Alpha() / 255.0 ),
214 wxColour::AlphaBlend( fg.Green(), bg.Green(), fg.Alpha() / 255.0 ),
215 wxColour::AlphaBlend( fg.Blue(), bg.Blue(), fg.Alpha() / 255.0 ) );
216
217 layername = wxT( " " ) + getLayerName( layerid );
218
219 if( IsCopperLayer( layerid ) )
220 {
221 if( left_row )
222 m_leftGridLayers->AppendRows( 1 );
223
224 m_leftGridLayers->SetCellBackgroundColour ( left_row, COLOR_COLNUM, color );
225 m_leftGridLayers->SetCellValue( left_row, LAYERNAME_COLNUM, layername );
226 m_leftGridLayers->SetCellValue( left_row, LAYER_HK_COLUMN, getLayerHotKey( layerid ) );
227
228 if( m_layerSelected == layerid )
229 m_leftGridLayers->SetCellValue( left_row, SELECT_COLNUM, wxT( "1" ) );
230
231 m_layersIdLeftColumn.push_back( layerid );
232 left_row++;
233 }
234 else
235 {
236 if( right_row )
237 m_rightGridLayers->AppendRows( 1 );
238
239 m_rightGridLayers->SetCellBackgroundColour( right_row, COLOR_COLNUM, color );
240 m_rightGridLayers->SetCellValue( right_row, LAYERNAME_COLNUM, layername );
241
242 if( m_layerSelected == layerid )
243 m_rightGridLayers->SetCellValue( right_row, SELECT_COLNUM, wxT( "1" ) );
244
245 m_layersIdRightColumn.push_back( layerid );
246 right_row++;
247 }
248 }
249
250 // Show only populated lists:
251 if( left_row <= 0 )
252 m_leftGridLayers->Show( false );
253
254 if( right_row <= 0 )
255 m_rightGridLayers->Show( false );
256
257 // Now fix min grid column size (it also sets a minimal size)
258 m_leftGridLayers->AutoSizeColumns();
259 m_rightGridLayers->AutoSizeColumns();
260}
261
262
264{
265 m_layerSelected = m_layersIdLeftColumn[ event.GetRow() ];
266
267 if( IsQuasiModal() )
268 EndQuasiModal( 1 );
269 else
270 EndDialog( 1 );
271}
272
273
275{
276 m_layerSelected = m_layersIdRightColumn[ event.GetRow() ];
277
278 if( IsQuasiModal() )
279 EndQuasiModal( 2 );
280 else
281 EndDialog( 2 );
282}
283
284
285PCB_LAYER_ID PCB_BASE_FRAME::SelectOneLayer( PCB_LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask,
286 wxPoint aDlgPosition )
287{
288 PCB_ONE_LAYER_SELECTOR dlg( this, GetBoard(), aDefaultLayer, aNotAllowedLayersMask, true );
289
290 if( aDlgPosition != wxDefaultPosition )
291 {
292 wxSize dlgSize = dlg.GetSize();
293 aDlgPosition.x -= dlgSize.x/2;
294 aDlgPosition.y -= dlgSize.y/2;
295 dlg.SetPosition( aDlgPosition );
296 }
297
298 if( dlg.ShowModal() != wxID_CANCEL )
299 return ToLAYER_ID( dlg.GetLayerSelection() );
300 else
301 return UNDEFINED_LAYER;
302}
303
304
310{
311public:
313 PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer );
314
315 void GetLayerPair( PCB_LAYER_ID& aFrontLayer, PCB_LAYER_ID& aBackLayer )
316 {
317 aFrontLayer = m_frontLayer;
318 aBackLayer = m_backLayer;
319 }
320
321private:
322 void OnLeftGridCellClick( wxGridEvent& event ) override;
323 void OnRightGridCellClick( wxGridEvent& event ) override;
324
325 void buildList();
326
332
333 std::vector<PCB_LAYER_ID> m_layersId;
334};
335
336
338{
339 PCB_SCREEN* screen = frame()->GetScreen();
340
342 screen->m_Route_Layer_BOTTOM );
343
344 if( dlg.ShowModal() == wxID_OK )
345 {
347
348 // select the same layer for both layers is allowed (normal in some boards)
349 // but could be a mistake. So display an info message
350 if( screen->m_Route_Layer_TOP == screen->m_Route_Layer_BOTTOM )
351 DisplayInfoMessage( frame(), _( "Warning: top and bottom layers are same." ) );
352 }
353
354 return 0;
355}
356
357
359 PCB_BASE_FRAME* aParent, BOARD * aPcb, PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer) :
360 PCB_LAYER_SELECTOR( aParent ),
362{
363 m_frontLayer = aFrontLayer;
364 m_backLayer = aBackLayer;
367 m_brd = aPcb;
368
369 m_leftGridLayers->SetCellHighlightPenWidth( 0 );
370 m_rightGridLayers->SetCellHighlightPenWidth( 0 );
371 m_leftGridLayers->SetColFormatBool( SELECT_COLNUM );
372 m_rightGridLayers->SetColFormatBool( SELECT_COLNUM );
373 buildList();
374
375 SetFocus();
376
377 GetSizer()->SetSizeHints( this );
378 Center();
379}
380
381
383{
385 int row = 0;
386 wxString layername;
387
388 for( LSEQ ui_seq = m_brd->GetEnabledLayers().UIOrder(); ui_seq; ++ui_seq )
389 {
390 PCB_LAYER_ID layerid = *ui_seq;
391
392 if( !IsCopperLayer( layerid ) )
393 continue;
394
395 wxColour fg = getLayerColor( layerid ).ToColour();
396 wxColour color( wxColour::AlphaBlend( fg.Red(), bg.Red(), fg.Alpha() / 255.0 ),
397 wxColour::AlphaBlend( fg.Green(), bg.Green(), fg.Alpha() / 255.0 ),
398 wxColour::AlphaBlend( fg.Blue(), bg.Blue(), fg.Alpha() / 255.0 ) );
399
400 layername = wxT( " " ) + getLayerName( layerid );
401
402 if( row )
403 m_leftGridLayers->AppendRows( 1 );
404
405 m_leftGridLayers->SetCellBackgroundColour( row, COLOR_COLNUM, color );
406 m_leftGridLayers->SetCellValue( row, LAYERNAME_COLNUM, layername );
407 m_layersId.push_back( layerid );
408
409 if( m_frontLayer == layerid )
410 {
411 m_leftGridLayers->SetCellValue( row, SELECT_COLNUM, wxT( "1" ) );
412 m_leftGridLayers->SetGridCursor( row, COLOR_COLNUM );
413 m_leftRowSelected = row;
414 }
415
416 if( row )
417 m_rightGridLayers->AppendRows( 1 );
418
419 m_rightGridLayers->SetCellBackgroundColour( row, COLOR_COLNUM, color );
420 m_rightGridLayers->SetCellValue( row, LAYERNAME_COLNUM, layername );
421
422 if( m_backLayer == layerid )
423 {
424 m_rightGridLayers->SetCellValue( row, SELECT_COLNUM, wxT( "1" ) );
425 m_rightRowSelected = row;
426 }
427
428 row++;
429 }
430
431 // Now fix min grid layer name column size (it also sets a minimal size)
432 m_leftGridLayers->AutoSizeColumn( LAYERNAME_COLNUM );
433 m_rightGridLayers->AutoSizeColumn( LAYERNAME_COLNUM );
434}
435
436
438{
439 int row = event.GetRow();
440 PCB_LAYER_ID layer = m_layersId[row];
441
442 if( m_frontLayer == layer )
443 return;
444
445 m_leftGridLayers->SetCellValue( m_leftRowSelected, SELECT_COLNUM, wxEmptyString );
446 m_frontLayer = layer;
447 m_leftRowSelected = row;
448 m_leftGridLayers->SetCellValue( m_leftRowSelected, SELECT_COLNUM, wxT( "1" ) );
449}
450
451
453{
454 int row = event.GetRow();
455 PCB_LAYER_ID layer = m_layersId[row];
456
457 if( m_backLayer == layer )
458 return;
459
460 m_rightGridLayers->SetCellValue( m_rightRowSelected, SELECT_COLNUM, wxEmptyString );
461 m_backLayer = layer;
462 m_rightRowSelected = row;
463 m_rightGridLayers->SetCellValue( m_rightRowSelected, SELECT_COLNUM, wxT( "1" ) );
464}
int color
Definition: DXF_plotter.cpp:58
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:276
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:689
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:715
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:576
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:209
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:519
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:573
LSEQ UIOrder() const
Definition: lset.cpp:1012
static TOOL_ACTION * LayerIDToAction(PCB_LAYER_ID aLayerID)
Translate a layer ID into the action that switches to that layer.
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:285
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:263
void OnRightGridCellClick(wxGridEvent &aEvent) override
Definition: sel_layer.cpp:274
void onCharHook(wxKeyEvent &event)
Definition: sel_layer.cpp:191
std::vector< PCB_LAYER_ID > m_layersIdLeftColumn
Definition: sel_layer.cpp:109
PCB_ONE_LAYER_SELECTOR(PCB_BASE_FRAME *aParent, BOARD *aBrd, PCB_LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask, bool aHideCheckBoxes=false)
Definition: sel_layer.cpp:114
std::vector< PCB_LAYER_ID > m_layersIdRightColumn
Definition: sel_layer.cpp:110
void OnMouseMove(wxUpdateUIEvent &aEvent) override
Definition: sel_layer.cpp:156
PCB_LAYER_ID m_layerSelected
Definition: sel_layer.cpp:106
wxString getLayerHotKey(PCB_LAYER_ID aLayer) const
Definition: sel_layer.cpp:98
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:337
Display a pair PCB copper layers list in a dialog to select a layer pair from these lists.
Definition: sel_layer.cpp:310
std::vector< PCB_LAYER_ID > m_layersId
Definition: sel_layer.cpp:333
void GetLayerPair(PCB_LAYER_ID &aFrontLayer, PCB_LAYER_ID &aBackLayer)
Definition: sel_layer.cpp:315
void OnRightGridCellClick(wxGridEvent &event) override
Definition: sel_layer.cpp:452
void OnLeftGridCellClick(wxGridEvent &event) override
Definition: sel_layer.cpp:437
SELECT_COPPER_LAYERS_PAIR_DIALOG(PCB_BASE_FRAME *aParent, BOARD *aPcb, PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer)
Definition: sel_layer.cpp:358
int GetHotKey() const
Return the hotkey keycode which initiates the action.
Definition: tool_action.h:313
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)
wxString AddHotkeyName(const wxString &aText, int aHotKey, HOTKEY_ACTION_TYPE aStyle)
@ IS_COMMENT
Definition: hotkeys_basic.h:78
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:879
@ LAYER_PCB_BACKGROUND
PCB background color.
Definition: layer_ids.h:223
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:1022
wxPoint GetMousePosition()
Returns the mouse position in screen coordinates.
Definition: gtk/ui.cpp:601
BOARD * GetBoard()
#define LAYER_HK_COLUMN
Definition: sel_layer.cpp:40
#define LAYERNAME_COLNUM
Definition: sel_layer.cpp:39
#define SELECT_COLNUM
Definition: sel_layer.cpp:37
#define COLOR_COLNUM
Definition: sel_layer.cpp:38