KiCad PCB EDA Suite
Loading...
Searching...
No Matches
appearance_controls.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2020 Jon Evans <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
22
23#include <bitmaps.h>
24#include <board.h>
27#include <pad.h>
28#include <pcb_track.h>
29#include <eda_list_dialog.h>
30#include <string_utils.h>
32#include <confirm.h>
33#include <pcb_display_options.h>
34#include <pcb_edit_frame.h>
35#include <pcb_painter.h>
36#include <pcbnew_settings.h>
38#include <project.h>
42#include <tool/tool_manager.h>
43#include <tools/pcb_actions.h>
52#include <widgets/wx_infobar.h>
53#include <widgets/wx_grid.h>
55#include <wx/checkbox.h>
56#include <wx/hyperlink.h>
57#include <wx/msgdlg.h>
58#include <wx/radiobut.h>
59#include <wx/sizer.h>
60#include <wx/slider.h>
61#include <wx/statline.h>
62#include <wx/textdlg.h>
63#include <wx/bmpbuttn.h> // needed on wxMSW for OnSetFocus()
64#include <core/profile.h>
65#include <pgm_base.h>
66
67
68NET_GRID_TABLE::NET_GRID_TABLE( PCB_BASE_FRAME* aFrame, wxColor aBackgroundColor ) :
69 wxGridTableBase(),
70 m_frame( aFrame )
71{
72 m_defaultAttr = new wxGridCellAttr;
73 m_defaultAttr->SetBackgroundColour( aBackgroundColor );
74
75 m_labelAttr = new wxGridCellAttr;
77 m_labelAttr->SetBackgroundColour( aBackgroundColor );
78}
79
80
82{
83 m_defaultAttr->DecRef();
84 m_labelAttr->DecRef();
85}
86
87
88wxGridCellAttr* NET_GRID_TABLE::GetAttr( int aRow, int aCol, wxGridCellAttr::wxAttrKind )
89{
90 wxGridCellAttr* attr = nullptr;
91
92 switch( aCol )
93 {
94 case COL_COLOR: attr = m_defaultAttr; break;
95 case COL_VISIBILITY: attr = m_defaultAttr; break;
96 case COL_LABEL: attr = m_labelAttr; break;
97 default: wxFAIL;
98 }
99
100 if( attr )
101 attr->IncRef();
102
103 return attr;
104}
105
106
107wxString NET_GRID_TABLE::GetValue( int aRow, int aCol )
108{
109 wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
110
111 switch( aCol )
112 {
113 case COL_COLOR: return m_nets[aRow].color.ToCSSString();
114 case COL_VISIBILITY: return m_nets[aRow].visible ? wxT( "1" ) : wxT( "0" );
115 case COL_LABEL: return m_nets[aRow].name;
116 default: return wxEmptyString;
117 }
118}
119
120
121void NET_GRID_TABLE::SetValue( int aRow, int aCol, const wxString& aValue )
122{
123 wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
124
125 NET_GRID_ENTRY& net = m_nets[aRow];
126
127 switch( aCol )
128 {
129 case COL_COLOR:
130 net.color.SetFromWxString( aValue );
131 updateNetColor( net );
132 break;
133
134 case COL_VISIBILITY:
135 net.visible = ( aValue != wxT( "0" ) );
136 updateNetVisibility( net );
137 break;
138
139 case COL_LABEL:
140 net.name = aValue;
141 break;
142
143 default:
144 break;
145 }
146}
147
148
149wxString NET_GRID_TABLE::GetTypeName( int aRow, int aCol )
150{
151 switch( aCol )
152 {
153 case COL_COLOR: return wxT( "COLOR4D" );
154 case COL_VISIBILITY: return wxGRID_VALUE_BOOL;
155 case COL_LABEL: return wxGRID_VALUE_STRING;
156 default: return wxGRID_VALUE_STRING;
157 }
158}
159
160
161bool NET_GRID_TABLE::GetValueAsBool( int aRow, int aCol )
162{
163 wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
164 wxASSERT( aCol == COL_VISIBILITY );
165
166 return m_nets[aRow].visible;
167}
168
169
170void NET_GRID_TABLE::SetValueAsBool( int aRow, int aCol, bool aValue )
171{
172 wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
173 wxASSERT( aCol == COL_VISIBILITY );
174
175 SetVisibilityState( aRow, aValue );
177}
178
179
180void NET_GRID_TABLE::SetVisibilityState( int aRow, bool aVisible )
181{
182 wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
183
184 m_nets[aRow].visible = aVisible;
185}
186
187
188void* NET_GRID_TABLE::GetValueAsCustom( int aRow, int aCol, const wxString& aTypeName )
189{
190 wxASSERT( aCol == COL_COLOR );
191 wxASSERT( aTypeName == wxT( "COLOR4D" ) );
192 wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
193
194 return ColorToVoid( m_nets[aRow].color );
195}
196
197
198void NET_GRID_TABLE::SetValueAsCustom( int aRow, int aCol, const wxString& aTypeName, void* aValue )
199{
200 wxASSERT( aCol == COL_COLOR );
201 wxASSERT( aTypeName == wxT( "COLOR4D" ) );
202 wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
203
204 m_nets[aRow].color = VoidToColor( aValue );
205 updateNetColor( m_nets[aRow] );
206}
207
208
210{
211 wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
212 return m_nets[aRow];
213}
214
215
217{
218 auto it = m_netcodeToRow.find( aCode );
219 return it != m_netcodeToRow.end() ? it->second : -1;
220}
221
222
224{
225 BOARD* board = m_frame->GetBoard();
226
227 if( !board )
228 return;
229
230 const NETNAMES_MAP& nets = board->GetNetInfo().NetsByName();
231 KIGFX::RENDER_SETTINGS* renderSettings = m_frame->GetCanvas()->GetView()->GetPainter()->GetSettings();
232 KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( renderSettings );
233
234 std::set<int>& hiddenNets = rs->GetHiddenNets();
235 std::map<int, KIGFX::COLOR4D>& netColors = rs->GetNetColorMap();
236
237 int deleted = (int) m_nets.size();
238 m_nets.clear();
239 m_netcodeToRow.clear();
240
241 if( GetView() )
242 {
243 wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, 0, deleted );
244 GetView()->ProcessTableMessage( msg );
245 }
246
247 for( const std::pair<const wxString, NETINFO_ITEM*>& pair : nets )
248 {
249 int netCode = pair.second->GetNetCode();
250
251 if( netCode > 0 && !pair.first.StartsWith( wxT( "unconnected-(" ) ) )
252 {
253 COLOR4D color = netColors.count( netCode ) ? netColors.at( netCode )
255
256 bool visible = hiddenNets.count( netCode ) == 0;
257
258 m_nets.emplace_back( NET_GRID_ENTRY( netCode, pair.first, color, visible ) );
259 }
260 }
261
262 // TODO(JE) move to ::Compare so we can re-sort easily
263 std::sort( m_nets.begin(), m_nets.end(),
264 []( const NET_GRID_ENTRY& a, const NET_GRID_ENTRY& b )
265 {
266 return a.name < b.name;
267 } );
268
269 m_netcodeToRow.reserve( m_nets.size() );
270
271 for( size_t row = 0; row < m_nets.size(); ++row )
272 {
273 m_netcodeToRow.emplace( m_nets[row].code, static_cast<int>( row ) );
274 }
275
276 if( GetView() )
277 {
278 wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, (int) m_nets.size() );
279 GetView()->ProcessTableMessage( msg );
280 }
281}
282
283
285{
286 for( NET_GRID_ENTRY& net : m_nets )
287 {
288 net.visible = true;
289 updateNetVisibility( net );
290 }
291
292 if( GetView() )
293 GetView()->ForceRefresh();
294}
295
296
298{
299 for( NET_GRID_ENTRY& net : m_nets )
300 {
301 net.visible = ( net.code == aNet.code );
302 updateNetVisibility( net );
303 }
304
305 if( GetView() )
306 GetView()->ForceRefresh();
307}
308
309
311{
314
315 m_frame->GetToolManager()->RunAction( action, aNet.code );
316}
317
318
320{
321 KIGFX::RENDER_SETTINGS* rs = m_frame->GetCanvas()->GetView()->GetPainter()->GetSettings();
322 KIGFX::PCB_RENDER_SETTINGS* renderSettings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( rs );
323
324 std::map<int, KIGFX::COLOR4D>& netColors = renderSettings->GetNetColorMap();
325
326 if( aNet.color != COLOR4D::UNSPECIFIED )
327 netColors[aNet.code] = aNet.color;
328 else
329 netColors.erase( aNet.code );
330
331 m_frame->GetCanvas()->GetView()->UpdateAllLayersColor();
332 m_frame->GetCanvas()->RedrawRatsnest();
333 m_frame->GetCanvas()->Refresh();
334}
335
336
339
340#define RR APPEARANCE_CONTROLS::APPEARANCE_SETTING // Render Row abbreviation to reduce source width
341
342 // clang-format off
343
344 // text id tooltip opacity slider visibility checkbox
345 RR( _HKI( "Tracks" ), LAYER_TRACKS, _HKI( "Show tracks" ), true ),
346 RR( _HKI( "Vias" ), LAYER_VIAS, _HKI( "Show all vias" ), true ),
347 RR( _HKI( "Pads" ), LAYER_PADS, _HKI( "Show all pads" ), true ),
348 RR( _HKI( "Zones" ), LAYER_ZONES, _HKI( "Show copper zones" ), true ),
349 RR( _HKI( "Filled Shapes" ), LAYER_FILLED_SHAPES, _HKI( "Opacity of filled shapes" ), true, false ),
350 RR( _HKI( "Images" ), LAYER_DRAW_BITMAPS, _HKI( "Show user images" ), true ),
351 RR(),
352 RR( _HKI( "Footprints Front" ), LAYER_FOOTPRINTS_FR, _HKI( "Show footprints that are on board's front" ) ),
353 RR( _HKI( "Footprints Back" ), LAYER_FOOTPRINTS_BK, _HKI( "Show footprints that are on board's back" ) ),
354 RR( _HKI( "Values" ), LAYER_FP_VALUES, _HKI( "Show footprint values" ) ),
355 RR( _HKI( "References" ), LAYER_FP_REFERENCES, _HKI( "Show footprint references" ) ),
356 RR( _HKI( "Footprint Text" ), LAYER_FP_TEXT, _HKI( "Show all footprint text" ) ),
357 RR(),
358 RR(),
359 RR( _HKI( "Ratsnest" ), LAYER_RATSNEST, _HKI( "Show unconnected nets as a ratsnest") ),
360 RR( _HKI( "DRC Warnings" ), LAYER_DRC_WARNING, _HKI( "DRC violations with a Warning severity" ) ),
361 RR( _HKI( "DRC Errors" ), LAYER_DRC_ERROR, _HKI( "DRC violations with an Error severity" ) ),
362 RR( _HKI( "DRC Exclusions" ), LAYER_DRC_EXCLUSION, _HKI( "DRC violations which have been individually excluded" ) ),
363 RR( _HKI( "Anchors" ), LAYER_ANCHOR, _HKI( "Show footprint and text origins as a cross" ) ),
364 RR( _HKI( "Points" ), LAYER_POINTS, _HKI( "Show explicit snap points as crosses" ) ),
365 RR( _HKI( "Grids" ), LAYER_SUBGRIDS, _HKI( "Show custom routing/placement grids" ) ),
366 RR( _HKI( "Via Stitching" ), LAYER_VIA_STITCHING, _HKI( "Show via stitching generator outlines" ) ),
367 RR( _HKI( "Locked Item Shadow" ), LAYER_LOCKED_ITEM_SHADOW, _HKI( "Show a shadow on locked items" ) ),
368 RR( _HKI( "Colliding Courtyards" ), LAYER_CONFLICTS_SHADOW, _HKI( "Show colliding footprint courtyards" ) ),
369 RR( _HKI( "Constrained Item Shadow" ), LAYER_CONSTRAINT_SHADOW, _HKI( "Show a shadow on constrained items" ) ),
370 RR( _HKI( "Board Area Shadow" ), LAYER_BOARD_OUTLINE_AREA, _HKI( "Show board area shadow" ) ),
371 RR( _HKI( "Drawing Sheet" ), LAYER_DRAWINGSHEET, _HKI( "Show drawing sheet borders and title block" ) ),
372 RR( _HKI( "Grid" ), LAYER_GRID, _HKI( "Show the (x,y) grid dots" ) )
373 // clang-format on
374};
375
392
393// These are the built-in layer presets that cannot be deleted
394
396
398 LSET::AllLayersMask(), false );
399
401 LSET( LSET::AllCuMask() ).set( Edge_Cuts ), false );
402
404 LSET( LSET::InternalCuMask() ).set( Edge_Cuts ), false );
405
407 LSET( LSET::FrontMask() ).set( Edge_Cuts ), false );
408
411
413 LSET( LSET::BackMask() ).set( Edge_Cuts ), true );
414
417
418// this one is only used to store the object visibility settings of the last used
419// built-in layer preset
421
422
423APPEARANCE_CONTROLS::APPEARANCE_CONTROLS( PCB_BASE_FRAME* aParent, wxWindow* aFocusOwner, bool aFpEditorMode ) :
424 APPEARANCE_CONTROLS_BASE( aParent ),
425 m_frame( aParent ),
426 m_focusOwner( aFocusOwner ),
427 m_board( nullptr ),
428 m_isFpEditor( aFpEditorMode ),
429 m_currentPreset( nullptr ),
430 m_lastSelectedUserPreset( nullptr ),
431 m_layerContextMenu( nullptr ),
433{
434 // Correct the min size from wxformbuilder not using fromdip
435 SetMinSize( FromDIP( GetMinSize() ) );
436
437 // We pregenerate the visibility bundles to reuse to reduce gdi exhaustion on windows
438 // We can get a crazy amount of nets and netclasses
441
442 int screenHeight = wxSystemSettings::GetMetric( wxSYS_SCREEN_Y );
444 m_pointSize = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ).GetPointSize();
445 m_layerPanelColour = m_panelLayers->GetBackgroundColour().ChangeLightness( 110 );
446 SetBorders( true, false, false, false );
447
448 m_layersOuterSizer = new wxBoxSizer( wxVERTICAL );
450 m_windowLayers->SetScrollRate( 0, 5 );
451 m_windowLayers->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS::OnSetFocus, this );
452
453 m_objectsOuterSizer = new wxBoxSizer( wxVERTICAL );
455 m_windowObjects->SetScrollRate( 0, 5 );
456 m_windowObjects->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS::OnSetFocus, this );
457
458 wxFont infoFont = KIUI::GetInfoFont( this );
459 m_staticTextNets->SetFont( infoFont );
460 m_staticTextNetClasses->SetFont( infoFont );
461 m_panelLayers->SetFont( infoFont );
462 m_windowLayers->SetFont( infoFont );
463 m_windowObjects->SetFont( infoFont );
464 m_presetsLabel->SetFont( infoFont );
465 m_viewportsLabel->SetFont( infoFont );
466
467 m_cbLayerPresets->SetToolTip( wxString::Format( _( "Save and restore layer visibility combinations.\n"
468 "Use %s+Tab to activate selector.\n"
469 "Successive Tabs while holding %s down will "
470 "cycle through presets in the popup." ),
473
474 m_cbViewports->SetToolTip( wxString::Format( _( "Save and restore view location and zoom.\n"
475 "Use %s+Tab to activate selector.\n"
476 "Successive Tabs while holding %s down will "
477 "cycle through viewports in the popup." ),
480
482
484 m_btnNetInspector->SetPadding( 2 );
485
487 m_btnConfigureNetClasses->SetPadding( 2 );
488
489 m_txtNetFilter->SetHint( _( "Filter nets" ) );
490
491 if( screenHeight <= 900 && m_pointSize >= FromDIP( KIUI::c_IndicatorSizeDIP ) )
492 m_pointSize = m_pointSize * 8 / 10;
493
494 wxFont font = m_notebook->GetFont();
495
496#ifdef __WXMAC__
497 font.SetPointSize( m_pointSize );
498 m_notebook->SetFont( font );
499#endif
500
501 auto setHighContrastMode =
502 [&]( HIGH_CONTRAST_MODE aMode )
503 {
504 PCB_DISPLAY_OPTIONS opts = m_frame->GetDisplayOptions();
505 opts.m_ContrastModeDisplay = aMode;
506
507 m_frame->SetDisplayOptions( opts );
508 passOnFocus();
509 };
510
511 m_rbHighContrastNormal->Bind( wxEVT_RADIOBUTTON,
512 [=]( wxCommandEvent& aEvent )
513 {
514 setHighContrastMode( HIGH_CONTRAST_MODE::NORMAL );
515 } );
516
517 m_rbHighContrastDim->Bind( wxEVT_RADIOBUTTON,
518 [=]( wxCommandEvent& aEvent )
519 {
520 setHighContrastMode( HIGH_CONTRAST_MODE::DIMMED );
521 } );
522
523 m_rbHighContrastOff->Bind( wxEVT_RADIOBUTTON,
524 [=]( wxCommandEvent& aEvent )
525 {
526 setHighContrastMode( HIGH_CONTRAST_MODE::HIDDEN );
527 } );
528
530
531 m_btnNetInspector->Bind( wxEVT_BUTTON,
532 [&]( wxCommandEvent& aEvent )
533 {
534 m_frame->GetToolManager()->RunAction( PCB_ACTIONS::showNetInspector );
535 } );
536
537 m_btnConfigureNetClasses->Bind( wxEVT_BUTTON,
538 [&]( wxCommandEvent& aEvent )
539 {
540 // This panel should only be visible in the PCB_EDIT_FRAME anyway
541 if( PCB_EDIT_FRAME* editframe = dynamic_cast<PCB_EDIT_FRAME*>( m_frame ) )
542 editframe->ShowBoardSetupDialog( _( "Net Classes" ) );
543
544 passOnFocus();
545 } );
546
547 m_cbFlipBoard->SetValue( m_frame->GetDisplayOptions().m_FlipBoardView );
548 m_cbFlipBoard->Bind( wxEVT_CHECKBOX,
549 [&]( wxCommandEvent& aEvent )
550 {
551 m_frame->GetToolManager()->RunAction( PCB_ACTIONS::flipBoard );
553 } );
554
557
558 m_netsGrid->RegisterDataType( wxT( "bool" ), m_toggleGridRenderer, new wxGridCellBoolEditor );
559
560 m_netsGrid->RegisterDataType( wxT( "COLOR4D" ),
563
564 m_netsTable = new NET_GRID_TABLE( m_frame, m_panelNets->GetBackgroundColour() );
565 m_netsGrid->SetTable( m_netsTable, true );
566 m_netsGrid->SetColLabelSize( 0 );
567
568 m_netsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
569 m_netsGrid->SetSelectionForeground( m_netsGrid->GetDefaultCellTextColour() );
570 m_netsGrid->SetSelectionBackground( m_panelNets->GetBackgroundColour() );
571
572 const int cellPadding = 6;
573#ifdef __WXMAC__
574 const int rowHeightPadding = 5;
575#else
576 const int rowHeightPadding = 3;
577#endif
578
579 wxSize size = ConvertDialogToPixels( SWATCH_SIZE_SMALL_DU );
580 m_netsGrid->SetColSize( NET_GRID_TABLE::COL_COLOR, size.x + cellPadding );
581
582 size = m_visibleBitmapBundle.GetPreferredBitmapSizeFor( this );
583 m_netsGrid->SetColSize( NET_GRID_TABLE::COL_VISIBILITY, size.x + cellPadding );
584
585 m_netsGrid->SetDefaultCellFont( font );
586 m_netsGrid->SetDefaultRowSize( font.GetPixelSize().y + rowHeightPadding );
587
588 m_netsGrid->GetGridWindow()->Bind( wxEVT_MOTION, &APPEARANCE_CONTROLS::OnNetGridMouseEvent, this );
589
590 // To handle middle click on color swatches
591 m_netsGrid->GetGridWindow()->Bind( wxEVT_MIDDLE_UP, &APPEARANCE_CONTROLS::OnNetGridMouseEvent, this );
592
593 m_netsGrid->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_DEFAULT );
594 m_netclassScrolledWindow->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_DEFAULT );
595
596 if( m_isFpEditor )
597 m_notebook->RemovePage( 2 );
598
599 if( PCBNEW_SETTINGS* cfg = m_frame->GetPcbNewSettings() )
600 {
601 if( cfg->m_AuiPanels.appearance_expand_layer_display )
603
604 if( cfg->m_AuiPanels.appearance_expand_net_display )
605 m_paneNetDisplayOptions->Expand();
606 }
607
612
613 // Grid visibility is loaded and set to the GAL before we are constructed
614 SetObjectVisible( LAYER_GRID, m_frame->IsGridVisible() );
615
616 Bind( wxEVT_COMMAND_MENU_SELECTED, &APPEARANCE_CONTROLS::OnLayerContextMenu, this,
618
619 m_frame->Bind( EDA_LANG_CHANGED, &APPEARANCE_CONTROLS::OnLanguageChanged, this );
620}
621
622
624{
625 m_frame->Unbind( EDA_LANG_CHANGED, &APPEARANCE_CONTROLS::OnLanguageChanged, this );
626
627 delete m_iconProvider;
628}
629
630
632{
633 int hotkey;
634 wxString msg;
635 wxFont infoFont = KIUI::GetInfoFont( this );
636
637 // Create layer display options
638 m_paneLayerDisplayOptions = new WX_COLLAPSIBLE_PANE( m_panelLayers, wxID_ANY, _( "Layer Display Options" ) );
639 m_paneLayerDisplayOptions->Collapse();
640 m_paneLayerDisplayOptions->SetBackgroundColour( m_notebook->GetThemeBackgroundColour() );
641
642 wxWindow* layerDisplayPane = m_paneLayerDisplayOptions->GetPane();
643
644 wxBoxSizer* layerDisplayOptionsSizer;
645 layerDisplayOptionsSizer = new wxBoxSizer( wxVERTICAL );
646
647 hotkey = PCB_ACTIONS::highContrastModeCycle.GetHotKey();
648
649 if( hotkey )
650 msg = wxString::Format( _( "Inactive layers (%s):" ), KeyNameFromKeyCode( hotkey ) );
651 else
652 msg = _( "Inactive layers:" );
653
654 m_inactiveLayersLabel = new wxStaticText( layerDisplayPane, wxID_ANY, msg );
655 m_inactiveLayersLabel->SetFont( infoFont );
656 m_inactiveLayersLabel->Wrap( -1 );
657 layerDisplayOptionsSizer->Add( m_inactiveLayersLabel, 0, wxEXPAND | wxBOTTOM, 2 );
658
659 wxBoxSizer* contrastModeSizer;
660 contrastModeSizer = new wxBoxSizer( wxHORIZONTAL );
661
662 m_rbHighContrastNormal = new wxRadioButton( layerDisplayPane, wxID_ANY, _( "Normal" ),
663 wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
664 m_rbHighContrastNormal->SetFont( infoFont );
665 m_rbHighContrastNormal->SetValue( true );
666 m_rbHighContrastNormal->SetToolTip( _( "Inactive layers will be shown in full color" ) );
667
668 contrastModeSizer->Add( m_rbHighContrastNormal, 0, wxRIGHT, 5 );
669 contrastModeSizer->AddStretchSpacer();
670
671 m_rbHighContrastDim = new wxRadioButton( layerDisplayPane, wxID_ANY, _( "Dim" ) );
672 m_rbHighContrastDim->SetFont( infoFont );
673 m_rbHighContrastDim->SetToolTip( _( "Inactive layers will be dimmed" ) );
674
675 contrastModeSizer->Add( m_rbHighContrastDim, 0, wxRIGHT, 5 );
676 contrastModeSizer->AddStretchSpacer();
677
678 m_rbHighContrastOff = new wxRadioButton( layerDisplayPane, wxID_ANY, _( "Hide" ) );
679 m_rbHighContrastOff->SetFont( infoFont );
680 m_rbHighContrastOff->SetToolTip( _( "Inactive layers will be hidden" ) );
681
682 contrastModeSizer->Add( m_rbHighContrastOff, 0, 0, 5 );
683 contrastModeSizer->AddStretchSpacer();
684
685 layerDisplayOptionsSizer->Add( contrastModeSizer, 0, wxEXPAND, 5 );
686
687 m_layerDisplaySeparator = new wxStaticLine( layerDisplayPane, wxID_ANY, wxDefaultPosition,
688 wxDefaultSize, wxLI_HORIZONTAL );
689 layerDisplayOptionsSizer->Add( m_layerDisplaySeparator, 0, wxEXPAND | wxTOP, 4 );
690
691 m_cbFlipBoard = new wxCheckBox( layerDisplayPane, wxID_ANY, _( "Flip board view" ) );
692 m_cbFlipBoard->SetFont( infoFont );
693 layerDisplayOptionsSizer->Add( m_cbFlipBoard, 0, wxTOP | wxBOTTOM, 3 );
694
695 layerDisplayPane->SetSizer( layerDisplayOptionsSizer );
696 layerDisplayPane->Layout();
697 layerDisplayOptionsSizer->Fit( layerDisplayPane );
698
699 m_panelLayersSizer->Add( m_paneLayerDisplayOptions, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 3 );
700
702 [&]( wxCommandEvent& aEvent )
703 {
704 Freeze();
705 m_panelLayers->Fit();
706 m_sizerOuter->Layout();
707 Thaw();
708 } );
709
710 // Create net display options
711
712 m_paneNetDisplayOptions = new WX_COLLAPSIBLE_PANE( m_panelNetsAndClasses, wxID_ANY, _( "Net Display Options" ) );
713 m_paneNetDisplayOptions->Collapse();
714 m_paneNetDisplayOptions->SetBackgroundColour( m_notebook->GetThemeBackgroundColour() );
715
716 wxWindow* netDisplayPane = m_paneNetDisplayOptions->GetPane();
717 wxBoxSizer* netDisplayOptionsSizer = new wxBoxSizer( wxVERTICAL );
718
720
721 hotkey = PCB_ACTIONS::netColorModeCycle.GetHotKey();
722
723 if( hotkey )
724 msg = wxString::Format( _( "Net colors (%s):" ), KeyNameFromKeyCode( hotkey ) );
725 else
726 msg = _( "Net colors:" );
727
728 m_txtNetDisplayTitle = new wxStaticText( netDisplayPane, wxID_ANY, msg );
729 m_txtNetDisplayTitle->SetFont( infoFont );
730 m_txtNetDisplayTitle->Wrap( -1 );
731 m_txtNetDisplayTitle->SetToolTip( _( "Choose when to show net and netclass colors" ) );
732
733 netDisplayOptionsSizer->Add( m_txtNetDisplayTitle, 0, wxEXPAND | wxBOTTOM | wxLEFT, 2 );
734
735 wxBoxSizer* netColorSizer = new wxBoxSizer( wxHORIZONTAL );
736
737 m_rbNetColorAll = new wxRadioButton( netDisplayPane, wxID_ANY, _( "All" ), wxDefaultPosition,
738 wxDefaultSize, wxRB_GROUP );
739 m_rbNetColorAll->SetFont( infoFont );
740 m_rbNetColorAll->SetToolTip( _( "Net and netclass colors are shown on all copper items" ) );
741
742 netColorSizer->Add( m_rbNetColorAll, 0, wxRIGHT, 5 );
743 netColorSizer->AddStretchSpacer();
744
745 m_rbNetColorRatsnest = new wxRadioButton( netDisplayPane, wxID_ANY, _( "Ratsnest" ) );
746 m_rbNetColorRatsnest->SetFont( infoFont );
747 m_rbNetColorRatsnest->SetValue( true );
748 m_rbNetColorRatsnest->SetToolTip( _( "Net and netclass colors are shown on the ratsnest only" ) );
749
750 netColorSizer->Add( m_rbNetColorRatsnest, 0, wxRIGHT, 5 );
751 netColorSizer->AddStretchSpacer();
752
753 m_rbNetColorOff = new wxRadioButton( netDisplayPane, wxID_ANY, _( "None" ) );
754 m_rbNetColorOff->SetFont( infoFont );
755 m_rbNetColorOff->SetToolTip( _( "Net and netclass colors are not shown" ) );
756
757 netColorSizer->Add( m_rbNetColorOff, 0, 0, 5 );
758
759 netDisplayOptionsSizer->Add( netColorSizer, 0, wxEXPAND | wxBOTTOM, 5 );
760
762
763 hotkey = PCB_ACTIONS::ratsnestModeCycle.GetHotKey();
764
765 if( hotkey )
766 msg = wxString::Format( _( "Ratsnest display (%s):" ), KeyNameFromKeyCode( hotkey ) );
767 else
768 msg = _( "Ratsnest display:" );
769
770 m_txtRatsnestVisibility = new wxStaticText( netDisplayPane, wxID_ANY, msg );
771 m_txtRatsnestVisibility->SetFont( infoFont );
772 m_txtRatsnestVisibility->Wrap( -1 );
773 m_txtRatsnestVisibility->SetToolTip( _( "Choose which ratsnest lines to display" ) );
774
775 netDisplayOptionsSizer->Add( m_txtRatsnestVisibility, 0, wxEXPAND | wxBOTTOM | wxLEFT, 2 );
776
777 wxBoxSizer* ratsnestDisplayModeSizer = new wxBoxSizer( wxHORIZONTAL );
778
779 m_rbRatsnestAllLayers = new wxRadioButton( netDisplayPane, wxID_ANY, _( "All" ),
780 wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
781 m_rbRatsnestAllLayers->SetFont( infoFont );
782 m_rbRatsnestAllLayers->SetValue( true );
783 m_rbRatsnestAllLayers->SetToolTip( _( "Show ratsnest lines to items on all layers" ) );
784
785 ratsnestDisplayModeSizer->Add( m_rbRatsnestAllLayers, 0, wxRIGHT, 5 );
786 ratsnestDisplayModeSizer->AddStretchSpacer();
787
788 m_rbRatsnestVisLayers = new wxRadioButton( netDisplayPane, wxID_ANY, _( "Visible layers" ) );
789 m_rbRatsnestVisLayers->SetFont( infoFont );
790 m_rbRatsnestVisLayers->SetToolTip( _( "Show ratsnest lines to items on visible layers" ) );
791
792 ratsnestDisplayModeSizer->Add( m_rbRatsnestVisLayers, 0, wxRIGHT, 5 );
793 ratsnestDisplayModeSizer->AddStretchSpacer();
794
795 m_rbRatsnestNone = new wxRadioButton( netDisplayPane, wxID_ANY, _( "None" ) );
796 m_rbRatsnestNone->SetFont( infoFont );
797 m_rbRatsnestNone->SetToolTip( _( "Hide all ratsnest lines" ) );
798
799 ratsnestDisplayModeSizer->Add( m_rbRatsnestNone, 0, 0, 5 );
800
801 netDisplayOptionsSizer->Add( ratsnestDisplayModeSizer, 0, wxEXPAND | wxBOTTOM, 5 );
802
804
805 netDisplayPane->SetSizer( netDisplayOptionsSizer );
806 netDisplayPane->Layout();
807 netDisplayOptionsSizer->Fit( netDisplayPane );
808
809 m_netsTabOuterSizer->Add( m_paneNetDisplayOptions, 0, wxEXPAND | wxTOP, 5 );
810
812 [&]( wxCommandEvent& aEvent )
813 {
814 Freeze();
816 m_sizerOuter->Layout();
817 passOnFocus();
818 Thaw();
819 } );
820
821 m_rbNetColorAll->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onNetColorMode, this );
822 m_rbNetColorOff->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onNetColorMode, this );
823 m_rbNetColorRatsnest->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onNetColorMode, this );
824
825 m_rbRatsnestAllLayers->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onRatsnestMode, this );
826 m_rbRatsnestVisLayers->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onRatsnestMode, this );
827 m_rbRatsnestNone->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onRatsnestMode, this );
828}
829
830
832{
833 DPI_SCALING_COMMON dpi( nullptr, m_frame );
834 wxSize size( 220 * dpi.GetScaleFactor(), 480 * dpi.GetScaleFactor() );
835 return size;
836}
837
838
843
844
849
850
851void APPEARANCE_CONTROLS::OnNotebookPageChanged( wxNotebookEvent& aEvent )
852{
853 // Work around wxMac issue where the notebook pages are blank
854#ifdef __WXMAC__
855 int page = aEvent.GetSelection();
856
857 if( page >= 0 )
858 m_notebook->ChangeSelection( static_cast<unsigned>( page ) );
859#endif
860
861#ifndef __WXMSW__
862 // Because wxWidgets is broken and will send click events to children of the collapsible
863 // panes even if they are collapsed without this
864 Freeze();
865 m_panelLayers->Fit();
867 m_sizerOuter->Layout();
868 Thaw();
869#endif
870
871 Bind( wxEVT_IDLE, &APPEARANCE_CONTROLS::idleFocusHandler, this );
872}
873
874
875void APPEARANCE_CONTROLS::idleFocusHandler( wxIdleEvent& aEvent )
876{
877 passOnFocus();
878 Unbind( wxEVT_IDLE, &APPEARANCE_CONTROLS::idleFocusHandler, this );
879}
880
881
882void APPEARANCE_CONTROLS::OnSetFocus( wxFocusEvent& aEvent )
883{
884#ifdef __WXMSW__
885 // In wxMSW, buttons won't process events unless they have focus, so we'll let it take the
886 // focus and give it back to the parent in the button event handler.
887 if( wxBitmapButton* btn = dynamic_cast<wxBitmapButton*>( aEvent.GetEventObject() ) )
888 {
889 wxCommandEvent evt( wxEVT_BUTTON );
890 wxPostEvent( btn, evt );
891 }
892#endif
893
894 passOnFocus();
895 aEvent.Skip();
896}
897
898
899void APPEARANCE_CONTROLS::OnSize( wxSizeEvent& aEvent )
900{
901 aEvent.Skip();
902}
903
904
905void APPEARANCE_CONTROLS::OnNetGridClick( wxGridEvent& event )
906{
907 int row = event.GetRow();
908 int col = event.GetCol();
909
910 switch( col )
911 {
913 m_netsTable->SetValueAsBool( row, col, !m_netsTable->GetValueAsBool( row, col ) );
914 m_netsGrid->ForceRefresh();
915 break;
916
917 default:
918 break;
919 }
920}
921
922
924{
925 int row = event.GetRow();
926 int col = event.GetCol();
927
928 switch( col )
929 {
931 {
932 wxGridCellEditor* editor = m_netsGrid->GetCellEditor( row, col );
933
934 if( editor )
935 {
936 editor->BeginEdit( row, col, m_netsGrid );
937 editor->DecRef();
938 }
939
940 break;
941 }
942
943 default:
944 break;
945 }
946}
947
948
950{
951 m_netsGrid->SelectRow( event.GetRow() );
952
953 wxString netName = UnescapeString( m_netsGrid->GetCellValue( event.GetRow(),
955 wxMenu menu;
956
957 menu.Append( new wxMenuItem( &menu, ID_SET_NET_COLOR, _( "Set Net Color" ), wxEmptyString,
958 wxITEM_NORMAL ) );
959 menu.Append( new wxMenuItem( &menu, ID_CLEAR_NET_COLOR, _( "Clear Net Color" ), wxEmptyString,
960 wxITEM_NORMAL ) );
961
962 menu.AppendSeparator();
963
964 menu.Append( new wxMenuItem( &menu, ID_HIGHLIGHT_NET,
965 wxString::Format( _( "Highlight %s" ), netName ), wxEmptyString,
966 wxITEM_NORMAL ) );
967 menu.Append( new wxMenuItem( &menu, ID_SELECT_NET,
968 wxString::Format( _( "Select Tracks and Vias in %s" ), netName ),
969 wxEmptyString, wxITEM_NORMAL ) );
970 menu.Append( new wxMenuItem( &menu, ID_DESELECT_NET,
971 wxString::Format( _( "Unselect Tracks and Vias in %s" ), netName ),
972 wxEmptyString, wxITEM_NORMAL ) );
973
974 menu.AppendSeparator();
975
976 menu.Append( new wxMenuItem( &menu, ID_SHOW_ALL_NETS, _( "Show All Nets" ), wxEmptyString,
977 wxITEM_NORMAL ) );
978 menu.Append( new wxMenuItem( &menu, ID_HIDE_OTHER_NETS, _( "Hide All Other Nets" ),
979 wxEmptyString, wxITEM_NORMAL ) );
980
981 menu.Bind( wxEVT_COMMAND_MENU_SELECTED, &APPEARANCE_CONTROLS::onNetContextMenu, this );
982
983 PopupMenu( &menu );
984}
985
986
988{
989 wxPoint pos = m_netsGrid->CalcUnscrolledPosition( aEvent.GetPosition() );
990 wxGridCellCoords cell = m_netsGrid->XYToCell( pos );
991
992 if( aEvent.Moving() || aEvent.Entering() )
993 {
994 aEvent.Skip();
995
996 if( !cell )
997 {
998 m_netsGrid->GetGridWindow()->UnsetToolTip();
999 return;
1000 }
1001
1002 if( cell == m_hoveredCell )
1003 return;
1004
1005 m_hoveredCell = cell;
1006
1007 const NET_GRID_ENTRY& net = m_netsTable->GetEntry( cell.GetRow() );
1008
1009 wxString name = net.name;
1010 wxString showOrHide = net.visible ? _( "Click to hide ratsnest for %s" )
1011 : _( "Click to show ratsnest for %s" );
1012 wxString tip;
1013
1014 if( cell.GetCol() == NET_GRID_TABLE::COL_VISIBILITY )
1015 tip.Printf( showOrHide, name );
1016 else if( cell.GetCol() == NET_GRID_TABLE::COL_COLOR )
1017 tip = _( "Double click (or middle click) to change color; right click for more actions" );
1018
1019 m_netsGrid->GetGridWindow()->SetToolTip( tip );
1020 }
1021 else if( aEvent.Leaving() )
1022 {
1023 m_netsGrid->UnsetToolTip();
1024 aEvent.Skip();
1025 }
1026 else if( aEvent.Dragging() )
1027 {
1028 // not allowed
1029 CallAfter( [this]()
1030 {
1031 m_netsGrid->ClearSelection();
1032 } );
1033 }
1034 else if( aEvent.ButtonUp( wxMOUSE_BTN_MIDDLE ) && !!cell )
1035 {
1036 int row = cell.GetRow();
1037 int col = cell.GetCol();
1038
1039 if( col == NET_GRID_TABLE::COL_COLOR )
1040 {
1041 wxGridCellEditor* editor = m_netsGrid->GetCellEditor( row, col );
1042
1043 if( editor )
1044 {
1045 editor->BeginEdit( row, col, m_netsGrid );
1046 editor->DecRef();
1047 }
1048 }
1049
1050 aEvent.Skip();
1051 }
1052 else
1053 {
1054 aEvent.Skip();
1055 }
1056}
1057
1058
1059void APPEARANCE_CONTROLS::OnLanguageChanged( wxCommandEvent& aEvent )
1060{
1061 m_notebook->SetPageText( 0, _( "Layers" ) );
1062 m_notebook->SetPageText( 1, _( "Objects" ) );
1063
1064 if( m_notebook->GetPageCount() >= 3 )
1065 m_notebook->SetPageText( 2, _( "Nets" ) );
1066
1067 m_netsGrid->ClearSelection();
1068
1069 Freeze();
1070 rebuildLayers();
1075 rebuildNets();
1076
1080
1082
1083 Thaw();
1084 Refresh();
1085
1086 aEvent.Skip();
1087}
1088
1090{
1091 if( aFlags & HOTKEYS_CHANGED )
1092 rebuildLayers();
1093}
1094
1096{
1097 if( !m_frame->GetBoard() )
1098 return;
1099
1100 m_netsGrid->ClearSelection();
1101
1102 Freeze();
1103 rebuildLayers();
1107 rebuildNets();
1111
1113
1114 m_board = m_frame->GetBoard();
1115
1116 if( m_board )
1117 m_board->AddListener( this );
1118
1119 Thaw();
1120 Refresh();
1121}
1122
1123
1128
1129
1130void APPEARANCE_CONTROLS::OnNetVisibilityChanged( int aNetCode, bool aVisibility )
1131{
1133 return;
1134
1135 int row = m_netsTable->GetRowByNetcode( aNetCode );
1136
1137 if( row >= 0 )
1138 {
1139 m_netsTable->SetVisibilityState( row, aVisibility );
1140 m_netsGrid->ForceRefresh();
1141 }
1142}
1143
1144
1146{
1147 return aBoardItem->Type() == PCB_NETINFO_T;
1148}
1149
1150
1151bool APPEARANCE_CONTROLS::doesBoardItemNeedRebuild( std::vector<BOARD_ITEM*>& aBoardItems )
1152{
1153 bool rebuild = std::any_of( aBoardItems.begin(), aBoardItems.end(),
1154 []( const BOARD_ITEM* a )
1155 {
1156 return a->Type() == PCB_NETINFO_T;
1157 } );
1158
1159 return rebuild;
1160}
1161
1162
1168
1169
1170void APPEARANCE_CONTROLS::OnBoardItemsAdded( BOARD& aBoard, std::vector<BOARD_ITEM*>& aItems )
1171{
1172 if( doesBoardItemNeedRebuild( aItems ) )
1174}
1175
1176
1182
1183
1184void APPEARANCE_CONTROLS::OnBoardItemsRemoved( BOARD& aBoard, std::vector<BOARD_ITEM*>& aItems )
1185{
1186 if( doesBoardItemNeedRebuild( aItems ) )
1188}
1189
1190
1196
1197
1198void APPEARANCE_CONTROLS::OnBoardItemsChanged( BOARD& aBoard, std::vector<BOARD_ITEM*>& aItems )
1199{
1200 if( doesBoardItemNeedRebuild( aItems ) )
1202}
1203
1204
1206 std::vector<BOARD_ITEM*>& aAddedItems,
1207 std::vector<BOARD_ITEM*>& aRemovedItems,
1208 std::vector<BOARD_ITEM*>& aChangedItems )
1209{
1210 if( doesBoardItemNeedRebuild( aAddedItems ) || doesBoardItemNeedRebuild( aRemovedItems )
1211 || doesBoardItemNeedRebuild( aChangedItems ) )
1212 {
1214 }
1215}
1216
1217
1219{
1220 if( !m_frame->GetBoard() )
1221 return;
1222
1223 m_netsGrid->ClearSelection();
1224
1225 Freeze();
1226 rebuildNets();
1227 Thaw();
1228}
1229
1230
1232{
1233 if( !m_frame->GetBoard() )
1234 return;
1235
1238}
1239
1240
1242{
1243 // This is essentially a list of hacks because DarkMode isn't yet implemented inside
1244 // wxWidgets.
1245 //
1246 // The individual wxPanels, COLOR_SWATCHes and GRID_CELL_COLOR_RENDERERs should really be
1247 // overriding some virtual method or responding to some wxWidgets event so that the parent
1248 // doesn't have to know what it contains. But, that's not where we are, so... :shrug:
1249
1250 m_layerPanelColour = m_panelLayers->GetBackgroundColour().ChangeLightness( 110 );
1251
1252 m_windowLayers->SetBackgroundColour( m_layerPanelColour );
1253
1254 for( wxSizerItem* child : m_layersOuterSizer->GetChildren() )
1255 {
1256 if( child && child->GetWindow() )
1257 child->GetWindow()->SetBackgroundColour( m_layerPanelColour );
1258 }
1259
1260 // Easier than calling OnDarkModeToggle on all the GRID_CELL_COLOR_RENDERERs:
1261 m_netsGrid->RegisterDataType( wxT( "COLOR4D" ),
1264
1265 for( const std::pair<const wxString, APPEARANCE_SETTING*>& pair : m_netclassSettingsMap )
1266 {
1267 if( pair.second->ctl_color )
1268 pair.second->ctl_color->OnDarkModeToggle();
1269 }
1270
1271 OnLayerChanged(); // Update selected highlighting
1272}
1273
1274
1276{
1277 for( const std::unique_ptr<APPEARANCE_SETTING>& setting : m_layerSettings )
1278 {
1279 setting->ctl_panel->SetBackgroundColour( m_layerPanelColour );
1280 setting->ctl_indicator->SetIndicatorState( ROW_ICON_PROVIDER::STATE::OFF );
1281 }
1282
1283 wxChar r = m_layerPanelColour.Red();
1284 wxChar g = m_layerPanelColour.Green();
1285 wxChar b = m_layerPanelColour.Blue();
1286
1287 if( r < 240 || g < 240 || b < 240 )
1288 {
1289 r = wxChar( std::min( (int) r + 15, 255 ) );
1290 g = wxChar( std::min( (int) g + 15, 255 ) );
1291 b = wxChar( std::min( (int) b + 15, 255 ) );
1292 }
1293 else
1294 {
1295 r = wxChar( std::max( (int) r - 15, 0 ) );
1296 g = wxChar( std::max( (int) g - 15, 0 ) );
1297 b = wxChar( std::max( (int) b - 15, 0 ) );
1298 }
1299
1300 PCB_LAYER_ID current = m_frame->GetActiveLayer();
1301
1302 if( !m_layerSettingsMap.count( current ) )
1303 {
1304 wxASSERT( m_layerSettingsMap.count( F_Cu ) );
1305 current = F_Cu;
1306 }
1307
1308 APPEARANCE_SETTING* newSetting = m_layerSettingsMap[ current ];
1309
1310 newSetting->ctl_panel->SetBackgroundColour( wxColour( r, g, b ) );
1312
1313 Refresh();
1314}
1315
1316
1317void APPEARANCE_CONTROLS::SetLayerVisible( int aLayer, bool isVisible )
1318{
1319 LSET visible = getVisibleLayers();
1320 PCB_LAYER_ID layer = ToLAYER_ID( aLayer );
1321
1322 if( visible.test( layer ) == isVisible )
1323 return;
1324
1325 visible.set( layer, isVisible );
1326 setVisibleLayers( visible );
1327
1328 m_frame->GetCanvas()->GetView()->SetLayerVisible( layer, isVisible );
1329
1331}
1332
1333
1335{
1336 if( m_objectSettingsMap.count( aLayer ) )
1337 {
1338 APPEARANCE_SETTING* setting = m_objectSettingsMap.at( aLayer );
1339
1340 if( setting->can_control_visibility )
1341 setting->ctl_visibility->SetValue( isVisible );
1342 }
1343
1344 BOARD* board = m_frame->GetBoard();
1345
1346 if( !board )
1347 return;
1348
1349 board->SetElementVisibility( aLayer, isVisible );
1350
1351 m_frame->Update3DView( true, m_frame->GetPcbNewSettings()->m_Display.m_Live3DRefresh );
1352
1353 m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, isVisible );
1354 m_frame->GetCanvas()->Refresh();
1355}
1356
1357
1359{
1360 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1361
1362 if( m_isFpEditor )
1363 {
1364 for( PCB_LAYER_ID layer : LSET::AllLayersMask().Seq() )
1365 view->SetLayerVisible( layer, aLayers.Contains( layer ) );
1366 }
1367 else if( BOARD* board = m_frame->GetBoard() )
1368 {
1369 board->SetVisibleLayers( aLayers );
1370
1371 // Note: KIGFX::REPAINT isn't enough for things that go from invisible to visible as
1372 // they won't be found in the view layer's itemset for repainting.
1374 []( KIGFX::VIEW_ITEM* aItem ) -> bool
1375 {
1376 // Items rendered to composite layers (such as LAYER_PAD_TH) must be redrawn
1377 // whether they're optionally flashed or not (as the layer being hidden/shown
1378 // might be the last layer the item is visible on).
1379 return dynamic_cast<PCB_VIA*>( aItem ) || dynamic_cast<PAD*>( aItem );
1380 } );
1381
1382 m_frame->Update3DView( true, m_frame->GetPcbNewSettings()->m_Display.m_Live3DRefresh );
1383 }
1384}
1385
1386
1388{
1389 // This used to be used for disabling some layers in the footprint editor, but
1390 // now all layers are enabled in the footprint editor.
1391 // But this function is the place to add logic if you do need to grey out a layer
1392 // from the appearance panel for some reason.
1393 return true;
1394}
1395
1396
1398{
1399 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1400
1401 if( m_isFpEditor )
1402 {
1403 for( size_t i = 0; i < GAL_LAYER_INDEX( LAYER_ZONE_START ); i++ )
1404 view->SetLayerVisible( GAL_LAYER_ID_START + GAL_LAYER_ID( i ), aLayers.test( i ) );
1405 }
1406 else
1407 {
1408 // Ratsnest visibility is controlled by the ratsnest option, and not by the preset
1409 if( m_frame->IsType( FRAME_PCB_EDITOR ) )
1410 aLayers.set( LAYER_RATSNEST, m_frame->GetPcbNewSettings()->m_Display.m_ShowGlobalRatsnest );
1411
1412 BOARD* board = m_frame->GetBoard();
1413
1414 if( !board )
1415 return;
1416
1417 m_frame->SetGridVisibility( aLayers.test( LAYER_GRID - GAL_LAYER_ID_START ) );
1418 board->SetVisibleElements( aLayers );
1419
1420 // Update VIEW layer visibility to stay in sync with board settings
1421 for( size_t i = 0; i < GAL_LAYER_INDEX( LAYER_ZONE_START ) && i < aLayers.size(); i++ )
1422 {
1423 // Warning: all GAL layers are not handled by the apparence panel (i.e. LAYER_SELECT_OVERLAY)
1424 // but only some, only set visiblity if the layer is handled by the APPEARANCE_CONTROLS
1426
1427 if( gal_ly == LAYER_RATSNEST )
1428 continue;
1429
1430 for( const APPEARANCE_SETTING& s_setting : s_objectSettings )
1431 {
1432 // See if this gal layer is handled
1433 if( s_setting.id == gal_ly )
1434 {
1435 view->SetLayerVisible( gal_ly, aLayers.test( i ) );
1436 break;
1437 }
1438 }
1439 }
1440
1441 m_frame->Update3DView( true, m_frame->GetPcbNewSettings()->m_Display.m_Live3DRefresh );
1442 }
1443}
1444
1445
1447{
1448 if( m_isFpEditor )
1449 {
1450 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1451 LSET set;
1452
1453 for( PCB_LAYER_ID layer : LSET::AllLayersMask().Seq() )
1454 set.set( layer, view->IsLayerVisible( layer ) );
1455
1456 return set;
1457 }
1458 else if( BOARD* board = m_frame->GetBoard() )
1459 {
1460 return board->GetVisibleLayers();
1461 }
1462
1463 return LSET();
1464}
1465
1466
1468{
1469 if( m_isFpEditor )
1470 {
1471 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1472 GAL_SET set;
1473 set.reset();
1474
1475 for( size_t i = 0; i < set.size(); i++ )
1476 set.set( i, view->IsLayerVisible( GAL_LAYER_ID_START + GAL_LAYER_ID( i ) ) );
1477
1478 return set;
1479 }
1480 else if( BOARD* board = m_frame->GetBoard() )
1481 {
1482 return board->GetVisibleElements();
1483 }
1484
1485 return GAL_SET();
1486}
1487
1488
1490{
1491 const PCB_DISPLAY_OPTIONS& options = m_frame->GetDisplayOptions();
1492
1493 switch( options.m_ContrastModeDisplay )
1494 {
1495 case HIGH_CONTRAST_MODE::NORMAL: m_rbHighContrastNormal->SetValue( true ); break;
1496 case HIGH_CONTRAST_MODE::DIMMED: m_rbHighContrastDim->SetValue( true ); break;
1497 case HIGH_CONTRAST_MODE::HIDDEN: m_rbHighContrastOff->SetValue( true ); break;
1498 }
1499
1500 switch( options.m_NetColorMode )
1501 {
1502 case NET_COLOR_MODE::ALL: m_rbNetColorAll->SetValue( true ); break;
1503 case NET_COLOR_MODE::RATSNEST: m_rbNetColorRatsnest->SetValue( true ); break;
1504 case NET_COLOR_MODE::OFF: m_rbNetColorOff->SetValue( true ); break;
1505 }
1506
1507 m_cbFlipBoard->SetValue( m_frame->GetDisplayOptions().m_FlipBoardView );
1508
1509 if( !m_isFpEditor )
1510 {
1511 if( PCBNEW_SETTINGS* cfg = m_frame->GetPcbNewSettings() )
1512 {
1513 if( !cfg->m_Display.m_ShowGlobalRatsnest )
1514 m_rbRatsnestNone->SetValue( true );
1515 else if( cfg->m_Display.m_RatsnestMode == RATSNEST_MODE::ALL )
1516 m_rbRatsnestAllLayers->SetValue( true );
1517 else
1518 m_rbRatsnestVisLayers->SetValue( true );
1519
1520 wxASSERT( m_objectSettingsMap.count( LAYER_RATSNEST ) );
1522 ratsnest->ctl_visibility->SetValue( cfg->m_Display.m_ShowGlobalRatsnest );
1523 }
1524 }
1525}
1526
1527
1528std::vector<LAYER_PRESET> APPEARANCE_CONTROLS::GetUserLayerPresets() const
1529{
1530 std::vector<LAYER_PRESET> ret;
1531
1532 for( const std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
1533 {
1534 if( !pair.second.readOnly )
1535 ret.emplace_back( pair.second );
1536 }
1537
1538 return ret;
1539}
1540
1541
1542void APPEARANCE_CONTROLS::SetUserLayerPresets( std::vector<LAYER_PRESET>& aPresetList )
1543{
1544 // Reset to defaults
1546
1547 for( const LAYER_PRESET& preset : aPresetList )
1548 {
1549 if( m_layerPresets.count( preset.name ) )
1550 continue;
1551
1552 m_layerPresets[preset.name] = preset;
1553
1554 m_presetMRU.Add( preset.name );
1555 }
1556
1558}
1559
1560
1562{
1563 m_layerPresets.clear();
1564
1565 // Load the read-only defaults
1566 for( const LAYER_PRESET& preset : { presetAllLayers,
1572 presetBack,
1574 {
1575 m_layerPresets[preset.name] = preset;
1576 m_layerPresets[preset.name].readOnly = true;
1577 }
1578}
1579
1580
1581void APPEARANCE_CONTROLS::ApplyLayerPreset( const wxString& aPresetName )
1582{
1583 updateLayerPresetSelection( aPresetName );
1584
1585 wxCommandEvent dummy;
1587}
1588
1589
1591{
1592 if( m_layerPresets.count( aPreset.name ) )
1594 else
1595 m_currentPreset = nullptr;
1596
1598 : nullptr;
1599
1601 doApplyLayerPreset( aPreset );
1602}
1603
1604
1605std::vector<VIEWPORT> APPEARANCE_CONTROLS::GetUserViewports() const
1606{
1607 std::vector<VIEWPORT> ret;
1608
1609 for( const std::pair<const wxString, VIEWPORT>& pair : m_viewports )
1610 ret.emplace_back( pair.second );
1611
1612 return ret;
1613}
1614
1615
1616void APPEARANCE_CONTROLS::SetUserViewports( std::vector<VIEWPORT>& aViewportList )
1617{
1618 m_viewports.clear();
1619
1620 for( const VIEWPORT& viewport : aViewportList )
1621 {
1622 if( m_viewports.count( viewport.name ) )
1623 continue;
1624
1625 m_viewports[viewport.name] = viewport;
1626
1627 m_viewportMRU.Add( viewport.name );
1628 }
1629
1631}
1632
1633
1634void APPEARANCE_CONTROLS::ApplyViewport( const wxString& aViewportName )
1635{
1636 updateViewportSelection( aViewportName );
1637
1638 wxCommandEvent dummy;
1640}
1641
1642
1644{
1645 updateViewportSelection( aViewport.name );
1646 doApplyViewport( aViewport );
1647}
1648
1649
1651{
1652 BOARD* board = m_frame->GetBoard();
1653
1654 if( !board )
1655 return;
1656
1657 LSET enabled = board->GetEnabledLayers();
1658 LSET visible = getVisibleLayers();
1659
1660 COLOR_SETTINGS* theme = m_frame->GetColorSettings();
1661 COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
1662 bool readOnly = theme->IsReadOnly();
1663
1665
1666#ifdef __WXMAC__
1667 wxSizerItem* m_windowLayersSizerItem = m_panelLayersSizer->GetItem( m_windowLayers );
1668 m_windowLayersSizerItem->SetFlag( m_windowLayersSizerItem->GetFlag() & ~wxTOP );
1669#endif
1670
1671 auto appendLayer =
1672 [&]( std::unique_ptr<APPEARANCE_SETTING>& aSetting )
1673 {
1674 int layer = aSetting->id;
1675
1676 wxPanel* panel = new wxPanel( m_windowLayers, layer );
1677 wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
1678 panel->SetSizer( sizer );
1679
1680 panel->SetBackgroundColour( m_layerPanelColour );
1681
1682 aSetting->visible = visible[layer];
1683
1684 // TODO(JE) consider restyling this indicator
1685 INDICATOR_ICON* indicator = new INDICATOR_ICON( panel, *m_iconProvider,
1687
1688 COLOR_SWATCH* swatch = new COLOR_SWATCH( panel, COLOR4D::UNSPECIFIED, layer, bgColor,
1689 theme->GetColor( layer ), SWATCH_SMALL );
1690 swatch->SetToolTip( _( "Double click or middle click for color change, right click for menu" ) );
1691
1692 BITMAP_TOGGLE* btn_visible = new BITMAP_TOGGLE( panel, layer,
1695 aSetting->visible );
1696 btn_visible->SetToolTip( _( "Show or hide this layer" ) );
1697
1698 wxStaticText* label = new wxStaticText( panel, layer, aSetting->label );
1699 label->Wrap( -1 );
1700 label->SetToolTip( aSetting->tooltip );
1701
1702 sizer->AddSpacer( 1 );
1703 sizer->Add( indicator, 0, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1704 sizer->AddSpacer( 5 );
1705 sizer->Add( swatch, 0, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1706 sizer->AddSpacer( 6 );
1707 sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1708 sizer->AddSpacer( 5 );
1709 sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1710
1711 m_layersOuterSizer->Add( panel, 0, wxEXPAND, 0 );
1712
1713 aSetting->ctl_panel = panel;
1714 aSetting->ctl_indicator = indicator;
1715 aSetting->ctl_visibility = btn_visible;
1716 aSetting->ctl_color = swatch;
1717 aSetting->ctl_text = label;
1718
1719 panel->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1720 indicator->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1721 swatch->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1722 label->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1723
1724 btn_visible->Bind( TOGGLE_CHANGED,
1725 [&]( wxCommandEvent& aEvent )
1726 {
1727 wxObject* btn = aEvent.GetEventObject();
1728 int layerId = static_cast<wxWindow*>( btn )->GetId();
1729
1730 onLayerVisibilityToggled( static_cast<PCB_LAYER_ID>( layerId ) );
1731 } );
1732
1733 swatch->Bind( COLOR_SWATCH_CHANGED, &APPEARANCE_CONTROLS::OnColorSwatchChanged, this );
1734 swatch->SetReadOnlyCallback( std::bind( &APPEARANCE_CONTROLS::onReadOnlySwatch, this ) );
1735 swatch->SetReadOnly( readOnly );
1736
1737 panel->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1738 indicator->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1739 swatch->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1740 btn_visible->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1741 label->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1742 };
1743
1744 auto updateLayer =
1745 [&]( std::unique_ptr<APPEARANCE_SETTING>& aSetting )
1746 {
1747 int layer = aSetting->id;
1748 aSetting->visible = visible[layer];
1749 aSetting->ctl_panel->Show();
1750 aSetting->ctl_panel->SetId( layer );
1751 aSetting->ctl_indicator->SetWindowID( layer );
1752 aSetting->ctl_color->SetWindowID( layer );
1753 aSetting->ctl_color->SetSwatchColor( theme->GetColor( layer ), false );
1754 aSetting->ctl_visibility->SetWindowID( layer );
1755 aSetting->ctl_text->SetLabelText( aSetting->label );
1756 aSetting->ctl_text->SetId( layer );
1757 aSetting->ctl_text->SetToolTip( aSetting->tooltip );
1758 };
1759
1760 // technical layers are shown in this order:
1761 // Because they are static, wxGetTranslation must be explicitly
1762 // called for tooltips.
1763 static const struct {
1764 PCB_LAYER_ID layerId;
1765 wxString tooltip;
1766 } non_cu_seq[] = {
1767 { F_Adhes, _HKI( "Adhesive on board's front" ) },
1768 { B_Adhes, _HKI( "Adhesive on board's back" ) },
1769 { F_Paste, _HKI( "Solder paste on board's front" ) },
1770 { B_Paste, _HKI( "Solder paste on board's back" ) },
1771 { F_SilkS, _HKI( "Silkscreen on board's front" ) },
1772 { B_SilkS, _HKI( "Silkscreen on board's back" ) },
1773 { F_Mask, _HKI( "Solder mask on board's front" ) },
1774 { B_Mask, _HKI( "Solder mask on board's back" ) },
1775 { Dwgs_User, _HKI( "Explanatory drawings" ) },
1776 { Cmts_User, _HKI( "Explanatory comments" ) },
1777 { Eco1_User, _HKI( "User defined meaning" ) },
1778 { Eco2_User, _HKI( "User defined meaning" ) },
1779 { Edge_Cuts, _HKI( "Board's perimeter definition" ) },
1780 { Margin, _HKI( "Board's edge setback outline" ) },
1781 { F_CrtYd, _HKI( "Footprint courtyards on board's front" ) },
1782 { B_CrtYd, _HKI( "Footprint courtyards on board's back" ) },
1783 { F_Fab, _HKI( "Footprint assembly on board's front" ) },
1784 { B_Fab, _HKI( "Footprint assembly on board's back" ) },
1785 { User_1, _HKI( "User defined layer 1" ) },
1786 { User_2, _HKI( "User defined layer 2" ) },
1787 { User_3, _HKI( "User defined layer 3" ) },
1788 { User_4, _HKI( "User defined layer 4" ) },
1789 { User_5, _HKI( "User defined layer 5" ) },
1790 { User_6, _HKI( "User defined layer 6" ) },
1791 { User_7, _HKI( "User defined layer 7" ) },
1792 { User_8, _HKI( "User defined layer 8" ) },
1793 { User_9, _HKI( "User defined layer 9" ) },
1794 { User_10, _HKI( "User defined layer 10" ) },
1795 { User_11, _HKI( "User defined layer 11" ) },
1796 { User_12, _HKI( "User defined layer 12" ) },
1797 { User_13, _HKI( "User defined layer 13" ) },
1798 { User_14, _HKI( "User defined layer 14" ) },
1799 { User_15, _HKI( "User defined layer 15" ) },
1800 { User_16, _HKI( "User defined layer 16" ) },
1801 { User_17, _HKI( "User defined layer 17" ) },
1802 { User_18, _HKI( "User defined layer 18" ) },
1803 { User_19, _HKI( "User defined layer 19" ) },
1804 { User_20, _HKI( "User defined layer 20" ) },
1805 { User_21, _HKI( "User defined layer 21" ) },
1806 { User_22, _HKI( "User defined layer 22" ) },
1807 { User_23, _HKI( "User defined layer 23" ) },
1808 { User_24, _HKI( "User defined layer 24" ) },
1809 { User_25, _HKI( "User defined layer 25" ) },
1810 { User_26, _HKI( "User defined layer 26" ) },
1811 { User_27, _HKI( "User defined layer 27" ) },
1812 { User_28, _HKI( "User defined layer 28" ) },
1813 { User_29, _HKI( "User defined layer 29" ) },
1814 { User_30, _HKI( "User defined layer 30" ) },
1815 { User_31, _HKI( "User defined layer 31" ) },
1816 { User_32, _HKI( "User defined layer 32" ) },
1817 { User_33, _HKI( "User defined layer 33" ) },
1818 { User_34, _HKI( "User defined layer 34" ) },
1819 { User_35, _HKI( "User defined layer 35" ) },
1820 { User_36, _HKI( "User defined layer 36" ) },
1821 { User_37, _HKI( "User defined layer 37" ) },
1822 { User_38, _HKI( "User defined layer 38" ) },
1823 { User_39, _HKI( "User defined layer 39" ) },
1824 { User_40, _HKI( "User defined layer 40" ) },
1825 { User_41, _HKI( "User defined layer 41" ) },
1826 { User_42, _HKI( "User defined layer 42" ) },
1827 { User_43, _HKI( "User defined layer 43" ) },
1828 { User_44, _HKI( "User defined layer 44" ) },
1829 { User_45, _HKI( "User defined layer 45" ) },
1830 };
1831
1832 // There is a spacer added to the end of the list that we need to remove and re-add
1833 // after possibly adding additional layers
1834 if( m_layersOuterSizer->GetItemCount() > 0 )
1835 {
1836 m_layersOuterSizer->Detach( m_layersOuterSizer->GetItemCount() - 1 );
1837 }
1838 // Otherwise, this is the first time we are updating the control, so we need to attach
1839 // the handler
1840 else
1841 {
1842 // Add right click handling to show the context menu when clicking to the free area in
1843 // m_windowLayers (below the layer items)
1844 m_windowLayers->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1845 }
1846
1847 std::size_t total_layers = enabled.CuStack().size();
1848
1849 for( const auto& entry : non_cu_seq )
1850 {
1851 if( enabled[entry.layerId] )
1852 total_layers++;
1853 }
1854
1855 // Adds layers to the panel until we have enough to hold our total count
1856 while( total_layers > m_layerSettings.size() )
1857 m_layerSettings.push_back( std::make_unique<APPEARANCE_SETTING>() );
1858
1859 // We never delete layers from the panel, only hide them. This saves us
1860 // having to recreate the (possibly) later with minimal overhead
1861 for( std::size_t ii = total_layers; ii < m_layerSettings.size(); ++ii )
1862 {
1863 if( m_layerSettings[ii]->ctl_panel )
1864 m_layerSettings[ii]->ctl_panel->Show( false );
1865 }
1866
1867 auto layer_it = m_layerSettings.begin();
1868
1869 // show all coppers first, with front on top, back on bottom, then technical layers
1870 for( PCB_LAYER_ID layer : enabled.CuStack() )
1871 {
1872 wxString dsc;
1873
1874 switch( layer )
1875 {
1876 case F_Cu: dsc = _( "Front copper layer" ); break;
1877 case B_Cu: dsc = _( "Back copper layer" ); break;
1878 default: dsc = _( "Inner copper layer" ); break;
1879 }
1880
1881 std::unique_ptr<APPEARANCE_SETTING>& setting = *layer_it;
1882
1883 setting->label = board->GetLayerName( layer );
1884 setting->id = layer;
1885 setting->tooltip = dsc;
1886
1887 if( setting->ctl_panel == nullptr )
1888 appendLayer( setting );
1889 else
1890 updateLayer( setting );
1891
1892 m_layerSettingsMap[layer] = setting.get();
1893
1894 if( !isLayerEnabled( layer ) )
1895 {
1896 setting->ctl_text->Disable();
1897 setting->ctl_color->SetToolTip( wxEmptyString );
1898 }
1899
1900 ++layer_it;
1901 }
1902
1903 for( const auto& entry : non_cu_seq )
1904 {
1905 PCB_LAYER_ID layer = entry.layerId;
1906
1907 if( !enabled[layer] )
1908 continue;
1909
1910 std::unique_ptr<APPEARANCE_SETTING>& setting = *layer_it;
1911
1912 if( m_isFpEditor )
1913 {
1914 wxString canonicalName = LSET::Name( static_cast<PCB_LAYER_ID>( layer ) );
1915
1916 if( cfg->m_DesignSettings.m_UserLayerNames.contains( canonicalName.ToStdString() ) )
1917 setting->label = cfg->m_DesignSettings.m_UserLayerNames[canonicalName.ToStdString()];
1918 else
1919 setting->label = board->GetStandardLayerName( layer );
1920 }
1921 else
1922 {
1923 setting->label = board->GetLayerName( layer );
1924 }
1925
1926 setting->id = layer;
1927 // Because non_cu_seq is created static, we must explicitly call wxGetTranslation for
1928 // texts which are internationalized
1929 setting->tooltip = wxGetTranslation( entry.tooltip );
1930
1931 if( setting->ctl_panel == nullptr )
1932 appendLayer( setting );
1933 else
1934 updateLayer( setting );
1935
1936 m_layerSettingsMap[layer] = setting.get();
1937
1938 if( !isLayerEnabled( layer ) )
1939 {
1940 setting->ctl_text->Disable();
1941 setting->ctl_color->SetToolTip( wxEmptyString );
1942 }
1943
1944 ++layer_it;
1945 }
1946
1947 m_layersOuterSizer->AddSpacer( 10 );
1948 m_windowLayers->SetBackgroundColour( m_layerPanelColour );
1949 m_windowLayers->FitInside(); // Updates virtual size to fit subwindows, also auto-layouts.
1950
1951 m_paneLayerDisplayOptions->SetLabel( _( "Layer Display Options" ) );
1952
1953 int hotkey = PCB_ACTIONS::highContrastModeCycle.GetHotKey();
1954 wxString msg;
1955
1956 if( hotkey )
1957 msg = wxString::Format( _( "Inactive layers (%s):" ), KeyNameFromKeyCode( hotkey ) );
1958 else
1959 msg = _( "Inactive layers:" );
1960
1961 m_inactiveLayersLabel->SetLabel( msg );
1962
1963 m_rbHighContrastNormal->SetLabel( _( "Normal" ) );
1964 m_rbHighContrastNormal->SetToolTip( _( "Inactive layers will be shown in full color" ) );
1965
1966 m_rbHighContrastDim->SetLabel( _( "Dim" ) );
1967 m_rbHighContrastDim->SetToolTip( _( "Inactive layers will be dimmed" ) );
1968
1969 m_rbHighContrastOff->SetLabel( _( "Hide" ) );
1970 m_rbHighContrastOff->SetToolTip( _( "Inactive layers will be hidden" ) );
1971
1972 m_cbFlipBoard->SetLabel( _( "Flip board view" ) );
1973}
1974
1975
1977{
1978 delete m_layerContextMenu;
1979 m_layerContextMenu = new wxMenu;
1980
1981 KIUI::AddMenuItem( m_layerContextMenu, ID_SHOW_ALL_COPPER_LAYERS, _( "Show All Copper Layers" ),
1983 KIUI::AddMenuItem( m_layerContextMenu, ID_HIDE_ALL_COPPER_LAYERS, _( "Hide All Copper Layers" ),
1985
1986 m_layerContextMenu->AppendSeparator();
1987
1988 KIUI::AddMenuItem( m_layerContextMenu, ID_HIDE_ALL_BUT_ACTIVE, _( "Hide All Layers But Active" ),
1990
1991 m_layerContextMenu->AppendSeparator();
1992
1993 KIUI::AddMenuItem( m_layerContextMenu, ID_SHOW_ALL_NON_COPPER, _( "Show All Non Copper Layers" ),
1995
1996 KIUI::AddMenuItem( m_layerContextMenu, ID_HIDE_ALL_NON_COPPER, _( "Hide All Non Copper Layers" ),
1998
1999 m_layerContextMenu->AppendSeparator();
2000
2003
2006
2007 m_layerContextMenu->AppendSeparator();
2008
2009 KIUI::AddMenuItem( m_layerContextMenu, ID_PRESET_FRONT_ASSEMBLY, _( "Show Only Front Assembly Layers" ),
2011
2012 KIUI::AddMenuItem( m_layerContextMenu, ID_PRESET_FRONT, _( "Show Only Front Layers" ),
2014
2015 // Only show the internal layer option if internal layers are enabled
2016 if( m_frame->GetBoard() && m_frame->GetBoard()->GetCopperLayerCount() > 2 )
2017 {
2018 KIUI::AddMenuItem( m_layerContextMenu, ID_PRESET_INNER_COPPER, _( "Show Only Inner Layers" ),
2020 }
2021
2022 KIUI::AddMenuItem( m_layerContextMenu, ID_PRESET_BACK, _( "Show Only Back Layers" ),
2024
2025 KIUI::AddMenuItem( m_layerContextMenu, ID_PRESET_BACK_ASSEMBLY, _( "Show Only Back Assembly Layers" ),
2027}
2028
2029
2030void APPEARANCE_CONTROLS::OnLayerContextMenu( wxCommandEvent& aEvent )
2031{
2032 BOARD* board = m_frame->GetBoard();
2033
2034 if( !board )
2035 return;
2036
2037 LSET visible = getVisibleLayers();
2038
2039 PCB_LAYER_ID current = m_frame->GetActiveLayer();
2040
2041 // The new preset. We keep the visibility state of objects:
2042 LAYER_PRESET preset;
2044 preset.flipBoard = m_frame->GetDisplayOptions().m_FlipBoardView;
2045
2046 switch( aEvent.GetId() )
2047 {
2049 preset.layers = presetNoLayers.layers;
2050 ApplyLayerPreset( preset );
2051 return;
2052
2054 preset.layers = presetAllLayers.layers;
2055 ApplyLayerPreset( preset );
2056 return;
2057
2059 visible |= presetAllCopper.layers;
2060 setVisibleLayers( visible );
2061 break;
2062
2064 preset.layers = presetNoLayers.layers | LSET( { current } );
2065 ApplyLayerPreset( preset );
2066 break;
2067
2069 visible &= ~presetAllCopper.layers;
2070
2071 if( !visible.test( current ) && visible.count() > 0 )
2072 m_frame->SetActiveLayer( *visible.Seq().begin() );
2073
2074 setVisibleLayers( visible );
2075 break;
2076
2078 visible &= presetAllCopper.layers;
2079
2080 if( !visible.test( current ) && visible.count() > 0 )
2081 m_frame->SetActiveLayer( *visible.Seq().begin() );
2082
2083 setVisibleLayers( visible );
2084 break;
2085
2087 visible |= ~presetAllCopper.layers;
2088
2089 setVisibleLayers( visible );
2090 break;
2091
2093 preset.layers = presetFrontAssembly.layers;
2094 ApplyLayerPreset( preset );
2095 return;
2096
2097 case ID_PRESET_FRONT:
2098 preset.layers = presetFront.layers;
2099 ApplyLayerPreset( preset );
2100 return;
2101
2103 preset.layers = presetInnerCopper.layers;
2104 ApplyLayerPreset( preset );
2105 return;
2106
2107 case ID_PRESET_BACK:
2108 preset.layers = presetBack.layers;
2109 ApplyLayerPreset( preset );
2110 return;
2111
2113 preset.layers = presetBackAssembly.layers;
2114 ApplyLayerPreset( preset );
2115 return;
2116 }
2117
2120
2121 if( !m_isFpEditor )
2122 m_frame->GetCanvas()->SyncLayersVisibility( board );
2123
2124 m_frame->GetCanvas()->Refresh();
2125}
2126
2127
2129{
2130 return m_notebook->GetSelection();
2131}
2132
2133
2135{
2136 size_t max = m_notebook->GetPageCount();
2137
2138 if( aTab >= 0 && static_cast<size_t>( aTab ) < max )
2139 m_notebook->SetSelection( aTab );
2140}
2141
2142
2144{
2145 COLOR_SETTINGS* theme = m_frame->GetColorSettings();
2146 bool readOnly = theme->IsReadOnly();
2147 LSET visible = getVisibleLayers();
2148 GAL_SET objects = getVisibleObjects();
2149
2150 Freeze();
2151
2152 for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_layerSettings )
2153 {
2154 int layer = setting->id;
2155
2156 if( setting->ctl_visibility )
2157 setting->ctl_visibility->SetValue( visible[layer] );
2158
2159 if( setting->ctl_color )
2160 {
2161 const COLOR4D& color = theme->GetColor( layer );
2162 setting->ctl_color->SetSwatchColor( color, false );
2163 setting->ctl_color->SetReadOnly( readOnly );
2164 }
2165 }
2166
2167 for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
2168 {
2169 GAL_LAYER_ID layer = static_cast<GAL_LAYER_ID>( setting->id );
2170
2171 if( setting->ctl_visibility )
2172 setting->ctl_visibility->SetValue( objects.Contains( layer ) );
2173
2174 if( setting->ctl_color )
2175 {
2176 const COLOR4D& color = theme->GetColor( layer );
2177 setting->ctl_color->SetSwatchColor( color, false );
2178 setting->ctl_color->SetReadOnly( readOnly );
2179 }
2180 }
2181
2182 // Update indicators and panel background colors
2184
2185 Thaw();
2186
2187 m_windowLayers->Refresh();
2188}
2189
2190
2191void APPEARANCE_CONTROLS::onLayerLeftClick( wxMouseEvent& aEvent )
2192{
2193 wxWindow* eventSource = static_cast<wxWindow*>( aEvent.GetEventObject() );
2194
2195 PCB_LAYER_ID layer = ToLAYER_ID( eventSource->GetId() );
2196
2197 if( !isLayerEnabled( layer ) )
2198 return;
2199
2200 m_frame->SetActiveLayer( layer );
2201 passOnFocus();
2202}
2203
2204
2205void APPEARANCE_CONTROLS::rightClickHandler( wxMouseEvent& aEvent )
2206{
2207 wxASSERT( m_layerContextMenu );
2208 PopupMenu( m_layerContextMenu );
2209 passOnFocus();
2210};
2211
2212
2214{
2215 LSET visibleLayers = getVisibleLayers();
2216
2217 visibleLayers.set( aLayer, !visibleLayers.test( aLayer ) );
2218 setVisibleLayers( visibleLayers );
2219 m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, visibleLayers.test( aLayer ) );
2220
2222 m_frame->GetCanvas()->Refresh();
2223}
2224
2225
2226void APPEARANCE_CONTROLS::onObjectVisibilityChanged( GAL_LAYER_ID aLayer, bool isVisible, bool isFinal )
2227{
2228 // Special-case controls
2229 switch( aLayer )
2230 {
2231 case LAYER_RATSNEST:
2232 {
2233 // don't touch the layers. ratsnest is enabled on per-item basis.
2234 m_frame->GetCanvas()->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
2235 m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, true );
2236
2237 if( m_frame->IsType( FRAME_PCB_EDITOR ) )
2238 {
2239 m_frame->GetPcbNewSettings()->m_Display.m_ShowGlobalRatsnest = isVisible;
2240
2241 if( m_frame->GetBoard() )
2242 m_frame->GetBoard()->SetElementVisibility( aLayer, isVisible );
2243
2244 m_frame->OnDisplayOptionsChanged();
2245 m_frame->GetCanvas()->RedrawRatsnest();
2246 }
2247
2248 break;
2249 }
2250
2251 case LAYER_GRID:
2252 m_frame->SetGridVisibility( isVisible );
2253 m_frame->GetCanvas()->Refresh();
2255 break;
2256
2257 case LAYER_FP_TEXT:
2258 // Because Footprint Text is a meta-control that also can disable values/references,
2259 // drag them along here so that the user is less likely to be confused.
2260 if( isFinal )
2261 {
2262 // Should only trigger when you actually click the Footprint Text button
2263 // Otherwise it goes into infinite recursive loop with the following case section
2265 onObjectVisibilityChanged( LAYER_FP_VALUES, isVisible, false );
2266 m_objectSettingsMap[LAYER_FP_REFERENCES]->ctl_visibility->SetValue( isVisible );
2267 m_objectSettingsMap[LAYER_FP_VALUES]->ctl_visibility->SetValue( isVisible );
2268 }
2269 break;
2270
2272 case LAYER_FP_VALUES:
2273 // In case that user changes Footprint Value/References when the Footprint Text
2274 // meta-control is disabled, we should put it back on.
2275 if( isVisible )
2276 {
2277 onObjectVisibilityChanged( LAYER_FP_TEXT, isVisible, false );
2278 m_objectSettingsMap[LAYER_FP_TEXT]->ctl_visibility->SetValue( isVisible );
2279 }
2280 break;
2281
2282 default:
2283 break;
2284 }
2285
2286 GAL_SET visible = getVisibleObjects();
2287
2288 if( visible.Contains( aLayer ) != isVisible )
2289 {
2290 visible.set( aLayer, isVisible );
2291 setVisibleObjects( visible );
2292 m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, isVisible );
2294 }
2295
2296 if( isFinal )
2297 {
2298 m_frame->GetCanvas()->Refresh();
2299 passOnFocus();
2300 }
2301}
2302
2303
2305{
2306 COLOR_SETTINGS* theme = m_frame->GetColorSettings();
2307 COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
2308 GAL_SET visible = getVisibleObjects();
2309 int swatchWidth = m_windowObjects->ConvertDialogToPixels( wxSize( 8, 0 ) ).x;
2310 int labelWidth = 0;
2311
2312 int btnWidth = m_visibleBitmapBundle.GetPreferredLogicalSizeFor( m_windowObjects ).x;
2313
2314 m_objectSettings.clear();
2315 m_objectsOuterSizer->Clear( true );
2316 m_objectsOuterSizer->AddSpacer( 5 );
2317
2318 auto appendObject =
2319 [&]( const std::unique_ptr<APPEARANCE_SETTING>& aSetting )
2320 {
2321 wxPanel* panel = new wxPanel( m_windowObjects, wxID_ANY );
2322 wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
2323 panel->SetSizer( sizer );
2324 int layer = aSetting->id;
2325
2326 aSetting->visible = visible.Contains( ToGalLayer( layer ) );
2327 COLOR4D color = theme->GetColor( layer );
2328 COLOR4D defColor = theme->GetDefaultColor( layer );
2329
2330 if( color != COLOR4D::UNSPECIFIED || defColor != COLOR4D::UNSPECIFIED )
2331 {
2332 COLOR_SWATCH* swatch = new COLOR_SWATCH( panel, color, layer,
2333 bgColor, defColor, SWATCH_SMALL );
2334 swatch->SetToolTip( _( "Left double click or middle click for color change, "
2335 "right click for menu" ) );
2336
2337 sizer->Add( swatch, 0, wxALIGN_CENTER_VERTICAL, 0 );
2338 aSetting->ctl_color = swatch;
2339
2340 swatch->Bind( COLOR_SWATCH_CHANGED, &APPEARANCE_CONTROLS::OnColorSwatchChanged, this );
2341
2342 swatch->SetReadOnlyCallback( std::bind( &APPEARANCE_CONTROLS::onReadOnlySwatch, this ) );
2343 }
2344 else
2345 {
2346 sizer->AddSpacer( swatchWidth );
2347 }
2348
2349 BITMAP_TOGGLE* btn_visible = nullptr;
2350 wxString tip;
2351
2352 if( aSetting->can_control_visibility )
2353 {
2354 btn_visible = new BITMAP_TOGGLE( panel, layer,
2357 aSetting->visible );
2358
2359 tip.Printf( _( "Show or hide %s" ), aSetting->label.Lower() );
2360 btn_visible->SetToolTip( tip );
2361
2362 aSetting->ctl_visibility = btn_visible;
2363
2364 btn_visible->Bind( TOGGLE_CHANGED,
2365 [&]( wxCommandEvent& aEvent )
2366 {
2367 int id = static_cast<wxWindow*>( aEvent.GetEventObject() )->GetId();
2368 bool isVisible = aEvent.GetInt();
2369 onObjectVisibilityChanged( ToGalLayer( id ), isVisible, true );
2370 } );
2371 }
2372
2373 sizer->AddSpacer( 5 );
2374
2375 wxStaticText* label = new wxStaticText( panel, layer, aSetting->label );
2376 label->Wrap( -1 );
2377 label->SetToolTip( aSetting->tooltip );
2378
2379 if( aSetting->can_control_opacity )
2380 {
2381 label->SetMinSize( wxSize( labelWidth, -1 ) );
2382#ifdef __WXMAC__
2383 if( btn_visible )
2384 sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, 10 );
2385 else
2386 sizer->AddSpacer( btnWidth );
2387
2388 sizer->AddSpacer( 5 );
2389 sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, 10 );
2390#else
2391 if( btn_visible )
2392 sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL, 0 );
2393 else
2394 sizer->AddSpacer( btnWidth );
2395
2396 sizer->AddSpacer( 5 );
2397 sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL, 0 );
2398#endif
2399
2400 wxSlider* slider = new wxSlider( panel, wxID_ANY, 100, 0, 100,
2401 wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL );
2402#ifdef __WXMAC__
2403 slider->SetMinSize( wxSize( 80, 16 ) );
2404#else
2405 slider->SetMinSize( wxSize( 80, -1 ) );
2406#endif
2407
2408 tip.Printf( _( "Set opacity of %s" ), aSetting->label.Lower() );
2409 slider->SetToolTip( tip );
2410
2411 sizer->Add( slider, 1, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 5 );
2412 aSetting->ctl_opacity = slider;
2413
2414 auto opacitySliderHandler =
2415 [this, layer]( wxCommandEvent& aEvent )
2416 {
2417 wxSlider* ctrl = static_cast<wxSlider*>( aEvent.GetEventObject() );
2418 int value = ctrl->GetValue();
2419 onObjectOpacitySlider( layer, value / 100.0f );
2420 };
2421
2422 slider->Bind( wxEVT_SCROLL_CHANGED, opacitySliderHandler );
2423 slider->Bind( wxEVT_SCROLL_THUMBTRACK, opacitySliderHandler );
2424 slider->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS::OnSetFocus, this );
2425 }
2426 else
2427 {
2428 if( btn_visible )
2429 sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL, 0 );
2430 else
2431 sizer->AddSpacer( btnWidth );
2432
2433 sizer->AddSpacer( 5 );
2434 sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL, 0 );
2435 }
2436
2437 aSetting->ctl_text = label;
2438 m_objectsOuterSizer->Add( panel, 0, wxEXPAND | wxLEFT | wxRIGHT, 5 );
2439
2440 if( !aSetting->can_control_opacity )
2441 m_objectsOuterSizer->AddSpacer( 2 );
2442 };
2443
2444 for( const APPEARANCE_SETTING& s_setting : s_objectSettings )
2445 {
2446 if( m_isFpEditor && !s_allowedInFpEditor.count( s_setting.id ) )
2447 continue;
2448
2449 m_objectSettings.emplace_back( std::make_unique<APPEARANCE_SETTING>( s_setting ) );
2450
2451 std::unique_ptr<APPEARANCE_SETTING>& setting = m_objectSettings.back();
2452
2453 // Because s_render_rows is created static, we must explicitly call wxGetTranslation
2454 // for texts which are internationalized (tool tips and item names)
2455 setting->tooltip = wxGetTranslation( s_setting.tooltip );
2456 setting->label = wxGetTranslation( s_setting.label );
2457
2458 if( setting->can_control_opacity )
2459 {
2460 int width = m_windowObjects->GetTextExtent( setting->label ).x + 5;
2461 labelWidth = std::max( labelWidth, width );
2462 }
2463
2464 if( !s_setting.spacer )
2465 m_objectSettingsMap[ToGalLayer( setting->id )] = setting.get();
2466 }
2467
2468 for( const std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
2469 {
2470 if( setting->spacer )
2471 m_objectsOuterSizer->AddSpacer( m_pointSize / 2 );
2472 else
2473 appendObject( setting );
2474 }
2475
2476 m_objectsOuterSizer->Layout();
2477 m_windowObjects->FitInside();
2478}
2479
2480
2482{
2483 GAL_SET visible = getVisibleObjects();
2484
2485 const PCB_DISPLAY_OPTIONS& opts = m_frame->GetDisplayOptions();
2486
2487 for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
2488 {
2489 if( setting->spacer )
2490 continue;
2491
2492 GAL_LAYER_ID layer = ToGalLayer( setting->id );
2493
2494 if( setting->ctl_visibility )
2495 setting->ctl_visibility->SetValue( visible.Contains( layer ) );
2496
2497 if( setting->ctl_color )
2498 {
2499 COLOR4D color = m_frame->GetColorSettings()->GetColor( setting->id );
2500 setting->ctl_color->SetSwatchColor( color, false );
2501 }
2502 }
2503
2504 wxASSERT( m_objectSettingsMap.count( LAYER_TRACKS )
2510
2511 m_objectSettingsMap[LAYER_TRACKS]->ctl_opacity->SetValue( opts.m_TrackOpacity * 100 );
2512 m_objectSettingsMap[LAYER_VIAS]->ctl_opacity->SetValue( opts.m_ViaOpacity * 100 );
2513 m_objectSettingsMap[LAYER_PADS]->ctl_opacity->SetValue( opts.m_PadOpacity * 100 );
2514 m_objectSettingsMap[LAYER_ZONES]->ctl_opacity->SetValue( opts.m_ZoneOpacity * 100 );
2515 m_objectSettingsMap[LAYER_DRAW_BITMAPS]->ctl_opacity->SetValue( opts.m_ImageOpacity * 100 );
2516 m_objectSettingsMap[LAYER_FILLED_SHAPES]->ctl_opacity->SetValue( opts.m_FilledShapeOpacity * 100 );
2517}
2518
2519
2520void APPEARANCE_CONTROLS::buildNetClassMenu( wxMenu& aMenu, bool isDefaultClass,
2521 const wxString& aName )
2522{
2523 BOARD* board = m_frame->GetBoard();
2524
2525 if( !board )
2526 return;
2527
2528 std::shared_ptr<NET_SETTINGS>& netSettings = board->GetDesignSettings().m_NetSettings;
2529
2530 if( !isDefaultClass)
2531 {
2532 aMenu.Append( new wxMenuItem( &aMenu, ID_SET_NET_COLOR, _( "Set Netclass Color" ),
2533 wxEmptyString, wxITEM_NORMAL ) );
2534
2535 wxMenuItem* schematicColor = new wxMenuItem( &aMenu, ID_USE_SCHEMATIC_NET_COLOR,
2536 _( "Use Color from Schematic" ),
2537 wxEmptyString, wxITEM_NORMAL );
2538 std::shared_ptr<NETCLASS> nc = netSettings->GetNetClassByName( aName );
2539 const KIGFX::COLOR4D ncColor = nc->GetSchematicColor();
2540 aMenu.Append( schematicColor );
2541
2542 if( ncColor == KIGFX::COLOR4D::UNSPECIFIED )
2543 schematicColor->Enable( false );
2544
2545 aMenu.Append( new wxMenuItem( &aMenu, ID_CLEAR_NET_COLOR, _( "Clear Netclass Color" ),
2546 wxEmptyString, wxITEM_NORMAL ) );
2547 aMenu.AppendSeparator();
2548 }
2549
2550 wxString name = UnescapeString( aName );
2551
2552 aMenu.Append( new wxMenuItem( &aMenu, ID_HIGHLIGHT_NET,
2553 wxString::Format( _( "Highlight Nets in %s" ), name ),
2554 wxEmptyString, wxITEM_NORMAL ) );
2555 aMenu.Append( new wxMenuItem( &aMenu, ID_SELECT_NET,
2556 wxString::Format( _( "Select Tracks and Vias in %s" ), name ),
2557 wxEmptyString, wxITEM_NORMAL ) );
2558 aMenu.Append( new wxMenuItem( &aMenu, ID_DESELECT_NET,
2559 wxString::Format( _( "Unselect Tracks and Vias in %s" ), name ),
2560 wxEmptyString, wxITEM_NORMAL ) );
2561
2562 aMenu.AppendSeparator();
2563
2564 aMenu.Append( new wxMenuItem( &aMenu, ID_SHOW_ALL_NETS, _( "Show All Netclasses" ),
2565 wxEmptyString, wxITEM_NORMAL ) );
2566 aMenu.Append( new wxMenuItem( &aMenu, ID_HIDE_OTHER_NETS, _( "Hide All Other Netclasses" ),
2567 wxEmptyString, wxITEM_NORMAL ) );
2568
2569 aMenu.Bind( wxEVT_COMMAND_MENU_SELECTED, &APPEARANCE_CONTROLS::onNetclassContextMenu, this );
2570
2571}
2572
2573
2575{
2576 BOARD* board = m_frame->GetBoard();
2577
2578 if( !board || !board->GetProject() )
2579 return;
2580
2581 COLOR_SETTINGS* theme = m_frame->GetColorSettings();
2582 COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
2583
2584 m_staticTextNets->SetLabel( _( "Nets" ) );
2585 m_staticTextNetClasses->SetLabel( _( "Net Classes" ) );
2586
2587 std::shared_ptr<NET_SETTINGS>& netSettings = board->GetDesignSettings().m_NetSettings;
2588
2589 const std::set<wxString>& hiddenClasses = m_frame->Prj().GetLocalSettings().m_HiddenNetclasses;
2590
2591 m_netclassSettings.clear();
2592 m_netclassSettingsMap.clear();
2593 m_netclassOuterSizer->Clear( true );
2594
2595 auto appendNetclass =
2596 [&]( int aId, const std::shared_ptr<NETCLASS>& aClass, bool isDefaultClass = false )
2597 {
2598 wxString name = aClass->GetName();
2599
2600 m_netclassSettings.emplace_back( std::make_unique<APPEARANCE_SETTING>() );
2601 APPEARANCE_SETTING* setting = m_netclassSettings.back().get();
2602 m_netclassSettingsMap[name] = setting;
2603
2604 setting->ctl_panel = new wxPanel( m_netclassScrolledWindow, aId );
2605 wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
2606 setting->ctl_panel->SetSizer( sizer );
2607
2608 COLOR4D color = netSettings->HasNetclass( name )
2609 ? netSettings->GetNetClassByName( name )->GetPcbColor()
2611
2612 setting->ctl_color = new COLOR_SWATCH( setting->ctl_panel, color, aId, bgColor,
2614 setting->ctl_color->SetToolTip( _( "Left double click or middle click for color "
2615 "change, right click for menu" ) );
2616
2617 setting->ctl_color->Bind( COLOR_SWATCH_CHANGED,
2619
2620 // Default netclass can't have an override color
2621 if( isDefaultClass )
2622 setting->ctl_color->Hide();
2623
2624 setting->ctl_visibility = new BITMAP_TOGGLE( setting->ctl_panel, aId,
2627 !hiddenClasses.count( name ) );
2628
2629 wxString tip;
2630 tip.Printf( _( "Show or hide ratsnest for nets in %s" ), name );
2631 setting->ctl_visibility->SetToolTip( tip );
2632
2633 setting->ctl_text = new wxStaticText( setting->ctl_panel, aId, name );
2634 setting->ctl_text->Wrap( -1 );
2635
2636 int flags = wxALIGN_CENTER_VERTICAL;
2637
2638 sizer->Add( setting->ctl_color, 0, flags | wxRESERVE_SPACE_EVEN_IF_HIDDEN, 5 );
2639 sizer->AddSpacer( 7 );
2640 sizer->Add( setting->ctl_visibility, 0, flags, 5 );
2641 sizer->AddSpacer( 3 );
2642 sizer->Add( setting->ctl_text, 1, flags, 5 );
2643
2644 m_netclassOuterSizer->Add( setting->ctl_panel, 0, wxEXPAND, 5 );
2645 m_netclassOuterSizer->AddSpacer( 2 );
2646
2647 setting->ctl_visibility->Bind( TOGGLE_CHANGED,
2649 this );
2650
2651 auto menuHandler =
2652 [&, name, isDefaultClass]( wxMouseEvent& aEvent )
2653 {
2654 wxMenu menu;
2655 buildNetClassMenu( menu, isDefaultClass, name );
2656
2658 PopupMenu( &menu );
2659 };
2660
2661 setting->ctl_panel->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2662 setting->ctl_visibility->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2663 setting->ctl_color->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2664 setting->ctl_text->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2665 };
2666
2667 std::vector<wxString> names;
2668
2669 for( const auto& [name, netclass] : netSettings->GetNetclasses() )
2670 names.emplace_back( name );
2671
2672 std::sort( names.begin(), names.end() );
2673
2674 m_netclassIdMap.clear();
2675
2676 int idx = wxID_HIGHEST;
2677
2678 m_netclassIdMap[idx] = netSettings->GetDefaultNetclass()->GetName();
2679 appendNetclass( idx++, netSettings->GetDefaultNetclass(), true );
2680
2681 for( const wxString& name : names )
2682 {
2683 m_netclassIdMap[idx] = name;
2684 appendNetclass( idx++, netSettings->GetNetclasses().at( name ) );
2685 }
2686
2687 int hotkey;
2688 wxString msg;
2689
2690 m_paneNetDisplayOptions->SetLabel( _( "Net Display Options" ) );
2691
2692 hotkey = PCB_ACTIONS::netColorModeCycle.GetHotKey();
2693
2694 if( hotkey )
2695 msg = wxString::Format( _( "Net colors (%s):" ), KeyNameFromKeyCode( hotkey ) );
2696 else
2697 msg = _( "Net colors:" );
2698
2699 m_txtNetDisplayTitle->SetLabel( msg );
2700 m_txtNetDisplayTitle->SetToolTip( _( "Choose when to show net and netclass colors" ) );
2701
2702 m_rbNetColorAll->SetLabel( _( "All" ) );
2703 m_rbNetColorAll->SetToolTip( _( "Net and netclass colors are shown on all copper items" ) );
2704
2705 m_rbNetColorRatsnest->SetLabel( _( "Ratsnest" ) );
2706 m_rbNetColorRatsnest->SetToolTip( _( "Net and netclass colors are shown on the ratsnest only" ) );
2707
2708 m_rbNetColorOff->SetLabel( _( "None" ) );
2709 m_rbNetColorOff->SetToolTip( _( "Net and netclass colors are not shown" ) );
2710
2711 hotkey = PCB_ACTIONS::ratsnestModeCycle.GetHotKey();
2712
2713 if( hotkey )
2714 msg = wxString::Format( _( "Ratsnest display (%s):" ), KeyNameFromKeyCode( hotkey ) );
2715 else
2716 msg = _( "Ratsnest display:" );
2717
2718 m_txtRatsnestVisibility->SetLabel( msg );
2719 m_txtRatsnestVisibility->SetToolTip( _( "Choose which ratsnest lines to display" ) );
2720
2721 m_rbRatsnestAllLayers->SetLabel( _( "All" ) );
2722 m_rbRatsnestAllLayers->SetToolTip( _( "Show ratsnest lines to items on all layers" ) );
2723
2724 m_rbRatsnestVisLayers->SetLabel( _( "Visible layers" ) );
2725 m_rbRatsnestVisLayers->SetToolTip( _( "Show ratsnest lines to items on visible layers" ) );
2726
2727 m_rbRatsnestNone->SetLabel( _( "None" ) );
2728 m_rbRatsnestNone->SetToolTip( _( "Hide all ratsnest lines" ) );
2729
2730 m_netclassOuterSizer->Layout();
2731
2732 m_netsTable->Rebuild();
2733 m_panelNets->GetSizer()->Layout();
2734}
2735
2736
2738{
2739 m_presetsLabel->SetLabel( wxString::Format( _( "Presets (%s+Tab):" ), KeyNameFromKeyCode( PRESET_SWITCH_KEY ) ) );
2740
2741 m_cbLayerPresets->Clear();
2742
2743 if( aReset )
2744 m_presetMRU.clear();
2745
2746 // Build the layers preset list.
2747 // By default, the presetAllLayers will be selected
2748 int idx = 0;
2749 int default_idx = 0;
2750 std::vector<std::pair<wxString, void*>> userPresets;
2751
2752 // m_layerPresets is alphabetical: m_presetMRU should also be alphabetical, but m_cbLayerPresets
2753 // is split into build-in and user sections.
2754 for( auto& [name, preset] : m_layerPresets )
2755 {
2756 const wxString translatedName = wxGetTranslation( name );
2757 void* userData = static_cast<void*>( &preset );
2758
2759 if( preset.readOnly )
2760 m_cbLayerPresets->Append( translatedName, userData );
2761 else
2762 userPresets.push_back( { name, userData } );
2763
2764 if( aReset )
2765 m_presetMRU.push_back( translatedName );
2766
2767 if( name == presetAllLayers.name )
2768 default_idx = idx;
2769
2770 idx++;
2771 }
2772
2773 if( !userPresets.empty() )
2774 {
2775 m_cbLayerPresets->Append( wxT( "---" ) );
2776
2777 for( auto& [name, userData] : userPresets )
2778 m_cbLayerPresets->Append( name, userData );
2779 }
2780
2781 m_cbLayerPresets->Append( wxT( "---" ) );
2782 m_cbLayerPresets->Append( _( "Save preset..." ) );
2783 m_cbLayerPresets->Append( _( "Delete preset..." ) );
2784
2785 // At least the built-in presets should always be present
2786 wxASSERT( !m_layerPresets.empty() );
2787
2788 if( aReset )
2789 {
2790 // Default preset: all layers
2791 m_cbLayerPresets->SetSelection( default_idx );
2793 }
2794}
2795
2796
2798{
2799 LSET visibleLayers = getVisibleLayers();
2800 GAL_SET visibleObjects = getVisibleObjects();
2801 bool flipBoard = m_cbFlipBoard->GetValue();
2802
2803 auto it = std::find_if( m_layerPresets.begin(), m_layerPresets.end(),
2804 [&]( const std::pair<const wxString, LAYER_PRESET>& aPair )
2805 {
2806 // see onLayerPresetChanged logic for built-in presets
2807 const GAL_SET& presetObjects = aPair.second.readOnly
2808 ? m_lastBuiltinPreset.renderLayers
2809 : aPair.second.renderLayers;
2810
2811 return ( aPair.second.layers == visibleLayers
2812 && presetObjects == visibleObjects
2813 && aPair.second.flipBoard == flipBoard );
2814 } );
2815
2816 if( it != m_layerPresets.end() )
2817 {
2818 // Select the right m_cbLayersPresets item.
2819 // but these items are translated if they are predefined items.
2820 bool do_translate = it->second.readOnly;
2821 wxString text = do_translate ? wxGetTranslation( it->first ) : it->first;
2822
2823 m_cbLayerPresets->SetStringSelection( text );
2824 }
2825 else
2826 {
2827 m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator
2828 }
2829
2830 m_currentPreset = static_cast<LAYER_PRESET*>( m_cbLayerPresets->GetClientData( m_cbLayerPresets->GetSelection() ) );
2831}
2832
2833
2835{
2836 // look at m_layerPresets to know if aName is a read only preset, or a user preset.
2837 // Read only presets have translated names in UI, so we have to use
2838 // a translated name in UI selection.
2839 // But for a user preset name we should search for aName (not translated)
2840 wxString ui_label = aName;
2841
2842 for( std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
2843 {
2844 if( pair.first != aName )
2845 continue;
2846
2847 if( pair.second.readOnly == true )
2848 ui_label = wxGetTranslation( aName );
2849
2850 break;
2851 }
2852
2853 int idx = m_cbLayerPresets->FindString( ui_label );
2854
2855 if( idx >= 0 && m_cbLayerPresets->GetSelection() != idx )
2856 {
2857 m_cbLayerPresets->SetSelection( idx );
2858 m_currentPreset = static_cast<LAYER_PRESET*>( m_cbLayerPresets->GetClientData( idx ) );
2859 }
2860 else if( idx < 0 )
2861 {
2862 m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator
2863 }
2864}
2865
2866
2867void APPEARANCE_CONTROLS::onLayerPresetChanged( wxCommandEvent& aEvent )
2868{
2869 int count = m_cbLayerPresets->GetCount();
2870 int index = m_cbLayerPresets->GetSelection();
2871
2872 auto resetSelection =
2873 [&]()
2874 {
2875 if( m_currentPreset )
2876 m_cbLayerPresets->SetStringSelection( m_currentPreset->name );
2877 else
2878 m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 );
2879 };
2880
2881 if( index == count - 2 )
2882 {
2883 // Save current state to new preset
2884 wxString name;
2885
2888
2889 wxTextEntryDialog dlg( wxGetTopLevelParent( this ), _( "Layer preset name:" ),
2890 _( "Save Layer Preset" ), name );
2891
2892 if( dlg.ShowModal() != wxID_OK )
2893 {
2894 resetSelection();
2895 return;
2896 }
2897
2898 name = dlg.GetValue();
2899 bool exists = m_layerPresets.count( name );
2900
2901 if( !exists )
2902 {
2904 UNSELECTED_LAYER, m_cbFlipBoard->GetValue() );
2905 }
2906
2907 LAYER_PRESET* preset = &m_layerPresets[name];
2908
2909 if( !exists )
2910 {
2912 index = m_cbLayerPresets->FindString( name );
2913 }
2914 else if( preset->readOnly )
2915 {
2916 wxMessageBox( _( "Default presets cannot be modified.\nPlease use a different name." ),
2917 _( "Error" ), wxOK | wxICON_ERROR, wxGetTopLevelParent( this ) );
2918 resetSelection();
2919 return;
2920 }
2921 else
2922 {
2923 // Ask the user if they want to overwrite the existing preset
2924 if( !IsOK( wxGetTopLevelParent( this ), _( "Overwrite existing preset?" ) ) )
2925 {
2926 resetSelection();
2927 return;
2928 }
2929
2930 preset->layers = getVisibleLayers();
2931 preset->renderLayers = getVisibleObjects();
2932 preset->flipBoard = m_cbFlipBoard->GetValue();
2933
2934 index = m_cbLayerPresets->FindString( name );
2935
2936 if( m_presetMRU.Index( name ) != wxNOT_FOUND )
2937 m_presetMRU.Remove( name );
2938 }
2939
2940 m_currentPreset = preset;
2941 m_cbLayerPresets->SetSelection( index );
2942 m_presetMRU.Insert( name, 0 );
2943
2944 return;
2945 }
2946 else if( index == count - 1 )
2947 {
2948 // Delete a preset
2949 wxArrayString headers;
2950 std::vector<wxArrayString> items;
2951
2952 headers.Add( _( "Presets" ) );
2953
2954 for( std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
2955 {
2956 if( !pair.second.readOnly )
2957 {
2958 wxArrayString item;
2959 item.Add( pair.first );
2960 items.emplace_back( item );
2961 }
2962 }
2963
2964 EDA_LIST_DIALOG dlg( m_frame, _( "Delete Preset" ), headers, items );
2965 dlg.SetListLabel( _( "Select preset:" ) );
2966
2967 if( dlg.ShowModal() == wxID_OK )
2968 {
2969 wxString presetName = dlg.GetTextSelection();
2970 int idx = m_cbLayerPresets->FindString( presetName );
2971
2972 if( idx != wxNOT_FOUND )
2973 {
2974 if( m_lastSelectedUserPreset && m_lastSelectedUserPreset->name == presetName )
2975 m_lastSelectedUserPreset = nullptr;
2976
2977 if( m_currentPreset && m_currentPreset->name == presetName )
2978 m_currentPreset = nullptr;
2979
2980 m_cbLayerPresets->Delete( idx );
2981 }
2982
2983 if( m_presetMRU.Index( presetName ) != wxNOT_FOUND )
2984 m_presetMRU.Remove( presetName );
2985 }
2986
2987 resetSelection();
2988 return;
2989 }
2990 else if( m_cbLayerPresets->GetString( index ) == wxT( "---" ) )
2991 {
2992 // Separator: reject the selection
2993 resetSelection();
2994 return;
2995 }
2996
2997 // Store the objects visibility settings if the preset is not a user preset,
2998 // to be reused when selecting a new built-in layer preset, even if a previous
2999 // user preset has changed the object visibility
3000 if( !m_currentPreset || m_currentPreset->readOnly )
3001 {
3002 m_lastBuiltinPreset.renderLayers = getVisibleObjects();
3003 }
3004
3005 LAYER_PRESET* preset = static_cast<LAYER_PRESET*>( m_cbLayerPresets->GetClientData( index ) );
3006 m_currentPreset = preset;
3007
3008 m_lastSelectedUserPreset = ( !preset || preset->readOnly ) ? nullptr : preset;
3009
3010 if( preset )
3011 {
3012 // Change board layers visibility, but do not change objects visibility
3013 LAYER_PRESET curr_layers_choice = *preset;
3014
3015 // For predefined presets that do not manage objects visibility, use
3016 // the objects visibility settings of the last used predefined preset.
3017 if( curr_layers_choice.readOnly )
3018 curr_layers_choice.renderLayers = m_lastBuiltinPreset.renderLayers;
3019
3020 doApplyLayerPreset( curr_layers_choice );
3021 }
3022
3023 if( !m_currentPreset->name.IsEmpty() )
3024 {
3025 const wxString translatedName = wxGetTranslation( m_currentPreset->name );
3026
3027 if( m_presetMRU.Index( translatedName ) != wxNOT_FOUND )
3028 m_presetMRU.Remove( translatedName );
3029
3030 m_presetMRU.Insert( translatedName, 0 );
3031 }
3032
3033 passOnFocus();
3034}
3035
3036
3038{
3039 BOARD* board = m_frame->GetBoard();
3040
3041 if( !board )
3042 return;
3043
3044 setVisibleLayers( aPreset.layers );
3046
3047 // If the preset doesn't have an explicit active layer to restore, we can at least
3048 // force the active layer to be something in the preset's layer set
3049 PCB_LAYER_ID activeLayer = UNSELECTED_LAYER;
3050
3051 if( aPreset.activeLayer != UNSELECTED_LAYER )
3052 activeLayer = aPreset.activeLayer;
3053 else if( aPreset.layers.any() && !aPreset.layers.test( m_frame->GetActiveLayer() ) )
3054 activeLayer = *aPreset.layers.Seq().begin();
3055
3056 LSET boardLayers = board->GetLayerSet();
3057
3058 if( activeLayer != UNSELECTED_LAYER && boardLayers.Contains( activeLayer ) )
3059 m_frame->SetActiveLayer( activeLayer );
3060
3061 if( !m_isFpEditor )
3062 m_frame->GetCanvas()->SyncLayersVisibility( board );
3063
3064 PCB_DISPLAY_OPTIONS options = m_frame->GetDisplayOptions();
3065 options.m_FlipBoardView = aPreset.flipBoard;
3066 m_frame->SetDisplayOptions( options, false );
3067
3068 m_frame->GetCanvas()->Refresh();
3069
3072}
3073
3074
3076{
3077 m_viewportsLabel->SetLabel( wxString::Format( _( "Viewports (%s+Tab):" ),
3079
3080 m_cbViewports->Clear();
3081
3082 for( std::pair<const wxString, VIEWPORT>& pair : m_viewports )
3083 m_cbViewports->Append( pair.first, static_cast<void*>( &pair.second ) );
3084
3085 m_cbViewports->Append( wxT( "---" ) );
3086 m_cbViewports->Append( _( "Save viewport..." ) );
3087 m_cbViewports->Append( _( "Delete viewport..." ) );
3088
3089 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 );
3090 m_lastSelectedViewport = nullptr;
3091}
3092
3093
3095{
3096 int idx = m_cbViewports->FindString( aName );
3097
3098 if( idx >= 0 && idx < (int)m_cbViewports->GetCount() - 3 /* separator */ )
3099 {
3100 m_cbViewports->SetSelection( idx );
3101 m_lastSelectedViewport = static_cast<VIEWPORT*>( m_cbViewports->GetClientData( idx ) );
3102 }
3103 else if( idx < 0 )
3104 {
3105 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 ); // separator
3106 m_lastSelectedViewport = nullptr;
3107 }
3108}
3109
3110
3111void APPEARANCE_CONTROLS::onViewportChanged( wxCommandEvent& aEvent )
3112{
3113 int count = m_cbViewports->GetCount();
3114 int index = m_cbViewports->GetSelection();
3115
3116 if( index >= 0 && index < count - 3 )
3117 {
3118 VIEWPORT* viewport = static_cast<VIEWPORT*>( m_cbViewports->GetClientData( index ) );
3119
3120 wxCHECK( viewport, /* void */ );
3121
3122 doApplyViewport( *viewport );
3123
3124 if( !viewport->name.IsEmpty() )
3125 {
3126 if( m_viewportMRU.Index( viewport->name ) != wxNOT_FOUND )
3127 m_viewportMRU.Remove( viewport->name );
3128
3129 m_viewportMRU.Insert( viewport->name, 0 );
3130 }
3131 }
3132 else if( index == count - 2 )
3133 {
3134 // Save current state to new preset
3135 wxString name;
3136
3137 wxTextEntryDialog dlg( wxGetTopLevelParent( this ), _( "Viewport name:" ), _( "Save Viewport" ), name );
3138
3139 if( dlg.ShowModal() != wxID_OK )
3140 {
3142 m_cbViewports->SetStringSelection( m_lastSelectedViewport->name );
3143 else
3144 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 );
3145
3146 return;
3147 }
3148
3149 name = dlg.GetValue();
3150 bool exists = m_viewports.count( name );
3151
3152 if( !exists )
3153 {
3154 m_viewports[name] = VIEWPORT( name, m_frame->GetCanvas()->GetView()->GetViewport() );
3155
3156 index = m_cbViewports->Insert( name, index-1, static_cast<void*>( &m_viewports[name] ) );
3157 }
3158 else
3159 {
3160 m_viewports[name].rect = m_frame->GetCanvas()->GetView()->GetViewport();
3161 index = m_cbViewports->FindString( name );
3162
3163 if( m_viewportMRU.Index( name ) != wxNOT_FOUND )
3164 m_viewportMRU.Remove( name );
3165 }
3166
3167 m_cbViewports->SetSelection( index );
3168 m_viewportMRU.Insert( name, 0 );
3169
3170 return;
3171 }
3172 else if( index == count - 1 )
3173 {
3174 // Delete an existing viewport
3175 wxArrayString headers;
3176 std::vector<wxArrayString> items;
3177
3178 headers.Add( _( "Viewports" ) );
3179
3180 for( std::pair<const wxString, VIEWPORT>& pair : m_viewports )
3181 {
3182 wxArrayString item;
3183 item.Add( pair.first );
3184 items.emplace_back( item );
3185 }
3186
3187 EDA_LIST_DIALOG dlg( m_frame, _( "Delete Viewport" ), headers, items );
3188 dlg.SetListLabel( _( "Select viewport:" ) );
3189
3190 if( dlg.ShowModal() == wxID_OK )
3191 {
3192 wxString viewportName = dlg.GetTextSelection();
3193 int idx = m_cbViewports->FindString( viewportName );
3194
3195 if( idx != wxNOT_FOUND )
3196 {
3197 if( m_lastSelectedViewport && m_lastSelectedViewport->name == viewportName )
3198 m_lastSelectedViewport = nullptr;
3199
3200 m_viewports.erase( viewportName );
3201 m_cbViewports->Delete( idx );
3202 }
3203
3204 if( m_viewportMRU.Index( viewportName ) != wxNOT_FOUND )
3205 m_viewportMRU.Remove( viewportName );
3206 }
3207
3209 m_cbViewports->SetStringSelection( m_lastSelectedViewport->name );
3210 else
3211 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 );
3212
3213 return;
3214 }
3215
3216 passOnFocus();
3217}
3218
3219
3221{
3222 m_frame->GetCanvas()->GetView()->SetViewport( aViewport.rect );
3223 m_frame->GetCanvas()->Refresh();
3224}
3225
3226
3227void APPEARANCE_CONTROLS::OnColorSwatchChanged( wxCommandEvent& aEvent )
3228{
3229 COLOR_SWATCH* swatch = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
3230 COLOR4D newColor = swatch->GetSwatchColor();
3231 int layer = swatch->GetId();
3232
3233 COLOR_SETTINGS* cs = m_frame->GetColorSettings();
3234
3235 cs->SetColor( layer, newColor );
3236 m_frame->GetSettingsManager()->SaveColorSettings( cs, "board" );
3237
3238 m_frame->GetCanvas()->UpdateColors();
3239
3240 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
3241 view->UpdateLayerColor( layer );
3242 view->UpdateLayerColor( GetNetnameLayer( layer ) );
3243
3244 if( IsCopperLayer( layer ) )
3245 {
3246 view->UpdateLayerColor( ZONE_LAYER_FOR( layer ) );
3247 view->UpdateLayerColor( VIA_COPPER_LAYER_FOR( layer ) );
3248 view->UpdateLayerColor( PAD_COPPER_LAYER_FOR( layer ) );
3249 view->UpdateLayerColor( CLEARANCE_LAYER_FOR( layer ) );
3250 }
3251
3252 // Update the bitmap of the layer box
3253 if( m_frame->IsType( FRAME_PCB_EDITOR ) )
3254 static_cast<PCB_EDIT_FRAME*>( m_frame )->ReCreateLayerBox( false );
3255
3256 m_frame->GetCanvas()->Refresh();
3257
3258 if( layer == LAYER_PCB_BACKGROUND )
3259 m_frame->SetDrawBgColor( newColor );
3260
3261 passOnFocus();
3262}
3263
3264
3265void APPEARANCE_CONTROLS::onObjectOpacitySlider( int aLayer, float aOpacity )
3266{
3267 PCB_DISPLAY_OPTIONS options = m_frame->GetDisplayOptions();
3268
3269 switch( aLayer )
3270 {
3271 case static_cast<int>( LAYER_TRACKS ): options.m_TrackOpacity = aOpacity; break;
3272 case static_cast<int>( LAYER_VIAS ): options.m_ViaOpacity = aOpacity; break;
3273 case static_cast<int>( LAYER_PADS ): options.m_PadOpacity = aOpacity; break;
3274 case static_cast<int>( LAYER_ZONES ): options.m_ZoneOpacity = aOpacity; break;
3275 case static_cast<int>( LAYER_DRAW_BITMAPS ): options.m_ImageOpacity = aOpacity; break;
3276 case static_cast<int>( LAYER_FILLED_SHAPES ): options.m_FilledShapeOpacity = aOpacity; break;
3277 default: return;
3278 }
3279
3280 m_frame->SetDisplayOptions( options );
3281 passOnFocus();
3282}
3283
3284
3285void APPEARANCE_CONTROLS::onNetContextMenu( wxCommandEvent& aEvent )
3286{
3287 wxASSERT( m_netsGrid->GetSelectedRows().size() == 1 );
3288
3289 int row = m_netsGrid->GetSelectedRows()[0];
3290 const NET_GRID_ENTRY& net = m_netsTable->GetEntry( row );
3291
3292 m_netsGrid->ClearSelection();
3293
3294 switch( aEvent.GetId() )
3295 {
3296 case ID_SET_NET_COLOR:
3297 {
3298 wxGridCellEditor* editor = m_netsGrid->GetCellEditor( row, NET_GRID_TABLE::COL_COLOR );
3299
3300 if( editor )
3301 {
3302 editor->BeginEdit( row, NET_GRID_TABLE::COL_COLOR, m_netsGrid );
3303 editor->DecRef();
3304 }
3305
3306 break;
3307 }
3308
3309 case ID_CLEAR_NET_COLOR:
3310 m_netsGrid->SetCellValue( row, NET_GRID_TABLE::COL_COLOR, wxS( "rgba(0,0,0,0)" ) );
3311 break;
3312
3313 case ID_HIGHLIGHT_NET:
3314 m_frame->GetToolManager()->RunAction( PCB_ACTIONS::highlightNet, net.code );
3315 m_frame->GetCanvas()->Refresh();
3316 break;
3317
3318 case ID_SELECT_NET:
3319 m_frame->GetToolManager()->RunAction( PCB_ACTIONS::selectNet, net.code );
3320 m_frame->GetCanvas()->Refresh();
3321 break;
3322
3323 case ID_DESELECT_NET:
3324 m_frame->GetToolManager()->RunAction( PCB_ACTIONS::deselectNet, net.code );
3325 m_frame->GetCanvas()->Refresh();
3326 break;
3327
3328 case ID_SHOW_ALL_NETS:
3329 m_netsTable->ShowAllNets();
3330 break;
3331
3332 case ID_HIDE_OTHER_NETS:
3333 m_netsTable->HideOtherNets( net );
3334 break;
3335
3336 default:
3337 break;
3338 }
3339
3340 passOnFocus();
3341}
3342
3343
3345{
3346 wxString className = netclassNameFromEvent( aEvent );
3347 bool show = aEvent.GetInt();
3348 showNetclass( className, show );
3349 passOnFocus();
3350}
3351
3352
3353void APPEARANCE_CONTROLS::showNetclass( const wxString& aClassName, bool aShow )
3354{
3355 BOARD* board = m_frame->GetBoard();
3356
3357 if( !board )
3358 return;
3359
3361
3362 for( NETINFO_ITEM* net : board->GetNetInfo() )
3363 {
3364 if( net->GetNetClass()->ContainsNetclassWithName( aClassName ) )
3365 {
3366 m_frame->GetToolManager()->RunAction( aShow ? PCB_ACTIONS::showNetInRatsnest
3368 net->GetNetCode() );
3369
3370 int row = m_netsTable->GetRowByNetcode( net->GetNetCode() );
3371
3372 if( row >= 0 )
3373 m_netsTable->SetVisibilityState( row, aShow );
3374 }
3375 }
3376
3377 PROJECT_LOCAL_SETTINGS& localSettings = m_frame->Prj().GetLocalSettings();
3378
3379 if( !aShow )
3380 localSettings.m_HiddenNetclasses.insert( aClassName );
3381 else
3382 localSettings.m_HiddenNetclasses.erase( aClassName );
3383
3384 m_netsGrid->ForceRefresh();
3385 m_frame->GetCanvas()->RedrawRatsnest();
3386 m_frame->GetCanvas()->Refresh();
3388}
3389
3390
3392{
3393 BOARD* board = m_frame->GetBoard();
3394
3395 if( !board )
3396 return;
3397
3398 COLOR_SWATCH* swatch = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
3399 wxString netclassName = netclassNameFromEvent( aEvent );
3400
3401 std::shared_ptr<NET_SETTINGS>& netSettings = board->GetDesignSettings().m_NetSettings;
3402 std::shared_ptr<NETCLASS> nc = netSettings->GetNetClassByName( netclassName );
3403
3404 nc->SetPcbColor( swatch->GetSwatchColor() );
3405 netSettings->RecomputeEffectiveNetclasses();
3406
3407 m_frame->GetCanvas()->GetView()->UpdateAllLayersColor();
3408 m_frame->GetCanvas()->RedrawRatsnest();
3409 m_frame->GetCanvas()->Refresh();
3410}
3411
3412
3414{
3415 COLOR_SWATCH* s = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
3416 int classId = s->GetId();
3417
3418 wxASSERT( m_netclassIdMap.count( classId ) );
3419 return m_netclassIdMap.at( classId );
3420}
3421
3422
3423void APPEARANCE_CONTROLS::onNetColorMode( wxCommandEvent& aEvent )
3424{
3425 PCB_DISPLAY_OPTIONS options = m_frame->GetDisplayOptions();
3426
3427 if( m_rbNetColorAll->GetValue() )
3429 else if( m_rbNetColorRatsnest->GetValue() )
3431 else
3433
3434 m_frame->SetDisplayOptions( options );
3435 m_frame->GetCanvas()->GetView()->UpdateAllLayersColor();
3436 passOnFocus();
3437}
3438
3439
3440void APPEARANCE_CONTROLS::onRatsnestMode( wxCommandEvent& aEvent )
3441{
3442 if( PCBNEW_SETTINGS* cfg = m_frame->GetPcbNewSettings() )
3443 {
3444 if( m_rbRatsnestAllLayers->GetValue() )
3445 {
3446 cfg->m_Display.m_ShowGlobalRatsnest = true;
3447 cfg->m_Display.m_RatsnestMode = RATSNEST_MODE::ALL;
3448 }
3449 else if( m_rbRatsnestVisLayers->GetValue() )
3450 {
3451 cfg->m_Display.m_ShowGlobalRatsnest = true;
3452 cfg->m_Display.m_RatsnestMode = RATSNEST_MODE::VISIBLE;
3453 }
3454 else
3455 {
3456 cfg->m_Display.m_ShowGlobalRatsnest = false;
3457 }
3458 }
3459
3460 if( PCB_EDIT_FRAME* editframe = dynamic_cast<PCB_EDIT_FRAME*>( m_frame ) )
3461 {
3462 if( PCBNEW_SETTINGS* cfg = m_frame->GetPcbNewSettings() )
3463 editframe->SetElementVisibility( LAYER_RATSNEST, cfg->m_Display.m_ShowGlobalRatsnest );
3464
3465 editframe->OnDisplayOptionsChanged();
3466 editframe->GetCanvas()->RedrawRatsnest();
3467 editframe->GetCanvas()->Refresh();
3468 }
3469
3470 passOnFocus();
3471}
3472
3473
3475{
3476 BOARD* board = m_frame->GetBoard();
3477
3478 if( !board )
3479 return;
3480
3481 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
3483 static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
3484
3485 std::shared_ptr<NET_SETTINGS>& netSettings = board->GetDesignSettings().m_NetSettings;
3486 APPEARANCE_SETTING* setting = nullptr;
3487
3489
3490 if( it != m_netclassSettingsMap.end() )
3491 setting = it->second;
3492
3493 auto runOnNetsOfClass =
3494 [&]( const wxString& netClassName, std::function<void( NETINFO_ITEM* )> aFunction )
3495 {
3496 for( NETINFO_ITEM* net : board->GetNetInfo() )
3497 {
3498 if( net->GetNetClass()->ContainsNetclassWithName( netClassName ) )
3499 aFunction( net );
3500 }
3501 };
3502
3503 switch( aEvent.GetId() )
3504 {
3505 case ID_SET_NET_COLOR:
3506 {
3507 if( setting )
3508 {
3509 setting->ctl_color->GetNewSwatchColor();
3510
3511 COLOR4D color = setting->ctl_color->GetSwatchColor();
3512
3513 if( color != COLOR4D::UNSPECIFIED )
3514 {
3515 netSettings->GetNetClassByName( m_contextMenuNetclass )->SetPcbColor( color );
3516 netSettings->RecomputeEffectiveNetclasses();
3517 }
3518
3519 view->UpdateAllLayersColor();
3520 }
3521
3522 break;
3523 }
3524
3525 case ID_CLEAR_NET_COLOR:
3526 {
3527 if( setting )
3528 {
3529 setting->ctl_color->SetSwatchColor( COLOR4D( 0, 0, 0, 0 ), true );
3530
3531 netSettings->GetNetClassByName( m_contextMenuNetclass )->SetPcbColor( COLOR4D::UNSPECIFIED );
3532 netSettings->RecomputeEffectiveNetclasses();
3533
3534 view->UpdateAllLayersColor();
3535 }
3536
3537 break;
3538 }
3539
3541 {
3542 if( setting )
3543 {
3544 std::shared_ptr<NETCLASS> nc = netSettings->GetNetClassByName( m_contextMenuNetclass );
3545 const KIGFX::COLOR4D ncColor = nc->GetSchematicColor();
3546
3547 setting->ctl_color->SetSwatchColor( ncColor, true );
3548
3549 netSettings->GetNetClassByName( m_contextMenuNetclass )->SetPcbColor( ncColor );
3550 netSettings->RecomputeEffectiveNetclasses();
3551
3552 view->UpdateAllLayersColor();
3553 }
3554
3555 break;
3556 }
3557
3558 case ID_HIGHLIGHT_NET:
3559 {
3560 if( !m_contextMenuNetclass.IsEmpty() )
3561 {
3562 board->ResetNetHighLight();
3563 rs->SetHighlight( false );
3564
3565 runOnNetsOfClass( m_contextMenuNetclass,
3566 [&]( const NETINFO_ITEM* aItem )
3567 {
3568 int code = aItem->GetNetCode();
3569
3570 board->SetHighLightNet( code, true );
3571 rs->SetHighlight( true, code, true );
3572 } );
3573
3574 view->UpdateAllLayersColor();
3575 board->HighLightON();
3576 }
3577
3578 break;
3579 }
3580
3581 case ID_SELECT_NET:
3582 case ID_DESELECT_NET:
3583 {
3584 if( !m_contextMenuNetclass.IsEmpty() )
3585 {
3586 TOOL_MANAGER* toolMgr = m_frame->GetToolManager();
3587 TOOL_ACTION& action = aEvent.GetId() == ID_SELECT_NET ? PCB_ACTIONS::selectNet
3589
3590 runOnNetsOfClass( m_contextMenuNetclass,
3591 [&]( NETINFO_ITEM* aItem )
3592 {
3593 toolMgr->RunAction( action, aItem->GetNetCode() );
3594 } );
3595 }
3596 break;
3597 }
3598
3599
3600 case ID_SHOW_ALL_NETS:
3601 {
3603 wxASSERT( m_netclassSettingsMap.count( NETCLASS::Default ) );
3604 m_netclassSettingsMap.at( NETCLASS::Default )->ctl_visibility->SetValue( true );
3605
3606 for( const auto& [name, netclass] : netSettings->GetNetclasses() )
3607 {
3608 showNetclass( name );
3609
3610 if( m_netclassSettingsMap.count( name ) )
3611 m_netclassSettingsMap.at( name )->ctl_visibility->SetValue( true );
3612 }
3613
3614 break;
3615 }
3616
3617 case ID_HIDE_OTHER_NETS:
3618 {
3619 bool showDefault = m_contextMenuNetclass == NETCLASS::Default;
3620 showNetclass( NETCLASS::Default, showDefault );
3621 wxASSERT( m_netclassSettingsMap.count( NETCLASS::Default ) );
3622 m_netclassSettingsMap.at( NETCLASS::Default )->ctl_visibility->SetValue( showDefault );
3623
3624 for( const auto& [name, netclass] : netSettings->GetNetclasses() )
3625 {
3626 bool show = ( name == m_contextMenuNetclass );
3627
3628 showNetclass( name, show );
3629
3630 if( m_netclassSettingsMap.count( name ) )
3631 m_netclassSettingsMap.at( name )->ctl_visibility->SetValue( show );
3632 }
3633
3634 break;
3635 }
3636
3637 default:
3638 break;
3639 }
3640
3641 m_frame->GetCanvas()->RedrawRatsnest();
3642 m_frame->GetCanvas()->Refresh();
3643
3644 m_contextMenuNetclass.clear();
3645}
3646
3647
3649{
3650 m_focusOwner->SetFocus();
3651}
3652
3653
3655{
3656 WX_INFOBAR* infobar = m_frame->GetInfoBar();
3657
3658 infobar->RemoveAllButtons();
3659 infobar->AddLink( _( "Open Preferences" ),
3660 [&]( wxHyperlinkEvent& aEvent )
3661 {
3662 m_frame->ShowPreferences( wxEmptyString, wxEmptyString );
3663 } );
3664 infobar->AddCloseButton();
3665
3666 infobar->ShowMessageFor( _( "The current color theme is read-only. Create a new theme in Preferences to "
3667 "enable color editing." ),
3668 10000, wxICON_INFORMATION );
3669}
3670
3671
3676
3677
int index
const char * name
static std::set< int > s_allowedInFpEditor
These GAL layers are shown in the Objects tab in the footprint editor.
#define RR
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition bitmap.cpp:100
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:106
@ show_all_back_layers
@ show_front_assembly_layers
@ options_generic
@ show_back_assembly_layers
@ show_all_front_layers
@ show_no_copper_layers
@ show_all_layers
@ show_all_copper_layers
HIGH_CONTRAST_MODE
Determine how inactive layers should be displayed.
@ NORMAL
Inactive layers are shown normally (no high-contrast mode)
@ HIDDEN
Inactive layers are hidden.
@ DIMMED
Inactive layers are dimmed (old high-contrast mode)
@ RATSNEST
Net/netclass colors are shown on ratsnest lines only.
@ ALL
Net/netclass colors are shown on all net copper.
@ OFF
Net (and netclass) colors are not shown.
@ VISIBLE
Ratsnest lines are drawn to items on visible layers only.
@ ALL
Ratsnest lines are drawn to items on all layers (default)
static TOOL_ACTION highContrastModeCycle
Definition actions.h:152
APPEARANCE_CONTROLS_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxTAB_TRAVERSAL, const wxString &name=wxEmptyString)
wxScrolledWindow * m_netclassScrolledWindow
void OnBoardNetSettingsChanged(BOARD &aBoard) override
void doApplyLayerPreset(const LAYER_PRESET &aPreset)
std::map< PCB_LAYER_ID, APPEARANCE_SETTING * > m_layerSettingsMap
wxStaticText * m_inactiveLayersLabel
std::map< GAL_LAYER_ID, APPEARANCE_SETTING * > m_objectSettingsMap
void ApplyLayerPreset(const wxString &aPresetName)
static LAYER_PRESET m_lastBuiltinPreset
wxRadioButton * m_rbHighContrastNormal
void onObjectVisibilityChanged(GAL_LAYER_ID aLayer, bool isVisible, bool isFinal)
static LAYER_PRESET presetFrontAssembly
void OnBoardItemAdded(BOARD &aBoard, BOARD_ITEM *aItem) override
static LAYER_PRESET presetBackAssembly
void OnNetGridClick(wxGridEvent &event) override
void setVisibleObjects(GAL_SET aObjects)
wxRadioButton * m_rbRatsnestNone
WX_COLLAPSIBLE_PANE * m_paneLayerDisplayOptions
void buildNetClassMenu(wxMenu &aMenu, bool isDefaultClass, const wxString &aName)
void onLayerVisibilityToggled(PCB_LAYER_ID aLayer)
void onLayerPresetChanged(wxCommandEvent &aEvent) override
wxBitmapBundle m_visibleBitmapBundle
void OnBoardItemRemoved(BOARD &aBoard, BOARD_ITEM *aItem) override
wxRadioButton * m_rbRatsnestVisLayers
wxRadioButton * m_rbNetColorAll
bool doesBoardItemNeedRebuild(BOARD_ITEM *aBoardItem)
void SetUserLayerPresets(std::vector< LAYER_PRESET > &aPresetList)
Update the current layer presets from those saved in the project file.
std::vector< LAYER_PRESET > GetUserLayerPresets() const
Return a list of the layer presets created by the user.
static LAYER_PRESET presetInnerCopper
void updateViewportSelection(const wxString &aName)
std::map< wxString, VIEWPORT > m_viewports
void onViewportChanged(wxCommandEvent &aEvent) override
NET_GRID_TABLE * m_netsTable
std::vector< std::unique_ptr< APPEARANCE_SETTING > > m_layerSettings
std::vector< std::unique_ptr< APPEARANCE_SETTING > > m_objectSettings
void onObjectOpacitySlider(int aLayer, float aOpacity)
bool isLayerEnabled(PCB_LAYER_ID aLayer) const
void setVisibleLayers(const LSET &aLayers)
wxRadioButton * m_rbRatsnestAllLayers
LAYER_PRESET * m_lastSelectedUserPreset
wxString m_contextMenuNetclass
The name of the netclass that was right-clicked.
wxRadioButton * m_rbNetColorRatsnest
void rebuildLayerPresetsWidget(bool aReset)
void onRatsnestMode(wxCommandEvent &aEvent)
wxRadioButton * m_rbNetColorOff
static LAYER_PRESET presetFront
void doApplyViewport(const VIEWPORT &aViewport)
static const APPEARANCE_SETTING s_objectSettings[]
Template for object appearance settings.
void OnNetGridMouseEvent(wxMouseEvent &aEvent)
WX_COLLAPSIBLE_PANE * m_paneNetDisplayOptions
void OnNotebookPageChanged(wxNotebookEvent &event) override
int GetTabIndex() const
Return the index of the current tab (0-2).
void onNetclassVisibilityChanged(wxCommandEvent &aEvent)
void OnBoardItemsRemoved(BOARD &aBoard, std::vector< BOARD_ITEM * > &aItems) override
void onNetContextMenu(wxCommandEvent &aEvent)
void OnColorSwatchChanged(wxCommandEvent &aEvent)
void updateLayerPresetSelection(const wxString &aName)
void OnLayerChanged()
Update the widget when the active board layer is changed.
ROW_ICON_PROVIDER * m_iconProvider
std::map< wxString, LAYER_PRESET > m_layerPresets
static LAYER_PRESET presetBack
void RefreshCollapsiblePanes()
Function to force a redraw of the collapsible panes in this control.
static LAYER_PRESET presetNoLayers
void idleFocusHandler(wxIdleEvent &aEvent)
void rightClickHandler(wxMouseEvent &aEvent)
wxBitmapBundle m_notVisibileBitmapBundle
void OnNetGridRightClick(wxGridEvent &event) override
void OnBoardItemsChanged(BOARD &aBoard, std::vector< BOARD_ITEM * > &aItems) override
std::vector< std::unique_ptr< APPEARANCE_SETTING > > m_netclassSettings
wxRadioButton * m_rbHighContrastOff
void OnBoardCompositeUpdate(BOARD &aBoard, std::vector< BOARD_ITEM * > &aAddedItems, std::vector< BOARD_ITEM * > &aRemovedItems, std::vector< BOARD_ITEM * > &aChangedItems) override
void OnBoardItemsAdded(BOARD &aBoard, std::vector< BOARD_ITEM * > &aItems) override
void OnColorThemeChanged()
Update the colors on all the widgets from the new chosen color theme.
LAYER_PRESET * m_currentPreset
std::map< wxString, APPEARANCE_SETTING * > m_netclassSettingsMap
void OnSetFocus(wxFocusEvent &aEvent) override
void OnLanguageChanged(wxCommandEvent &aEvent)
static LAYER_PRESET presetAllCopper
void SetUserViewports(std::vector< VIEWPORT > &aPresetList)
Update the current viewports from those saved in the project file.
wxRadioButton * m_rbHighContrastDim
void OnSize(wxSizeEvent &aEvent) override
wxString netclassNameFromEvent(wxEvent &aEvent)
wxGridCellCoords m_hoveredCell
Grid cell that is being hovered over, for tooltips.
void showNetclass(const wxString &aClassName, bool aShow=true)
wxStaticText * m_txtRatsnestVisibility
void OnBoardChanged()
Update the panel contents from the application and board models.
void onLayerLeftClick(wxMouseEvent &aEvent)
std::vector< VIEWPORT > GetUserViewports() const
Return a list of viewports created by the user.
void SetTabIndex(int aTab)
Set the current notebook tab.
void CommonSettingsChanged(int aFlag)
std::map< int, wxString > m_netclassIdMap
Stores wxIDs for each netclass for control event mapping.
void OnLayerContextMenu(wxCommandEvent &aEvent)
void onNetColorMode(wxCommandEvent &aEvent)
void OnNetVisibilityChanged(int aNetCode, bool aVisibility)
Notifies the panel when a net has been hidden or shown via the external tool.
void OnDarkModeToggle()
Respond to change in OS's DarkMode.
static LAYER_PRESET presetAllLayers
void onNetclassContextMenu(wxCommandEvent &aEvent)
wxStaticText * m_txtNetDisplayTitle
wxStaticLine * m_layerDisplaySeparator
APPEARANCE_CONTROLS(PCB_BASE_FRAME *aParent, wxWindow *aFocusOwner, bool aFpEditor=false)
void SetObjectVisible(GAL_LAYER_ID aLayer, bool isVisible=true)
void OnNetGridDoubleClick(wxGridEvent &event) override
void SetLayerVisible(int aLayer, bool isVisible)
Manually update visibility for a given layer.
void OnBoardItemChanged(BOARD &aBoard, BOARD_ITEM *aItem) override
void onNetclassColorChanged(wxCommandEvent &aEvent)
void ApplyViewport(const wxString &aPresetName)
GRID_BITMAP_TOGGLE_RENDERER * m_toggleGridRenderer
BASE_SET & set(size_t pos)
Definition base_set.h:126
A checkbox control except with custom bitmaps for the checked and unchecked states.
void SetValue(bool aValue)
Set the checkbox state.
std::shared_ptr< NET_SETTINGS > m_NetSettings
std::map< std::string, wxString > m_UserLayerNames
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:410
const NETINFO_LIST & GetNetInfo() const
Definition board.h:1215
static wxString GetStandardLayerName(PCB_LAYER_ID aLayerId)
Return an "English Standard" name of a PCB layer when given aLayerNumber.
Definition board.h:1120
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition board.h:899
void SetHighLightNet(int aNetCode, bool aMulti=false)
Select the netcode to be highlighted.
Definition board.cpp:4077
void ResetNetHighLight()
Reset all high light data to the init state.
Definition board.cpp:4068
void SetElementVisibility(GAL_LAYER_ID aLayer, bool aNewState)
Change the visibility of an element category.
Definition board.cpp:1258
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition board.cpp:943
PROJECT * GetProject() const
Definition board.h:775
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1301
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition board.cpp:1185
void HighLightON(bool aValue=true)
Enable or disable net highlighting.
Definition board.cpp:4092
void SetVisibleElements(const GAL_SET &aMask)
A proxy function that calls the correspondent function in m_BoardSettings.
Definition board.cpp:1225
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:400
Color settings are a bit different than most of the settings objects in that there can be more than o...
void SetColor(int aLayer, const COLOR4D &aColor)
COLOR4D GetColor(int aLayer) const
COLOR4D GetDefaultColor(int aLayer)
A simple color swatch of the kind used to set layer colors.
void SetSwatchColor(const KIGFX::COLOR4D &aColor, bool aSendEvent)
Set the current swatch color directly.
void GetNewSwatchColor()
Prompt for a new colour, using the colour picker dialog.
KIGFX::COLOR4D GetSwatchColor() const
void SetReadOnlyCallback(std::function< void()> aCallback)
Register a handler for when the user tries to interact with a read-only swatch.
void SetReadOnly(bool aReadOnly=true)
int ShowModal() override
Class to handle configuration and automatic determination of the DPI scale to use for canvases.
double GetScaleFactor() const override
Get the DPI scale from all known sources in order:
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
A dialog which shows:
wxString GetTextSelection(int aColumn=0)
Return the selected text from aColumn in the wxListCtrl in the dialog.
void SetListLabel(const wxString &aLabel)
BOARD_DESIGN_SETTINGS m_DesignSettings
Only some of these settings are actually used for footprint editing.
Helper for storing and iterating over GAL_LAYER_IDs.
Definition layer_ids.h:425
bool Contains(GAL_LAYER_ID aPos)
Definition layer_ids.h:459
GAL_SET & set()
Definition layer_ids.h:441
static GAL_SET DefaultVisible()
Definition lset.cpp:782
A toggle button renderer for a wxGrid, similar to BITMAP_TOGGLE.
A text renderer that can unescape text for display This is useful where it's desired to keep the unde...
Represent a row indicator icon for use in places like the layer widget.
void SetIndicatorState(ICON_ID aIconId)
Set the row indicator to the given state.
bool IsReadOnly() const
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
bool SetFromWxString(const wxString &aColorString)
Set color values by parsing a string using wxColour::Set().
Definition color4d.cpp:127
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:400
PCB specific render settings.
Definition pcb_painter.h:84
std::set< int > & GetHiddenNets()
std::map< int, KIGFX::COLOR4D > & GetNetColorMap()
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
void SetHighlight(bool aEnabled, int aNetcode=-1, bool aMulti=false)
Turns on/off highlighting.
An abstract base class for deriving all objects that can be added to a VIEW.
Definition view_item.h:82
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:63
void UpdateAllLayersColor()
Apply the new coloring scheme to all layers.
Definition view.cpp:884
void SetLayerVisible(int aLayer, bool aVisible=true)
Control the visibility of a particular layer.
Definition view.h:407
void UpdateLayerColor(int aLayer)
Apply the new coloring scheme held by RENDER_SETTINGS in case that it has changed.
Definition view.cpp:860
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition view.h:429
PAINTER * GetPainter() const
Return the painter object used by the view for drawing VIEW_ITEM objects.
Definition view.h:227
void UpdateAllItemsConditionally(int aUpdateFlags, std::function< bool(VIEW_ITEM *)> aCondition)
Update items in the view according to the given flags and condition.
Definition view.cpp:1759
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static const LSET & FrontMask()
Return a mask holding all technical layers and the external CU layer on front side.
Definition lset.cpp:718
static const LSET & BackAssembly()
Return a complete set of all bottom assembly layers which is all B_SilkS and B_Mask.
Definition lset.cpp:566
static const LSET & BackMask()
Return a mask holding all technical layers and the external CU layer on back side.
Definition lset.cpp:725
static const LSET & FrontAssembly()
Return a complete set of all top assembly layers which is all F_SilkS and F_Mask.
Definition lset.cpp:559
LSEQ CuStack() const
Return a sequence of copper layers in starting from the front/top and extending to the back/bottom.
Definition lset.cpp:259
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition lset.cpp:309
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition lset.cpp:595
static const LSET & AllLayersMask()
Definition lset.cpp:637
static const LSET & InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
Definition lset.cpp:573
static wxString Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Definition lset.cpp:184
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
Definition lset.h:63
static const char Default[]
the name of the default NETCLASS
Definition netclass.h:45
Handle the data for a net.
Definition netinfo.h:50
int GetNetCode() const
Definition netinfo.h:104
const NETNAMES_MAP & NetsByName() const
Return the name map, at least for python.
Definition netinfo.h:258
void SetValue(int aRow, int aCol, const wxString &aValue) override
void SetValueAsCustom(int aRow, int aCol, const wxString &aTypeName, void *aValue) override
std::vector< NET_GRID_ENTRY > m_nets
void updateNetColor(const NET_GRID_ENTRY &aNet)
void SetValueAsBool(int aRow, int aCol, bool aValue) override
void * GetValueAsCustom(int aRow, int aCol, const wxString &aTypeName) override
NET_GRID_TABLE(PCB_BASE_FRAME *aFrame, wxColor aBackgroundColor)
void updateNetVisibility(const NET_GRID_ENTRY &aNet)
wxString GetValue(int aRow, int aCol) override
wxGridCellAttr * m_labelAttr
PCB_BASE_FRAME * m_frame
void SetVisibilityState(int aRow, bool aVisible)
Update cached visibility without dispatching a ratsnest action.
void HideOtherNets(const NET_GRID_ENTRY &aNet)
std::unordered_map< int, int > m_netcodeToRow
wxGridCellAttr * m_defaultAttr
bool GetValueAsBool(int aRow, int aCol) override
const NET_GRID_ENTRY & GetEntry(int aRow) const
wxGridCellAttr * GetAttr(int aRow, int aCol, wxGridCellAttr::wxAttrKind) override
static void * ColorToVoid(COLOR4D &aColor)
int GetRowByNetcode(int aCode) const
wxString GetTypeName(int aRow, int aCol) override
static COLOR4D VoidToColor(void *aColor)
Definition pad.h:61
static TOOL_ACTION highlightNet
static TOOL_ACTION hideNetInRatsnest
static TOOL_ACTION showNetInRatsnest
static TOOL_ACTION showNetInspector
static TOOL_ACTION ratsnestModeCycle
static TOOL_ACTION netColorModeCycle
static TOOL_ACTION selectNet
Select all connections belonging to a single net.
Definition pcb_actions.h:82
static TOOL_ACTION flipBoard
static TOOL_ACTION deselectNet
Remove all connections belonging to a single net from the active selection.
Definition pcb_actions.h:85
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
double m_TrackOpacity
Opacity override for all tracks.
bool m_FlipBoardView
true if the board is flipped to show the mirrored view
double m_FilledShapeOpacity
Opacity override for graphic shapes.
double m_ZoneOpacity
Opacity override for filled zone areas.
double m_ImageOpacity
Opacity override for user images.
double m_PadOpacity
Opacity override for SMD pads and PTHs.
double m_ViaOpacity
Opacity override for all types of via.
HIGH_CONTRAST_MODE m_ContrastModeDisplay
How inactive layers are displayed.
NET_COLOR_MODE m_NetColorMode
How to use color overrides on specific nets and netclasses.
The main frame for Pcbnew.
The project local settings are things that are attached to a particular project, but also might be pa...
std::set< wxString > m_HiddenNetclasses
Icon provider for the "standard" row indicators, for example in layer selection lists.
@ OFF
Row "off" or "deselected".
@ ON
Row "on" or "selected".
Represent a single user action.
Master controller class:
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
A better wxCollapsiblePane that.
A modified version of the wxInfoBar class that allows us to:
Definition wx_infobar.h:76
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
void ShowMessageFor(const wxString &aMessage, int aTime, int aFlags=wxICON_INFORMATION, MESSAGE_TYPE aType=WX_INFOBAR::MESSAGE_TYPE::GENERIC)
Show the infobar with the provided message and icon for a specific period of time.
void AddLink(const wxString &aLinkText, const std::function< void(wxHyperlinkEvent &)> &aFn)
Add a hypertext link to the infobar.
void AddCloseButton(const wxString &aTooltip=_("Hide this message."))
Add the default close button to the infobar on the right side.
void SetBorders(bool aLeft, bool aRight, bool aTop, bool aBottom)
Definition wx_panel.h:35
static const wxSize SWATCH_SIZE_SMALL_DU(8, 6)
@ SWATCH_SMALL
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:274
This file is part of the common library.
#define _(s)
#define VIEWPORT_SWITCH_KEY
#define PRESET_SWITCH_KEY
@ FRAME_PCB_EDITOR
Definition frame_type.h:38
wxString KeyNameFromKeyCode(int aKeycode, bool *aIsFound)
Return the key name from the key code.
GAL_LAYER_ID ToGalLayer(int aInteger)
Definition layer_ids.h:404
int GetNetnameLayer(int aLayer)
Return a netname layer corresponding to the given layer.
Definition layer_ids.h:880
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition layer_ids.h:703
GAL_LAYER_ID
GAL layers are "virtual" layers, i.e.
Definition layer_ids.h:224
@ LAYER_GRID
Definition layer_ids.h:250
@ LAYER_POINTS
PCB reference/manual snap points visibility.
Definition layer_ids.h:317
@ GAL_LAYER_ID_START
Definition layer_ids.h:225
@ LAYER_LOCKED_ITEM_SHADOW
Shadow layer for locked items.
Definition layer_ids.h:303
@ LAYER_FILLED_SHAPES
Copper graphic shape opacity/visibility (color ignored).
Definition layer_ids.h:309
@ LAYER_CONFLICTS_SHADOW
Shadow layer for items flagged conflicting.
Definition layer_ids.h:306
@ LAYER_FOOTPRINTS_FR
Show footprints on front.
Definition layer_ids.h:255
@ LAYER_VIA_STITCHING
Outline of via stitching generators.
Definition layer_ids.h:326
@ LAYER_DRAWINGSHEET
Sheet frame and title block.
Definition layer_ids.h:274
@ LAYER_DRAW_BITMAPS
Draw images.
Definition layer_ids.h:280
@ LAYER_FP_REFERENCES
Show footprints references (when texts are visible).
Definition layer_ids.h:262
@ LAYER_BOARD_OUTLINE_AREA
PCB board outline.
Definition layer_ids.h:314
@ LAYER_DRC_EXCLUSION
Layer for DRC markers which have been individually excluded.
Definition layer_ids.h:300
@ LAYER_PCB_BACKGROUND
PCB background color.
Definition layer_ids.h:277
@ LAYER_ZONES
Control for copper zone opacity/visibility (color ignored).
Definition layer_ids.h:291
@ LAYER_PADS
Meta control for all pads opacity/visibility (color ignored).
Definition layer_ids.h:288
@ LAYER_DRC_WARNING
Layer for DRC markers with RPT_SEVERITY_WARNING.
Definition layer_ids.h:297
@ LAYER_TRACKS
Definition layer_ids.h:263
@ LAYER_CONSTRAINT_SHADOW
Shadow layer for items bound to a constraint.
Definition layer_ids.h:320
@ LAYER_RATSNEST
Definition layer_ids.h:249
@ LAYER_ZONE_START
Virtual layers for stacking zones and tracks on a given copper layer.
Definition layer_ids.h:345
@ LAYER_FP_TEXT
Definition layer_ids.h:236
@ LAYER_FOOTPRINTS_BK
Show footprints on back.
Definition layer_ids.h:256
@ LAYER_ANCHOR
Anchor of items having an anchor point (texts, footprints).
Definition layer_ids.h:244
@ LAYER_FP_VALUES
Show footprints values (when texts are visible).
Definition layer_ids.h:259
@ LAYER_SUBGRIDS
Routing/placement subgrids (PCB_GRID_ITEM) visibility and color.
Definition layer_ids.h:323
@ LAYER_DRC_ERROR
Layer for DRC markers with RPT_SEVERITY_ERROR.
Definition layer_ids.h:273
@ LAYER_VIAS
Meta control for all vias opacity/visibility.
Definition layer_ids.h:228
#define CLEARANCE_LAYER_FOR(boardLayer)
Definition layer_ids.h:390
#define VIA_COPPER_LAYER_FOR(boardLayer)
Definition layer_ids.h:389
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ User_16
Definition layer_ids.h:135
@ User_29
Definition layer_ids.h:148
@ User_40
Definition layer_ids.h:159
@ User_15
Definition layer_ids.h:134
@ User_8
Definition layer_ids.h:127
@ F_CrtYd
Definition layer_ids.h:112
@ User_11
Definition layer_ids.h:130
@ User_25
Definition layer_ids.h:144
@ User_34
Definition layer_ids.h:153
@ User_45
Definition layer_ids.h:164
@ B_Adhes
Definition layer_ids.h:99
@ User_36
Definition layer_ids.h:155
@ Edge_Cuts
Definition layer_ids.h:108
@ Dwgs_User
Definition layer_ids.h:103
@ F_Paste
Definition layer_ids.h:100
@ Cmts_User
Definition layer_ids.h:104
@ User_6
Definition layer_ids.h:125
@ User_7
Definition layer_ids.h:126
@ User_19
Definition layer_ids.h:138
@ User_23
Definition layer_ids.h:142
@ F_Adhes
Definition layer_ids.h:98
@ User_41
Definition layer_ids.h:160
@ B_Mask
Definition layer_ids.h:94
@ B_Cu
Definition layer_ids.h:61
@ User_14
Definition layer_ids.h:133
@ User_39
Definition layer_ids.h:158
@ User_5
Definition layer_ids.h:124
@ User_20
Definition layer_ids.h:139
@ Eco1_User
Definition layer_ids.h:105
@ F_Mask
Definition layer_ids.h:93
@ User_42
Definition layer_ids.h:161
@ User_43
Definition layer_ids.h:162
@ B_Paste
Definition layer_ids.h:101
@ User_10
Definition layer_ids.h:129
@ User_9
Definition layer_ids.h:128
@ User_27
Definition layer_ids.h:146
@ User_28
Definition layer_ids.h:147
@ UNSELECTED_LAYER
Definition layer_ids.h:58
@ F_Fab
Definition layer_ids.h:115
@ Margin
Definition layer_ids.h:109
@ F_SilkS
Definition layer_ids.h:96
@ B_CrtYd
Definition layer_ids.h:111
@ Eco2_User
Definition layer_ids.h:106
@ User_35
Definition layer_ids.h:154
@ User_31
Definition layer_ids.h:150
@ User_3
Definition layer_ids.h:122
@ User_1
Definition layer_ids.h:120
@ User_12
Definition layer_ids.h:131
@ B_SilkS
Definition layer_ids.h:97
@ User_30
Definition layer_ids.h:149
@ User_37
Definition layer_ids.h:156
@ User_22
Definition layer_ids.h:141
@ User_38
Definition layer_ids.h:157
@ User_4
Definition layer_ids.h:123
@ User_21
Definition layer_ids.h:140
@ User_24
Definition layer_ids.h:143
@ User_13
Definition layer_ids.h:132
@ User_2
Definition layer_ids.h:121
@ User_17
Definition layer_ids.h:136
@ User_33
Definition layer_ids.h:152
@ User_26
Definition layer_ids.h:145
@ User_32
Definition layer_ids.h:151
@ User_18
Definition layer_ids.h:137
@ User_44
Definition layer_ids.h:163
@ F_Cu
Definition layer_ids.h:60
@ B_Fab
Definition layer_ids.h:114
#define ZONE_LAYER_FOR(boardLayer)
Definition layer_ids.h:387
#define PAD_COPPER_LAYER_FOR(boardLayer)
Definition layer_ids.h:388
#define GAL_LAYER_INDEX(x)
Use this macro to convert a GAL layer to a 0-indexed offset from LAYER_VIAS.
Definition layer_ids.h:383
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition lset.cpp:750
@ ALL
All except INITIAL_ADD.
Definition view_item.h:55
@ TARGET_NONCACHED
Auxiliary rendering target (noncached)
Definition definitions.h:34
KICOMMON_API wxFont GetInfoFont(wxWindow *aWindow)
KICOMMON_API wxMenuItem * AddMenuItem(wxMenu *aMenu, int aId, const wxString &aText, const wxBitmapBundle &aImage, wxItemKind aType=wxITEM_NORMAL)
Create and insert a menu item with an icon into aMenu.
const int c_IndicatorSizeDIP
Definition ui_common.h:52
std::map< wxString, NETINFO_ITEM * > NETNAMES_MAP
Definition netinfo.h:225
#define _HKI(x)
Definition page_info.cpp:40
see class PGM_BASE
T * GetAppSettings(const char *aFilename)
std::vector< FAB_LAYER_COLOR > dummy
wxString UnescapeString(const wxString &aSource)
Container for an appearance setting (can control a single board layer, or GAL layer,...
A saved set of layers that are visible.
GAL_SET renderLayers
Render layers (e.g. object types) that are visible.
wxString name
A name for this layer set.
bool flipBoard
True if the flip board is enabled.
LSET layers
Board layers that are visible.
bool readOnly
True if this is a read-only (built-in) preset.
PCB_LAYER_ID activeLayer
Optional layer to set active when this preset is loaded.
COLOR4D color
int code
wxString name
bool visible
#define HOTKEYS_CHANGED
@ PCB_NETINFO_T
class NETINFO_ITEM, a description of a net
Definition typeinfo.h:102
const KICOMMON_API wxEventTypeTag< wxCommandEvent > WX_COLLAPSIBLE_PANE_CHANGED