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