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