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