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