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