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