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