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/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 int indicatorSize = ConvertDialogToPixels( wxSize( 6, 6 ) ).x;
410 int screenHeight = wxSystemSettings::GetMetric( wxSYS_SCREEN_Y );
411 m_iconProvider = new ROW_ICON_PROVIDER( indicatorSize );
412 m_pointSize = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ).GetPointSize();
413
414 m_layerPanelColour = m_panelLayers->GetBackgroundColour().ChangeLightness( 110 );
415 SetBorders( true, false, false, false );
416
417 m_layersOuterSizer = new wxBoxSizer( wxVERTICAL );
419 m_windowLayers->SetScrollRate( 0, 5 );
420 m_windowLayers->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS::OnSetFocus, this );
421
422 m_objectsOuterSizer = new wxBoxSizer( wxVERTICAL );
424 m_windowObjects->SetScrollRate( 0, 5 );
425 m_windowObjects->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS::OnSetFocus, this );
426
427 wxFont infoFont = KIUI::GetInfoFont( this );
428 m_staticTextNets->SetFont( infoFont );
429 m_staticTextNetClasses->SetFont( infoFont );
430 m_panelLayers->SetFont( infoFont );
431 m_windowLayers->SetFont( infoFont );
432 m_windowObjects->SetFont( infoFont );
433 m_presetsLabel->SetFont( infoFont );
434 m_viewportsLabel->SetFont( infoFont );
435
436 m_cbLayerPresets->SetToolTip( wxString::Format( _( "Save and restore layer visibility combinations.\n"
437 "Use %s+Tab to activate selector.\n"
438 "Successive Tabs while holding %s down will "
439 "cycle through presets in the popup." ),
442
443 m_cbViewports->SetToolTip( wxString::Format( _( "Save and restore view location and zoom.\n"
444 "Use %s+Tab to activate selector.\n"
445 "Successive Tabs while holding %s down will "
446 "cycle through viewports in the popup." ),
449
451
454
457
458 m_txtNetFilter->SetHint( _( "Filter nets" ) );
459
460 if( screenHeight <= 900 && m_pointSize >= indicatorSize )
461 m_pointSize = m_pointSize * 8 / 10;
462
463 wxFont font = m_notebook->GetFont();
464
465#ifdef __WXMAC__
466 font.SetPointSize( m_pointSize );
467 m_notebook->SetFont( font );
468#endif
469
470 auto setHighContrastMode =
471 [&]( HIGH_CONTRAST_MODE aMode )
472 {
474 opts.m_ContrastModeDisplay = aMode;
475
476 m_frame->SetDisplayOptions( opts );
477 passOnFocus();
478 };
479
480 m_rbHighContrastNormal->Bind( wxEVT_RADIOBUTTON,
481 [=]( wxCommandEvent& aEvent )
482 {
483 setHighContrastMode( HIGH_CONTRAST_MODE::NORMAL );
484 } );
485
486 m_rbHighContrastDim->Bind( wxEVT_RADIOBUTTON,
487 [=]( wxCommandEvent& aEvent )
488 {
489 setHighContrastMode( HIGH_CONTRAST_MODE::DIMMED );
490 } );
491
492 m_rbHighContrastOff->Bind( wxEVT_RADIOBUTTON,
493 [=]( wxCommandEvent& aEvent )
494 {
495 setHighContrastMode( HIGH_CONTRAST_MODE::HIDDEN );
496 } );
497
499
500 m_btnNetInspector->Bind( wxEVT_BUTTON,
501 [&]( wxCommandEvent& aEvent )
502 {
504 passOnFocus();
505 } );
506
507 m_btnConfigureNetClasses->Bind( wxEVT_BUTTON,
508 [&]( wxCommandEvent& aEvent )
509 {
510 // This panel should only be visible in the PCB_EDIT_FRAME anyway
511 if( PCB_EDIT_FRAME* editframe = dynamic_cast<PCB_EDIT_FRAME*>( m_frame ) )
512 editframe->ShowBoardSetupDialog( _( "Net Classes" ) );
513
514 passOnFocus();
515 } );
516
517 m_cbFlipBoard->SetValue( m_frame->GetCanvas()->GetView()->IsMirroredX() );
518 m_cbFlipBoard->Bind( wxEVT_CHECKBOX,
519 [&]( wxCommandEvent& aEvent )
520 {
522 } );
523
526
527 m_netsGrid->RegisterDataType( wxT( "bool" ), m_toggleGridRenderer, new wxGridCellBoolEditor );
528
529 m_netsGrid->RegisterDataType( wxT( "COLOR4D" ),
532
533 m_netsTable = new NET_GRID_TABLE( m_frame, m_panelNets->GetBackgroundColour() );
536
537 m_netsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
538 m_netsGrid->SetSelectionForeground( m_netsGrid->GetDefaultCellTextColour() );
539 m_netsGrid->SetSelectionBackground( m_panelNets->GetBackgroundColour() );
540
541 const int cellPadding = 6;
542#ifdef __WXMAC__
543 const int rowHeightPadding = 5;
544#else
545 const int rowHeightPadding = 3;
546#endif
547
548 wxSize size = ConvertDialogToPixels( SWATCH_SIZE_SMALL_DU );
549 m_netsGrid->SetColSize( NET_GRID_TABLE::COL_COLOR, size.x + cellPadding );
550
551 size = KiBitmap( BITMAPS::visibility ).GetSize();
552 m_netsGrid->SetColSize( NET_GRID_TABLE::COL_VISIBILITY, size.x + cellPadding );
553
554 m_netsGrid->SetDefaultCellFont( font );
555 m_netsGrid->SetDefaultRowSize( font.GetPixelSize().y + rowHeightPadding );
556
557 m_netsGrid->GetGridWindow()->Bind( wxEVT_MOTION, &APPEARANCE_CONTROLS::OnNetGridMouseEvent,
558 this );
559
560 // To handle middle click on color swatches
561 m_netsGrid->GetGridWindow()->Bind( wxEVT_MIDDLE_UP, &APPEARANCE_CONTROLS::OnNetGridMouseEvent,
562 this );
563
564 m_netsGrid->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_DEFAULT );
565 m_netclassScrolledWindow->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_DEFAULT );
566
567 if( m_isFpEditor )
568 m_notebook->RemovePage( 2 );
569
571
574
577
581
582 // Grid visibility is loaded and set to the GAL before we are constructed
584
585 Bind( wxEVT_COMMAND_MENU_SELECTED, &APPEARANCE_CONTROLS::OnLayerContextMenu, this,
587}
588
589
591{
593
596
597 delete m_iconProvider;
598}
599
600
602{
603 int hotkey;
604 wxString msg;
605 wxFont infoFont = KIUI::GetInfoFont( this );
606
607 // Create layer display options
609 _( "Layer Display Options" ) );
611 m_paneLayerDisplayOptions->SetBackgroundColour( m_notebook->GetThemeBackgroundColour() );
612
613 wxWindow* layerDisplayPane = m_paneLayerDisplayOptions->GetPane();
614
615 wxBoxSizer* layerDisplayOptionsSizer;
616 layerDisplayOptionsSizer = new wxBoxSizer( wxVERTICAL );
617
619
620 if( hotkey )
621 msg = wxString::Format( _( "Inactive layers (%s):" ), KeyNameFromKeyCode( hotkey ) );
622 else
623 msg = _( "Inactive layers:" );
624
625 m_inactiveLayersLabel = new wxStaticText( layerDisplayPane, wxID_ANY, msg );
626 m_inactiveLayersLabel->SetFont( infoFont );
627 m_inactiveLayersLabel->Wrap( -1 );
628 layerDisplayOptionsSizer->Add( m_inactiveLayersLabel, 0, wxEXPAND | wxBOTTOM | wxLEFT, 2 );
629
630 wxBoxSizer* contrastModeSizer;
631 contrastModeSizer = new wxBoxSizer( wxHORIZONTAL );
632
633 m_rbHighContrastNormal = new wxRadioButton( layerDisplayPane, wxID_ANY, _( "Normal" ),
634 wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
635 m_rbHighContrastNormal->SetFont( infoFont );
636 m_rbHighContrastNormal->SetValue( true );
637 m_rbHighContrastNormal->SetToolTip( _( "Inactive layers will be shown in full color" ) );
638
639 contrastModeSizer->Add( m_rbHighContrastNormal, 0, wxRIGHT, 5 );
640 contrastModeSizer->AddStretchSpacer();
641
642 m_rbHighContrastDim = new wxRadioButton( layerDisplayPane, wxID_ANY, _( "Dim" ) );
643 m_rbHighContrastDim->SetFont( infoFont );
644 m_rbHighContrastDim->SetToolTip( _( "Inactive layers will be dimmed" ) );
645
646 contrastModeSizer->Add( m_rbHighContrastDim, 0, wxRIGHT, 5 );
647 contrastModeSizer->AddStretchSpacer();
648
649 m_rbHighContrastOff = new wxRadioButton( layerDisplayPane, wxID_ANY, _( "Hide" ) );
650 m_rbHighContrastOff->SetFont( infoFont );
651 m_rbHighContrastOff->SetToolTip( _( "Inactive layers will be hidden" ) );
652
653 contrastModeSizer->Add( m_rbHighContrastOff, 0, 0, 5 );
654 contrastModeSizer->AddStretchSpacer();
655
656 layerDisplayOptionsSizer->Add( contrastModeSizer, 0, wxEXPAND, 5 );
657
658 m_layerDisplaySeparator = new wxStaticLine( layerDisplayPane, wxID_ANY, wxDefaultPosition,
659 wxDefaultSize, wxLI_HORIZONTAL );
660 layerDisplayOptionsSizer->Add( m_layerDisplaySeparator, 0, wxEXPAND | wxTOP | wxBOTTOM, 5 );
661
662 m_cbFlipBoard = new wxCheckBox( layerDisplayPane, wxID_ANY, _( "Flip board view" ) );
663 m_cbFlipBoard->SetFont( infoFont );
664 layerDisplayOptionsSizer->Add( m_cbFlipBoard, 0, 0, 5 );
665
666 layerDisplayPane->SetSizer( layerDisplayOptionsSizer );
667 layerDisplayPane->Layout();
668 layerDisplayOptionsSizer->Fit( layerDisplayPane );
669
670 m_panelLayersSizer->Add( m_paneLayerDisplayOptions, 0, wxEXPAND | wxTOP, 5 );
671
672 m_paneLayerDisplayOptions->Bind( WX_COLLAPSIBLE_PANE_CHANGED,
673 [&]( wxCommandEvent& aEvent )
674 {
675 Freeze();
676 m_panelLayers->Fit();
677 m_sizerOuter->Layout();
678 Thaw();
679 } );
680
681 // Create net display options
682
684 _( "Net Display Options" ) );
686 m_paneNetDisplayOptions->SetBackgroundColour( m_notebook->GetThemeBackgroundColour() );
687
688 wxWindow* netDisplayPane = m_paneNetDisplayOptions->GetPane();
689 wxBoxSizer* netDisplayOptionsSizer = new wxBoxSizer( wxVERTICAL );
690
692
694
695 if( hotkey )
696 msg = wxString::Format( _( "Net colors (%s):" ), KeyNameFromKeyCode( hotkey ) );
697 else
698 msg = _( "Net colors:" );
699
700 m_txtNetDisplayTitle = new wxStaticText( netDisplayPane, wxID_ANY, msg );
701 m_txtNetDisplayTitle->SetFont( infoFont );
702 m_txtNetDisplayTitle->Wrap( -1 );
703 m_txtNetDisplayTitle->SetToolTip( _( "Choose when to show net and netclass colors" ) );
704
705 netDisplayOptionsSizer->Add( m_txtNetDisplayTitle, 0, wxEXPAND | wxBOTTOM | wxLEFT, 2 );
706
707 wxBoxSizer* netColorSizer = new wxBoxSizer( wxHORIZONTAL );
708
709 m_rbNetColorAll = new wxRadioButton( netDisplayPane, wxID_ANY, _( "All" ), wxDefaultPosition,
710 wxDefaultSize, wxRB_GROUP );
711 m_rbNetColorAll->SetFont( infoFont );
712 m_rbNetColorAll->SetToolTip( _( "Net and netclass colors are shown on all copper items" ) );
713
714 netColorSizer->Add( m_rbNetColorAll, 0, wxRIGHT, 5 );
715 netColorSizer->AddStretchSpacer();
716
717 m_rbNetColorRatsnest = new wxRadioButton( netDisplayPane, wxID_ANY, _( "Ratsnest" ) );
718 m_rbNetColorRatsnest->SetFont( infoFont );
719 m_rbNetColorRatsnest->SetValue( true );
720 m_rbNetColorRatsnest->SetToolTip( _( "Net and netclass colors are shown on the ratsnest only" ) );
721
722 netColorSizer->Add( m_rbNetColorRatsnest, 0, wxRIGHT, 5 );
723 netColorSizer->AddStretchSpacer();
724
725 m_rbNetColorOff = new wxRadioButton( netDisplayPane, wxID_ANY, _( "None" ) );
726 m_rbNetColorOff->SetFont( infoFont );
727 m_rbNetColorOff->SetToolTip( _( "Net and netclass colors are not shown" ) );
728
729 netColorSizer->Add( m_rbNetColorOff, 0, 0, 5 );
730
731 netDisplayOptionsSizer->Add( netColorSizer, 0, wxEXPAND | wxBOTTOM, 5 );
732
734
736
737 if( hotkey )
738 msg = wxString::Format( _( "Ratsnest display (%s):" ), KeyNameFromKeyCode( hotkey ) );
739 else
740 msg = _( "Ratsnest display:" );
741
742 m_txtRatsnestVisibility = new wxStaticText( netDisplayPane, wxID_ANY, msg );
743 m_txtRatsnestVisibility->SetFont( infoFont );
744 m_txtRatsnestVisibility->Wrap( -1 );
745 m_txtRatsnestVisibility->SetToolTip( _( "Choose which ratsnest lines to display" ) );
746
747 netDisplayOptionsSizer->Add( m_txtRatsnestVisibility, 0, wxEXPAND | wxBOTTOM | wxLEFT, 2 );
748
749 wxBoxSizer* ratsnestDisplayModeSizer = new wxBoxSizer( wxHORIZONTAL );
750
751 m_rbRatsnestAllLayers = new wxRadioButton( netDisplayPane, wxID_ANY, _( "All" ),
752 wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
753 m_rbRatsnestAllLayers->SetFont( infoFont );
754 m_rbRatsnestAllLayers->SetValue( true );
755 m_rbRatsnestAllLayers->SetToolTip( _( "Show ratsnest lines to items on all layers" ) );
756
757 ratsnestDisplayModeSizer->Add( m_rbRatsnestAllLayers, 0, wxRIGHT, 5 );
758 ratsnestDisplayModeSizer->AddStretchSpacer();
759
760 m_rbRatsnestVisLayers = new wxRadioButton( netDisplayPane, wxID_ANY, _( "Visible layers" ) );
761 m_rbRatsnestVisLayers->SetFont( infoFont );
762 m_rbRatsnestVisLayers->SetToolTip( _( "Show ratsnest lines to items on visible layers" ) );
763
764 ratsnestDisplayModeSizer->Add( m_rbRatsnestVisLayers, 0, wxRIGHT, 5 );
765 ratsnestDisplayModeSizer->AddStretchSpacer();
766
767 m_rbRatsnestNone = new wxRadioButton( netDisplayPane, wxID_ANY, _( "None" ) );
768 m_rbRatsnestNone->SetFont( infoFont );
769 m_rbRatsnestNone->SetToolTip( _( "Hide all ratsnest lines" ) );
770
771 ratsnestDisplayModeSizer->Add( m_rbRatsnestNone, 0, 0, 5 );
772
773 netDisplayOptionsSizer->Add( ratsnestDisplayModeSizer, 0, wxEXPAND | wxBOTTOM, 5 );
774
776
777 netDisplayPane->SetSizer( netDisplayOptionsSizer );
778 netDisplayPane->Layout();
779 netDisplayOptionsSizer->Fit( netDisplayPane );
780
781 m_netsTabOuterSizer->Add( m_paneNetDisplayOptions, 0, wxEXPAND | wxTOP, 5 );
782
783 m_paneNetDisplayOptions->Bind( WX_COLLAPSIBLE_PANE_CHANGED,
784 [&]( wxCommandEvent& aEvent )
785 {
786 Freeze();
788 m_sizerOuter->Layout();
789 passOnFocus();
790 Thaw();
791 } );
792
793 m_rbNetColorAll->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onNetColorMode, this );
794 m_rbNetColorOff->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onNetColorMode, this );
795 m_rbNetColorRatsnest->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onNetColorMode, this );
796
797 m_rbRatsnestAllLayers->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onRatsnestMode, this );
798 m_rbRatsnestVisLayers->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onRatsnestMode, this );
799 m_rbRatsnestNone->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onRatsnestMode, this );
800}
801
802
804{
805 wxSize size( 220, 480 );
806 // TODO(JE) appropriate logic
807 return size;
808}
809
810
811void APPEARANCE_CONTROLS::OnNotebookPageChanged( wxNotebookEvent& aEvent )
812{
813 // Work around wxMac issue where the notebook pages are blank
814#ifdef __WXMAC__
815 int page = aEvent.GetSelection();
816
817 if( page >= 0 )
818 m_notebook->ChangeSelection( static_cast<unsigned>( page ) );
819#endif
820
821#ifndef __WXMSW__
822 // Because wxWidgets is broken and will send click events to children of the collapsible
823 // panes even if they are collapsed without this
824 Freeze();
825 m_panelLayers->Fit();
827 m_sizerOuter->Layout();
828 Thaw();
829#endif
830
831 Bind( wxEVT_IDLE, &APPEARANCE_CONTROLS::idleFocusHandler, this );
832}
833
834
835void APPEARANCE_CONTROLS::idleFocusHandler( wxIdleEvent& aEvent )
836{
837 passOnFocus();
838 Unbind( wxEVT_IDLE, &APPEARANCE_CONTROLS::idleFocusHandler, this );
839}
840
841
842void APPEARANCE_CONTROLS::OnSetFocus( wxFocusEvent& aEvent )
843{
844#ifdef __WXMSW__
845 // In wxMSW, buttons won't process events unless they have focus, so we'll let it take the
846 // focus and give it back to the parent in the button event handler.
847 if( wxBitmapButton* btn = dynamic_cast<wxBitmapButton*>( aEvent.GetEventObject() ) )
848 {
849 wxCommandEvent evt( wxEVT_BUTTON );
850 wxPostEvent( btn, evt );
851 }
852#endif
853
854 passOnFocus();
855 aEvent.Skip();
856}
857
858
859void APPEARANCE_CONTROLS::OnSize( wxSizeEvent& aEvent )
860{
861 aEvent.Skip();
862}
863
864
865void APPEARANCE_CONTROLS::OnNetGridClick( wxGridEvent& event )
866{
867 int row = event.GetRow();
868 int col = event.GetCol();
869
870 switch( col )
871 {
873 m_netsTable->SetValueAsBool( row, col, !m_netsTable->GetValueAsBool( row, col ) );
874 m_netsGrid->ForceRefresh();
875 break;
876
877 default:
878 break;
879 }
880}
881
882
884{
885 int row = event.GetRow();
886 int col = event.GetCol();
887
888 switch( col )
889 {
891 m_netsGrid->GetCellEditor( row, col )->BeginEdit( row, col, m_netsGrid );
892 break;
893
894 default:
895 break;
896 }
897}
898
899
901{
902 m_netsGrid->SelectRow( event.GetRow() );
903
904 wxString netName = UnescapeString( m_netsGrid->GetCellValue( event.GetRow(),
906 wxMenu menu;
907
908 menu.Append( new wxMenuItem( &menu, ID_SET_NET_COLOR, _( "Set Net Color" ), wxEmptyString,
909 wxITEM_NORMAL ) );
910 menu.Append( new wxMenuItem( &menu, ID_HIGHLIGHT_NET,
911 wxString::Format( _( "Highlight %s" ), netName ), wxEmptyString,
912 wxITEM_NORMAL ) );
913 menu.Append( new wxMenuItem( &menu, ID_SELECT_NET,
914 wxString::Format( _( "Select Tracks and Vias in %s" ), netName ),
915 wxEmptyString, wxITEM_NORMAL ) );
916 menu.Append( new wxMenuItem( &menu, ID_DESELECT_NET,
917 wxString::Format( _( "Unselect Tracks and Vias in %s" ), netName ),
918 wxEmptyString, wxITEM_NORMAL ) );
919
920 menu.AppendSeparator();
921
922 menu.Append( new wxMenuItem( &menu, ID_SHOW_ALL_NETS, _( "Show All Nets" ), wxEmptyString,
923 wxITEM_NORMAL ) );
924 menu.Append( new wxMenuItem( &menu, ID_HIDE_OTHER_NETS, _( "Hide All Other Nets" ),
925 wxEmptyString, wxITEM_NORMAL ) );
926
927 menu.Bind( wxEVT_COMMAND_MENU_SELECTED, &APPEARANCE_CONTROLS::onNetContextMenu, this );
928
929 PopupMenu( &menu );
930}
931
932
934{
935 wxPoint pos = m_netsGrid->CalcUnscrolledPosition( aEvent.GetPosition() );
936 wxGridCellCoords cell = m_netsGrid->XYToCell( pos );
937
938 if( aEvent.Moving() || aEvent.Entering() )
939 {
940 aEvent.Skip();
941
942 if( !cell )
943 {
944 m_netsGrid->GetGridWindow()->UnsetToolTip();
945 return;
946 }
947
948 if( cell == m_hoveredCell )
949 return;
950
951 m_hoveredCell = cell;
952
953 NET_GRID_ENTRY& net = m_netsTable->GetEntry( cell.GetRow() );
954
955 wxString name = net.name;
956 wxString showOrHide = net.visible ? _( "Click to hide ratsnest for %s" )
957 : _( "Click to show ratsnest for %s" );
958 wxString tip;
959
960 if( cell.GetCol() == NET_GRID_TABLE::COL_VISIBILITY )
961 {
962 tip.Printf( showOrHide, name );
963 }
964 else if( cell.GetCol() == NET_GRID_TABLE::COL_COLOR )
965 {
966 tip = _( "Double click (or middle click) to change color; "
967 "right click for more actions" );
968 }
969
970 m_netsGrid->GetGridWindow()->SetToolTip( tip );
971 }
972 else if( aEvent.Leaving() )
973 {
974 m_netsGrid->UnsetToolTip();
975 aEvent.Skip();
976 }
977 else if( aEvent.Dragging() )
978 {
979 // not allowed
980 CallAfter( [&]()
981 {
982 m_netsGrid->ClearSelection();
983 } );
984 }
985 else if( aEvent.ButtonUp( wxMOUSE_BTN_MIDDLE ) && !!cell )
986 {
987 int row = cell.GetRow();
988 int col = cell.GetCol();
989
990 if(col == NET_GRID_TABLE::COL_COLOR )
991 m_netsGrid->GetCellEditor( row, col )->BeginEdit( row, col, m_netsGrid );
992
993 aEvent.Skip();
994 }
995 else
996 {
997 aEvent.Skip();
998 }
999}
1000
1001
1003{
1004 m_notebook->SetPageText( 0, _( "Layers" ) );
1005 m_notebook->SetPageText( 1, _( "Objects" ) );
1006 m_notebook->SetPageText( 2, _( "Nets" ) );
1007
1008 Freeze();
1009 rebuildLayers();
1014 rebuildNets();
1015
1019
1021
1022 Thaw();
1023 Refresh();
1024}
1025
1026
1028{
1029 Freeze();
1030 rebuildLayers();
1034 rebuildNets();
1038
1040
1042
1043 if( m_board )
1044 m_board->AddListener( this );
1045
1046 Thaw();
1047 Refresh();
1048}
1049
1050
1052{
1054}
1055
1056
1057void APPEARANCE_CONTROLS::OnNetVisibilityChanged( int aNetCode, bool aVisibility )
1058{
1059 int row = m_netsTable->GetRowByNetcode( aNetCode );
1060
1061 if( row >= 0 )
1062 {
1064 m_netsGrid->ForceRefresh();
1065 }
1066}
1067
1068
1070{
1071 return aBoardItem->Type() == PCB_NETINFO_T;
1072}
1073
1074
1075bool APPEARANCE_CONTROLS::doesBoardItemNeedRebuild( std::vector<BOARD_ITEM*>& aBoardItems )
1076{
1077 bool rebuild = std::any_of( aBoardItems.begin(), aBoardItems.end(),
1078 []( const BOARD_ITEM* a )
1079 {
1080 return a->Type() == PCB_NETINFO_T;
1081 } );
1082
1083 return rebuild;
1084}
1085
1086
1088{
1089 if( doesBoardItemNeedRebuild( aItem ) )
1091}
1092
1093
1094void APPEARANCE_CONTROLS::OnBoardItemsAdded( BOARD& aBoard, std::vector<BOARD_ITEM*>& aItems )
1095{
1096 if( doesBoardItemNeedRebuild( aItems ) )
1098}
1099
1100
1102{
1103 if( doesBoardItemNeedRebuild( aItem ) )
1105}
1106
1107
1108void APPEARANCE_CONTROLS::OnBoardItemsRemoved( BOARD& aBoard, std::vector<BOARD_ITEM*>& aItems )
1109{
1110 if( doesBoardItemNeedRebuild( aItems ) )
1112}
1113
1114
1116{
1117 if( doesBoardItemNeedRebuild( aItem ) )
1119}
1120
1121
1122void APPEARANCE_CONTROLS::OnBoardItemsChanged( BOARD& aBoard, std::vector<BOARD_ITEM*>& aItems )
1123{
1124 if( doesBoardItemNeedRebuild( aItems ) )
1126}
1127
1128
1130{
1131 Freeze();
1132 rebuildNets();
1133 Thaw();
1134}
1135
1136
1138{
1141}
1142
1143
1145{
1146 // This is essentially a list of hacks because DarkMode isn't yet implemented inside
1147 // wxWidgets.
1148 //
1149 // The individual wxPanels, COLOR_SWATCHes and GRID_CELL_COLOR_RENDERERs should really be
1150 // overriding some virtual method or responding to some wxWidgets event so that the parent
1151 // doesn't have to know what it contains. But, that's not where we are, so... :shrug:
1152
1153 m_layerPanelColour = m_panelLayers->GetBackgroundColour().ChangeLightness( 110 );
1154
1155 for( wxSizerItem* child : m_layersOuterSizer->GetChildren() )
1156 {
1157 if( child && child->GetWindow() )
1158 child->GetWindow()->SetBackgroundColour( m_layerPanelColour );
1159 }
1160
1161 // Easier than calling OnDarkModeToggle on all the GRID_CELL_COLOR_RENDERERs:
1162 m_netsGrid->RegisterDataType( wxT( "COLOR4D" ),
1165
1166 for( const std::pair<const wxString, APPEARANCE_SETTING*>& pair : m_netclassSettingsMap )
1167 {
1168 if( pair.second->ctl_color )
1169 pair.second->ctl_color->OnDarkModeToggle();
1170 }
1171
1172 OnLayerChanged(); // Update selected highlighting
1173}
1174
1175
1177{
1178 for( const std::unique_ptr<APPEARANCE_SETTING>& setting : m_layerSettings )
1179 {
1180 setting->ctl_panel->SetBackgroundColour( m_layerPanelColour );
1181 setting->ctl_indicator->SetIndicatorState( ROW_ICON_PROVIDER::STATE::OFF );
1182 }
1183
1184 wxChar r = m_layerPanelColour.Red();
1185 wxChar g = m_layerPanelColour.Green();
1186 wxChar b = m_layerPanelColour.Blue();
1187
1188 if( r < 240 || g < 240 || b < 240 )
1189 {
1190 r = wxChar( std::min( (int) r + 15, 255 ) );
1191 g = wxChar( std::min( (int) g + 15, 255 ) );
1192 b = wxChar( std::min( (int) b + 15, 255 ) );
1193 }
1194 else
1195 {
1196 r = wxChar( std::max( (int) r - 15, 0 ) );
1197 g = wxChar( std::max( (int) g - 15, 0 ) );
1198 b = wxChar( std::max( (int) b - 15, 0 ) );
1199 }
1200
1201 PCB_LAYER_ID current = m_frame->GetActiveLayer();
1202
1203 if( !m_layerSettingsMap.count( current ) )
1204 {
1205 wxASSERT( m_layerSettingsMap.count( F_Cu ) );
1206 current = F_Cu;
1207 }
1208
1209 APPEARANCE_SETTING* newSetting = m_layerSettingsMap[ current ];
1210
1211 newSetting->ctl_panel->SetBackgroundColour( wxColour( r, g, b ) );
1213
1214 Refresh();
1215}
1216
1217
1218void APPEARANCE_CONTROLS::SetLayerVisible( int aLayer, bool isVisible )
1219{
1220 LSET visible = getVisibleLayers();
1221 PCB_LAYER_ID layer = ToLAYER_ID( aLayer );
1222
1223 if( visible.test( layer ) == isVisible )
1224 return;
1225
1226 visible.set( layer, isVisible );
1227 setVisibleLayers( visible );
1228
1229 m_frame->GetCanvas()->GetView()->SetLayerVisible( layer, isVisible );
1230
1232}
1233
1234
1236{
1237 if( m_objectSettingsMap.count( aLayer ) )
1238 {
1239 APPEARANCE_SETTING* setting = m_objectSettingsMap.at( aLayer );
1240 setting->ctl_visibility->SetValue( isVisible );
1241 }
1242
1243 m_frame->GetBoard()->SetElementVisibility( aLayer, isVisible );
1244
1245 m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, isVisible );
1247}
1248
1249
1251{
1252 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1253
1254 if( m_isFpEditor )
1255 {
1256 for( PCB_LAYER_ID layer : LSET::AllLayersMask().Seq() )
1257 view->SetLayerVisible( layer, aLayers.Contains( layer ) );
1258 }
1259 else
1260 {
1261 m_frame->GetBoard()->SetVisibleLayers( aLayers );
1262
1264 []( KIGFX::VIEW_ITEM* aItem ) -> bool
1265 {
1266 if( PCB_VIA* via = dynamic_cast<PCB_VIA*>( aItem ) )
1267 return via->GetRemoveUnconnected();
1268 else if( PAD* pad = dynamic_cast<PAD*>( aItem ) )
1269 return pad->GetRemoveUnconnected();
1270
1271 return false;
1272 } );
1273 }
1274}
1275
1276
1278{
1279 if( m_isFpEditor )
1280 {
1281 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1282
1283 for( size_t i = 0; i < GAL_LAYER_INDEX( LAYER_ZONE_START ); i++ )
1284 view->SetLayerVisible( GAL_LAYER_ID_START + GAL_LAYER_ID( i ), aLayers.test( i ) );
1285 }
1286 else
1287 {
1288 // Ratsnest visibility is controlled by the ratsnest option, and not by the preset
1291
1292 m_frame->GetBoard()->SetVisibleElements( aLayers );
1293 }
1294}
1295
1296
1298{
1299 if( m_isFpEditor )
1300 {
1301 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1302 LSET set;
1303
1304 for( PCB_LAYER_ID layer : LSET::AllLayersMask().Seq() )
1305 set.set( layer, view->IsLayerVisible( layer ) );
1306
1307 return set;
1308 }
1309 else
1310 {
1311 return m_frame->GetBoard()->GetVisibleLayers();
1312 }
1313}
1314
1315
1317{
1318 if( m_isFpEditor )
1319 {
1320 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1321 GAL_SET set;
1322 set.reset();
1323
1324 for( size_t i = 0; i < set.size(); i++ )
1325 set.set( i, view->IsLayerVisible( GAL_LAYER_ID_START + GAL_LAYER_ID( i ) ) );
1326
1327 return set;
1328 }
1329 else
1330 {
1331 return m_frame->GetBoard()->GetVisibleElements();
1332 }
1333}
1334
1335
1337{
1338 const PCB_DISPLAY_OPTIONS& options = m_frame->GetDisplayOptions();
1339
1340 switch( options.m_ContrastModeDisplay )
1341 {
1342 case HIGH_CONTRAST_MODE::NORMAL: m_rbHighContrastNormal->SetValue( true ); break;
1343 case HIGH_CONTRAST_MODE::DIMMED: m_rbHighContrastDim->SetValue( true ); break;
1344 case HIGH_CONTRAST_MODE::HIDDEN: m_rbHighContrastOff->SetValue( true ); break;
1345 }
1346
1347 switch( options.m_NetColorMode )
1348 {
1349 case NET_COLOR_MODE::ALL: m_rbNetColorAll->SetValue( true ); break;
1350 case NET_COLOR_MODE::RATSNEST: m_rbNetColorRatsnest->SetValue( true ); break;
1351 case NET_COLOR_MODE::OFF: m_rbNetColorOff->SetValue( true ); break;
1352 }
1353
1354 m_cbFlipBoard->SetValue( m_frame->GetCanvas()->GetView()->IsMirroredX() );
1355
1356 if( !m_isFpEditor )
1357 {
1359
1361 m_rbRatsnestNone->SetValue( true );
1363 m_rbRatsnestAllLayers->SetValue( true );
1364 else
1365 m_rbRatsnestVisLayers->SetValue( true );
1366
1367 wxASSERT( m_objectSettingsMap.count( LAYER_RATSNEST ) );
1370 }
1371}
1372
1373
1374std::vector<LAYER_PRESET> APPEARANCE_CONTROLS::GetUserLayerPresets() const
1375{
1376 std::vector<LAYER_PRESET> ret;
1377
1378 for( const std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
1379 {
1380 if( !pair.second.readOnly )
1381 ret.emplace_back( pair.second );
1382 }
1383
1384 return ret;
1385}
1386
1387
1388void APPEARANCE_CONTROLS::SetUserLayerPresets( std::vector<LAYER_PRESET>& aPresetList )
1389{
1390 // Reset to defaults
1392
1393 for( const LAYER_PRESET& preset : aPresetList )
1394 {
1395 if( m_layerPresets.count( preset.name ) )
1396 continue;
1397
1398 m_layerPresets[preset.name] = preset;
1399
1400 m_presetMRU.Add( preset.name );
1401 }
1402
1404}
1405
1406
1408{
1409 m_layerPresets.clear();
1410 m_presetMRU.clear();
1411
1412 // Load the read-only defaults
1416 {
1417 m_layerPresets[preset.name] = preset;
1418 m_layerPresets[preset.name].readOnly = true;
1419
1420 m_presetMRU.Add( preset.name );
1421 }
1422}
1423
1424
1425void APPEARANCE_CONTROLS::ApplyLayerPreset( const wxString& aPresetName )
1426{
1427 updateLayerPresetSelection( aPresetName );
1428
1429 wxCommandEvent dummy;
1431}
1432
1433
1435{
1436 if( m_layerPresets.count( aPreset.name ) )
1438 else
1439 m_currentPreset = nullptr;
1440
1442 : nullptr;
1443
1445 doApplyLayerPreset( aPreset );
1446}
1447
1448
1449std::vector<VIEWPORT> APPEARANCE_CONTROLS::GetUserViewports() const
1450{
1451 std::vector<VIEWPORT> ret;
1452
1453 for( const std::pair<const wxString, VIEWPORT>& pair : m_viewports )
1454 ret.emplace_back( pair.second );
1455
1456 return ret;
1457}
1458
1459
1460void APPEARANCE_CONTROLS::SetUserViewports( std::vector<VIEWPORT>& aViewportList )
1461{
1462 m_viewports.clear();
1463
1464 for( const VIEWPORT& viewport : aViewportList )
1465 {
1466 if( m_viewports.count( viewport.name ) )
1467 continue;
1468
1469 m_viewports[viewport.name] = viewport;
1470
1471 m_viewportMRU.Add( viewport.name );
1472 }
1473
1475}
1476
1477
1478void APPEARANCE_CONTROLS::ApplyViewport( const wxString& aViewportName )
1479{
1480 updateViewportSelection( aViewportName );
1481
1482 wxCommandEvent dummy;
1484}
1485
1486
1488{
1489 updateViewportSelection( aViewport.name );
1490 doApplyViewport( aViewport );
1491}
1492
1493
1495{
1496 BOARD* board = m_frame->GetBoard();
1497 LSET enabled = board->GetEnabledLayers();
1498 LSET visible = getVisibleLayers();
1499
1501 COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
1502 bool readOnly = theme->IsReadOnly();
1503
1504#ifdef __WXMAC__
1505 wxSizerItem* m_windowLayersSizerItem = m_panelLayersSizer->GetItem( m_windowLayers );
1506 m_windowLayersSizerItem->SetFlag( m_windowLayersSizerItem->GetFlag() & ~wxTOP );
1507#endif
1508
1509 auto appendLayer =
1510 [&]( std::unique_ptr<APPEARANCE_SETTING>& aSetting )
1511 {
1512 int layer = aSetting->id;
1513
1514 wxPanel* panel = new wxPanel( m_windowLayers, layer );
1515 wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
1516 panel->SetSizer( sizer );
1517
1518 panel->SetBackgroundColour( m_layerPanelColour );
1519
1520 aSetting->visible = visible[layer];
1521
1522 // TODO(JE) consider restyling this indicator
1523 INDICATOR_ICON* indicator = new INDICATOR_ICON( panel, *m_iconProvider,
1524 ROW_ICON_PROVIDER::STATE::OFF,
1525 layer );
1526
1527 COLOR_SWATCH* swatch = new COLOR_SWATCH( panel, COLOR4D::UNSPECIFIED, layer,
1528 bgColor, theme->GetColor( layer ),
1529 SWATCH_SMALL );
1530 swatch->SetToolTip( _( "Double click or middle click for color change, "
1531 "right click for menu" ) );
1532
1533 BITMAP_TOGGLE* btn_visible = new BITMAP_TOGGLE( panel, layer,
1536 aSetting->visible );
1537 btn_visible->SetToolTip( _( "Show or hide this layer" ) );
1538
1539 wxStaticText* label = new wxStaticText( panel, layer, aSetting->label );
1540 label->Wrap( -1 );
1541 label->SetToolTip( aSetting->tooltip );
1542
1543 sizer->AddSpacer( 1 );
1544 sizer->Add( indicator, 0, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1545 sizer->AddSpacer( 5 );
1546 sizer->Add( swatch, 0, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1547 sizer->AddSpacer( 6 );
1548 sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1549 sizer->AddSpacer( 5 );
1550 sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1551
1552 m_layersOuterSizer->Add( panel, 0, wxEXPAND, 0 );
1553
1554 aSetting->ctl_panel = panel;
1555 aSetting->ctl_indicator = indicator;
1556 aSetting->ctl_visibility = btn_visible;
1557 aSetting->ctl_color = swatch;
1558 aSetting->ctl_text = label;
1559
1560 panel->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1561 indicator->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1562 swatch->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1563 label->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1564
1565 btn_visible->Bind( TOGGLE_CHANGED,
1566 [&]( wxCommandEvent& aEvent )
1567 {
1568 wxObject* btn = aEvent.GetEventObject();
1569 int layerId = static_cast<wxWindow*>( btn )->GetId();
1570
1571 onLayerVisibilityToggled( static_cast<PCB_LAYER_ID>( layerId ) );
1572 } );
1573
1574 swatch->Bind( COLOR_SWATCH_CHANGED, &APPEARANCE_CONTROLS::OnColorSwatchChanged,
1575 this );
1577 this ) );
1578 swatch->SetReadOnly( readOnly );
1579
1580 panel->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1581 indicator->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1582 swatch->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1583 btn_visible->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1584 label->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1585 };
1586
1587 auto updateLayer =
1588 [&]( std::unique_ptr<APPEARANCE_SETTING>& aSetting )
1589 {
1590 int layer = aSetting->id;
1591 aSetting->visible = visible[layer];
1592 aSetting->ctl_panel->Show();
1593 aSetting->ctl_panel->SetId( layer );
1594 aSetting->ctl_indicator->SetWindowID( layer );
1595 aSetting->ctl_color->SetWindowID( layer );
1596 aSetting->ctl_color->SetSwatchColor( theme->GetColor( layer ), false );
1597 aSetting->ctl_visibility->SetWindowID( layer );
1598 aSetting->ctl_text->SetLabelText( aSetting->label );
1599 aSetting->ctl_text->SetId( layer );
1600 aSetting->ctl_text->SetToolTip( aSetting->tooltip );
1601 };
1602
1603 // technical layers are shown in this order:
1604 // Because they are static, wxGetTranslation must be explicitly
1605 // called for tooltips.
1606 static const struct {
1607 PCB_LAYER_ID layerId;
1608 wxString tooltip;
1609 } non_cu_seq[] = {
1610 { F_Adhes, _HKI( "Adhesive on board's front" ) },
1611 { B_Adhes, _HKI( "Adhesive on board's back" ) },
1612 { F_Paste, _HKI( "Solder paste on board's front" ) },
1613 { B_Paste, _HKI( "Solder paste on board's back" ) },
1614 { F_SilkS, _HKI( "Silkscreen on board's front" ) },
1615 { B_SilkS, _HKI( "Silkscreen on board's back" ) },
1616 { F_Mask, _HKI( "Solder mask on board's front" ) },
1617 { B_Mask, _HKI( "Solder mask on board's back" ) },
1618 { Dwgs_User, _HKI( "Explanatory drawings" ) },
1619 { Cmts_User, _HKI( "Explanatory comments" ) },
1620 { Eco1_User, _HKI( "User defined meaning" ) },
1621 { Eco2_User, _HKI( "User defined meaning" ) },
1622 { Edge_Cuts, _HKI( "Board's perimeter definition" ) },
1623 { Margin, _HKI( "Board's edge setback outline" ) },
1624 { F_CrtYd, _HKI( "Footprint courtyards on board's front" ) },
1625 { B_CrtYd, _HKI( "Footprint courtyards on board's back" ) },
1626 { F_Fab, _HKI( "Footprint assembly on board's front" ) },
1627 { B_Fab, _HKI( "Footprint assembly on board's back" ) },
1628 { User_1, _HKI( "User defined layer 1" ) },
1629 { User_2, _HKI( "User defined layer 2" ) },
1630 { User_3, _HKI( "User defined layer 3" ) },
1631 { User_4, _HKI( "User defined layer 4" ) },
1632 { User_5, _HKI( "User defined layer 5" ) },
1633 { User_6, _HKI( "User defined layer 6" ) },
1634 { User_7, _HKI( "User defined layer 7" ) },
1635 { User_8, _HKI( "User defined layer 8" ) },
1636 { User_9, _HKI( "User defined layer 9" ) },
1637 };
1638
1639 // There is a spacer added to the end of the list that we need to remove and re-add
1640 // after possibly adding additional layers
1641 if( m_layersOuterSizer->GetItemCount() > 0 )
1642 {
1643 m_layersOuterSizer->Detach( m_layersOuterSizer->GetItemCount() - 1 );
1644 }
1645 // Otherwise, this is the first time we are updating the control, so we need to attach
1646 // the handler
1647 else
1648 {
1649 // Add right click handling to show the context menu when clicking to the free area in
1650 // m_windowLayers (below the layer items)
1651 m_windowLayers->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1652 }
1653
1654 std::size_t total_layers = enabled.CuStack().size();
1655
1656 for( const auto& entry : non_cu_seq )
1657 {
1658 if( enabled[entry.layerId] )
1659 total_layers++;
1660 }
1661
1662 // Adds layers to the panel until we have enough to hold our total count
1663 while( total_layers > m_layerSettings.size() )
1664 m_layerSettings.push_back( std::make_unique<APPEARANCE_SETTING>() );
1665
1666 // We never delete layers from the panel, only hide them. This saves us
1667 // having to recreate the (possibly) later with minimal overhead
1668 for( std::size_t ii = total_layers; ii < m_layerSettings.size(); ++ii )
1669 {
1670 if( m_layerSettings[ii]->ctl_panel )
1671 m_layerSettings[ii]->ctl_panel->Show( false );
1672 }
1673
1674 auto layer_it = m_layerSettings.begin();
1675
1676 // show all coppers first, with front on top, back on bottom, then technical layers
1677 for( LSEQ cu_stack = enabled.CuStack(); cu_stack; ++cu_stack, ++layer_it )
1678 {
1679 PCB_LAYER_ID layer = *cu_stack;
1680 wxString dsc;
1681
1682 switch( layer )
1683 {
1684 case F_Cu: dsc = _( "Front copper layer" ); break;
1685 case B_Cu: dsc = _( "Back copper layer" ); break;
1686 default: dsc = _( "Inner copper layer" ); break;
1687 }
1688
1689 std::unique_ptr<APPEARANCE_SETTING>& setting = *layer_it;
1690
1691 setting->label = board->GetLayerName( layer );
1692 setting->id = layer;
1693 setting->tooltip = dsc;
1694
1695 if( setting->ctl_panel == nullptr )
1696 appendLayer( setting );
1697 else
1698 updateLayer( setting );
1699
1700 m_layerSettingsMap[layer] = setting.get();
1701
1703 {
1704 setting->ctl_text->Disable();
1705 setting->ctl_color->SetToolTip( wxEmptyString );
1706 }
1707 }
1708
1709 for( const auto& entry : non_cu_seq )
1710 {
1711 PCB_LAYER_ID layer = entry.layerId;
1712
1713 if( !enabled[layer] )
1714 continue;
1715
1716 std::unique_ptr<APPEARANCE_SETTING>& setting = *layer_it;
1717
1718 setting->label = board->GetLayerName( layer );
1719 setting->id = layer;
1720 // Because non_cu_seq is created static, we must explicitly call wxGetTranslation for
1721 // texts which are internationalized
1722 setting->tooltip = wxGetTranslation( entry.tooltip );
1723
1724 if( setting->ctl_panel == nullptr )
1725 appendLayer( setting );
1726 else
1727 updateLayer( setting );
1728
1729 m_layerSettingsMap[layer] = setting.get();
1730
1732 {
1733 setting->ctl_text->Disable();
1734 setting->ctl_color->SetToolTip( wxEmptyString );
1735 }
1736
1737 ++layer_it;
1738 }
1739
1740 m_layersOuterSizer->AddSpacer( 10 );
1741 m_windowLayers->SetBackgroundColour( m_layerPanelColour );
1742 m_windowLayers->Layout();
1743
1744 m_paneLayerDisplayOptions->SetLabel( _( "Layer Display Options" ) );
1745
1747 wxString msg;
1748
1749 if( hotkey )
1750 msg = wxString::Format( _( "Inactive layers (%s):" ), KeyNameFromKeyCode( hotkey ) );
1751 else
1752 msg = _( "Inactive layers:" );
1753
1754 m_inactiveLayersLabel->SetLabel( msg );
1755
1756 m_rbHighContrastNormal->SetLabel( _( "Normal" ) );
1757 m_rbHighContrastNormal->SetToolTip( _( "Inactive layers will be shown in full color" ) );
1758
1759 m_rbHighContrastDim->SetLabel( _( "Dim" ) );
1760 m_rbHighContrastDim->SetToolTip( _( "Inactive layers will be dimmed" ) );
1761
1762 m_rbHighContrastOff->SetLabel( _( "Hide" ) );
1763 m_rbHighContrastOff->SetToolTip( _( "Inactive layers will be hidden" ) );
1764
1765 m_cbFlipBoard->SetLabel( _( "Flip board view" ) );
1766}
1767
1768
1770{
1771 delete m_layerContextMenu;
1772 m_layerContextMenu = new wxMenu;
1773
1774 AddMenuItem( m_layerContextMenu, ID_SHOW_ALL_COPPER_LAYERS, _( "Show All Copper Layers" ),
1776 AddMenuItem( m_layerContextMenu, ID_HIDE_ALL_COPPER_LAYERS, _( "Hide All Copper Layers" ),
1778
1779 m_layerContextMenu->AppendSeparator();
1780
1781 AddMenuItem( m_layerContextMenu, ID_HIDE_ALL_BUT_ACTIVE, _( "Hide All Layers But Active" ),
1783
1784 m_layerContextMenu->AppendSeparator();
1785
1786 AddMenuItem( m_layerContextMenu, ID_SHOW_ALL_NON_COPPER, _( "Show All Non Copper Layers" ),
1788
1789 AddMenuItem( m_layerContextMenu, ID_HIDE_ALL_NON_COPPER, _( "Hide All Non Copper Layers" ),
1791
1792 m_layerContextMenu->AppendSeparator();
1793
1794 AddMenuItem( m_layerContextMenu, ID_PRESET_ALL_LAYERS, _( "Show All Layers" ),
1796
1797 AddMenuItem( m_layerContextMenu, ID_PRESET_NO_LAYERS, _( "Hide All Layers" ),
1799
1800 m_layerContextMenu->AppendSeparator();
1801
1802 AddMenuItem( m_layerContextMenu, ID_PRESET_FRONT_ASSEMBLY, _( "Show Only Front Assembly Layers" ),
1804
1805 AddMenuItem( m_layerContextMenu, ID_PRESET_FRONT, _( "Show Only Front Layers" ),
1807
1808 // Only show the internal layer option if internal layers are enabled
1809 if( m_frame->GetBoard()->GetCopperLayerCount() > 2 )
1810 {
1811 AddMenuItem( m_layerContextMenu, ID_PRESET_INNER_COPPER, _( "Show Only Inner Layers" ),
1813 }
1814
1815 AddMenuItem( m_layerContextMenu, ID_PRESET_BACK, _( "Show Only Back Layers" ),
1817
1818 AddMenuItem( m_layerContextMenu, ID_PRESET_BACK_ASSEMBLY, _( "Show Only Back Assembly Layers" ),
1820}
1821
1822
1823void APPEARANCE_CONTROLS::OnLayerContextMenu( wxCommandEvent& aEvent )
1824{
1825 BOARD* board = m_frame->GetBoard();
1826 LSET visible = getVisibleLayers();
1827
1828 PCB_LAYER_ID current = m_frame->GetActiveLayer();
1829
1830 switch( aEvent.GetId() )
1831 {
1834 return;
1835
1838 return;
1839
1841 visible |= presetAllCopper.layers;
1842 setVisibleLayers( visible );
1843 break;
1844
1847 SetLayerVisible( current, true );
1848 break;
1849
1851 visible &= ~presetAllCopper.layers;
1852
1853 if( !visible.test( current ) && visible.count() > 0 )
1854 m_frame->SetActiveLayer( *visible.Seq().begin() );
1855
1856 setVisibleLayers( visible );
1857 break;
1858
1860 visible &= presetAllCopper.layers;
1861
1862 if( !visible.test( current ) && visible.count() > 0 )
1863 m_frame->SetActiveLayer( *visible.Seq().begin() );
1864
1865 setVisibleLayers( visible );
1866 break;
1867
1869 visible |= ~presetAllCopper.layers;
1870
1871 setVisibleLayers( visible );
1872 break;
1873
1876 return;
1877
1878 case ID_PRESET_FRONT:
1880 return;
1881
1884 return;
1885
1886 case ID_PRESET_BACK:
1888 return;
1889
1892 return;
1893 }
1894
1897
1898 if( !m_isFpEditor )
1900
1902}
1903
1904
1906{
1907 return m_notebook->GetSelection();
1908}
1909
1910
1912{
1913 size_t max = m_notebook->GetPageCount();
1914
1915 if( aTab >= 0 && static_cast<size_t>( aTab ) < max )
1916 m_notebook->SetSelection( aTab );
1917}
1918
1919
1921{
1923 bool readOnly = theme->IsReadOnly();
1924 LSET visible = getVisibleLayers();
1925 GAL_SET objects = getVisibleObjects();
1926
1927 Freeze();
1928
1929 for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_layerSettings )
1930 {
1931 int layer = setting->id;
1932
1933 if( setting->ctl_visibility )
1934 setting->ctl_visibility->SetValue( visible[layer] );
1935
1936 if( setting->ctl_color )
1937 {
1938 const COLOR4D& color = theme->GetColor( layer );
1939 setting->ctl_color->SetSwatchColor( color, false );
1940 setting->ctl_color->SetReadOnly( readOnly );
1941 }
1942 }
1943
1944 for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
1945 {
1946 GAL_LAYER_ID layer = static_cast<GAL_LAYER_ID>( setting->id );
1947
1948 if( setting->ctl_visibility )
1949 setting->ctl_visibility->SetValue( objects.Contains( 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 // Update indicators and panel background colors
1961
1962 Thaw();
1963
1964 m_windowLayers->Refresh();
1965}
1966
1967
1968void APPEARANCE_CONTROLS::onLayerLeftClick( wxMouseEvent& aEvent )
1969{
1970 wxWindow* eventSource = static_cast<wxWindow*>( aEvent.GetEventObject() );
1971
1972 PCB_LAYER_ID layer = ToLAYER_ID( eventSource->GetId() );
1973
1975 return;
1976
1977 m_frame->SetActiveLayer( layer );
1978 passOnFocus();
1979}
1980
1981
1982void APPEARANCE_CONTROLS::rightClickHandler( wxMouseEvent& aEvent )
1983{
1984 wxASSERT( m_layerContextMenu );
1985 PopupMenu( m_layerContextMenu );
1986 passOnFocus();
1987};
1988
1989
1991{
1992 LSET visibleLayers = getVisibleLayers();
1993
1994 visibleLayers.set( aLayer, !visibleLayers.test( aLayer ) );
1995 setVisibleLayers( visibleLayers );
1996 m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, visibleLayers.test( aLayer ) );
1997
2000}
2001
2002
2004 bool isFinal )
2005{
2006 // Special-case controls
2007 switch( aLayer )
2008 {
2009 case LAYER_RATSNEST:
2010 {
2011 // don't touch the layers. ratsnest is enabled on per-item basis.
2013 m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, true );
2014
2016 {
2018 m_frame->GetBoard()->SetElementVisibility( aLayer, isVisible );
2020 }
2021
2022 break;
2023 }
2024
2025 case LAYER_GRID:
2026 m_frame->SetGridVisibility( isVisible );
2029 break;
2030
2031 case LAYER_MOD_TEXT:
2032 // Because Footprint Text is a meta-control that also can disable values/references,
2033 // drag them along here so that the user is less likely to be confused.
2034 if( isFinal )
2035 {
2036 // Should only trigger when you actually click the Footprint Text button
2037 // Otherwise it goes into infinite recursive loop with the following case section
2039 onObjectVisibilityChanged( LAYER_MOD_VALUES, isVisible, false );
2040 m_objectSettingsMap[LAYER_MOD_REFERENCES]->ctl_visibility->SetValue( isVisible );
2041 m_objectSettingsMap[LAYER_MOD_VALUES]->ctl_visibility->SetValue( isVisible );
2042 }
2043 break;
2044
2046 case LAYER_MOD_VALUES:
2047 // In case that user changes Footprint Value/References when the Footprint Text
2048 // meta-control is disabled, we should put it back on.
2049 if( isVisible )
2050 {
2051 onObjectVisibilityChanged( LAYER_MOD_TEXT, isVisible, false );
2052 m_objectSettingsMap[LAYER_MOD_TEXT]->ctl_visibility->SetValue( isVisible );
2053 }
2054 break;
2055
2056 default:
2057 break;
2058 }
2059
2060 GAL_SET visible = getVisibleObjects();
2061
2062 if( visible.Contains( aLayer ) != isVisible )
2063 {
2064 visible.set( aLayer, isVisible );
2065 setVisibleObjects( visible );
2066 m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, isVisible );
2068 }
2069
2070 if( isFinal )
2071 {
2073 passOnFocus();
2074 }
2075}
2076
2077
2079{
2081 COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
2082 GAL_SET visible = getVisibleObjects();
2083 int swatchWidth = m_windowObjects->ConvertDialogToPixels( wxSize( 8, 0 ) ).x;
2084 int labelWidth = 0;
2085
2086 m_objectSettings.clear();
2087 m_objectsOuterSizer->Clear( true );
2088 m_objectsOuterSizer->AddSpacer( 5 );
2089
2090 auto appendObject =
2091 [&]( const std::unique_ptr<APPEARANCE_SETTING>& aSetting )
2092 {
2093 wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
2094 int layer = aSetting->id;
2095
2096 aSetting->visible = visible.Contains( ToGalLayer( layer ) );
2097 COLOR4D color = theme->GetColor( layer );
2098 COLOR4D defColor = theme->GetDefaultColor( layer );
2099
2100 if( color != COLOR4D::UNSPECIFIED )
2101 {
2102 COLOR_SWATCH* swatch = new COLOR_SWATCH( m_windowObjects, color, layer,
2103 bgColor, defColor, SWATCH_SMALL );
2104 swatch->SetToolTip( _( "Left double click or middle click for color change, "
2105 "right click for menu" ) );
2106
2107 sizer->Add( swatch, 0, wxALIGN_CENTER_VERTICAL, 0 );
2108 aSetting->ctl_color = swatch;
2109
2110 swatch->Bind( COLOR_SWATCH_CHANGED, &APPEARANCE_CONTROLS::OnColorSwatchChanged,
2111 this );
2112
2114 this ) );
2115 }
2116 else
2117 {
2118 sizer->AddSpacer( swatchWidth );
2119 }
2120
2121 BITMAP_TOGGLE* btn_visible = new BITMAP_TOGGLE( m_windowObjects, layer,
2124 aSetting->visible );
2125
2126 wxString tip;
2127 tip.Printf( _( "Show or hide %s" ), aSetting->label.Lower() );
2128 btn_visible->SetToolTip( tip );
2129
2130 aSetting->ctl_visibility = btn_visible;
2131
2132 sizer->AddSpacer( 5 );
2133
2134 btn_visible->Bind( TOGGLE_CHANGED,
2135 [&]( wxCommandEvent& aEvent )
2136 {
2137 int id = static_cast<wxWindow*>( aEvent.GetEventObject() )->GetId();
2138 bool isVisible = aEvent.GetInt();
2139 onObjectVisibilityChanged( ToGalLayer( id ), isVisible, true );
2140 } );
2141
2142 wxStaticText* label = new wxStaticText( m_windowObjects, layer, aSetting->label );
2143 label->Wrap( -1 );
2144 label->SetToolTip( aSetting->tooltip );
2145
2146 if( aSetting->can_control_opacity )
2147 {
2148 label->SetMinSize( wxSize( labelWidth, -1 ) );
2149#ifdef __WXMAC__
2150 sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, 10 );
2151 sizer->AddSpacer( 5 );
2152 sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, 10 );
2153#else
2154 sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL, 0 );
2155 sizer->AddSpacer( 5 );
2156 sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL, 0 );
2157#endif
2158
2159 wxSlider* slider = new wxSlider( m_windowObjects, wxID_ANY, 100, 0, 100,
2160 wxDefaultPosition, wxDefaultSize,
2161 wxSL_HORIZONTAL );
2162#ifdef __WXMAC__
2163 slider->SetMinSize( wxSize( 80, 16 ) );
2164#else
2165 slider->SetMinSize( wxSize( 80, -1 ) );
2166#endif
2167
2168 tip.Printf( _( "Set opacity of %s" ), aSetting->label.Lower() );
2169 slider->SetToolTip( tip );
2170
2171 sizer->Add( slider, 1, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 5 );
2172 aSetting->ctl_opacity = slider;
2173
2174 auto opacitySliderHandler =
2175 [=]( wxCommandEvent& aEvent )
2176 {
2177 wxSlider* ctrl = static_cast<wxSlider*>( aEvent.GetEventObject() );
2178 int value = ctrl->GetValue();
2179 onObjectOpacitySlider( layer, value / 100.0f );
2180 };
2181
2182 slider->Bind( wxEVT_SCROLL_CHANGED, opacitySliderHandler );
2183 slider->Bind( wxEVT_SCROLL_THUMBTRACK, opacitySliderHandler );
2184 slider->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS::OnSetFocus, this );
2185 }
2186 else
2187 {
2188 sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL, 0 );
2189 sizer->AddSpacer( 5 );
2190 sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL, 0 );
2191 }
2192
2193 aSetting->ctl_text = label;
2194 m_objectsOuterSizer->Add( sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, 5 );
2195
2196 if( !aSetting->can_control_opacity )
2197 m_objectsOuterSizer->AddSpacer( 2 );
2198 };
2199
2200 for( const APPEARANCE_SETTING& s_setting : s_objectSettings )
2201 {
2202 if( m_isFpEditor && !s_allowedInFpEditor.count( s_setting.id ) )
2203 continue;
2204
2205 if( !s_setting.spacer )
2206 {
2207 m_objectSettings.emplace_back( std::make_unique<APPEARANCE_SETTING>( s_setting ) );
2208
2209 std::unique_ptr<APPEARANCE_SETTING>& setting = m_objectSettings.back();
2210
2211 // Because s_render_rows is created static, we must explicitly call wxGetTranslation
2212 // for texts which are internationalized (tool tips and item names)
2213 setting->tooltip = wxGetTranslation( s_setting.tooltip );
2214 setting->label = wxGetTranslation( s_setting.label );
2215
2216 if( setting->can_control_opacity )
2217 {
2218 int width = m_windowObjects->GetTextExtent( setting->label ).x + 5;
2219 labelWidth = std::max( labelWidth, width );
2220 }
2221
2222 m_objectSettingsMap[ToGalLayer( setting->id )] = setting.get();
2223 }
2224 }
2225
2226 for( const std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
2227 {
2228 if( setting->spacer )
2229 m_objectsOuterSizer->AddSpacer( m_pointSize );
2230 else
2231 appendObject( setting );
2232 }
2233
2234 m_objectsOuterSizer->Layout();
2235}
2236
2237
2239{
2240 GAL_SET visible = getVisibleObjects();
2241
2243
2244 for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
2245 {
2246 if( setting->spacer )
2247 continue;
2248
2249 GAL_LAYER_ID layer = ToGalLayer( setting->id );
2250
2251 if( setting->ctl_visibility )
2252 setting->ctl_visibility->SetValue( visible.Contains( layer ) );
2253
2254 if( setting->ctl_color )
2255 {
2256 COLOR4D color = m_frame->GetColorSettings()->GetColor( setting->id );
2257 setting->ctl_color->SetSwatchColor( color, false );
2258 }
2259 }
2260
2261 wxASSERT( m_objectSettingsMap.count( LAYER_TRACKS )
2266
2267 m_objectSettingsMap[LAYER_TRACKS]->ctl_opacity->SetValue( opts.m_TrackOpacity * 100 );
2268 m_objectSettingsMap[LAYER_VIAS]->ctl_opacity->SetValue( opts.m_ViaOpacity * 100 );
2269 m_objectSettingsMap[LAYER_PADS]->ctl_opacity->SetValue( opts.m_PadOpacity * 100 );
2270 m_objectSettingsMap[LAYER_ZONES]->ctl_opacity->SetValue( opts.m_ZoneOpacity * 100 );
2271 m_objectSettingsMap[LAYER_DRAW_BITMAPS]->ctl_opacity->SetValue( opts.m_ImageOpacity * 100 );
2272}
2273
2274
2275void APPEARANCE_CONTROLS::buildNetClassMenu( wxMenu& aMenu, bool isDefaultClass,
2276 const wxString& aName )
2277{
2278 if( !isDefaultClass)
2279 {
2280 aMenu.Append( new wxMenuItem( &aMenu, ID_SET_NET_COLOR, _( "Set Netclass Color" ),
2281 wxEmptyString, wxITEM_NORMAL ) );
2282 }
2283
2284 wxString name = UnescapeString( aName );
2285
2286 aMenu.Append( new wxMenuItem( &aMenu, ID_HIGHLIGHT_NET,
2287 wxString::Format( _( "Highlight Nets in %s" ), name ),
2288 wxEmptyString, wxITEM_NORMAL ) );
2289 aMenu.Append( new wxMenuItem( &aMenu, ID_SELECT_NET,
2290 wxString::Format( _( "Select Tracks and Vias in %s" ), name ),
2291 wxEmptyString, wxITEM_NORMAL ) );
2292 aMenu.Append( new wxMenuItem( &aMenu, ID_DESELECT_NET,
2293 wxString::Format( _( "Unselect Tracks and Vias in %s" ), name ),
2294 wxEmptyString, wxITEM_NORMAL ) );
2295
2296 aMenu.AppendSeparator();
2297
2298 aMenu.Append( new wxMenuItem( &aMenu, ID_SHOW_ALL_NETS, _( "Show All Netclasses" ),
2299 wxEmptyString, wxITEM_NORMAL ) );
2300 aMenu.Append( new wxMenuItem( &aMenu, ID_HIDE_OTHER_NETS, _( "Hide All Other Netclasses" ),
2301 wxEmptyString, wxITEM_NORMAL ) );
2302
2303 aMenu.Bind( wxEVT_COMMAND_MENU_SELECTED, &APPEARANCE_CONTROLS::onNetclassContextMenu, this );
2304
2305}
2306
2307
2309{
2310 BOARD* board = m_frame->GetBoard();
2312 COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
2313
2314 // If the board isn't fully loaded, we can't yet rebuild
2315 if( !board->GetProject() )
2316 return;
2317
2318 m_staticTextNets->SetLabel( _( "Nets" ) );
2319 m_staticTextNetClasses->SetLabel( _( "Net Classes" ) );
2320
2323
2324 std::map<wxString, KIGFX::COLOR4D>& netclassColors = rs->GetNetclassColorMap();
2325 const std::set<wxString>& hiddenClasses = m_frame->Prj().GetLocalSettings().m_HiddenNetclasses;
2326
2327 m_netclassOuterSizer->Clear( true );
2328
2329 auto appendNetclass =
2330 [&]( int aId, const std::shared_ptr<NETCLASS>& aClass, bool isDefaultClass = false )
2331 {
2332 wxString name = aClass->GetName();
2333
2334 m_netclassSettings.emplace_back( std::make_unique<APPEARANCE_SETTING>() );
2335 APPEARANCE_SETTING* setting = m_netclassSettings.back().get();
2336 m_netclassSettingsMap[name] = setting;
2337
2338 setting->ctl_panel = new wxPanel( m_netclassScrolledWindow, aId );
2339 wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
2340 setting->ctl_panel->SetSizer( sizer );
2341 COLOR4D color = netclassColors.count( name ) ? netclassColors.at( name ) :
2342 COLOR4D::UNSPECIFIED;
2343
2344 setting->ctl_color = new COLOR_SWATCH( setting->ctl_panel, color, aId, bgColor,
2345 COLOR4D::UNSPECIFIED, SWATCH_SMALL );
2346 setting->ctl_color->SetToolTip( _( "Left double click or middle click for color "
2347 "change, right click for menu" ) );
2348
2349 setting->ctl_color->Bind( COLOR_SWATCH_CHANGED,
2351
2352 // Default netclass can't have an override color
2353 if( isDefaultClass )
2354 setting->ctl_color->Hide();
2355
2356 setting->ctl_visibility = new BITMAP_TOGGLE( setting->ctl_panel, aId,
2359 !hiddenClasses.count( name ) );
2360
2361 wxString tip;
2362 tip.Printf( _( "Show or hide ratsnest for nets in %s" ), name );
2363 setting->ctl_visibility->SetToolTip( tip );
2364
2365 setting->ctl_text = new wxStaticText( setting->ctl_panel, aId, name );
2366 setting->ctl_text->Wrap( -1 );
2367
2368 int flags = wxALIGN_CENTER_VERTICAL;
2369
2370 sizer->Add( setting->ctl_color, 0, flags | wxRESERVE_SPACE_EVEN_IF_HIDDEN, 5 );
2371 sizer->AddSpacer( 7 );
2372 sizer->Add( setting->ctl_visibility, 0, flags, 5 );
2373 sizer->AddSpacer( 3 );
2374 sizer->Add( setting->ctl_text, 1, flags, 5 );
2375
2376 m_netclassOuterSizer->Add( setting->ctl_panel, 0, wxEXPAND, 5 );
2377 m_netclassOuterSizer->AddSpacer( 2 );
2378
2379 setting->ctl_visibility->Bind( TOGGLE_CHANGED,
2381 this );
2382
2383 auto menuHandler =
2384 [&, name, isDefaultClass]( wxMouseEvent& aEvent )
2385 {
2386 wxMenu menu;
2387 buildNetClassMenu( menu, isDefaultClass, name );
2388
2390 PopupMenu( &menu );
2391 };
2392
2393 setting->ctl_panel->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2394 setting->ctl_visibility->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2395 setting->ctl_color->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2396 setting->ctl_text->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2397 };
2398
2399 std::shared_ptr<NET_SETTINGS>& netSettings = board->GetDesignSettings().m_NetSettings;
2400
2401 std::vector<wxString> names;
2402
2403 for( const auto& [ name, netclass ] : netSettings->m_NetClasses )
2404 names.emplace_back( name );
2405
2406 std::sort( names.begin(), names.end() );
2407
2408 m_netclassIdMap.clear();
2409
2410 int idx = wxID_HIGHEST;
2411
2412 m_netclassIdMap[idx] = netSettings->m_DefaultNetClass->GetName();
2413 appendNetclass( idx++, netSettings->m_DefaultNetClass, true );
2414
2415 for( const wxString& name : names )
2416 {
2417 m_netclassIdMap[idx] = name;
2418 appendNetclass( idx++, netSettings->m_NetClasses.at( name ) );
2419 }
2420
2421 int hotkey;
2422 wxString msg;
2423
2424 m_paneNetDisplayOptions->SetLabel( _( "Net Display Options" ) );
2425
2427
2428 if( hotkey )
2429 msg = wxString::Format( _( "Net colors (%s):" ), KeyNameFromKeyCode( hotkey ) );
2430 else
2431 msg = _( "Net colors:" );
2432
2433 m_txtNetDisplayTitle->SetLabel( msg );
2434 m_txtNetDisplayTitle->SetToolTip( _( "Choose when to show net and netclass colors" ) );
2435
2436 m_rbNetColorAll->SetLabel( _( "All" ) );
2437 m_rbNetColorAll->SetToolTip( _( "Net and netclass colors are shown on all copper items" ) );
2438
2439 m_rbNetColorRatsnest->SetLabel( _( "Ratsnest" ) );
2440 m_rbNetColorRatsnest->SetToolTip( _( "Net and netclass colors are shown on the ratsnest only" ) );
2441
2442 m_rbNetColorOff->SetLabel( _( "None" ) );
2443 m_rbNetColorOff->SetToolTip( _( "Net and netclass colors are not shown" ) );
2444
2446
2447 if( hotkey )
2448 msg = wxString::Format( _( "Ratsnest display (%s):" ), KeyNameFromKeyCode( hotkey ) );
2449 else
2450 msg = _( "Ratsnest display:" );
2451
2452 m_txtRatsnestVisibility->SetLabel( msg );
2453 m_txtRatsnestVisibility->SetToolTip( _( "Choose which ratsnest lines to display" ) );
2454
2455 m_rbRatsnestAllLayers->SetLabel( _( "All" ) );
2456 m_rbRatsnestAllLayers->SetToolTip( _( "Show ratsnest lines to items on all layers" ) );
2457
2458 m_rbRatsnestVisLayers->SetLabel( _( "Visible layers" ) );
2459 m_rbRatsnestVisLayers->SetToolTip( _( "Show ratsnest lines to items on visible layers" ) );
2460
2461 m_rbRatsnestNone->SetLabel( _( "None" ) );
2462 m_rbRatsnestNone->SetToolTip( _( "Hide all ratsnest lines" ) );
2463
2464 m_netclassOuterSizer->Layout();
2465
2467 m_panelNets->GetSizer()->Layout();
2468}
2469
2470
2472{
2473 m_viewportsLabel->SetLabel( wxString::Format( _( "Presets (%s+Tab):" ),
2475
2476 m_cbLayerPresets->Clear();
2477
2478 // Build the layers preset list.
2479 // By default, the presetAllLayers will be selected
2480 int idx = 0;
2481 int default_idx = 0;
2482
2483 for( std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
2484 {
2485 m_cbLayerPresets->Append( wxGetTranslation( pair.first ),
2486 static_cast<void*>( &pair.second ) );
2487
2488 if( pair.first == presetAllLayers.name )
2489 default_idx = idx;
2490
2491 idx++;
2492 }
2493
2494 m_cbLayerPresets->Append( wxT( "---" ) );
2495 m_cbLayerPresets->Append( _( "Save preset..." ) );
2496 m_cbLayerPresets->Append( _( "Delete preset..." ) );
2497
2498 // At least the built-in presets should always be present
2499 wxASSERT( !m_layerPresets.empty() );
2500
2501 // Default preset: all layers
2502 m_cbLayerPresets->SetSelection( default_idx );
2504}
2505
2506
2508{
2509 LSET visibleLayers = getVisibleLayers();
2510 GAL_SET visibleObjects = getVisibleObjects();
2511
2512 auto it = std::find_if( m_layerPresets.begin(), m_layerPresets.end(),
2513 [&]( const std::pair<const wxString, LAYER_PRESET>& aPair )
2514 {
2515 return ( aPair.second.layers == visibleLayers
2516 && aPair.second.renderLayers == visibleObjects );
2517 } );
2518
2519 if( it != m_layerPresets.end() )
2520 {
2521 // Select the right m_cbLayersPresets item.
2522 // but these items are translated if they are predefined items.
2523 bool do_translate = it->second.readOnly;
2524 wxString text = do_translate ? wxGetTranslation( it->first ) : it->first;
2525
2526 m_cbLayerPresets->SetStringSelection( text );
2527 }
2528 else
2529 {
2530 m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator
2531 }
2532
2533 m_currentPreset = static_cast<LAYER_PRESET*>(
2534 m_cbLayerPresets->GetClientData( m_cbLayerPresets->GetSelection() ) );
2535}
2536
2537
2539{
2540 // look at m_layerPresets to know if aName is a read only preset, or a user preset.
2541 // Read only presets have translated names in UI, so we have to use
2542 // a translated name in UI selection.
2543 // But for a user preset name we should search for aName (not translated)
2544 wxString ui_label = aName;
2545
2546 for( std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
2547 {
2548 if( pair.first != aName )
2549 continue;
2550
2551 if( pair.second.readOnly == true )
2552 ui_label = wxGetTranslation( aName );
2553
2554 break;
2555 }
2556
2557 int idx = m_cbLayerPresets->FindString( ui_label );
2558
2559 if( idx >= 0 && m_cbLayerPresets->GetSelection() != idx )
2560 {
2561 m_cbLayerPresets->SetSelection( idx );
2562 m_currentPreset = static_cast<LAYER_PRESET*>( m_cbLayerPresets->GetClientData( idx ) );
2563 }
2564 else if( idx < 0 )
2565 {
2566 m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator
2567 }
2568}
2569
2570
2571void APPEARANCE_CONTROLS::onLayerPresetChanged( wxCommandEvent& aEvent )
2572{
2573 int count = m_cbLayerPresets->GetCount();
2574 int index = m_cbLayerPresets->GetSelection();
2575
2576 auto resetSelection =
2577 [&]()
2578 {
2579 if( m_currentPreset )
2580 m_cbLayerPresets->SetStringSelection( m_currentPreset->name );
2581 else
2582 m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 );
2583 };
2584
2585 if( index == count - 3 )
2586 {
2587 // Separator: reject the selection
2588 resetSelection();
2589 return;
2590 }
2591 else if( index == count - 2 )
2592 {
2593 // Save current state to new preset
2594 wxString name;
2595
2598
2599 wxTextEntryDialog dlg( this, _( "Layer preset name:" ), _( "Save Layer Preset" ), name );
2600
2601 if( dlg.ShowModal() != wxID_OK )
2602 {
2603 resetSelection();
2604 return;
2605 }
2606
2607 name = dlg.GetValue();
2608 bool exists = m_layerPresets.count( name );
2609
2610 if( !exists )
2611 {
2614 }
2615
2616 LAYER_PRESET* preset = &m_layerPresets[name];
2617 m_currentPreset = preset;
2618
2619 if( !exists )
2620 {
2621 index = m_cbLayerPresets->Insert( name, index - 1, static_cast<void*>( preset ) );
2622 }
2623 else
2624 {
2625 preset->layers = getVisibleLayers();
2626 preset->renderLayers = getVisibleObjects();
2627
2628 index = m_cbLayerPresets->FindString( name );
2629 m_presetMRU.Remove( name );
2630 }
2631
2632 m_cbLayerPresets->SetSelection( index );
2633 m_presetMRU.Insert( name, 0 );
2634
2635 return;
2636 }
2637 else if( index == count - 1 )
2638 {
2639 // Delete a preset
2640 wxArrayString headers;
2641 std::vector<wxArrayString> items;
2642
2643 headers.Add( _( "Presets" ) );
2644
2645 for( std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
2646 {
2647 if( !pair.second.readOnly )
2648 {
2649 wxArrayString item;
2650 item.Add( pair.first );
2651 items.emplace_back( item );
2652 }
2653 }
2654
2655 EDA_LIST_DIALOG dlg( m_frame, _( "Delete Preset" ), headers, items );
2656 dlg.SetListLabel( _( "Select preset:" ) );
2657
2658 if( dlg.ShowModal() == wxID_OK )
2659 {
2660 wxString presetName = dlg.GetTextSelection();
2661 int idx = m_cbLayerPresets->FindString( presetName );
2662
2663 if( idx != wxNOT_FOUND )
2664 {
2665 m_layerPresets.erase( presetName );
2666
2667 m_cbLayerPresets->Delete( idx );
2668 m_currentPreset = nullptr;
2669
2670 m_presetMRU.Remove( presetName );
2671 }
2672 }
2673
2674 resetSelection();
2675 return;
2676 }
2677
2678 LAYER_PRESET* preset = static_cast<LAYER_PRESET*>( m_cbLayerPresets->GetClientData( index ) );
2679 m_currentPreset = preset;
2680
2681 m_lastSelectedUserPreset = ( !preset || preset->readOnly ) ? nullptr : preset;
2682
2683 if( preset )
2684 doApplyLayerPreset( *preset );
2685
2686 if( !m_currentPreset->name.IsEmpty() )
2687 {
2688 m_presetMRU.Remove( m_currentPreset->name );
2689 m_presetMRU.Insert( m_currentPreset->name, 0 );
2690 }
2691
2692 passOnFocus();
2693}
2694
2695
2697{
2698 BOARD* board = m_frame->GetBoard();
2699
2700 setVisibleLayers( aPreset.layers );
2702
2703 // If the preset doesn't have an explicit active layer to restore, we can at least
2704 // force the active layer to be something in the preset's layer set
2705 PCB_LAYER_ID activeLayer = UNSELECTED_LAYER;
2706
2707 if( aPreset.activeLayer != UNSELECTED_LAYER )
2708 activeLayer = aPreset.activeLayer;
2709 else if( aPreset.layers.any() && !aPreset.layers.test( m_frame->GetActiveLayer() ) )
2710 activeLayer = *aPreset.layers.Seq().begin();
2711
2712 LSET boardLayers = board->GetLayerSet();
2713
2714 if( activeLayer != UNSELECTED_LAYER && boardLayers.Contains( activeLayer ) )
2715 m_frame->SetActiveLayer( activeLayer );
2716
2717 if( !m_isFpEditor )
2719
2721
2723}
2724
2725
2727{
2728 m_viewportsLabel->SetLabel( wxString::Format( _( "Viewports (%s+Tab):" ),
2730
2731 m_cbViewports->Clear();
2732
2733 for( std::pair<const wxString, VIEWPORT>& pair : m_viewports )
2734 m_cbViewports->Append( pair.first, static_cast<void*>( &pair.second ) );
2735
2736 m_cbViewports->Append( wxT( "---" ) );
2737 m_cbViewports->Append( _( "Save viewport..." ) );
2738 m_cbViewports->Append( _( "Delete viewport..." ) );
2739
2740 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 );
2741 m_lastSelectedViewport = nullptr;
2742}
2743
2744
2746{
2747 int idx = m_cbViewports->FindString( aName );
2748
2749 if( idx >= 0 && idx < (int)m_cbViewports->GetCount() - 3 /* separator */ )
2750 {
2751 m_cbViewports->SetSelection( idx );
2752 m_lastSelectedViewport = static_cast<VIEWPORT*>( m_cbViewports->GetClientData( idx ) );
2753 }
2754 else if( idx < 0 )
2755 {
2756 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 ); // separator
2757 m_lastSelectedViewport = nullptr;
2758 }
2759}
2760
2761
2762void APPEARANCE_CONTROLS::onViewportChanged( wxCommandEvent& aEvent )
2763{
2764 int count = m_cbViewports->GetCount();
2765 int index = m_cbViewports->GetSelection();
2766
2767 if( index >= 0 && index < count - 3 )
2768 {
2769 VIEWPORT* viewport = static_cast<VIEWPORT*>( m_cbViewports->GetClientData( index ) );
2770
2771 wxCHECK( viewport, /* void */ );
2772
2773 doApplyViewport( *viewport );
2774
2775 if( !viewport->name.IsEmpty() )
2776 {
2777 m_viewportMRU.Remove( viewport->name );
2778 m_viewportMRU.Insert( viewport->name, 0 );
2779 }
2780 }
2781 else if( index == count - 2 )
2782 {
2783 // Save current state to new preset
2784 wxString name;
2785
2786 wxTextEntryDialog dlg( this, _( "Viewport name:" ), _( "Save Viewport" ), name );
2787
2788 if( dlg.ShowModal() != wxID_OK )
2789 {
2791 m_cbViewports->SetStringSelection( m_lastSelectedViewport->name );
2792 else
2793 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 );
2794
2795 return;
2796 }
2797
2798 name = dlg.GetValue();
2799 bool exists = m_viewports.count( name );
2800
2801 if( !exists )
2802 {
2804
2805 index = m_cbViewports->Insert( name, index-1, static_cast<void*>( &m_viewports[name] ) );
2806 }
2807 else
2808 {
2810 index = m_cbViewports->FindString( name );
2811 m_viewportMRU.Remove( name );
2812 }
2813
2814 m_cbViewports->SetSelection( index );
2815 m_viewportMRU.Insert( name, 0 );
2816
2817 return;
2818 }
2819 else if( index == count - 1 )
2820 {
2821 // Delete an existing viewport
2822 wxArrayString headers;
2823 std::vector<wxArrayString> items;
2824
2825 headers.Add( _( "Viewports" ) );
2826
2827 for( std::pair<const wxString, VIEWPORT>& pair : m_viewports )
2828 {
2829 wxArrayString item;
2830 item.Add( pair.first );
2831 items.emplace_back( item );
2832 }
2833
2834 EDA_LIST_DIALOG dlg( m_frame, _( "Delete Viewport" ), headers, items );
2835 dlg.SetListLabel( _( "Select viewport:" ) );
2836
2837 if( dlg.ShowModal() == wxID_OK )
2838 {
2839 wxString viewportName = dlg.GetTextSelection();
2840 int idx = m_cbViewports->FindString( viewportName );
2841
2842 if( idx != wxNOT_FOUND )
2843 {
2844 m_viewports.erase( viewportName );
2845 m_cbViewports->Delete( idx );
2846 m_viewportMRU.Remove( viewportName );
2847 }
2848 }
2849
2851 m_cbViewports->SetStringSelection( m_lastSelectedViewport->name );
2852 else
2853 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 );
2854
2855 return;
2856 }
2857
2858 passOnFocus();
2859}
2860
2861
2863{
2864 m_frame->GetCanvas()->GetView()->SetViewport( aViewport.rect );
2866}
2867
2868
2869void APPEARANCE_CONTROLS::OnColorSwatchChanged( wxCommandEvent& aEvent )
2870{
2871 COLOR_SWATCH* swatch = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
2872 COLOR4D newColor = swatch->GetSwatchColor();
2873 int layer = swatch->GetId();
2874
2876 cs->SetColor( layer, newColor );
2877
2879
2880 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
2881 view->UpdateLayerColor( layer );
2882 view->UpdateLayerColor( GetNetnameLayer( layer ) );
2883
2884 if( IsCopperLayer( layer ) )
2885 view->UpdateLayerColor( ZONE_LAYER_FOR( layer ) );
2886
2887 if( layer == F_Cu )
2889 else if( layer == B_Cu )
2891
2892 // Update the bitmap of the layer box
2894 static_cast<PCB_EDIT_FRAME*>( m_frame )->ReCreateLayerBox( false );
2895
2897
2898 if( layer == LAYER_PCB_BACKGROUND )
2899 m_frame->SetDrawBgColor( newColor );
2900
2901 passOnFocus();
2902}
2903
2904
2905void APPEARANCE_CONTROLS::onObjectOpacitySlider( int aLayer, float aOpacity )
2906{
2908
2909 switch( aLayer )
2910 {
2911 case static_cast<int>( LAYER_TRACKS ): options.m_TrackOpacity = aOpacity; break;
2912 case static_cast<int>( LAYER_VIAS ): options.m_ViaOpacity = aOpacity; break;
2913 case static_cast<int>( LAYER_PADS ): options.m_PadOpacity = aOpacity; break;
2914 case static_cast<int>( LAYER_ZONES ): options.m_ZoneOpacity = aOpacity; break;
2915 case static_cast<int>( LAYER_DRAW_BITMAPS ): options.m_ImageOpacity = aOpacity; break;
2916 default: return;
2917 }
2918
2919 m_frame->SetDisplayOptions( options );
2920 passOnFocus();
2921}
2922
2923
2924void APPEARANCE_CONTROLS::onNetContextMenu( wxCommandEvent& aEvent )
2925{
2926 wxASSERT( m_netsGrid->GetSelectedRows().size() == 1 );
2927
2928 int row = m_netsGrid->GetSelectedRows()[0];
2929 NET_GRID_ENTRY& net = m_netsTable->GetEntry( row );
2930
2931 m_netsGrid->ClearSelection();
2932
2933 switch( aEvent.GetId() )
2934 {
2935 case ID_SET_NET_COLOR:
2936 {
2937 wxGridCellEditor* editor = m_netsGrid->GetCellEditor( row, NET_GRID_TABLE::COL_COLOR );
2938 editor->BeginEdit( row, NET_GRID_TABLE::COL_COLOR, m_netsGrid );
2939 break;
2940 }
2941
2942 case ID_HIGHLIGHT_NET:
2944 static_cast<intptr_t>( net.code ) );
2946 break;
2947
2948 case ID_SELECT_NET:
2950 static_cast<intptr_t>( net.code ) );
2952 break;
2953
2954 case ID_DESELECT_NET:
2956 static_cast<intptr_t>( net.code ) );
2958 break;
2959
2960 case ID_SHOW_ALL_NETS:
2962 break;
2963
2964 case ID_HIDE_OTHER_NETS:
2965 m_netsTable->HideOtherNets( net );
2966 break;
2967
2968 default:
2969 break;
2970 }
2971
2972 passOnFocus();
2973}
2974
2975
2977{
2978 wxString className = netclassNameFromEvent( aEvent );
2979 bool show = aEvent.GetInt();
2980 showNetclass( className, show );
2981 passOnFocus();
2982}
2983
2984
2985void APPEARANCE_CONTROLS::showNetclass( const wxString& aClassName, bool aShow )
2986{
2987 for( NETINFO_ITEM* net : m_frame->GetBoard()->GetNetInfo() )
2988 {
2989 if( net->GetNetClass()->GetName() == aClassName )
2990 {
2993 true,
2994 static_cast<intptr_t>( net->GetNetCode() ) );
2995
2996 int row = m_netsTable->GetRowByNetcode( net->GetNetCode() );
2997
2998 if( row >= 0 )
3000 }
3001 }
3002
3003 PROJECT_LOCAL_SETTINGS& localSettings = m_frame->Prj().GetLocalSettings();
3004
3005 if( !aShow )
3006 localSettings.m_HiddenNetclasses.insert( aClassName );
3007 else
3008 localSettings.m_HiddenNetclasses.erase( aClassName );
3009
3010 m_netsGrid->ForceRefresh();
3011}
3012
3013
3015{
3018
3019 std::map<wxString, KIGFX::COLOR4D>& netclassColors = rs->GetNetclassColorMap();
3020
3021 COLOR_SWATCH* swatch = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
3022 wxString netclassName = netclassNameFromEvent( aEvent );
3023
3024 netclassColors[netclassName] = swatch->GetSwatchColor();
3025
3029}
3030
3031
3033{
3034 COLOR_SWATCH* s = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
3035 int classId = s->GetId();
3036
3037 wxASSERT( m_netclassIdMap.count( classId ) );
3038 return m_netclassIdMap.at( classId );
3039}
3040
3041
3042void APPEARANCE_CONTROLS::onNetColorMode( wxCommandEvent& aEvent )
3043{
3045
3046 if( m_rbNetColorAll->GetValue() )
3048 else if( m_rbNetColorRatsnest->GetValue() )
3050 else
3052
3053 m_frame->SetDisplayOptions( options );
3055 passOnFocus();
3056}
3057
3058
3059void APPEARANCE_CONTROLS::onRatsnestMode( wxCommandEvent& aEvent )
3060{
3062
3063 if( m_rbRatsnestAllLayers->GetValue() )
3064 {
3065 cfg->m_Display.m_ShowGlobalRatsnest = true;
3067 }
3068 else if( m_rbRatsnestVisLayers->GetValue() )
3069 {
3070 cfg->m_Display.m_ShowGlobalRatsnest = true;
3072 }
3073 else
3074 {
3075 cfg->m_Display.m_ShowGlobalRatsnest = false;
3076 }
3077
3079 passOnFocus();
3080}
3081
3082
3084{
3085 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
3087 static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
3088
3089 BOARD* board = m_frame->GetBoard();
3090 std::shared_ptr<NET_SETTINGS>& netSettings = board->GetDesignSettings().m_NetSettings;
3091 APPEARANCE_SETTING* setting = nullptr;
3092
3094
3095 if( it != m_netclassSettingsMap.end() )
3096 setting = it->second;
3097
3098 auto runOnNetsOfClass =
3099 [&]( const wxString& netClassName, std::function<void( NETINFO_ITEM* )> aFunction )
3100 {
3101 for( NETINFO_ITEM* net : board->GetNetInfo() )
3102 {
3103 if( net->GetNetClass()->GetName() == netClassName )
3104 aFunction( net );
3105 }
3106 };
3107
3108 switch( aEvent.GetId() )
3109 {
3110 case ID_SET_NET_COLOR:
3111 if( setting )
3112 {
3113 setting->ctl_color->GetNewSwatchColor();
3114
3115 COLOR4D color = setting->ctl_color->GetSwatchColor();
3116
3117 std::map<wxString, KIGFX::COLOR4D>& netclassColors = rs->GetNetclassColorMap();
3118
3119 if( color != COLOR4D::UNSPECIFIED )
3120 netclassColors[m_contextMenuNetclass] = color;
3121 else
3122 netclassColors.erase( m_contextMenuNetclass );
3123
3124 view->UpdateAllLayersColor();
3125 }
3126
3127 break;
3128
3129 case ID_HIGHLIGHT_NET:
3130 if( !m_contextMenuNetclass.IsEmpty() )
3131 {
3132 runOnNetsOfClass( m_contextMenuNetclass,
3133 [&]( NETINFO_ITEM* aItem )
3134 {
3135 static bool first = true;
3136 int code = aItem->GetNetCode();
3137
3138 if( first )
3139 {
3140 board->SetHighLightNet( code );
3141 rs->SetHighlight( true, code );
3142 first = false;
3143 }
3144 else
3145 {
3146 board->SetHighLightNet( code, true );
3147 rs->SetHighlight( true, code, true );
3148 }
3149 } );
3150
3151 view->UpdateAllLayersColor();
3152 board->HighLightON();
3153 }
3154
3155 break;
3156
3157 case ID_SELECT_NET:
3158 case ID_DESELECT_NET:
3159 if( !m_contextMenuNetclass.IsEmpty() )
3160 {
3161 TOOL_MANAGER* toolMgr = m_frame->GetToolManager();
3164
3165 runOnNetsOfClass( m_contextMenuNetclass,
3166 [&]( NETINFO_ITEM* aItem )
3167 {
3168 toolMgr->RunAction( action, true,
3169 static_cast<intptr_t>( aItem->GetNetCode() ) );
3170 } );
3171 }
3172 break;
3173
3174
3175 case ID_SHOW_ALL_NETS:
3177 wxASSERT( m_netclassSettingsMap.count( NETCLASS::Default ) );
3178 m_netclassSettingsMap.at( NETCLASS::Default )->ctl_visibility->SetValue( true );
3179
3180 for( const auto& [ name, netclass ] : netSettings->m_NetClasses )
3181 {
3182 showNetclass( name );
3183
3184 if( m_netclassSettingsMap.count( name ) )
3185 m_netclassSettingsMap.at( name )->ctl_visibility->SetValue( true );
3186 }
3187
3188 break;
3189
3190 case ID_HIDE_OTHER_NETS:
3191 {
3192 bool showDefault = m_contextMenuNetclass == NETCLASS::Default;
3193 showNetclass( NETCLASS::Default, showDefault );
3194 wxASSERT( m_netclassSettingsMap.count( NETCLASS::Default ) );
3195 m_netclassSettingsMap.at( NETCLASS::Default )->ctl_visibility->SetValue( showDefault );
3196
3197 for( const auto& [ name, netclass ] : netSettings->m_NetClasses )
3198 {
3199 bool show = ( name == m_contextMenuNetclass );
3200
3201 showNetclass( name, show );
3202
3203 if( m_netclassSettingsMap.count( name ) )
3204 m_netclassSettingsMap.at( name )->ctl_visibility->SetValue( show );
3205 }
3206
3207 break;
3208 }
3209
3210 default:
3211 break;
3212 }
3213
3216
3217 m_contextMenuNetclass.clear();
3218}
3219
3220
3222{
3223 m_focusOwner->SetFocus();
3224}
3225
3226
3228{
3229 WX_INFOBAR* infobar = m_frame->GetInfoBar();
3230
3231 wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY, _( "Open Preferences" ),
3232 wxEmptyString );
3233
3234 button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
3235 [&]( wxHyperlinkEvent& aEvent )
3236 {
3237 wxCommandEvent dummy;
3239 } ) );
3240
3241 infobar->RemoveAllButtons();
3242 infobar->AddButton( button );
3243 infobar->AddCloseButton();
3244
3245 infobar->ShowMessageFor( _( "The current color theme is read-only. Create a new theme in "
3246 "Preferences to enable color editing." ),
3247 10000, wxICON_INFORMATION );
3248}
3249
3250
3252{
3253 m_paneLayerDisplayOptions->Refresh();
3254}
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:105
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:265
@ 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:106
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:58
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:185
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:265
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:765
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:526
LSET GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:540
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:1984
GAL_SET GetVisibleElements() const
Return a set of all the element categories that are visible.
Definition: board.cpp:586
void SetHighLightNet(int aNetCode, bool aMulti=false)
Select the netcode to be highlighted.
Definition: board.cpp:2030
int GetCopperLayerCount() const
Definition: board.cpp:502
void SetVisibleLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings changes the bit-mask of vis...
Definition: board.cpp:558
void SetElementVisibility(GAL_LAYER_ID aLayer, bool aNewState)
Change the visibility of an element category.
Definition: board.cpp:598
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:413
PROJECT * GetProject() const
Definition: board.h:440
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:643
void HighLightON(bool aValue=true)
Enable or disable net highlighting.
Definition: board.cpp:2043
void SetVisibleElements(const GAL_SET &aMask)
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:565
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
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:104
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:508
void SetViewport(const BOX2D &aViewport)
Set the visible area of the VIEW.
Definition: view.cpp:520
void UpdateAllLayersColor()
Apply the new coloring scheme to all layers.
Definition: view.cpp:758
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:737
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:1489
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:491
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:530
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:600
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:66
int GetNetCode() const
Definition: netinfo.h:113
const NETNAMES_MAP & NetsByName() const
Return the name map, at least for python.
Definition: netinfo.h:366
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:59
DISPLAY_OPTIONS m_Display
AUI_PANELS m_AuiPanels
static TOOL_ACTION listNets
Definition: pcb_actions.h:379
static TOOL_ACTION highlightNet
Definition: pcb_actions.h:493
static TOOL_ACTION hideNetInRatsnest
Definition: pcb_actions.h:500
static TOOL_ACTION showNetInRatsnest
Definition: pcb_actions.h:501
static TOOL_ACTION ratsnestModeCycle
Definition: pcb_actions.h:274
static TOOL_ACTION netColorModeCycle
Definition: pcb_actions.h:273
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:326
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.
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:154
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:95
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:76
A modified version of the wxInfoBar class that allows us to:
Definition: infobar.h:75
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
Definition: infobar.cpp:286
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: infobar.cpp:128
void AddButton(wxButton *aButton)
Add an already created button to the infobar.
Definition: infobar.cpp:245
void AddCloseButton(const wxString &aTooltip=_("Hide this message."))
Add the default close button to the infobar on the right side.
Definition: infobar.cpp:276
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
E_SERIE r
Definition: eserie.cpp:41
@ 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:966
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:825
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.
@ REPAINT
Item needs to be redrawn.
Definition: view_item.h:52
@ TARGET_NONCACHED
Auxiliary rendering target (noncached)
Definition: definitions.h:49
wxFont GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:144
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)
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:74
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