KiCad PCB EDA Suite
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 (C) 2021-2022 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>
26#include <pad.h>
27#include <pcb_track.h>
28#include <eda_list_dialog.h>
29#include <string_utils.h>
31#include <menus_helpers.h>
32#include <pcb_display_options.h>
33#include <pcb_edit_frame.h>
34#include <pcb_painter.h>
35#include <pcbnew_settings.h>
36#include <project.h>
39#include <tool/tool_manager.h>
40#include <tools/pcb_actions.h>
49#include <widgets/wx_infobar.h>
50#include <widgets/wx_grid.h>
52#include <wx/bmpbuttn.h>
53#include <wx/checkbox.h>
54#include <wx/hyperlink.h>
55#include <wx/radiobut.h>
56#include <wx/sizer.h>
57#include <wx/slider.h>
58#include <wx/statline.h>
59#include <wx/textdlg.h>
60
61
62NET_GRID_TABLE::NET_GRID_TABLE( PCB_BASE_FRAME* aFrame, wxColor aBackgroundColor ) :
63 wxGridTableBase(),
64 m_frame( aFrame )
65{
66 m_defaultAttr = new wxGridCellAttr;
67 m_defaultAttr->SetBackgroundColour( aBackgroundColor );
68
69 m_labelAttr = new wxGridCellAttr;
71 m_labelAttr->SetBackgroundColour( aBackgroundColor );
72}
73
74
76{
77 m_defaultAttr->DecRef();
78 m_labelAttr->DecRef();
79}
80
81
82wxGridCellAttr* NET_GRID_TABLE::GetAttr( int aRow, int aCol, wxGridCellAttr::wxAttrKind )
83{
84 wxGridCellAttr* attr = nullptr;
85
86 switch( aCol )
87 {
88 case COL_COLOR: attr = m_defaultAttr; break;
89 case COL_VISIBILITY: attr = m_defaultAttr; break;
90 case COL_LABEL: attr = m_labelAttr; break;
91 default: wxFAIL;
92 }
93
94 if( attr )
95 attr->IncRef();
96
97 return attr;
98}
99
100
101wxString NET_GRID_TABLE::GetValue( int aRow, int aCol )
102{
103 wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
104
105 switch( aCol )
106 {
107 case COL_COLOR: return m_nets[aRow].color.ToCSSString();
108 case COL_VISIBILITY: return m_nets[aRow].visible ? wxT( "1" ) : wxT( "0" );
109 case COL_LABEL: return m_nets[aRow].name;
110 default: return wxEmptyString;
111 }
112}
113
114
115void NET_GRID_TABLE::SetValue( int aRow, int aCol, const wxString& aValue )
116{
117 wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
118
119 NET_GRID_ENTRY& net = m_nets[aRow];
120
121 switch( aCol )
122 {
123 case COL_COLOR:
124 net.color.SetFromWxString( aValue );
125 updateNetColor( net );
126 break;
127
128 case COL_VISIBILITY:
129 net.visible = ( aValue != wxT( "0" ) );
130 updateNetVisibility( net );
131 break;
132
133 case COL_LABEL:
134 net.name = aValue;
135 break;
136
137 default:
138 break;
139 }
140}
141
142
143wxString NET_GRID_TABLE::GetTypeName( int aRow, int aCol )
144{
145 switch( aCol )
146 {
147 case COL_COLOR: return wxT( "COLOR4D" );
148 case COL_VISIBILITY: return wxGRID_VALUE_BOOL;
149 case COL_LABEL: return wxGRID_VALUE_STRING;
150 default: return wxGRID_VALUE_STRING;
151 }
152}
153
154
155bool NET_GRID_TABLE::GetValueAsBool( int aRow, int aCol )
156{
157 wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
158 wxASSERT( aCol == COL_VISIBILITY );
159
160 return m_nets[aRow].visible;
161}
162
163
164void NET_GRID_TABLE::SetValueAsBool( int aRow, int aCol, bool aValue )
165{
166 wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
167 wxASSERT( aCol == COL_VISIBILITY );
168
169 m_nets[aRow].visible = aValue;
171}
172
173
174void* NET_GRID_TABLE::GetValueAsCustom( int aRow, int aCol, const wxString& aTypeName )
175{
176 wxASSERT( aCol == COL_COLOR );
177 wxASSERT( aTypeName == wxT( "COLOR4D" ) );
178 wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
179
180 return ColorToVoid( m_nets[aRow].color );
181}
182
183
184void NET_GRID_TABLE::SetValueAsCustom( int aRow, int aCol, const wxString& aTypeName, void* aValue )
185{
186 wxASSERT( aCol == COL_COLOR );
187 wxASSERT( aTypeName == wxT( "COLOR4D" ) );
188 wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
189
190 m_nets[aRow].color = VoidToColor( aValue );
191 updateNetColor( m_nets[aRow] );
192
193 if( GetView() )
194 {
195 wxGridTableMessage msg( this, wxGRIDTABLE_REQUEST_VIEW_GET_VALUES );
196 GetView()->ProcessTableMessage( msg );
197 }
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 const NETNAMES_MAP& nets = board->GetNetInfo().NetsByName();
227
230
231 std::set<int>& hiddenNets = rs->GetHiddenNets();
232 std::map<int, KIGFX::COLOR4D>& netColors = rs->GetNetColorMap();
233
234 int deleted = m_nets.size();
235 m_nets.clear();
236
237 if( GetView() )
238 {
239 wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, 0, deleted );
240 GetView()->ProcessTableMessage( msg );
241 }
242
243 for( const std::pair<const wxString, NETINFO_ITEM*>& pair : nets )
244 {
245 int netCode = pair.second->GetNetCode();
246
247 if( netCode > 0 && !pair.first.StartsWith( wxT( "unconnected-(" ) ) )
248 {
249 COLOR4D color = netColors.count( netCode ) ? netColors.at( netCode ) :
250 COLOR4D::UNSPECIFIED;
251
252 bool visible = hiddenNets.count( netCode ) == 0;
253
254 m_nets.emplace_back( NET_GRID_ENTRY( netCode, pair.first, color, visible ) );
255 }
256 }
257
258 // TODO(JE) move to ::Compare so we can re-sort easily
259 std::sort( m_nets.begin(), m_nets.end(),
260 []( const NET_GRID_ENTRY& a, const NET_GRID_ENTRY& b )
261 {
262 return a.name < b.name;
263 } );
264
265 if( GetView() )
266 {
267 wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_nets.size() );
268 GetView()->ProcessTableMessage( msg );
269 }
270}
271
272
274{
275 for( NET_GRID_ENTRY& net : m_nets )
276 {
277 net.visible = true;
278 updateNetVisibility( net );
279 }
280
281 if( GetView() )
282 GetView()->ForceRefresh();
283}
284
285
287{
288 for( NET_GRID_ENTRY& net : m_nets )
289 {
290 net.visible = ( net.code == aNet.code );
291 updateNetVisibility( net );
292 }
293
294 if( GetView() )
295 GetView()->ForceRefresh();
296}
297
298
300{
303
304 m_frame->GetToolManager()->RunAction( action, true, static_cast<intptr_t>( aNet.code ) );
305}
306
307
309{
311 KIGFX::PCB_RENDER_SETTINGS* renderSettings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( rs );
312
313 std::map<int, KIGFX::COLOR4D>& netColors = renderSettings->GetNetColorMap();
314
315 if( aNet.color != COLOR4D::UNSPECIFIED )
316 netColors[aNet.code] = aNet.color;
317 else
318 netColors.erase( aNet.code );
319
323}
324
325
328
329#define RR APPEARANCE_CONTROLS::APPEARANCE_SETTING // Render Row abbreviation to reduce source width
330
331 // text id tooltip opacity slider
332 RR( _HKI( "Tracks" ), LAYER_TRACKS, _HKI( "Show tracks" ), true ),
333 RR( _HKI( "Vias" ), LAYER_VIAS, _HKI( "Show all vias" ), true ),
334 RR( _HKI( "Pads" ), LAYER_PADS, _HKI( "Show all pads" ), true ),
335 RR( _HKI( "Zones" ), LAYER_ZONES, _HKI( "Show copper zones" ), true ),
336 RR( _HKI( "Images" ), LAYER_DRAW_BITMAPS, _HKI( "Show user images" ), true ),
337 RR(),
338 RR( _HKI( "Footprints Front" ), LAYER_MOD_FR, _HKI( "Show footprints that are on board's front" ) ),
339 RR( _HKI( "Footprints Back" ), LAYER_MOD_BK, _HKI( "Show footprints that are on board's back" ) ),
340 RR( _HKI( "Through-hole Pads" ), LAYER_PADS_TH, _HKI( "Show through-hole pads" ) ),
341 RR( _HKI( "Values" ), LAYER_MOD_VALUES, _HKI( "Show footprint values" ) ),
342 RR( _HKI( "References" ), LAYER_MOD_REFERENCES, _HKI( "Show footprint references" ) ),
343 RR( _HKI( "Footprint Text" ), LAYER_MOD_TEXT, _HKI( "Show all footprint text" ) ),
344 RR( _HKI( "Hidden Text" ), LAYER_MOD_TEXT_INVISIBLE, _HKI( "Show footprint text marked as invisible" ) ),
345 RR(),
346 RR(),
347 RR( _HKI( "Ratsnest" ), LAYER_RATSNEST, _HKI( "Show unconnected nets as a ratsnest") ),
348 RR( _HKI( "DRC Warnings" ), LAYER_DRC_WARNING, _HKI( "DRC violations with a Warning severity" ) ),
349 RR( _HKI( "DRC Errors" ), LAYER_DRC_ERROR, _HKI( "DRC violations with an Error severity" ) ),
350 RR( _HKI( "DRC Exclusions" ), LAYER_DRC_EXCLUSION, _HKI( "DRC violations which have been individually excluded" ) ),
351 RR( _HKI( "Anchors" ), LAYER_ANCHOR, _HKI( "Show footprint and text origins as a cross" ) ),
352 RR( _HKI( "Locked Item Shadow" ), LAYER_LOCKED_ITEM_SHADOW, _HKI( "Show a shadow marker on locked items" ) ),
353 RR( _HKI( "Drawing Sheet" ), LAYER_DRAWINGSHEET, _HKI( "Show drawing sheet borders and title block" ) ),
354 RR( _HKI( "Grid" ), LAYER_GRID, _HKI( "Show the (x,y) grid dots" ) )
355};
356
358static std::set<int> s_allowedInFpEditor =
359 {
371 };
372
373// These are the built-in layer presets that cannot be deleted
374
376
378
380 LSET::AllCuMask().set( Edge_Cuts ) );
381
384
386 LSET::FrontMask().set( Edge_Cuts ) );
387
390
392 LSET::BackMask().set( Edge_Cuts ) );
393
396
397
399 bool aFpEditorMode ) :
400 APPEARANCE_CONTROLS_BASE( aParent ),
401 m_frame( aParent ),
402 m_focusOwner( aFocusOwner ),
403 m_board( nullptr ),
404 m_isFpEditor( aFpEditorMode ),
405 m_currentPreset( nullptr ),
406 m_lastSelectedUserPreset( nullptr ),
407 m_layerContextMenu( nullptr )
408{
409 DPI_SCALING dpi( nullptr, m_frame );
410
411 int indicatorSize = ConvertDialogToPixels( wxSize( 6, 6 ) ).x / dpi.GetContentScaleFactor();
412 int screenHeight = wxSystemSettings::GetMetric( wxSYS_SCREEN_Y );
413 m_iconProvider = new ROW_ICON_PROVIDER( indicatorSize );
414 m_pointSize = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ).GetPointSize();
415
416 m_layerPanelColour = m_panelLayers->GetBackgroundColour().ChangeLightness( 110 );
417 SetBorders( true, false, false, false );
418
419 m_layersOuterSizer = new wxBoxSizer( wxVERTICAL );
421 m_windowLayers->SetScrollRate( 0, 5 );
422 m_windowLayers->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS::OnSetFocus, this );
423
424 m_objectsOuterSizer = new wxBoxSizer( wxVERTICAL );
426 m_windowObjects->SetScrollRate( 0, 5 );
427 m_windowObjects->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS::OnSetFocus, this );
428
429 wxFont infoFont = KIUI::GetInfoFont( this );
430 m_staticTextNets->SetFont( infoFont );
431 m_staticTextNetClasses->SetFont( infoFont );
432 m_panelLayers->SetFont( infoFont );
433 m_windowLayers->SetFont( infoFont );
434 m_windowObjects->SetFont( infoFont );
435 m_presetsLabel->SetFont( infoFont );
436 m_viewportsLabel->SetFont( infoFont );
437
438 m_cbLayerPresets->SetToolTip( wxString::Format( _( "Save and restore layer visibility combinations.\n"
439 "Use %s+Tab to activate selector.\n"
440 "Successive Tabs while holding %s down will "
441 "cycle through presets in the popup." ),
444
445 m_cbViewports->SetToolTip( wxString::Format( _( "Save and restore view location and zoom.\n"
446 "Use %s+Tab to activate selector.\n"
447 "Successive Tabs while holding %s down will "
448 "cycle through viewports in the popup." ),
451
453
456
459
460 m_txtNetFilter->SetHint( _( "Filter nets" ) );
461
462 if( screenHeight <= 900 && m_pointSize >= indicatorSize )
463 m_pointSize = m_pointSize * 8 / 10;
464
465 wxFont font = m_notebook->GetFont();
466
467#ifdef __WXMAC__
468 font.SetPointSize( m_pointSize );
469 m_notebook->SetFont( font );
470#endif
471
472 auto setHighContrastMode =
473 [&]( HIGH_CONTRAST_MODE aMode )
474 {
476 opts.m_ContrastModeDisplay = aMode;
477
478 m_frame->SetDisplayOptions( opts );
479 passOnFocus();
480 };
481
482 m_rbHighContrastNormal->Bind( wxEVT_RADIOBUTTON,
483 [=]( wxCommandEvent& aEvent )
484 {
485 setHighContrastMode( HIGH_CONTRAST_MODE::NORMAL );
486 } );
487
488 m_rbHighContrastDim->Bind( wxEVT_RADIOBUTTON,
489 [=]( wxCommandEvent& aEvent )
490 {
491 setHighContrastMode( HIGH_CONTRAST_MODE::DIMMED );
492 } );
493
494 m_rbHighContrastOff->Bind( wxEVT_RADIOBUTTON,
495 [=]( wxCommandEvent& aEvent )
496 {
497 setHighContrastMode( HIGH_CONTRAST_MODE::HIDDEN );
498 } );
499
501
502 m_btnNetInspector->Bind( wxEVT_BUTTON,
503 [&]( wxCommandEvent& aEvent )
504 {
506 passOnFocus();
507 } );
508
509 m_btnConfigureNetClasses->Bind( wxEVT_BUTTON,
510 [&]( wxCommandEvent& aEvent )
511 {
512 // This panel should only be visible in the PCB_EDIT_FRAME anyway
513 if( PCB_EDIT_FRAME* editframe = dynamic_cast<PCB_EDIT_FRAME*>( m_frame ) )
514 editframe->ShowBoardSetupDialog( _( "Net Classes" ) );
515
516 passOnFocus();
517 } );
518
519 m_cbFlipBoard->SetValue( m_frame->GetCanvas()->GetView()->IsMirroredX() );
520 m_cbFlipBoard->Bind( wxEVT_CHECKBOX,
521 [&]( wxCommandEvent& aEvent )
522 {
524 } );
525
528
529 m_netsGrid->RegisterDataType( wxT( "bool" ), m_toggleGridRenderer, new wxGridCellBoolEditor );
530
531 m_netsGrid->RegisterDataType( wxT( "COLOR4D" ),
534
535 m_netsTable = new NET_GRID_TABLE( m_frame, m_panelNets->GetBackgroundColour() );
538
539 m_netsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
540 m_netsGrid->SetSelectionForeground( m_netsGrid->GetDefaultCellTextColour() );
541 m_netsGrid->SetSelectionBackground( m_panelNets->GetBackgroundColour() );
542
543 const int cellPadding = 6;
544#ifdef __WXMAC__
545 const int rowHeightPadding = 5;
546#else
547 const int rowHeightPadding = 3;
548#endif
549
550 wxSize size = ConvertDialogToPixels( SWATCH_SIZE_SMALL_DU );
551 m_netsGrid->SetColSize( NET_GRID_TABLE::COL_COLOR, size.x + cellPadding );
552
553 size = KiBitmap( BITMAPS::visibility ).GetSize();
554 m_netsGrid->SetColSize( NET_GRID_TABLE::COL_VISIBILITY, size.x + cellPadding );
555
556 m_netsGrid->SetDefaultCellFont( font );
557 m_netsGrid->SetDefaultRowSize( font.GetPixelSize().y + rowHeightPadding );
558
559 m_netsGrid->GetGridWindow()->Bind( wxEVT_MOTION, &APPEARANCE_CONTROLS::OnNetGridMouseEvent,
560 this );
561
562 // To handle middle click on color swatches
563 m_netsGrid->GetGridWindow()->Bind( wxEVT_MIDDLE_UP, &APPEARANCE_CONTROLS::OnNetGridMouseEvent,
564 this );
565
566 m_netsGrid->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_DEFAULT );
567 m_netclassScrolledWindow->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_DEFAULT );
568
569 if( m_isFpEditor )
570 m_notebook->RemovePage( 2 );
571
573
576
579
583
584 // Grid visibility is loaded and set to the GAL before we are constructed
586
587 Bind( wxEVT_COMMAND_MENU_SELECTED, &APPEARANCE_CONTROLS::OnLayerContextMenu, this,
589}
590
591
593{
595
598
599 delete m_iconProvider;
600}
601
602
604{
605 int hotkey;
606 wxString msg;
607 wxFont infoFont = KIUI::GetInfoFont( this );
608
609 // Create layer display options
611 _( "Layer Display Options" ) );
613 m_paneLayerDisplayOptions->SetBackgroundColour( m_notebook->GetThemeBackgroundColour() );
614
615 wxWindow* layerDisplayPane = m_paneLayerDisplayOptions->GetPane();
616
617 wxBoxSizer* layerDisplayOptionsSizer;
618 layerDisplayOptionsSizer = new wxBoxSizer( wxVERTICAL );
619
621
622 if( hotkey )
623 msg = wxString::Format( _( "Inactive layers (%s):" ), KeyNameFromKeyCode( hotkey ) );
624 else
625 msg = _( "Inactive layers:" );
626
627 m_inactiveLayersLabel = new wxStaticText( layerDisplayPane, wxID_ANY, msg );
628 m_inactiveLayersLabel->SetFont( infoFont );
629 m_inactiveLayersLabel->Wrap( -1 );
630 layerDisplayOptionsSizer->Add( m_inactiveLayersLabel, 0, wxEXPAND | wxBOTTOM, 2 );
631
632 wxBoxSizer* contrastModeSizer;
633 contrastModeSizer = new wxBoxSizer( wxHORIZONTAL );
634
635 m_rbHighContrastNormal = new wxRadioButton( layerDisplayPane, wxID_ANY, _( "Normal" ),
636 wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
637 m_rbHighContrastNormal->SetFont( infoFont );
638 m_rbHighContrastNormal->SetValue( true );
639 m_rbHighContrastNormal->SetToolTip( _( "Inactive layers will be shown in full color" ) );
640
641 contrastModeSizer->Add( m_rbHighContrastNormal, 0, wxRIGHT, 5 );
642 contrastModeSizer->AddStretchSpacer();
643
644 m_rbHighContrastDim = new wxRadioButton( layerDisplayPane, wxID_ANY, _( "Dim" ) );
645 m_rbHighContrastDim->SetFont( infoFont );
646 m_rbHighContrastDim->SetToolTip( _( "Inactive layers will be dimmed" ) );
647
648 contrastModeSizer->Add( m_rbHighContrastDim, 0, wxRIGHT, 5 );
649 contrastModeSizer->AddStretchSpacer();
650
651 m_rbHighContrastOff = new wxRadioButton( layerDisplayPane, wxID_ANY, _( "Hide" ) );
652 m_rbHighContrastOff->SetFont( infoFont );
653 m_rbHighContrastOff->SetToolTip( _( "Inactive layers will be hidden" ) );
654
655 contrastModeSizer->Add( m_rbHighContrastOff, 0, 0, 5 );
656 contrastModeSizer->AddStretchSpacer();
657
658 layerDisplayOptionsSizer->Add( contrastModeSizer, 0, wxEXPAND, 5 );
659
660 m_layerDisplaySeparator = new wxStaticLine( layerDisplayPane, wxID_ANY, wxDefaultPosition,
661 wxDefaultSize, wxLI_HORIZONTAL );
662 layerDisplayOptionsSizer->Add( m_layerDisplaySeparator, 0, wxEXPAND | wxBOTTOM, 3 );
663
664 m_cbFlipBoard = new wxCheckBox( layerDisplayPane, wxID_ANY, _( "Flip board view" ) );
665 m_cbFlipBoard->SetFont( infoFont );
666 layerDisplayOptionsSizer->Add( m_cbFlipBoard, 0, wxTOP | wxBOTTOM, 5 );
667
668 layerDisplayPane->SetSizer( layerDisplayOptionsSizer );
669 layerDisplayPane->Layout();
670 layerDisplayOptionsSizer->Fit( layerDisplayPane );
671
672 m_panelLayersSizer->Add( m_paneLayerDisplayOptions, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 5 );
673
674 m_paneLayerDisplayOptions->Bind( WX_COLLAPSIBLE_PANE_CHANGED,
675 [&]( wxCommandEvent& aEvent )
676 {
677 Freeze();
678 m_panelLayers->Fit();
679 m_sizerOuter->Layout();
680 Thaw();
681 } );
682
683 // Create net display options
684
686 _( "Net Display Options" ) );
688 m_paneNetDisplayOptions->SetBackgroundColour( m_notebook->GetThemeBackgroundColour() );
689
690 wxWindow* netDisplayPane = m_paneNetDisplayOptions->GetPane();
691 wxBoxSizer* netDisplayOptionsSizer = new wxBoxSizer( wxVERTICAL );
692
694
696
697 if( hotkey )
698 msg = wxString::Format( _( "Net colors (%s):" ), KeyNameFromKeyCode( hotkey ) );
699 else
700 msg = _( "Net colors:" );
701
702 m_txtNetDisplayTitle = new wxStaticText( netDisplayPane, wxID_ANY, msg );
703 m_txtNetDisplayTitle->SetFont( infoFont );
704 m_txtNetDisplayTitle->Wrap( -1 );
705 m_txtNetDisplayTitle->SetToolTip( _( "Choose when to show net and netclass colors" ) );
706
707 netDisplayOptionsSizer->Add( m_txtNetDisplayTitle, 0, wxEXPAND | wxBOTTOM | wxLEFT, 2 );
708
709 wxBoxSizer* netColorSizer = new wxBoxSizer( wxHORIZONTAL );
710
711 m_rbNetColorAll = new wxRadioButton( netDisplayPane, wxID_ANY, _( "All" ), wxDefaultPosition,
712 wxDefaultSize, wxRB_GROUP );
713 m_rbNetColorAll->SetFont( infoFont );
714 m_rbNetColorAll->SetToolTip( _( "Net and netclass colors are shown on all copper items" ) );
715
716 netColorSizer->Add( m_rbNetColorAll, 0, wxRIGHT, 5 );
717 netColorSizer->AddStretchSpacer();
718
719 m_rbNetColorRatsnest = new wxRadioButton( netDisplayPane, wxID_ANY, _( "Ratsnest" ) );
720 m_rbNetColorRatsnest->SetFont( infoFont );
721 m_rbNetColorRatsnest->SetValue( true );
722 m_rbNetColorRatsnest->SetToolTip( _( "Net and netclass colors are shown on the ratsnest only" ) );
723
724 netColorSizer->Add( m_rbNetColorRatsnest, 0, wxRIGHT, 5 );
725 netColorSizer->AddStretchSpacer();
726
727 m_rbNetColorOff = new wxRadioButton( netDisplayPane, wxID_ANY, _( "None" ) );
728 m_rbNetColorOff->SetFont( infoFont );
729 m_rbNetColorOff->SetToolTip( _( "Net and netclass colors are not shown" ) );
730
731 netColorSizer->Add( m_rbNetColorOff, 0, 0, 5 );
732
733 netDisplayOptionsSizer->Add( netColorSizer, 0, wxEXPAND | wxBOTTOM, 5 );
734
736
738
739 if( hotkey )
740 msg = wxString::Format( _( "Ratsnest display (%s):" ), KeyNameFromKeyCode( hotkey ) );
741 else
742 msg = _( "Ratsnest display:" );
743
744 m_txtRatsnestVisibility = new wxStaticText( netDisplayPane, wxID_ANY, msg );
745 m_txtRatsnestVisibility->SetFont( infoFont );
746 m_txtRatsnestVisibility->Wrap( -1 );
747 m_txtRatsnestVisibility->SetToolTip( _( "Choose which ratsnest lines to display" ) );
748
749 netDisplayOptionsSizer->Add( m_txtRatsnestVisibility, 0, wxEXPAND | wxBOTTOM | wxLEFT, 2 );
750
751 wxBoxSizer* ratsnestDisplayModeSizer = new wxBoxSizer( wxHORIZONTAL );
752
753 m_rbRatsnestAllLayers = new wxRadioButton( netDisplayPane, wxID_ANY, _( "All" ),
754 wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
755 m_rbRatsnestAllLayers->SetFont( infoFont );
756 m_rbRatsnestAllLayers->SetValue( true );
757 m_rbRatsnestAllLayers->SetToolTip( _( "Show ratsnest lines to items on all layers" ) );
758
759 ratsnestDisplayModeSizer->Add( m_rbRatsnestAllLayers, 0, wxRIGHT, 5 );
760 ratsnestDisplayModeSizer->AddStretchSpacer();
761
762 m_rbRatsnestVisLayers = new wxRadioButton( netDisplayPane, wxID_ANY, _( "Visible layers" ) );
763 m_rbRatsnestVisLayers->SetFont( infoFont );
764 m_rbRatsnestVisLayers->SetToolTip( _( "Show ratsnest lines to items on visible layers" ) );
765
766 ratsnestDisplayModeSizer->Add( m_rbRatsnestVisLayers, 0, wxRIGHT, 5 );
767 ratsnestDisplayModeSizer->AddStretchSpacer();
768
769 m_rbRatsnestNone = new wxRadioButton( netDisplayPane, wxID_ANY, _( "None" ) );
770 m_rbRatsnestNone->SetFont( infoFont );
771 m_rbRatsnestNone->SetToolTip( _( "Hide all ratsnest lines" ) );
772
773 ratsnestDisplayModeSizer->Add( m_rbRatsnestNone, 0, 0, 5 );
774
775 netDisplayOptionsSizer->Add( ratsnestDisplayModeSizer, 0, wxEXPAND | wxBOTTOM, 5 );
776
778
779 netDisplayPane->SetSizer( netDisplayOptionsSizer );
780 netDisplayPane->Layout();
781 netDisplayOptionsSizer->Fit( netDisplayPane );
782
783 m_netsTabOuterSizer->Add( m_paneNetDisplayOptions, 0, wxEXPAND | wxTOP, 5 );
784
785 m_paneNetDisplayOptions->Bind( WX_COLLAPSIBLE_PANE_CHANGED,
786 [&]( wxCommandEvent& aEvent )
787 {
788 Freeze();
790 m_sizerOuter->Layout();
791 passOnFocus();
792 Thaw();
793 } );
794
795 m_rbNetColorAll->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onNetColorMode, this );
796 m_rbNetColorOff->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onNetColorMode, this );
797 m_rbNetColorRatsnest->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onNetColorMode, this );
798
799 m_rbRatsnestAllLayers->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onRatsnestMode, this );
800 m_rbRatsnestVisLayers->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onRatsnestMode, this );
801 m_rbRatsnestNone->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onRatsnestMode, this );
802}
803
804
806{
807 DPI_SCALING dpi( nullptr, m_frame );
808 wxSize size( 220 * dpi.GetScaleFactor(), 480 * dpi.GetScaleFactor() );
809 return size;
810}
811
812
813void APPEARANCE_CONTROLS::OnNotebookPageChanged( wxNotebookEvent& aEvent )
814{
815 // Work around wxMac issue where the notebook pages are blank
816#ifdef __WXMAC__
817 int page = aEvent.GetSelection();
818
819 if( page >= 0 )
820 m_notebook->ChangeSelection( static_cast<unsigned>( page ) );
821#endif
822
823#ifndef __WXMSW__
824 // Because wxWidgets is broken and will send click events to children of the collapsible
825 // panes even if they are collapsed without this
826 Freeze();
827 m_panelLayers->Fit();
829 m_sizerOuter->Layout();
830 Thaw();
831#endif
832
833 Bind( wxEVT_IDLE, &APPEARANCE_CONTROLS::idleFocusHandler, this );
834}
835
836
837void APPEARANCE_CONTROLS::idleFocusHandler( wxIdleEvent& aEvent )
838{
839 passOnFocus();
840 Unbind( wxEVT_IDLE, &APPEARANCE_CONTROLS::idleFocusHandler, this );
841}
842
843
844void APPEARANCE_CONTROLS::OnSetFocus( wxFocusEvent& aEvent )
845{
846#ifdef __WXMSW__
847 // In wxMSW, buttons won't process events unless they have focus, so we'll let it take the
848 // focus and give it back to the parent in the button event handler.
849 if( wxBitmapButton* btn = dynamic_cast<wxBitmapButton*>( aEvent.GetEventObject() ) )
850 {
851 wxCommandEvent evt( wxEVT_BUTTON );
852 wxPostEvent( btn, evt );
853 }
854#endif
855
856 passOnFocus();
857 aEvent.Skip();
858}
859
860
861void APPEARANCE_CONTROLS::OnSize( wxSizeEvent& aEvent )
862{
863 aEvent.Skip();
864}
865
866
867void APPEARANCE_CONTROLS::OnNetGridClick( wxGridEvent& event )
868{
869 int row = event.GetRow();
870 int col = event.GetCol();
871
872 switch( col )
873 {
875 m_netsTable->SetValueAsBool( row, col, !m_netsTable->GetValueAsBool( row, col ) );
876 m_netsGrid->ForceRefresh();
877 break;
878
879 default:
880 break;
881 }
882}
883
884
886{
887 int row = event.GetRow();
888 int col = event.GetCol();
889
890 switch( col )
891 {
893 m_netsGrid->GetCellEditor( row, col )->BeginEdit( row, col, m_netsGrid );
894 break;
895
896 default:
897 break;
898 }
899}
900
901
903{
904 m_netsGrid->SelectRow( event.GetRow() );
905
906 wxString netName = UnescapeString( m_netsGrid->GetCellValue( event.GetRow(),
908 wxMenu menu;
909
910 menu.Append( new wxMenuItem( &menu, ID_SET_NET_COLOR, _( "Set Net Color" ), wxEmptyString,
911 wxITEM_NORMAL ) );
912 menu.Append( new wxMenuItem( &menu, ID_HIGHLIGHT_NET,
913 wxString::Format( _( "Highlight %s" ), netName ), wxEmptyString,
914 wxITEM_NORMAL ) );
915 menu.Append( new wxMenuItem( &menu, ID_SELECT_NET,
916 wxString::Format( _( "Select Tracks and Vias in %s" ), netName ),
917 wxEmptyString, wxITEM_NORMAL ) );
918 menu.Append( new wxMenuItem( &menu, ID_DESELECT_NET,
919 wxString::Format( _( "Unselect Tracks and Vias in %s" ), netName ),
920 wxEmptyString, wxITEM_NORMAL ) );
921
922 menu.AppendSeparator();
923
924 menu.Append( new wxMenuItem( &menu, ID_SHOW_ALL_NETS, _( "Show All Nets" ), wxEmptyString,
925 wxITEM_NORMAL ) );
926 menu.Append( new wxMenuItem( &menu, ID_HIDE_OTHER_NETS, _( "Hide All Other Nets" ),
927 wxEmptyString, wxITEM_NORMAL ) );
928
929 menu.Bind( wxEVT_COMMAND_MENU_SELECTED, &APPEARANCE_CONTROLS::onNetContextMenu, this );
930
931 PopupMenu( &menu );
932}
933
934
936{
937 wxPoint pos = m_netsGrid->CalcUnscrolledPosition( aEvent.GetPosition() );
938 wxGridCellCoords cell = m_netsGrid->XYToCell( pos );
939
940 if( aEvent.Moving() || aEvent.Entering() )
941 {
942 aEvent.Skip();
943
944 if( !cell )
945 {
946 m_netsGrid->GetGridWindow()->UnsetToolTip();
947 return;
948 }
949
950 if( cell == m_hoveredCell )
951 return;
952
953 m_hoveredCell = cell;
954
955 NET_GRID_ENTRY& net = m_netsTable->GetEntry( cell.GetRow() );
956
957 wxString name = net.name;
958 wxString showOrHide = net.visible ? _( "Click to hide ratsnest for %s" )
959 : _( "Click to show ratsnest for %s" );
960 wxString tip;
961
962 if( cell.GetCol() == NET_GRID_TABLE::COL_VISIBILITY )
963 {
964 tip.Printf( showOrHide, name );
965 }
966 else if( cell.GetCol() == NET_GRID_TABLE::COL_COLOR )
967 {
968 tip = _( "Double click (or middle click) to change color; "
969 "right click for more actions" );
970 }
971
972 m_netsGrid->GetGridWindow()->SetToolTip( tip );
973 }
974 else if( aEvent.Leaving() )
975 {
976 m_netsGrid->UnsetToolTip();
977 aEvent.Skip();
978 }
979 else if( aEvent.Dragging() )
980 {
981 // not allowed
982 CallAfter( [&]()
983 {
984 m_netsGrid->ClearSelection();
985 } );
986 }
987 else if( aEvent.ButtonUp( wxMOUSE_BTN_MIDDLE ) && !!cell )
988 {
989 int row = cell.GetRow();
990 int col = cell.GetCol();
991
992 if(col == NET_GRID_TABLE::COL_COLOR )
993 m_netsGrid->GetCellEditor( row, col )->BeginEdit( row, col, m_netsGrid );
994
995 aEvent.Skip();
996 }
997 else
998 {
999 aEvent.Skip();
1000 }
1001}
1002
1003
1005{
1006 m_notebook->SetPageText( 0, _( "Layers" ) );
1007 m_notebook->SetPageText( 1, _( "Objects" ) );
1008 m_notebook->SetPageText( 2, _( "Nets" ) );
1009
1010 Freeze();
1011 rebuildLayers();
1016 rebuildNets();
1017
1021
1023
1024 Thaw();
1025 Refresh();
1026}
1027
1028
1030{
1031 Freeze();
1032 rebuildLayers();
1036 rebuildNets();
1040
1042
1044
1045 if( m_board )
1046 m_board->AddListener( this );
1047
1048 Thaw();
1049 Refresh();
1050}
1051
1052
1054{
1056}
1057
1058
1059void APPEARANCE_CONTROLS::OnNetVisibilityChanged( int aNetCode, bool aVisibility )
1060{
1061 int row = m_netsTable->GetRowByNetcode( aNetCode );
1062
1063 if( row >= 0 )
1064 {
1066 m_netsGrid->ForceRefresh();
1067 }
1068}
1069
1070
1072{
1073 return aBoardItem->Type() == PCB_NETINFO_T;
1074}
1075
1076
1077bool APPEARANCE_CONTROLS::doesBoardItemNeedRebuild( std::vector<BOARD_ITEM*>& aBoardItems )
1078{
1079 bool rebuild = std::any_of( aBoardItems.begin(), aBoardItems.end(),
1080 []( const BOARD_ITEM* a )
1081 {
1082 return a->Type() == PCB_NETINFO_T;
1083 } );
1084
1085 return rebuild;
1086}
1087
1088
1090{
1091 if( doesBoardItemNeedRebuild( aItem ) )
1093}
1094
1095
1096void APPEARANCE_CONTROLS::OnBoardItemsAdded( BOARD& aBoard, std::vector<BOARD_ITEM*>& aItems )
1097{
1098 if( doesBoardItemNeedRebuild( aItems ) )
1100}
1101
1102
1104{
1105 if( doesBoardItemNeedRebuild( aItem ) )
1107}
1108
1109
1110void APPEARANCE_CONTROLS::OnBoardItemsRemoved( BOARD& aBoard, std::vector<BOARD_ITEM*>& aItems )
1111{
1112 if( doesBoardItemNeedRebuild( aItems ) )
1114}
1115
1116
1118{
1119 if( doesBoardItemNeedRebuild( aItem ) )
1121}
1122
1123
1124void APPEARANCE_CONTROLS::OnBoardItemsChanged( BOARD& aBoard, std::vector<BOARD_ITEM*>& aItems )
1125{
1126 if( doesBoardItemNeedRebuild( aItems ) )
1128}
1129
1130
1132{
1133 Freeze();
1134 rebuildNets();
1135 Thaw();
1136}
1137
1138
1140{
1143}
1144
1145
1147{
1148 // This is essentially a list of hacks because DarkMode isn't yet implemented inside
1149 // wxWidgets.
1150 //
1151 // The individual wxPanels, COLOR_SWATCHes and GRID_CELL_COLOR_RENDERERs should really be
1152 // overriding some virtual method or responding to some wxWidgets event so that the parent
1153 // doesn't have to know what it contains. But, that's not where we are, so... :shrug:
1154
1155 m_layerPanelColour = m_panelLayers->GetBackgroundColour().ChangeLightness( 110 );
1156
1157 m_windowLayers->SetBackgroundColour( m_layerPanelColour );
1158
1159 for( wxSizerItem* child : m_layersOuterSizer->GetChildren() )
1160 {
1161 if( child && child->GetWindow() )
1162 child->GetWindow()->SetBackgroundColour( m_layerPanelColour );
1163 }
1164
1165 // Easier than calling OnDarkModeToggle on all the GRID_CELL_COLOR_RENDERERs:
1166 m_netsGrid->RegisterDataType( wxT( "COLOR4D" ),
1169
1170 for( const std::pair<const wxString, APPEARANCE_SETTING*>& pair : m_netclassSettingsMap )
1171 {
1172 if( pair.second->ctl_color )
1173 pair.second->ctl_color->OnDarkModeToggle();
1174 }
1175
1176 OnLayerChanged(); // Update selected highlighting
1177}
1178
1179
1181{
1182 for( const std::unique_ptr<APPEARANCE_SETTING>& setting : m_layerSettings )
1183 {
1184 setting->ctl_panel->SetBackgroundColour( m_layerPanelColour );
1185 setting->ctl_indicator->SetIndicatorState( ROW_ICON_PROVIDER::STATE::OFF );
1186 }
1187
1188 wxChar r = m_layerPanelColour.Red();
1189 wxChar g = m_layerPanelColour.Green();
1190 wxChar b = m_layerPanelColour.Blue();
1191
1192 if( r < 240 || g < 240 || b < 240 )
1193 {
1194 r = wxChar( std::min( (int) r + 15, 255 ) );
1195 g = wxChar( std::min( (int) g + 15, 255 ) );
1196 b = wxChar( std::min( (int) b + 15, 255 ) );
1197 }
1198 else
1199 {
1200 r = wxChar( std::max( (int) r - 15, 0 ) );
1201 g = wxChar( std::max( (int) g - 15, 0 ) );
1202 b = wxChar( std::max( (int) b - 15, 0 ) );
1203 }
1204
1205 PCB_LAYER_ID current = m_frame->GetActiveLayer();
1206
1207 if( !m_layerSettingsMap.count( current ) )
1208 {
1209 wxASSERT( m_layerSettingsMap.count( F_Cu ) );
1210 current = F_Cu;
1211 }
1212
1213 APPEARANCE_SETTING* newSetting = m_layerSettingsMap[ current ];
1214
1215 newSetting->ctl_panel->SetBackgroundColour( wxColour( r, g, b ) );
1217
1218 Refresh();
1219}
1220
1221
1222void APPEARANCE_CONTROLS::SetLayerVisible( int aLayer, bool isVisible )
1223{
1224 LSET visible = getVisibleLayers();
1225 PCB_LAYER_ID layer = ToLAYER_ID( aLayer );
1226
1227 if( visible.test( layer ) == isVisible )
1228 return;
1229
1230 visible.set( layer, isVisible );
1231 setVisibleLayers( visible );
1232
1233 m_frame->GetCanvas()->GetView()->SetLayerVisible( layer, isVisible );
1234
1236}
1237
1238
1240{
1241 if( m_objectSettingsMap.count( aLayer ) )
1242 {
1243 APPEARANCE_SETTING* setting = m_objectSettingsMap.at( aLayer );
1244 setting->ctl_visibility->SetValue( isVisible );
1245 }
1246
1247 m_frame->GetBoard()->SetElementVisibility( aLayer, isVisible );
1248
1249 m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, isVisible );
1251}
1252
1253
1255{
1256 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1257
1258 if( m_isFpEditor )
1259 {
1260 for( PCB_LAYER_ID layer : LSET::AllLayersMask().Seq() )
1261 view->SetLayerVisible( layer, aLayers.Contains( layer ) );
1262 }
1263 else
1264 {
1265 m_frame->GetBoard()->SetVisibleLayers( aLayers );
1266
1267 // Note: KIGFX::REPAINT isn't enough for things that go from invisible to visible as
1268 // they won't be found in the view layer's itemset for repainting.
1270 []( KIGFX::VIEW_ITEM* aItem ) -> bool
1271 {
1272 // Items rendered to composite layers (such as LAYER_PAD_TH) must be redrawn
1273 // whether they're optionally flashed or not (as the layer being hidden/shown
1274 // might be the last layer the item is visible on).
1275 return dynamic_cast<PCB_VIA*>( aItem ) || dynamic_cast<PAD*>( aItem );
1276 } );
1277 }
1278}
1279
1280
1282{
1283 if( m_isFpEditor )
1284 {
1285 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1286
1287 for( size_t i = 0; i < GAL_LAYER_INDEX( LAYER_ZONE_START ); i++ )
1288 view->SetLayerVisible( GAL_LAYER_ID_START + GAL_LAYER_ID( i ), aLayers.test( i ) );
1289 }
1290 else
1291 {
1292 // Ratsnest visibility is controlled by the ratsnest option, and not by the preset
1295
1296 m_frame->GetBoard()->SetVisibleElements( aLayers );
1297 }
1298}
1299
1300
1302{
1303 if( m_isFpEditor )
1304 {
1305 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1306 LSET set;
1307
1308 for( PCB_LAYER_ID layer : LSET::AllLayersMask().Seq() )
1309 set.set( layer, view->IsLayerVisible( layer ) );
1310
1311 return set;
1312 }
1313 else
1314 {
1315 return m_frame->GetBoard()->GetVisibleLayers();
1316 }
1317}
1318
1319
1321{
1322 if( m_isFpEditor )
1323 {
1324 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1325 GAL_SET set;
1326 set.reset();
1327
1328 for( size_t i = 0; i < set.size(); i++ )
1329 set.set( i, view->IsLayerVisible( GAL_LAYER_ID_START + GAL_LAYER_ID( i ) ) );
1330
1331 return set;
1332 }
1333 else
1334 {
1335 return m_frame->GetBoard()->GetVisibleElements();
1336 }
1337}
1338
1339
1341{
1342 const PCB_DISPLAY_OPTIONS& options = m_frame->GetDisplayOptions();
1343
1344 switch( options.m_ContrastModeDisplay )
1345 {
1346 case HIGH_CONTRAST_MODE::NORMAL: m_rbHighContrastNormal->SetValue( true ); break;
1347 case HIGH_CONTRAST_MODE::DIMMED: m_rbHighContrastDim->SetValue( true ); break;
1348 case HIGH_CONTRAST_MODE::HIDDEN: m_rbHighContrastOff->SetValue( true ); break;
1349 }
1350
1351 switch( options.m_NetColorMode )
1352 {
1353 case NET_COLOR_MODE::ALL: m_rbNetColorAll->SetValue( true ); break;
1354 case NET_COLOR_MODE::RATSNEST: m_rbNetColorRatsnest->SetValue( true ); break;
1355 case NET_COLOR_MODE::OFF: m_rbNetColorOff->SetValue( true ); break;
1356 }
1357
1358 m_cbFlipBoard->SetValue( m_frame->GetCanvas()->GetView()->IsMirroredX() );
1359
1360 if( !m_isFpEditor )
1361 {
1363
1365 m_rbRatsnestNone->SetValue( true );
1367 m_rbRatsnestAllLayers->SetValue( true );
1368 else
1369 m_rbRatsnestVisLayers->SetValue( true );
1370
1371 wxASSERT( m_objectSettingsMap.count( LAYER_RATSNEST ) );
1374 }
1375}
1376
1377
1378std::vector<LAYER_PRESET> APPEARANCE_CONTROLS::GetUserLayerPresets() const
1379{
1380 std::vector<LAYER_PRESET> ret;
1381
1382 for( const std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
1383 {
1384 if( !pair.second.readOnly )
1385 ret.emplace_back( pair.second );
1386 }
1387
1388 return ret;
1389}
1390
1391
1392void APPEARANCE_CONTROLS::SetUserLayerPresets( std::vector<LAYER_PRESET>& aPresetList )
1393{
1394 // Reset to defaults
1396
1397 for( const LAYER_PRESET& preset : aPresetList )
1398 {
1399 if( m_layerPresets.count( preset.name ) )
1400 continue;
1401
1402 m_layerPresets[preset.name] = preset;
1403
1404 m_presetMRU.Add( preset.name );
1405 }
1406
1408}
1409
1410
1412{
1413 m_layerPresets.clear();
1414 m_presetMRU.clear();
1415
1416 // Load the read-only defaults
1420 {
1421 m_layerPresets[preset.name] = preset;
1422 m_layerPresets[preset.name].readOnly = true;
1423
1424 m_presetMRU.Add( preset.name );
1425 }
1426}
1427
1428
1429void APPEARANCE_CONTROLS::ApplyLayerPreset( const wxString& aPresetName )
1430{
1431 updateLayerPresetSelection( aPresetName );
1432
1433 wxCommandEvent dummy;
1435}
1436
1437
1439{
1440 if( m_layerPresets.count( aPreset.name ) )
1442 else
1443 m_currentPreset = nullptr;
1444
1446 : nullptr;
1447
1449 doApplyLayerPreset( aPreset );
1450}
1451
1452
1453std::vector<VIEWPORT> APPEARANCE_CONTROLS::GetUserViewports() const
1454{
1455 std::vector<VIEWPORT> ret;
1456
1457 for( const std::pair<const wxString, VIEWPORT>& pair : m_viewports )
1458 ret.emplace_back( pair.second );
1459
1460 return ret;
1461}
1462
1463
1464void APPEARANCE_CONTROLS::SetUserViewports( std::vector<VIEWPORT>& aViewportList )
1465{
1466 m_viewports.clear();
1467
1468 for( const VIEWPORT& viewport : aViewportList )
1469 {
1470 if( m_viewports.count( viewport.name ) )
1471 continue;
1472
1473 m_viewports[viewport.name] = viewport;
1474
1475 m_viewportMRU.Add( viewport.name );
1476 }
1477
1479}
1480
1481
1482void APPEARANCE_CONTROLS::ApplyViewport( const wxString& aViewportName )
1483{
1484 updateViewportSelection( aViewportName );
1485
1486 wxCommandEvent dummy;
1488}
1489
1490
1492{
1493 updateViewportSelection( aViewport.name );
1494 doApplyViewport( aViewport );
1495}
1496
1497
1499{
1500 BOARD* board = m_frame->GetBoard();
1501 LSET enabled = board->GetEnabledLayers();
1502 LSET visible = getVisibleLayers();
1503
1505 COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
1506 bool readOnly = theme->IsReadOnly();
1507
1508#ifdef __WXMAC__
1509 wxSizerItem* m_windowLayersSizerItem = m_panelLayersSizer->GetItem( m_windowLayers );
1510 m_windowLayersSizerItem->SetFlag( m_windowLayersSizerItem->GetFlag() & ~wxTOP );
1511#endif
1512
1513 auto appendLayer =
1514 [&]( std::unique_ptr<APPEARANCE_SETTING>& aSetting )
1515 {
1516 int layer = aSetting->id;
1517
1518 wxPanel* panel = new wxPanel( m_windowLayers, layer );
1519 wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
1520 panel->SetSizer( sizer );
1521
1522 panel->SetBackgroundColour( m_layerPanelColour );
1523
1524 aSetting->visible = visible[layer];
1525
1526 // TODO(JE) consider restyling this indicator
1527 INDICATOR_ICON* indicator = new INDICATOR_ICON( panel, *m_iconProvider,
1528 ROW_ICON_PROVIDER::STATE::OFF,
1529 layer );
1530
1531 COLOR_SWATCH* swatch = new COLOR_SWATCH( panel, COLOR4D::UNSPECIFIED, layer,
1532 bgColor, theme->GetColor( layer ),
1533 SWATCH_SMALL );
1534 swatch->SetToolTip( _( "Double click or middle click for color change, "
1535 "right click for menu" ) );
1536
1537 BITMAP_TOGGLE* btn_visible = new BITMAP_TOGGLE( panel, layer,
1540 aSetting->visible );
1541 btn_visible->SetToolTip( _( "Show or hide this layer" ) );
1542
1543 wxStaticText* label = new wxStaticText( panel, layer, aSetting->label );
1544 label->Wrap( -1 );
1545 label->SetToolTip( aSetting->tooltip );
1546
1547 sizer->AddSpacer( 1 );
1548 sizer->Add( indicator, 0, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1549 sizer->AddSpacer( 5 );
1550 sizer->Add( swatch, 0, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1551 sizer->AddSpacer( 6 );
1552 sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1553 sizer->AddSpacer( 5 );
1554 sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1555
1556 m_layersOuterSizer->Add( panel, 0, wxEXPAND, 0 );
1557
1558 aSetting->ctl_panel = panel;
1559 aSetting->ctl_indicator = indicator;
1560 aSetting->ctl_visibility = btn_visible;
1561 aSetting->ctl_color = swatch;
1562 aSetting->ctl_text = label;
1563
1564 panel->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1565 indicator->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1566 swatch->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1567 label->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1568
1569 btn_visible->Bind( TOGGLE_CHANGED,
1570 [&]( wxCommandEvent& aEvent )
1571 {
1572 wxObject* btn = aEvent.GetEventObject();
1573 int layerId = static_cast<wxWindow*>( btn )->GetId();
1574
1575 onLayerVisibilityToggled( static_cast<PCB_LAYER_ID>( layerId ) );
1576 } );
1577
1578 swatch->Bind( COLOR_SWATCH_CHANGED, &APPEARANCE_CONTROLS::OnColorSwatchChanged,
1579 this );
1581 this ) );
1582 swatch->SetReadOnly( readOnly );
1583
1584 panel->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1585 indicator->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1586 swatch->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1587 btn_visible->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1588 label->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1589 };
1590
1591 auto updateLayer =
1592 [&]( std::unique_ptr<APPEARANCE_SETTING>& aSetting )
1593 {
1594 int layer = aSetting->id;
1595 aSetting->visible = visible[layer];
1596 aSetting->ctl_panel->Show();
1597 aSetting->ctl_panel->SetId( layer );
1598 aSetting->ctl_indicator->SetWindowID( layer );
1599 aSetting->ctl_color->SetWindowID( layer );
1600 aSetting->ctl_color->SetSwatchColor( theme->GetColor( layer ), false );
1601 aSetting->ctl_visibility->SetWindowID( layer );
1602 aSetting->ctl_text->SetLabelText( aSetting->label );
1603 aSetting->ctl_text->SetId( layer );
1604 aSetting->ctl_text->SetToolTip( aSetting->tooltip );
1605 };
1606
1607 // technical layers are shown in this order:
1608 // Because they are static, wxGetTranslation must be explicitly
1609 // called for tooltips.
1610 static const struct {
1611 PCB_LAYER_ID layerId;
1612 wxString tooltip;
1613 } non_cu_seq[] = {
1614 { F_Adhes, _HKI( "Adhesive on board's front" ) },
1615 { B_Adhes, _HKI( "Adhesive on board's back" ) },
1616 { F_Paste, _HKI( "Solder paste on board's front" ) },
1617 { B_Paste, _HKI( "Solder paste on board's back" ) },
1618 { F_SilkS, _HKI( "Silkscreen on board's front" ) },
1619 { B_SilkS, _HKI( "Silkscreen on board's back" ) },
1620 { F_Mask, _HKI( "Solder mask on board's front" ) },
1621 { B_Mask, _HKI( "Solder mask on board's back" ) },
1622 { Dwgs_User, _HKI( "Explanatory drawings" ) },
1623 { Cmts_User, _HKI( "Explanatory comments" ) },
1624 { Eco1_User, _HKI( "User defined meaning" ) },
1625 { Eco2_User, _HKI( "User defined meaning" ) },
1626 { Edge_Cuts, _HKI( "Board's perimeter definition" ) },
1627 { Margin, _HKI( "Board's edge setback outline" ) },
1628 { F_CrtYd, _HKI( "Footprint courtyards on board's front" ) },
1629 { B_CrtYd, _HKI( "Footprint courtyards on board's back" ) },
1630 { F_Fab, _HKI( "Footprint assembly on board's front" ) },
1631 { B_Fab, _HKI( "Footprint assembly on board's back" ) },
1632 { User_1, _HKI( "User defined layer 1" ) },
1633 { User_2, _HKI( "User defined layer 2" ) },
1634 { User_3, _HKI( "User defined layer 3" ) },
1635 { User_4, _HKI( "User defined layer 4" ) },
1636 { User_5, _HKI( "User defined layer 5" ) },
1637 { User_6, _HKI( "User defined layer 6" ) },
1638 { User_7, _HKI( "User defined layer 7" ) },
1639 { User_8, _HKI( "User defined layer 8" ) },
1640 { User_9, _HKI( "User defined layer 9" ) },
1641 };
1642
1643 // There is a spacer added to the end of the list that we need to remove and re-add
1644 // after possibly adding additional layers
1645 if( m_layersOuterSizer->GetItemCount() > 0 )
1646 {
1647 m_layersOuterSizer->Detach( m_layersOuterSizer->GetItemCount() - 1 );
1648 }
1649 // Otherwise, this is the first time we are updating the control, so we need to attach
1650 // the handler
1651 else
1652 {
1653 // Add right click handling to show the context menu when clicking to the free area in
1654 // m_windowLayers (below the layer items)
1655 m_windowLayers->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1656 }
1657
1658 std::size_t total_layers = enabled.CuStack().size();
1659
1660 for( const auto& entry : non_cu_seq )
1661 {
1662 if( enabled[entry.layerId] )
1663 total_layers++;
1664 }
1665
1666 // Adds layers to the panel until we have enough to hold our total count
1667 while( total_layers > m_layerSettings.size() )
1668 m_layerSettings.push_back( std::make_unique<APPEARANCE_SETTING>() );
1669
1670 // We never delete layers from the panel, only hide them. This saves us
1671 // having to recreate the (possibly) later with minimal overhead
1672 for( std::size_t ii = total_layers; ii < m_layerSettings.size(); ++ii )
1673 {
1674 if( m_layerSettings[ii]->ctl_panel )
1675 m_layerSettings[ii]->ctl_panel->Show( false );
1676 }
1677
1678 auto layer_it = m_layerSettings.begin();
1679
1680 // show all coppers first, with front on top, back on bottom, then technical layers
1681 for( LSEQ cu_stack = enabled.CuStack(); cu_stack; ++cu_stack, ++layer_it )
1682 {
1683 PCB_LAYER_ID layer = *cu_stack;
1684 wxString dsc;
1685
1686 switch( layer )
1687 {
1688 case F_Cu: dsc = _( "Front copper layer" ); break;
1689 case B_Cu: dsc = _( "Back copper layer" ); break;
1690 default: dsc = _( "Inner copper layer" ); break;
1691 }
1692
1693 std::unique_ptr<APPEARANCE_SETTING>& setting = *layer_it;
1694
1695 setting->label = board->GetLayerName( layer );
1696 setting->id = layer;
1697 setting->tooltip = dsc;
1698
1699 if( setting->ctl_panel == nullptr )
1700 appendLayer( setting );
1701 else
1702 updateLayer( setting );
1703
1704 m_layerSettingsMap[layer] = setting.get();
1705
1707 {
1708 setting->ctl_text->Disable();
1709 setting->ctl_color->SetToolTip( wxEmptyString );
1710 }
1711 }
1712
1713 for( const auto& entry : non_cu_seq )
1714 {
1715 PCB_LAYER_ID layer = entry.layerId;
1716
1717 if( !enabled[layer] )
1718 continue;
1719
1720 std::unique_ptr<APPEARANCE_SETTING>& setting = *layer_it;
1721
1722 setting->label = board->GetLayerName( layer );
1723 setting->id = layer;
1724 // Because non_cu_seq is created static, we must explicitly call wxGetTranslation for
1725 // texts which are internationalized
1726 setting->tooltip = wxGetTranslation( entry.tooltip );
1727
1728 if( setting->ctl_panel == nullptr )
1729 appendLayer( setting );
1730 else
1731 updateLayer( setting );
1732
1733 m_layerSettingsMap[layer] = setting.get();
1734
1736 {
1737 setting->ctl_text->Disable();
1738 setting->ctl_color->SetToolTip( wxEmptyString );
1739 }
1740
1741 ++layer_it;
1742 }
1743
1744 m_layersOuterSizer->AddSpacer( 10 );
1745 m_windowLayers->SetBackgroundColour( m_layerPanelColour );
1746 m_windowLayers->Layout();
1747
1748 m_paneLayerDisplayOptions->SetLabel( _( "Layer Display Options" ) );
1749
1751 wxString msg;
1752
1753 if( hotkey )
1754 msg = wxString::Format( _( "Inactive layers (%s):" ), KeyNameFromKeyCode( hotkey ) );
1755 else
1756 msg = _( "Inactive layers:" );
1757
1758 m_inactiveLayersLabel->SetLabel( msg );
1759
1760 m_rbHighContrastNormal->SetLabel( _( "Normal" ) );
1761 m_rbHighContrastNormal->SetToolTip( _( "Inactive layers will be shown in full color" ) );
1762
1763 m_rbHighContrastDim->SetLabel( _( "Dim" ) );
1764 m_rbHighContrastDim->SetToolTip( _( "Inactive layers will be dimmed" ) );
1765
1766 m_rbHighContrastOff->SetLabel( _( "Hide" ) );
1767 m_rbHighContrastOff->SetToolTip( _( "Inactive layers will be hidden" ) );
1768
1769 m_cbFlipBoard->SetLabel( _( "Flip board view" ) );
1770}
1771
1772
1774{
1775 delete m_layerContextMenu;
1776 m_layerContextMenu = new wxMenu;
1777
1778 AddMenuItem( m_layerContextMenu, ID_SHOW_ALL_COPPER_LAYERS, _( "Show All Copper Layers" ),
1780 AddMenuItem( m_layerContextMenu, ID_HIDE_ALL_COPPER_LAYERS, _( "Hide All Copper Layers" ),
1782
1783 m_layerContextMenu->AppendSeparator();
1784
1785 AddMenuItem( m_layerContextMenu, ID_HIDE_ALL_BUT_ACTIVE, _( "Hide All Layers But Active" ),
1787
1788 m_layerContextMenu->AppendSeparator();
1789
1790 AddMenuItem( m_layerContextMenu, ID_SHOW_ALL_NON_COPPER, _( "Show All Non Copper Layers" ),
1792
1793 AddMenuItem( m_layerContextMenu, ID_HIDE_ALL_NON_COPPER, _( "Hide All Non Copper Layers" ),
1795
1796 m_layerContextMenu->AppendSeparator();
1797
1798 AddMenuItem( m_layerContextMenu, ID_PRESET_ALL_LAYERS, _( "Show All Layers" ),
1800
1801 AddMenuItem( m_layerContextMenu, ID_PRESET_NO_LAYERS, _( "Hide All Layers" ),
1803
1804 m_layerContextMenu->AppendSeparator();
1805
1806 AddMenuItem( m_layerContextMenu, ID_PRESET_FRONT_ASSEMBLY, _( "Show Only Front Assembly Layers" ),
1808
1809 AddMenuItem( m_layerContextMenu, ID_PRESET_FRONT, _( "Show Only Front Layers" ),
1811
1812 // Only show the internal layer option if internal layers are enabled
1813 if( m_frame->GetBoard()->GetCopperLayerCount() > 2 )
1814 {
1815 AddMenuItem( m_layerContextMenu, ID_PRESET_INNER_COPPER, _( "Show Only Inner Layers" ),
1817 }
1818
1819 AddMenuItem( m_layerContextMenu, ID_PRESET_BACK, _( "Show Only Back Layers" ),
1821
1822 AddMenuItem( m_layerContextMenu, ID_PRESET_BACK_ASSEMBLY, _( "Show Only Back Assembly Layers" ),
1824}
1825
1826
1827void APPEARANCE_CONTROLS::OnLayerContextMenu( wxCommandEvent& aEvent )
1828{
1829 BOARD* board = m_frame->GetBoard();
1830 LSET visible = getVisibleLayers();
1831
1832 PCB_LAYER_ID current = m_frame->GetActiveLayer();
1833
1834 // The new preset. We keep the visibility state of objects:
1835 LAYER_PRESET preset;
1837
1838 switch( aEvent.GetId() )
1839 {
1841 preset.layers = presetNoLayers.layers;
1842 ApplyLayerPreset( preset );
1843 return;
1844
1846 preset.layers = presetAllLayers.layers;
1847 ApplyLayerPreset( preset );
1848 return;
1849
1851 visible |= presetAllCopper.layers;
1852 setVisibleLayers( visible );
1853 break;
1854
1856 preset.layers = presetNoLayers.layers | LSET( current );
1857 ApplyLayerPreset( preset );
1858 break;
1859
1861 visible &= ~presetAllCopper.layers;
1862
1863 if( !visible.test( current ) && visible.count() > 0 )
1864 m_frame->SetActiveLayer( *visible.Seq().begin() );
1865
1866 setVisibleLayers( visible );
1867 break;
1868
1870 visible &= presetAllCopper.layers;
1871
1872 if( !visible.test( current ) && visible.count() > 0 )
1873 m_frame->SetActiveLayer( *visible.Seq().begin() );
1874
1875 setVisibleLayers( visible );
1876 break;
1877
1879 visible |= ~presetAllCopper.layers;
1880
1881 setVisibleLayers( visible );
1882 break;
1883
1886 ApplyLayerPreset( preset );
1887 return;
1888
1889 case ID_PRESET_FRONT:
1890 preset.layers = presetFront.layers;
1891 ApplyLayerPreset( preset );
1892 return;
1893
1896 ApplyLayerPreset( preset );
1897 return;
1898
1899 case ID_PRESET_BACK:
1900 preset.layers = presetBack.layers;
1901 ApplyLayerPreset( preset );
1902 return;
1903
1906 ApplyLayerPreset( preset );
1907 return;
1908 }
1909
1912
1913 if( !m_isFpEditor )
1915
1917}
1918
1919
1921{
1922 return m_notebook->GetSelection();
1923}
1924
1925
1927{
1928 size_t max = m_notebook->GetPageCount();
1929
1930 if( aTab >= 0 && static_cast<size_t>( aTab ) < max )
1931 m_notebook->SetSelection( aTab );
1932}
1933
1934
1936{
1938 bool readOnly = theme->IsReadOnly();
1939 LSET visible = getVisibleLayers();
1940 GAL_SET objects = getVisibleObjects();
1941
1942 Freeze();
1943
1944 for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_layerSettings )
1945 {
1946 int layer = setting->id;
1947
1948 if( setting->ctl_visibility )
1949 setting->ctl_visibility->SetValue( visible[layer] );
1950
1951 if( setting->ctl_color )
1952 {
1953 const COLOR4D& color = theme->GetColor( layer );
1954 setting->ctl_color->SetSwatchColor( color, false );
1955 setting->ctl_color->SetReadOnly( readOnly );
1956 }
1957 }
1958
1959 for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
1960 {
1961 GAL_LAYER_ID layer = static_cast<GAL_LAYER_ID>( setting->id );
1962
1963 if( setting->ctl_visibility )
1964 setting->ctl_visibility->SetValue( objects.Contains( layer ) );
1965
1966 if( setting->ctl_color )
1967 {
1968 const COLOR4D& color = theme->GetColor( layer );
1969 setting->ctl_color->SetSwatchColor( color, false );
1970 setting->ctl_color->SetReadOnly( readOnly );
1971 }
1972 }
1973
1974 // Update indicators and panel background colors
1976
1977 Thaw();
1978
1979 m_windowLayers->Refresh();
1980}
1981
1982
1983void APPEARANCE_CONTROLS::onLayerLeftClick( wxMouseEvent& aEvent )
1984{
1985 wxWindow* eventSource = static_cast<wxWindow*>( aEvent.GetEventObject() );
1986
1987 PCB_LAYER_ID layer = ToLAYER_ID( eventSource->GetId() );
1988
1990 return;
1991
1992 m_frame->SetActiveLayer( layer );
1993 passOnFocus();
1994}
1995
1996
1997void APPEARANCE_CONTROLS::rightClickHandler( wxMouseEvent& aEvent )
1998{
1999 wxASSERT( m_layerContextMenu );
2000 PopupMenu( m_layerContextMenu );
2001 passOnFocus();
2002};
2003
2004
2006{
2007 LSET visibleLayers = getVisibleLayers();
2008
2009 visibleLayers.set( aLayer, !visibleLayers.test( aLayer ) );
2010 setVisibleLayers( visibleLayers );
2011 m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, visibleLayers.test( aLayer ) );
2012
2015}
2016
2017
2019 bool isFinal )
2020{
2021 // Special-case controls
2022 switch( aLayer )
2023 {
2024 case LAYER_RATSNEST:
2025 {
2026 // don't touch the layers. ratsnest is enabled on per-item basis.
2028 m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, true );
2029
2031 {
2033 m_frame->GetBoard()->SetElementVisibility( aLayer, isVisible );
2036 }
2037
2038 break;
2039 }
2040
2041 case LAYER_GRID:
2042 m_frame->SetGridVisibility( isVisible );
2045 break;
2046
2047 case LAYER_MOD_TEXT:
2048 // Because Footprint Text is a meta-control that also can disable values/references,
2049 // drag them along here so that the user is less likely to be confused.
2050 if( isFinal )
2051 {
2052 // Should only trigger when you actually click the Footprint Text button
2053 // Otherwise it goes into infinite recursive loop with the following case section
2055 onObjectVisibilityChanged( LAYER_MOD_VALUES, isVisible, false );
2056 m_objectSettingsMap[LAYER_MOD_REFERENCES]->ctl_visibility->SetValue( isVisible );
2057 m_objectSettingsMap[LAYER_MOD_VALUES]->ctl_visibility->SetValue( isVisible );
2058 }
2059 break;
2060
2062 case LAYER_MOD_VALUES:
2063 // In case that user changes Footprint Value/References when the Footprint Text
2064 // meta-control is disabled, we should put it back on.
2065 if( isVisible )
2066 {
2067 onObjectVisibilityChanged( LAYER_MOD_TEXT, isVisible, false );
2068 m_objectSettingsMap[LAYER_MOD_TEXT]->ctl_visibility->SetValue( isVisible );
2069 }
2070 break;
2071
2072 default:
2073 break;
2074 }
2075
2076 GAL_SET visible = getVisibleObjects();
2077
2078 if( visible.Contains( aLayer ) != isVisible )
2079 {
2080 visible.set( aLayer, isVisible );
2081 setVisibleObjects( visible );
2082 m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, isVisible );
2084 }
2085
2086 if( isFinal )
2087 {
2089 passOnFocus();
2090 }
2091}
2092
2093
2095{
2097 COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
2098 GAL_SET visible = getVisibleObjects();
2099 int swatchWidth = m_windowObjects->ConvertDialogToPixels( wxSize( 8, 0 ) ).x;
2100 int labelWidth = 0;
2101
2102 m_objectSettings.clear();
2103 m_objectsOuterSizer->Clear( true );
2104 m_objectsOuterSizer->AddSpacer( 5 );
2105
2106 auto appendObject =
2107 [&]( const std::unique_ptr<APPEARANCE_SETTING>& aSetting )
2108 {
2109 wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
2110 int layer = aSetting->id;
2111
2112 aSetting->visible = visible.Contains( ToGalLayer( layer ) );
2113 COLOR4D color = theme->GetColor( layer );
2114 COLOR4D defColor = theme->GetDefaultColor( layer );
2115
2116 if( color != COLOR4D::UNSPECIFIED )
2117 {
2118 COLOR_SWATCH* swatch = new COLOR_SWATCH( m_windowObjects, color, layer,
2119 bgColor, defColor, SWATCH_SMALL );
2120 swatch->SetToolTip( _( "Left double click or middle click for color change, "
2121 "right click for menu" ) );
2122
2123 sizer->Add( swatch, 0, wxALIGN_CENTER_VERTICAL, 0 );
2124 aSetting->ctl_color = swatch;
2125
2126 swatch->Bind( COLOR_SWATCH_CHANGED, &APPEARANCE_CONTROLS::OnColorSwatchChanged,
2127 this );
2128
2130 this ) );
2131 }
2132 else
2133 {
2134 sizer->AddSpacer( swatchWidth );
2135 }
2136
2137 BITMAP_TOGGLE* btn_visible = new BITMAP_TOGGLE( m_windowObjects, layer,
2140 aSetting->visible );
2141
2142 wxString tip;
2143 tip.Printf( _( "Show or hide %s" ), aSetting->label.Lower() );
2144 btn_visible->SetToolTip( tip );
2145
2146 aSetting->ctl_visibility = btn_visible;
2147
2148 sizer->AddSpacer( 5 );
2149
2150 btn_visible->Bind( TOGGLE_CHANGED,
2151 [&]( wxCommandEvent& aEvent )
2152 {
2153 int id = static_cast<wxWindow*>( aEvent.GetEventObject() )->GetId();
2154 bool isVisible = aEvent.GetInt();
2155 onObjectVisibilityChanged( ToGalLayer( id ), isVisible, true );
2156 } );
2157
2158 wxStaticText* label = new wxStaticText( m_windowObjects, layer, aSetting->label );
2159 label->Wrap( -1 );
2160 label->SetToolTip( aSetting->tooltip );
2161
2162 if( aSetting->can_control_opacity )
2163 {
2164 label->SetMinSize( wxSize( labelWidth, -1 ) );
2165#ifdef __WXMAC__
2166 sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, 10 );
2167 sizer->AddSpacer( 5 );
2168 sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, 10 );
2169#else
2170 sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL, 0 );
2171 sizer->AddSpacer( 5 );
2172 sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL, 0 );
2173#endif
2174
2175 wxSlider* slider = new wxSlider( m_windowObjects, wxID_ANY, 100, 0, 100,
2176 wxDefaultPosition, wxDefaultSize,
2177 wxSL_HORIZONTAL );
2178#ifdef __WXMAC__
2179 slider->SetMinSize( wxSize( 80, 16 ) );
2180#else
2181 slider->SetMinSize( wxSize( 80, -1 ) );
2182#endif
2183
2184 tip.Printf( _( "Set opacity of %s" ), aSetting->label.Lower() );
2185 slider->SetToolTip( tip );
2186
2187 sizer->Add( slider, 1, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 5 );
2188 aSetting->ctl_opacity = slider;
2189
2190 auto opacitySliderHandler =
2191 [=]( wxCommandEvent& aEvent )
2192 {
2193 wxSlider* ctrl = static_cast<wxSlider*>( aEvent.GetEventObject() );
2194 int value = ctrl->GetValue();
2195 onObjectOpacitySlider( layer, value / 100.0f );
2196 };
2197
2198 slider->Bind( wxEVT_SCROLL_CHANGED, opacitySliderHandler );
2199 slider->Bind( wxEVT_SCROLL_THUMBTRACK, opacitySliderHandler );
2200 slider->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS::OnSetFocus, this );
2201 }
2202 else
2203 {
2204 sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL, 0 );
2205 sizer->AddSpacer( 5 );
2206 sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL, 0 );
2207 }
2208
2209 aSetting->ctl_text = label;
2210 m_objectsOuterSizer->Add( sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, 5 );
2211
2212 if( !aSetting->can_control_opacity )
2213 m_objectsOuterSizer->AddSpacer( 2 );
2214 };
2215
2216 for( const APPEARANCE_SETTING& s_setting : s_objectSettings )
2217 {
2218 if( m_isFpEditor && !s_allowedInFpEditor.count( s_setting.id ) )
2219 continue;
2220
2221 if( !s_setting.spacer )
2222 {
2223 m_objectSettings.emplace_back( std::make_unique<APPEARANCE_SETTING>( s_setting ) );
2224
2225 std::unique_ptr<APPEARANCE_SETTING>& setting = m_objectSettings.back();
2226
2227 // Because s_render_rows is created static, we must explicitly call wxGetTranslation
2228 // for texts which are internationalized (tool tips and item names)
2229 setting->tooltip = wxGetTranslation( s_setting.tooltip );
2230 setting->label = wxGetTranslation( s_setting.label );
2231
2232 if( setting->can_control_opacity )
2233 {
2234 int width = m_windowObjects->GetTextExtent( setting->label ).x + 5;
2235 labelWidth = std::max( labelWidth, width );
2236 }
2237
2238 m_objectSettingsMap[ToGalLayer( setting->id )] = setting.get();
2239 }
2240 }
2241
2242 for( const std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
2243 {
2244 if( setting->spacer )
2245 m_objectsOuterSizer->AddSpacer( m_pointSize );
2246 else
2247 appendObject( setting );
2248 }
2249
2250 m_objectsOuterSizer->Layout();
2251}
2252
2253
2255{
2256 GAL_SET visible = getVisibleObjects();
2257
2259
2260 for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
2261 {
2262 if( setting->spacer )
2263 continue;
2264
2265 GAL_LAYER_ID layer = ToGalLayer( setting->id );
2266
2267 if( setting->ctl_visibility )
2268 setting->ctl_visibility->SetValue( visible.Contains( layer ) );
2269
2270 if( setting->ctl_color )
2271 {
2272 COLOR4D color = m_frame->GetColorSettings()->GetColor( setting->id );
2273 setting->ctl_color->SetSwatchColor( color, false );
2274 }
2275 }
2276
2277 wxASSERT( m_objectSettingsMap.count( LAYER_TRACKS )
2282
2283 m_objectSettingsMap[LAYER_TRACKS]->ctl_opacity->SetValue( opts.m_TrackOpacity * 100 );
2284 m_objectSettingsMap[LAYER_VIAS]->ctl_opacity->SetValue( opts.m_ViaOpacity * 100 );
2285 m_objectSettingsMap[LAYER_PADS]->ctl_opacity->SetValue( opts.m_PadOpacity * 100 );
2286 m_objectSettingsMap[LAYER_ZONES]->ctl_opacity->SetValue( opts.m_ZoneOpacity * 100 );
2287 m_objectSettingsMap[LAYER_DRAW_BITMAPS]->ctl_opacity->SetValue( opts.m_ImageOpacity * 100 );
2288}
2289
2290
2291void APPEARANCE_CONTROLS::buildNetClassMenu( wxMenu& aMenu, bool isDefaultClass,
2292 const wxString& aName )
2293{
2294 if( !isDefaultClass)
2295 {
2296 aMenu.Append( new wxMenuItem( &aMenu, ID_SET_NET_COLOR, _( "Set Netclass Color" ),
2297 wxEmptyString, wxITEM_NORMAL ) );
2298 }
2299
2300 wxString name = UnescapeString( aName );
2301
2302 aMenu.Append( new wxMenuItem( &aMenu, ID_HIGHLIGHT_NET,
2303 wxString::Format( _( "Highlight Nets in %s" ), name ),
2304 wxEmptyString, wxITEM_NORMAL ) );
2305 aMenu.Append( new wxMenuItem( &aMenu, ID_SELECT_NET,
2306 wxString::Format( _( "Select Tracks and Vias in %s" ), name ),
2307 wxEmptyString, wxITEM_NORMAL ) );
2308 aMenu.Append( new wxMenuItem( &aMenu, ID_DESELECT_NET,
2309 wxString::Format( _( "Unselect Tracks and Vias in %s" ), name ),
2310 wxEmptyString, wxITEM_NORMAL ) );
2311
2312 aMenu.AppendSeparator();
2313
2314 aMenu.Append( new wxMenuItem( &aMenu, ID_SHOW_ALL_NETS, _( "Show All Netclasses" ),
2315 wxEmptyString, wxITEM_NORMAL ) );
2316 aMenu.Append( new wxMenuItem( &aMenu, ID_HIDE_OTHER_NETS, _( "Hide All Other Netclasses" ),
2317 wxEmptyString, wxITEM_NORMAL ) );
2318
2319 aMenu.Bind( wxEVT_COMMAND_MENU_SELECTED, &APPEARANCE_CONTROLS::onNetclassContextMenu, this );
2320
2321}
2322
2323
2325{
2326 BOARD* board = m_frame->GetBoard();
2328 COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
2329
2330 // If the board isn't fully loaded, we can't yet rebuild
2331 if( !board->GetProject() )
2332 return;
2333
2334 m_staticTextNets->SetLabel( _( "Nets" ) );
2335 m_staticTextNetClasses->SetLabel( _( "Net Classes" ) );
2336
2339
2340 std::map<wxString, KIGFX::COLOR4D>& netclassColors = rs->GetNetclassColorMap();
2341 const std::set<wxString>& hiddenClasses = m_frame->Prj().GetLocalSettings().m_HiddenNetclasses;
2342
2343 m_netclassOuterSizer->Clear( true );
2344
2345 auto appendNetclass =
2346 [&]( int aId, const std::shared_ptr<NETCLASS>& aClass, bool isDefaultClass = false )
2347 {
2348 wxString name = aClass->GetName();
2349
2350 m_netclassSettings.emplace_back( std::make_unique<APPEARANCE_SETTING>() );
2351 APPEARANCE_SETTING* setting = m_netclassSettings.back().get();
2352 m_netclassSettingsMap[name] = setting;
2353
2354 setting->ctl_panel = new wxPanel( m_netclassScrolledWindow, aId );
2355 wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
2356 setting->ctl_panel->SetSizer( sizer );
2357 COLOR4D color = netclassColors.count( name ) ? netclassColors.at( name ) :
2358 COLOR4D::UNSPECIFIED;
2359
2360 setting->ctl_color = new COLOR_SWATCH( setting->ctl_panel, color, aId, bgColor,
2361 COLOR4D::UNSPECIFIED, SWATCH_SMALL );
2362 setting->ctl_color->SetToolTip( _( "Left double click or middle click for color "
2363 "change, right click for menu" ) );
2364
2365 setting->ctl_color->Bind( COLOR_SWATCH_CHANGED,
2367
2368 // Default netclass can't have an override color
2369 if( isDefaultClass )
2370 setting->ctl_color->Hide();
2371
2372 setting->ctl_visibility = new BITMAP_TOGGLE( setting->ctl_panel, aId,
2375 !hiddenClasses.count( name ) );
2376
2377 wxString tip;
2378 tip.Printf( _( "Show or hide ratsnest for nets in %s" ), name );
2379 setting->ctl_visibility->SetToolTip( tip );
2380
2381 setting->ctl_text = new wxStaticText( setting->ctl_panel, aId, name );
2382 setting->ctl_text->Wrap( -1 );
2383
2384 int flags = wxALIGN_CENTER_VERTICAL;
2385
2386 sizer->Add( setting->ctl_color, 0, flags | wxRESERVE_SPACE_EVEN_IF_HIDDEN, 5 );
2387 sizer->AddSpacer( 7 );
2388 sizer->Add( setting->ctl_visibility, 0, flags, 5 );
2389 sizer->AddSpacer( 3 );
2390 sizer->Add( setting->ctl_text, 1, flags, 5 );
2391
2392 m_netclassOuterSizer->Add( setting->ctl_panel, 0, wxEXPAND, 5 );
2393 m_netclassOuterSizer->AddSpacer( 2 );
2394
2395 setting->ctl_visibility->Bind( TOGGLE_CHANGED,
2397 this );
2398
2399 auto menuHandler =
2400 [&, name, isDefaultClass]( wxMouseEvent& aEvent )
2401 {
2402 wxMenu menu;
2403 buildNetClassMenu( menu, isDefaultClass, name );
2404
2406 PopupMenu( &menu );
2407 };
2408
2409 setting->ctl_panel->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2410 setting->ctl_visibility->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2411 setting->ctl_color->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2412 setting->ctl_text->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2413 };
2414
2415 std::shared_ptr<NET_SETTINGS>& netSettings = board->GetDesignSettings().m_NetSettings;
2416
2417 std::vector<wxString> names;
2418
2419 for( const auto& [ name, netclass ] : netSettings->m_NetClasses )
2420 names.emplace_back( name );
2421
2422 std::sort( names.begin(), names.end() );
2423
2424 m_netclassIdMap.clear();
2425
2426 int idx = wxID_HIGHEST;
2427
2428 m_netclassIdMap[idx] = netSettings->m_DefaultNetClass->GetName();
2429 appendNetclass( idx++, netSettings->m_DefaultNetClass, true );
2430
2431 for( const wxString& name : names )
2432 {
2433 m_netclassIdMap[idx] = name;
2434 appendNetclass( idx++, netSettings->m_NetClasses.at( name ) );
2435 }
2436
2437 int hotkey;
2438 wxString msg;
2439
2440 m_paneNetDisplayOptions->SetLabel( _( "Net Display Options" ) );
2441
2443
2444 if( hotkey )
2445 msg = wxString::Format( _( "Net colors (%s):" ), KeyNameFromKeyCode( hotkey ) );
2446 else
2447 msg = _( "Net colors:" );
2448
2449 m_txtNetDisplayTitle->SetLabel( msg );
2450 m_txtNetDisplayTitle->SetToolTip( _( "Choose when to show net and netclass colors" ) );
2451
2452 m_rbNetColorAll->SetLabel( _( "All" ) );
2453 m_rbNetColorAll->SetToolTip( _( "Net and netclass colors are shown on all copper items" ) );
2454
2455 m_rbNetColorRatsnest->SetLabel( _( "Ratsnest" ) );
2456 m_rbNetColorRatsnest->SetToolTip( _( "Net and netclass colors are shown on the ratsnest only" ) );
2457
2458 m_rbNetColorOff->SetLabel( _( "None" ) );
2459 m_rbNetColorOff->SetToolTip( _( "Net and netclass colors are not shown" ) );
2460
2462
2463 if( hotkey )
2464 msg = wxString::Format( _( "Ratsnest display (%s):" ), KeyNameFromKeyCode( hotkey ) );
2465 else
2466 msg = _( "Ratsnest display:" );
2467
2468 m_txtRatsnestVisibility->SetLabel( msg );
2469 m_txtRatsnestVisibility->SetToolTip( _( "Choose which ratsnest lines to display" ) );
2470
2471 m_rbRatsnestAllLayers->SetLabel( _( "All" ) );
2472 m_rbRatsnestAllLayers->SetToolTip( _( "Show ratsnest lines to items on all layers" ) );
2473
2474 m_rbRatsnestVisLayers->SetLabel( _( "Visible layers" ) );
2475 m_rbRatsnestVisLayers->SetToolTip( _( "Show ratsnest lines to items on visible layers" ) );
2476
2477 m_rbRatsnestNone->SetLabel( _( "None" ) );
2478 m_rbRatsnestNone->SetToolTip( _( "Hide all ratsnest lines" ) );
2479
2480 m_netclassOuterSizer->Layout();
2481
2483 m_panelNets->GetSizer()->Layout();
2484}
2485
2486
2488{
2489 m_viewportsLabel->SetLabel( wxString::Format( _( "Presets (%s+Tab):" ),
2491
2492 m_cbLayerPresets->Clear();
2493
2494 // Build the layers preset list.
2495 // By default, the presetAllLayers will be selected
2496 int idx = 0;
2497 int default_idx = 0;
2498
2499 for( std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
2500 {
2501 m_cbLayerPresets->Append( wxGetTranslation( pair.first ),
2502 static_cast<void*>( &pair.second ) );
2503
2504 if( pair.first == presetAllLayers.name )
2505 default_idx = idx;
2506
2507 idx++;
2508 }
2509
2510 m_cbLayerPresets->Append( wxT( "---" ) );
2511 m_cbLayerPresets->Append( _( "Save preset..." ) );
2512 m_cbLayerPresets->Append( _( "Delete preset..." ) );
2513
2514 // At least the built-in presets should always be present
2515 wxASSERT( !m_layerPresets.empty() );
2516
2517 // Default preset: all layers
2518 m_cbLayerPresets->SetSelection( default_idx );
2520}
2521
2522
2524{
2525 LSET visibleLayers = getVisibleLayers();
2526 GAL_SET visibleObjects = getVisibleObjects();
2527
2528 auto it = std::find_if( m_layerPresets.begin(), m_layerPresets.end(),
2529 [&]( const std::pair<const wxString, LAYER_PRESET>& aPair )
2530 {
2531 return ( aPair.second.layers == visibleLayers
2532 && aPair.second.renderLayers == visibleObjects );
2533 } );
2534
2535 if( it != m_layerPresets.end() )
2536 {
2537 // Select the right m_cbLayersPresets item.
2538 // but these items are translated if they are predefined items.
2539 bool do_translate = it->second.readOnly;
2540 wxString text = do_translate ? wxGetTranslation( it->first ) : it->first;
2541
2542 m_cbLayerPresets->SetStringSelection( text );
2543 }
2544 else
2545 {
2546 m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator
2547 }
2548
2549 m_currentPreset = static_cast<LAYER_PRESET*>(
2550 m_cbLayerPresets->GetClientData( m_cbLayerPresets->GetSelection() ) );
2551}
2552
2553
2555{
2556 // look at m_layerPresets to know if aName is a read only preset, or a user preset.
2557 // Read only presets have translated names in UI, so we have to use
2558 // a translated name in UI selection.
2559 // But for a user preset name we should search for aName (not translated)
2560 wxString ui_label = aName;
2561
2562 for( std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
2563 {
2564 if( pair.first != aName )
2565 continue;
2566
2567 if( pair.second.readOnly == true )
2568 ui_label = wxGetTranslation( aName );
2569
2570 break;
2571 }
2572
2573 int idx = m_cbLayerPresets->FindString( ui_label );
2574
2575 if( idx >= 0 && m_cbLayerPresets->GetSelection() != idx )
2576 {
2577 m_cbLayerPresets->SetSelection( idx );
2578 m_currentPreset = static_cast<LAYER_PRESET*>( m_cbLayerPresets->GetClientData( idx ) );
2579 }
2580 else if( idx < 0 )
2581 {
2582 m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator
2583 }
2584}
2585
2586
2587void APPEARANCE_CONTROLS::onLayerPresetChanged( wxCommandEvent& aEvent )
2588{
2589 int count = m_cbLayerPresets->GetCount();
2590 int index = m_cbLayerPresets->GetSelection();
2591
2592 auto resetSelection =
2593 [&]()
2594 {
2595 if( m_currentPreset )
2596 m_cbLayerPresets->SetStringSelection( m_currentPreset->name );
2597 else
2598 m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 );
2599 };
2600
2601 if( index == count - 3 )
2602 {
2603 // Separator: reject the selection
2604 resetSelection();
2605 return;
2606 }
2607 else if( index == count - 2 )
2608 {
2609 // Save current state to new preset
2610 wxString name;
2611
2614
2615 wxTextEntryDialog dlg( this, _( "Layer preset name:" ), _( "Save Layer Preset" ), name );
2616
2617 if( dlg.ShowModal() != wxID_OK )
2618 {
2619 resetSelection();
2620 return;
2621 }
2622
2623 name = dlg.GetValue();
2624 bool exists = m_layerPresets.count( name );
2625
2626 if( !exists )
2627 {
2630 }
2631
2632 LAYER_PRESET* preset = &m_layerPresets[name];
2633 m_currentPreset = preset;
2634
2635 if( !exists )
2636 {
2637 index = m_cbLayerPresets->Insert( name, index - 1, static_cast<void*>( preset ) );
2638 }
2639 else
2640 {
2641 preset->layers = getVisibleLayers();
2642 preset->renderLayers = getVisibleObjects();
2643
2644 index = m_cbLayerPresets->FindString( name );
2645 m_presetMRU.Remove( name );
2646 }
2647
2648 m_cbLayerPresets->SetSelection( index );
2649 m_presetMRU.Insert( name, 0 );
2650
2651 return;
2652 }
2653 else if( index == count - 1 )
2654 {
2655 // Delete a preset
2656 wxArrayString headers;
2657 std::vector<wxArrayString> items;
2658
2659 headers.Add( _( "Presets" ) );
2660
2661 for( std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
2662 {
2663 if( !pair.second.readOnly )
2664 {
2665 wxArrayString item;
2666 item.Add( pair.first );
2667 items.emplace_back( item );
2668 }
2669 }
2670
2671 EDA_LIST_DIALOG dlg( m_frame, _( "Delete Preset" ), headers, items );
2672 dlg.SetListLabel( _( "Select preset:" ) );
2673
2674 if( dlg.ShowModal() == wxID_OK )
2675 {
2676 wxString presetName = dlg.GetTextSelection();
2677 int idx = m_cbLayerPresets->FindString( presetName );
2678
2679 if( idx != wxNOT_FOUND )
2680 {
2681 m_layerPresets.erase( presetName );
2682
2683 m_cbLayerPresets->Delete( idx );
2684 m_currentPreset = nullptr;
2685
2686 m_presetMRU.Remove( presetName );
2687 }
2688 }
2689
2690 resetSelection();
2691 return;
2692 }
2693
2694 LAYER_PRESET* preset = static_cast<LAYER_PRESET*>( m_cbLayerPresets->GetClientData( index ) );
2695 m_currentPreset = preset;
2696
2697 m_lastSelectedUserPreset = ( !preset || preset->readOnly ) ? nullptr : preset;
2698
2699 if( preset )
2700 doApplyLayerPreset( *preset );
2701
2702 if( !m_currentPreset->name.IsEmpty() )
2703 {
2704 m_presetMRU.Remove( m_currentPreset->name );
2705 m_presetMRU.Insert( m_currentPreset->name, 0 );
2706 }
2707
2708 passOnFocus();
2709}
2710
2711
2713{
2714 BOARD* board = m_frame->GetBoard();
2715
2716 setVisibleLayers( aPreset.layers );
2718
2719 // If the preset doesn't have an explicit active layer to restore, we can at least
2720 // force the active layer to be something in the preset's layer set
2721 PCB_LAYER_ID activeLayer = UNSELECTED_LAYER;
2722
2723 if( aPreset.activeLayer != UNSELECTED_LAYER )
2724 activeLayer = aPreset.activeLayer;
2725 else if( aPreset.layers.any() && !aPreset.layers.test( m_frame->GetActiveLayer() ) )
2726 activeLayer = *aPreset.layers.Seq().begin();
2727
2728 LSET boardLayers = board->GetLayerSet();
2729
2730 if( activeLayer != UNSELECTED_LAYER && boardLayers.Contains( activeLayer ) )
2731 m_frame->SetActiveLayer( activeLayer );
2732
2733 if( !m_isFpEditor )
2735
2737
2739}
2740
2741
2743{
2744 m_viewportsLabel->SetLabel( wxString::Format( _( "Viewports (%s+Tab):" ),
2746
2747 m_cbViewports->Clear();
2748
2749 for( std::pair<const wxString, VIEWPORT>& pair : m_viewports )
2750 m_cbViewports->Append( pair.first, static_cast<void*>( &pair.second ) );
2751
2752 m_cbViewports->Append( wxT( "---" ) );
2753 m_cbViewports->Append( _( "Save viewport..." ) );
2754 m_cbViewports->Append( _( "Delete viewport..." ) );
2755
2756 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 );
2757 m_lastSelectedViewport = nullptr;
2758}
2759
2760
2762{
2763 int idx = m_cbViewports->FindString( aName );
2764
2765 if( idx >= 0 && idx < (int)m_cbViewports->GetCount() - 3 /* separator */ )
2766 {
2767 m_cbViewports->SetSelection( idx );
2768 m_lastSelectedViewport = static_cast<VIEWPORT*>( m_cbViewports->GetClientData( idx ) );
2769 }
2770 else if( idx < 0 )
2771 {
2772 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 ); // separator
2773 m_lastSelectedViewport = nullptr;
2774 }
2775}
2776
2777
2778void APPEARANCE_CONTROLS::onViewportChanged( wxCommandEvent& aEvent )
2779{
2780 int count = m_cbViewports->GetCount();
2781 int index = m_cbViewports->GetSelection();
2782
2783 if( index >= 0 && index < count - 3 )
2784 {
2785 VIEWPORT* viewport = static_cast<VIEWPORT*>( m_cbViewports->GetClientData( index ) );
2786
2787 wxCHECK( viewport, /* void */ );
2788
2789 doApplyViewport( *viewport );
2790
2791 if( !viewport->name.IsEmpty() )
2792 {
2793 m_viewportMRU.Remove( viewport->name );
2794 m_viewportMRU.Insert( viewport->name, 0 );
2795 }
2796 }
2797 else if( index == count - 2 )
2798 {
2799 // Save current state to new preset
2800 wxString name;
2801
2802 wxTextEntryDialog dlg( this, _( "Viewport name:" ), _( "Save Viewport" ), name );
2803
2804 if( dlg.ShowModal() != wxID_OK )
2805 {
2807 m_cbViewports->SetStringSelection( m_lastSelectedViewport->name );
2808 else
2809 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 );
2810
2811 return;
2812 }
2813
2814 name = dlg.GetValue();
2815 bool exists = m_viewports.count( name );
2816
2817 if( !exists )
2818 {
2820
2821 index = m_cbViewports->Insert( name, index-1, static_cast<void*>( &m_viewports[name] ) );
2822 }
2823 else
2824 {
2826 index = m_cbViewports->FindString( name );
2827 m_viewportMRU.Remove( name );
2828 }
2829
2830 m_cbViewports->SetSelection( index );
2831 m_viewportMRU.Insert( name, 0 );
2832
2833 return;
2834 }
2835 else if( index == count - 1 )
2836 {
2837 // Delete an existing viewport
2838 wxArrayString headers;
2839 std::vector<wxArrayString> items;
2840
2841 headers.Add( _( "Viewports" ) );
2842
2843 for( std::pair<const wxString, VIEWPORT>& pair : m_viewports )
2844 {
2845 wxArrayString item;
2846 item.Add( pair.first );
2847 items.emplace_back( item );
2848 }
2849
2850 EDA_LIST_DIALOG dlg( m_frame, _( "Delete Viewport" ), headers, items );
2851 dlg.SetListLabel( _( "Select viewport:" ) );
2852
2853 if( dlg.ShowModal() == wxID_OK )
2854 {
2855 wxString viewportName = dlg.GetTextSelection();
2856 int idx = m_cbViewports->FindString( viewportName );
2857
2858 if( idx != wxNOT_FOUND )
2859 {
2860 m_viewports.erase( viewportName );
2861 m_cbViewports->Delete( idx );
2862 m_viewportMRU.Remove( viewportName );
2863 }
2864 }
2865
2867 m_cbViewports->SetStringSelection( m_lastSelectedViewport->name );
2868 else
2869 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 );
2870
2871 return;
2872 }
2873
2874 passOnFocus();
2875}
2876
2877
2879{
2880 m_frame->GetCanvas()->GetView()->SetViewport( aViewport.rect );
2882}
2883
2884
2885void APPEARANCE_CONTROLS::OnColorSwatchChanged( wxCommandEvent& aEvent )
2886{
2887 COLOR_SWATCH* swatch = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
2888 COLOR4D newColor = swatch->GetSwatchColor();
2889 int layer = swatch->GetId();
2890
2892 cs->SetColor( layer, newColor );
2893
2895
2896 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
2897 view->UpdateLayerColor( layer );
2898 view->UpdateLayerColor( GetNetnameLayer( layer ) );
2899
2900 if( IsCopperLayer( layer ) )
2901 view->UpdateLayerColor( ZONE_LAYER_FOR( layer ) );
2902
2903 if( layer == F_Cu )
2905 else if( layer == B_Cu )
2907
2908 // Update the bitmap of the layer box
2910 static_cast<PCB_EDIT_FRAME*>( m_frame )->ReCreateLayerBox( false );
2911
2913
2914 if( layer == LAYER_PCB_BACKGROUND )
2915 m_frame->SetDrawBgColor( newColor );
2916
2917 passOnFocus();
2918}
2919
2920
2921void APPEARANCE_CONTROLS::onObjectOpacitySlider( int aLayer, float aOpacity )
2922{
2924
2925 switch( aLayer )
2926 {
2927 case static_cast<int>( LAYER_TRACKS ): options.m_TrackOpacity = aOpacity; break;
2928 case static_cast<int>( LAYER_VIAS ): options.m_ViaOpacity = aOpacity; break;
2929 case static_cast<int>( LAYER_PADS ): options.m_PadOpacity = aOpacity; break;
2930 case static_cast<int>( LAYER_ZONES ): options.m_ZoneOpacity = aOpacity; break;
2931 case static_cast<int>( LAYER_DRAW_BITMAPS ): options.m_ImageOpacity = aOpacity; break;
2932 default: return;
2933 }
2934
2935 m_frame->SetDisplayOptions( options );
2936 passOnFocus();
2937}
2938
2939
2940void APPEARANCE_CONTROLS::onNetContextMenu( wxCommandEvent& aEvent )
2941{
2942 wxASSERT( m_netsGrid->GetSelectedRows().size() == 1 );
2943
2944 int row = m_netsGrid->GetSelectedRows()[0];
2945 NET_GRID_ENTRY& net = m_netsTable->GetEntry( row );
2946
2947 m_netsGrid->ClearSelection();
2948
2949 switch( aEvent.GetId() )
2950 {
2951 case ID_SET_NET_COLOR:
2952 {
2953 wxGridCellEditor* editor = m_netsGrid->GetCellEditor( row, NET_GRID_TABLE::COL_COLOR );
2954 editor->BeginEdit( row, NET_GRID_TABLE::COL_COLOR, m_netsGrid );
2955 break;
2956 }
2957
2958 case ID_HIGHLIGHT_NET:
2960 static_cast<intptr_t>( net.code ) );
2962 break;
2963
2964 case ID_SELECT_NET:
2966 static_cast<intptr_t>( net.code ) );
2968 break;
2969
2970 case ID_DESELECT_NET:
2972 static_cast<intptr_t>( net.code ) );
2974 break;
2975
2976 case ID_SHOW_ALL_NETS:
2978 break;
2979
2980 case ID_HIDE_OTHER_NETS:
2981 m_netsTable->HideOtherNets( net );
2982 break;
2983
2984 default:
2985 break;
2986 }
2987
2988 passOnFocus();
2989}
2990
2991
2993{
2994 wxString className = netclassNameFromEvent( aEvent );
2995 bool show = aEvent.GetInt();
2996 showNetclass( className, show );
2997 passOnFocus();
2998}
2999
3000
3001void APPEARANCE_CONTROLS::showNetclass( const wxString& aClassName, bool aShow )
3002{
3003 for( NETINFO_ITEM* net : m_frame->GetBoard()->GetNetInfo() )
3004 {
3005 if( net->GetNetClass()->GetName() == aClassName )
3006 {
3009 true,
3010 static_cast<intptr_t>( net->GetNetCode() ) );
3011
3012 int row = m_netsTable->GetRowByNetcode( net->GetNetCode() );
3013
3014 if( row >= 0 )
3016 }
3017 }
3018
3019 PROJECT_LOCAL_SETTINGS& localSettings = m_frame->Prj().GetLocalSettings();
3020
3021 if( !aShow )
3022 localSettings.m_HiddenNetclasses.insert( aClassName );
3023 else
3024 localSettings.m_HiddenNetclasses.erase( aClassName );
3025
3026 m_netsGrid->ForceRefresh();
3027}
3028
3029
3031{
3034
3035 std::map<wxString, KIGFX::COLOR4D>& netclassColors = rs->GetNetclassColorMap();
3036
3037 COLOR_SWATCH* swatch = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
3038 wxString netclassName = netclassNameFromEvent( aEvent );
3039
3040 netclassColors[netclassName] = swatch->GetSwatchColor();
3041
3045}
3046
3047
3049{
3050 COLOR_SWATCH* s = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
3051 int classId = s->GetId();
3052
3053 wxASSERT( m_netclassIdMap.count( classId ) );
3054 return m_netclassIdMap.at( classId );
3055}
3056
3057
3058void APPEARANCE_CONTROLS::onNetColorMode( wxCommandEvent& aEvent )
3059{
3061
3062 if( m_rbNetColorAll->GetValue() )
3064 else if( m_rbNetColorRatsnest->GetValue() )
3066 else
3068
3069 m_frame->SetDisplayOptions( options );
3071 passOnFocus();
3072}
3073
3074
3075void APPEARANCE_CONTROLS::onRatsnestMode( wxCommandEvent& aEvent )
3076{
3078
3079 if( m_rbRatsnestAllLayers->GetValue() )
3080 {
3081 cfg->m_Display.m_ShowGlobalRatsnest = true;
3083 }
3084 else if( m_rbRatsnestVisLayers->GetValue() )
3085 {
3086 cfg->m_Display.m_ShowGlobalRatsnest = true;
3088 }
3089 else
3090 {
3091 cfg->m_Display.m_ShowGlobalRatsnest = false;
3092 }
3093
3094 if( PCB_EDIT_FRAME* editframe = dynamic_cast<PCB_EDIT_FRAME*>( m_frame ) )
3095 {
3096 editframe->SetElementVisibility( LAYER_RATSNEST, cfg->m_Display.m_ShowGlobalRatsnest );
3097 editframe->OnDisplayOptionsChanged();
3098 editframe->GetCanvas()->RedrawRatsnest();
3099 editframe->GetCanvas()->Refresh();
3100 }
3101 passOnFocus();
3102}
3103
3104
3106{
3107 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
3109 static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
3110
3111 BOARD* board = m_frame->GetBoard();
3112 std::shared_ptr<NET_SETTINGS>& netSettings = board->GetDesignSettings().m_NetSettings;
3113 APPEARANCE_SETTING* setting = nullptr;
3114
3116
3117 if( it != m_netclassSettingsMap.end() )
3118 setting = it->second;
3119
3120 auto runOnNetsOfClass =
3121 [&]( const wxString& netClassName, std::function<void( NETINFO_ITEM* )> aFunction )
3122 {
3123 for( NETINFO_ITEM* net : board->GetNetInfo() )
3124 {
3125 if( net->GetNetClass()->GetName() == netClassName )
3126 aFunction( net );
3127 }
3128 };
3129
3130 switch( aEvent.GetId() )
3131 {
3132 case ID_SET_NET_COLOR:
3133 if( setting )
3134 {
3135 setting->ctl_color->GetNewSwatchColor();
3136
3137 COLOR4D color = setting->ctl_color->GetSwatchColor();
3138
3139 std::map<wxString, KIGFX::COLOR4D>& netclassColors = rs->GetNetclassColorMap();
3140
3141 if( color != COLOR4D::UNSPECIFIED )
3142 netclassColors[m_contextMenuNetclass] = color;
3143 else
3144 netclassColors.erase( m_contextMenuNetclass );
3145
3146 view->UpdateAllLayersColor();
3147 }
3148
3149 break;
3150
3151 case ID_HIGHLIGHT_NET:
3152 if( !m_contextMenuNetclass.IsEmpty() )
3153 {
3154 runOnNetsOfClass( m_contextMenuNetclass,
3155 [&]( NETINFO_ITEM* aItem )
3156 {
3157 static bool first = true;
3158 int code = aItem->GetNetCode();
3159
3160 if( first )
3161 {
3162 board->SetHighLightNet( code );
3163 rs->SetHighlight( true, code );
3164 first = false;
3165 }
3166 else
3167 {
3168 board->SetHighLightNet( code, true );
3169 rs->SetHighlight( true, code, true );
3170 }
3171 } );
3172
3173 view->UpdateAllLayersColor();
3174 board->HighLightON();
3175 }
3176
3177 break;
3178
3179 case ID_SELECT_NET:
3180 case ID_DESELECT_NET:
3181 if( !m_contextMenuNetclass.IsEmpty() )
3182 {
3183 TOOL_MANAGER* toolMgr = m_frame->GetToolManager();
3186
3187 runOnNetsOfClass( m_contextMenuNetclass,
3188 [&]( NETINFO_ITEM* aItem )
3189 {
3190 toolMgr->RunAction( action, true,
3191 static_cast<intptr_t>( aItem->GetNetCode() ) );
3192 } );
3193 }
3194 break;
3195
3196
3197 case ID_SHOW_ALL_NETS:
3199 wxASSERT( m_netclassSettingsMap.count( NETCLASS::Default ) );
3200 m_netclassSettingsMap.at( NETCLASS::Default )->ctl_visibility->SetValue( true );
3201
3202 for( const auto& [ name, netclass ] : netSettings->m_NetClasses )
3203 {
3204 showNetclass( name );
3205
3206 if( m_netclassSettingsMap.count( name ) )
3207 m_netclassSettingsMap.at( name )->ctl_visibility->SetValue( true );
3208 }
3209
3210 break;
3211
3212 case ID_HIDE_OTHER_NETS:
3213 {
3214 bool showDefault = m_contextMenuNetclass == NETCLASS::Default;
3215 showNetclass( NETCLASS::Default, showDefault );
3216 wxASSERT( m_netclassSettingsMap.count( NETCLASS::Default ) );
3217 m_netclassSettingsMap.at( NETCLASS::Default )->ctl_visibility->SetValue( showDefault );
3218
3219 for( const auto& [ name, netclass ] : netSettings->m_NetClasses )
3220 {
3221 bool show = ( name == m_contextMenuNetclass );
3222
3223 showNetclass( name, show );
3224
3225 if( m_netclassSettingsMap.count( name ) )
3226 m_netclassSettingsMap.at( name )->ctl_visibility->SetValue( show );
3227 }
3228
3229 break;
3230 }
3231
3232 default:
3233 break;
3234 }
3235
3238
3239 m_contextMenuNetclass.clear();
3240}
3241
3242
3244{
3245 m_focusOwner->SetFocus();
3246}
3247
3248
3250{
3251 WX_INFOBAR* infobar = m_frame->GetInfoBar();
3252
3253 wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY, _( "Open Preferences" ),
3254 wxEmptyString );
3255
3256 button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
3257 [&]( wxHyperlinkEvent& aEvent )
3258 {
3259 wxCommandEvent dummy;
3261 } ) );
3262
3263 infobar->RemoveAllButtons();
3264 infobar->AddButton( button );
3265 infobar->AddCloseButton();
3266
3267 infobar->ShowMessageFor( _( "The current color theme is read-only. Create a new theme in "
3268 "Preferences to enable color editing." ),
3269 10000, wxICON_INFORMATION );
3270}
3271
3272
3274{
3275 m_paneLayerDisplayOptions->Refresh();
3276}
int color
Definition: DXF_plotter.cpp:57
const char * name
Definition: DXF_plotter.cpp:56
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:106
wxMenuItem * AddMenuItem(wxMenu *aMenu, int aId, const wxString &aText, const wxBitmap &aImage, wxItemKind aType=wxITEM_NORMAL)
Create and insert a menu item with an icon into aMenu.
Definition: bitmap.cpp:266
@ show_all_back_layers
@ show_front_assembly_layers
@ select_w_layer
@ show_back_assembly_layers
@ list_nets_16
@ visibility_off
@ show_all_front_layers
@ show_no_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)
#define ON
static TOOL_ACTION highContrastModeCycle
Definition: actions.h:107
Class APPEARANCE_CONTROLS_BASE.
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)
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
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)
wxRadioButton * m_rbRatsnestAllLayers
wxBoxSizer * m_objectsOuterSizer
void setVisibleLayers(LSET aLayers)
LAYER_PRESET * m_lastSelectedUserPreset
wxString m_contextMenuNetclass
The name of the netclass that was right-clicked.
wxRadioButton * m_rbNetColorRatsnest
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)
void OnNetGridRightClick(wxGridEvent &event) override
void OnBoardItemsChanged(BOARD &aBoard, std::vector< BOARD_ITEM * > &aItems) override
Update the colors on all the widgets from the new chosen color theme.
wxBoxSizer * m_layersOuterSizer
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 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
PCB_BASE_FRAME * m_frame
void OnSetFocus(wxFocusEvent &aEvent) override
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 OnLanguageChanged()
Update the panel contents from the application and board models.
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
void SetBitmap(const wxBitmap &aBmp)
Set the bitmap shown when the button is enabled.
void SetPadding(int aPadding)
Set the amount of padding present on each side of the bitmap.
A checkbox control except with custom bitmaps for the checked and unchecked states.
Definition: bitmap_toggle.h:44
void SetValue(bool aValue)
Read the checkbox state.
std::shared_ptr< NET_SETTINGS > m_NetSettings
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:70
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:197
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:269
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:784
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:587
LSET GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:601
void AddListener(BOARD_LISTENER *aListener)
Add a listener to the board to receive calls whenever something on the board has been modified.
Definition: board.cpp:2046
GAL_SET GetVisibleElements() const
Return a set of all the element categories that are visible.
Definition: board.cpp:647
void SetHighLightNet(int aNetCode, bool aMulti=false)
Select the netcode to be highlighted.
Definition: board.cpp:2092
int GetCopperLayerCount() const
Definition: board.cpp:563
void SetVisibleLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings changes the bit-mask of vis...
Definition: board.cpp:619
void SetElementVisibility(GAL_LAYER_ID aLayer, bool aNewState)
Change the visibility of an element category.
Definition: board.cpp:659
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:474
PROJECT * GetProject() const
Definition: board.h:446
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:704
void HighLightON(bool aValue=true)
Enable or disable net highlighting.
Definition: board.cpp:2105
void SetVisibleElements(const GAL_SET &aMask)
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:626
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.
Definition: color_swatch.h:57
void GetNewSwatchColor()
Prompt for a new colour, using the colour picker dialog.
KIGFX::COLOR4D GetSwatchColor() const
void SetReadOnlyCallback(std::function< void()> aCallback)
Registers a handler for when the user tries to interact with a read-only swatch.
Definition: color_swatch.h:125
void SetReadOnly(bool aReadOnly=true)
Definition: color_swatch.h:119
Class to handle configuration and automatic determination of the DPI scale to use for canvases.
Definition: dpi_scaling.h:37
double GetScaleFactor() const
Get the DPI scale from all known sources in order:
Definition: dpi_scaling.cpp:91
double GetContentScaleFactor() const
Get the content scale factor, which may be different from the scale factor on some platforms.
void OnPreferences(wxCommandEvent &event)
Displays the preferences and settings of all opened editors paged dialog.
bool IsType(FRAME_T aType) const
WX_INFOBAR * GetInfoBar()
virtual void SetGridVisibility(bool aVisible)
bool IsGridVisible() const
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
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)
Helper for storing and iterating over GAL_LAYER_IDs.
Definition: layer_ids.h:296
bool Contains(GAL_LAYER_ID aPos)
Definition: layer_ids.h:329
GAL_SET & set()
Definition: layer_ids.h:311
static GAL_SET DefaultVisible()
Definition: lset.cpp:960
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...
representing 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
Definition: json_settings.h:84
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:102
bool SetFromWxString(const wxString &aColorString)
Set color values by parsing a string using wxColour::Set().
Definition: color4d.cpp:128
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
PCB specific render settings.
Definition: pcb_painter.h:72
std::set< int > & GetHiddenNets()
Definition: pcb_painter.h:118
std::map< int, KIGFX::COLOR4D > & GetNetColorMap()
Definition: pcb_painter.h:116
std::map< wxString, KIGFX::COLOR4D > & GetNetclassColorMap()
Definition: pcb_painter.h:114
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:77
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:69
BOX2D GetViewport() const
Return the current viewport visible area rectangle.
Definition: view.cpp:511
void SetViewport(const BOX2D &aViewport)
Set the visible area of the VIEW.
Definition: view.cpp:523
void UpdateAllLayersColor()
Apply the new coloring scheme to all layers.
Definition: view.cpp:761
void SetLayerVisible(int aLayer, bool aVisible=true)
Control the visibility of a particular layer.
Definition: view.h:393
bool IsMirroredX() const
Return true if view is flipped across the X axis.
Definition: view.h:243
void UpdateLayerColor(int aLayer)
Apply the new coloring scheme held by RENDER_SETTINGS in case that it has changed.
Definition: view.cpp:740
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:410
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:213
void MarkTargetDirty(int aTarget)
Set or clear target 'dirty' flag.
Definition: view.h:617
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:1494
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: layer_ids.h:493
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:532
static LSET AllLayersMask()
Definition: lset.cpp:808
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:411
bool Contains(PCB_LAYER_ID aLayer)
See if the layer set contains a PCB layer.
Definition: layer_ids.h:602
LSEQ CuStack() const
Return a sequence of copper layers in starting from the front/top and extending to the back/bottom.
Definition: lset.cpp:170
static LSET FrontAssembly()
Return a complete set of all top assembly layers which is all F_SilkS and F_Mask.
Definition: lset.cpp:705
static LSET InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
Definition: lset.cpp:733
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:773
static LSET ForbiddenFootprintLayers()
Layers which are not allowed within footprint definitions.
Definition: lset.cpp:915
static LSET BackAssembly()
Return a complete set of all bottom assembly layers which is all B_SilkS and B_Mask.
Definition: lset.cpp:719
static LSET FrontMask()
Return a mask holding all technical layers and the external CU layer on front side.
Definition: lset.cpp:895
static LSET BackMask()
Return a mask holding all technical layers and the external CU layer on back side.
Definition: lset.cpp:902
static const char Default[]
the name of the default NETCLASS
Definition: netclass.h:49
Handle the data for a net.
Definition: netinfo.h:67
int GetNetCode() const
Definition: netinfo.h:119
const NETNAMES_MAP & NetsByName() const
Return the name map, at least for python.
Definition: netinfo.h:380
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:60
DISPLAY_OPTIONS m_Display
AUI_PANELS m_AuiPanels
static TOOL_ACTION listNets
Definition: pcb_actions.h:383
static TOOL_ACTION highlightNet
Definition: pcb_actions.h:497
static TOOL_ACTION hideNetInRatsnest
Definition: pcb_actions.h:504
static TOOL_ACTION showNetInRatsnest
Definition: pcb_actions.h:505
static TOOL_ACTION ratsnestModeCycle
Definition: pcb_actions.h:278
static TOOL_ACTION netColorModeCycle
Definition: pcb_actions.h:277
static TOOL_ACTION selectNet
Select all connections belonging to a single net.
Definition: pcb_actions.h:86
static TOOL_ACTION flipBoard
Definition: pcb_actions.h:330
static TOOL_ACTION deselectNet
Remove all connections belonging to a single net from the active selection.
Definition: pcb_actions.h:89
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
virtual void OnDisplayOptionsChanged()
const PCB_DISPLAY_OPTIONS & GetDisplayOptions() const
Display options control the way tracks, vias, outlines and other things are shown (for instance solid...
PCBNEW_SETTINGS * GetPcbNewSettings() const
virtual PCB_LAYER_ID GetActiveLayer() const
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
void SetDrawBgColor(const COLOR4D &aColor) override
BOARD * GetBoard() const
void SetDisplayOptions(const PCB_DISPLAY_OPTIONS &aOptions, bool aRefresh=true)
Updates the current display options from the given options struct.
virtual void SetActiveLayer(PCB_LAYER_ID aLayer)
virtual COLOR_SETTINGS * GetColorSettings(bool aForceRefresh=false) const override
Helper to retrieve the current color settings.
double m_TrackOpacity
Opacity override for all tracks.
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.
void UpdateColors()
Update the color settings in the painter and GAL.
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
void SyncLayersVisibility(const BOARD *aBoard)
Update "visibility" property of each layer of a given BOARD.
void RedrawRatsnest()
Return the bounding box of the view that should be used if model is not valid.
The main frame for Pcbnew.
void ReCreateLayerBox(bool aForceResizeToolbar=true)
Recreate the layer box by clearing the old list and building a new one from the new layer names and c...
The project local settings are things that are attached to a particular project, but also might be pa...
std::set< wxString > m_HiddenNetclasses
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition: project.h:155
Icon provider for the "standard" row indicators, for example in layer selection lists.
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:54
Represent a single user action.
Definition: tool_action.h:68
int GetId() const
Return the unique id of the TOOL_ACTION object.
Definition: tool_action.h:121
int GetHotKey() const
Return the hotkey keycode which initiates the action.
Definition: tool_action.h:111
Master controller class:
Definition: tool_manager.h:55
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:142
A better wxCollapsiblePane that.
void Collapse(bool aCollapse=true)
void SetLabel(const wxString &aLabel) override
bool SetBackgroundColour(const wxColour &aColor) override
void SetTable(wxGridTableBase *table, bool aTakeOwnership=false)
Hide wxGrid's SetTable() method with one which doesn't mess up the grid column widths when setting th...
Definition: wx_grid.cpp:164
void SetColLabelSize(int aHeight)
Hide wxGrid's SetColLabelSize() method with one which makes sure the size is tall enough for the syst...
Definition: wx_grid.cpp:144
A modified version of the wxInfoBar class that allows us to:
Definition: wx_infobar.h:75
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
Definition: wx_infobar.cpp:289
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.
Definition: wx_infobar.cpp:128
void AddButton(wxButton *aButton)
Add an already created button to the infobar.
Definition: wx_infobar.cpp:248
void AddCloseButton(const wxString &aTooltip=_("Hide this message."))
Add the default close button to the infobar on the right side.
Definition: wx_infobar.cpp:279
void SetBorders(bool aLeft, bool aRight, bool aTop, bool aBottom)
Definition: wx_panel.h:38
static const wxSize SWATCH_SIZE_SMALL_DU(8, 6)
@ SWATCH_SMALL
Definition: color_swatch.h:40
#define _HKI(x)
#define _(s)
#define VIEWPORT_SWITCH_KEY
#define PRESET_SWITCH_KEY
@ FRAME_PCB_EDITOR
Definition: frame_type.h:40
wxString KeyNameFromKeyCode(int aKeycode, bool *aIsFound)
Return the key name from the key code.
GAL_LAYER_ID ToGalLayer(int aInteger)
Definition: layer_ids.h:278
int GetNetnameLayer(int aLayer)
Returns a netname layer corresponding to the given layer.
Definition: layer_ids.h:968
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:827
GAL_LAYER_ID
GAL layers are "virtual" layers, i.e.
Definition: layer_ids.h:190
@ LAYER_GRID
Definition: layer_ids.h:205
@ LAYER_MOD_TEXT_INVISIBLE
text marked as invisible
Definition: layer_ids.h:200
@ GAL_LAYER_ID_START
Definition: layer_ids.h:191
@ LAYER_LOCKED_ITEM_SHADOW
shadow layer for locked items
Definition: layer_ids.h:239
@ LAYER_PAD_FR
smd pads, front layer
Definition: layer_ids.h:202
@ LAYER_DRAWINGSHEET
drawingsheet frame and titleblock
Definition: layer_ids.h:217
@ LAYER_DRAW_BITMAPS
to handle and draw images bitmaps
Definition: layer_ids.h:223
@ LAYER_DRC_EXCLUSION
layer for drc markers which have been individually excluded
Definition: layer_ids.h:236
@ LAYER_MOD_TEXT
Definition: layer_ids.h:198
@ LAYER_PCB_BACKGROUND
PCB background color.
Definition: layer_ids.h:220
@ LAYER_ZONES
Control for copper zone opacity/visibility (color ignored)
Definition: layer_ids.h:231
@ LAYER_PADS
Meta control for all pads opacity/visibility (color ignored)
Definition: layer_ids.h:230
@ LAYER_DRC_WARNING
layer for drc markers with SEVERITY_WARNING
Definition: layer_ids.h:235
@ LAYER_TRACKS
Definition: layer_ids.h:212
@ LAYER_RATSNEST
Definition: layer_ids.h:204
@ LAYER_MOD_FR
show footprints on front
Definition: layer_ids.h:208
@ LAYER_ZONE_START
Virtual layers for stacking zones and tracks on a given copper layer.
Definition: layer_ids.h:253
@ LAYER_ANCHOR
anchor of items having an anchor point (texts, footprints)
Definition: layer_ids.h:201
@ LAYER_PAD_BK
smd pads, back layer
Definition: layer_ids.h:203
@ LAYER_MOD_VALUES
show footprints values (when texts are visible)
Definition: layer_ids.h:210
@ LAYER_PADS_TH
multilayer pads, usually with holes
Definition: layer_ids.h:213
@ LAYER_DRC_ERROR
layer for drc markers with SEVERITY_ERROR
Definition: layer_ids.h:216
@ LAYER_VIAS
Meta control for all vias opacity/visibility.
Definition: layer_ids.h:193
@ LAYER_MOD_BK
show footprints on back
Definition: layer_ids.h:209
@ LAYER_MOD_REFERENCES
show footprints references (when texts are visible)
Definition: layer_ids.h:211
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:59
@ User_8
Definition: layer_ids.h:130
@ F_CrtYd
Definition: layer_ids.h:117
@ B_Adhes
Definition: layer_ids.h:97
@ Edge_Cuts
Definition: layer_ids.h:113
@ Dwgs_User
Definition: layer_ids.h:109
@ F_Paste
Definition: layer_ids.h:101
@ Cmts_User
Definition: layer_ids.h:110
@ User_6
Definition: layer_ids.h:128
@ User_7
Definition: layer_ids.h:129
@ F_Adhes
Definition: layer_ids.h:98
@ B_Mask
Definition: layer_ids.h:106
@ B_Cu
Definition: layer_ids.h:95
@ User_5
Definition: layer_ids.h:127
@ Eco1_User
Definition: layer_ids.h:111
@ F_Mask
Definition: layer_ids.h:107
@ B_Paste
Definition: layer_ids.h:100
@ User_9
Definition: layer_ids.h:131
@ UNSELECTED_LAYER
Definition: layer_ids.h:61
@ F_Fab
Definition: layer_ids.h:120
@ Margin
Definition: layer_ids.h:114
@ F_SilkS
Definition: layer_ids.h:104
@ B_CrtYd
Definition: layer_ids.h:116
@ Eco2_User
Definition: layer_ids.h:112
@ User_3
Definition: layer_ids.h:125
@ User_1
Definition: layer_ids.h:123
@ B_SilkS
Definition: layer_ids.h:103
@ User_4
Definition: layer_ids.h:126
@ User_2
Definition: layer_ids.h:124
@ F_Cu
Definition: layer_ids.h:64
@ B_Fab
Definition: layer_ids.h:119
#define ZONE_LAYER_FOR(boardLayer)
Definition: layer_ids.h:268
#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:264
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:932
Macros and inline functions to create menus items in menubars or popup menus.
@ ALL
All except INITIAL_ADD.
Definition: view_item.h:53
@ TARGET_NONCACHED
Auxiliary rendering target (noncached)
Definition: definitions.h:49
wxFont GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:156
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
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.
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
@ PCB_NETINFO_T
class NETINFO_ITEM, a description of a net
Definition: typeinfo.h:114