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 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1349
1350 if( m_isFpEditor )
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 // Update VIEW layer visibility to stay in sync with board settings
1365 for( size_t i = 0; i < GAL_LAYER_INDEX( LAYER_ZONE_START ) && i < aLayers.size(); i++ )
1366 {
1367 // Warning: all GAL layers are not handled by the apparence panel (i.e. LAYER_SELECT_OVERLAY)
1368 // but only some, only set visiblity if the layer is handled by the APPEARANCE_CONTROLS
1370
1371 for( const APPEARANCE_SETTING& s_setting : s_objectSettings )
1372 {
1373 // See if this gal layer is handled
1374 if( s_setting.id == gal_ly )
1375 {
1376 view->SetLayerVisible( gal_ly, aLayers.test( i ) );
1377 break;
1378 }
1379 }
1380 }
1381
1382 m_frame->Update3DView( true, m_frame->GetPcbNewSettings()->m_Display.m_Live3DRefresh );
1383 }
1384}
1385
1386
1388{
1389 if( m_isFpEditor )
1390 {
1391 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1392 LSET set;
1393
1394 for( PCB_LAYER_ID layer : LSET::AllLayersMask().Seq() )
1395 set.set( layer, view->IsLayerVisible( layer ) );
1396
1397 return set;
1398 }
1399 else
1400 {
1401 return m_frame->GetBoard()->GetVisibleLayers();
1402 }
1403}
1404
1405
1407{
1408 if( m_isFpEditor )
1409 {
1410 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1411 GAL_SET set;
1412 set.reset();
1413
1414 for( size_t i = 0; i < set.size(); i++ )
1415 set.set( i, view->IsLayerVisible( GAL_LAYER_ID_START + GAL_LAYER_ID( i ) ) );
1416
1417 return set;
1418 }
1419 else
1420 {
1421 return m_frame->GetBoard()->GetVisibleElements();
1422 }
1423}
1424
1425
1427{
1428 const PCB_DISPLAY_OPTIONS& options = m_frame->GetDisplayOptions();
1429
1430 switch( options.m_ContrastModeDisplay )
1431 {
1432 case HIGH_CONTRAST_MODE::NORMAL: m_rbHighContrastNormal->SetValue( true ); break;
1433 case HIGH_CONTRAST_MODE::DIMMED: m_rbHighContrastDim->SetValue( true ); break;
1434 case HIGH_CONTRAST_MODE::HIDDEN: m_rbHighContrastOff->SetValue( true ); break;
1435 }
1436
1437 switch( options.m_NetColorMode )
1438 {
1439 case NET_COLOR_MODE::ALL: m_rbNetColorAll->SetValue( true ); break;
1440 case NET_COLOR_MODE::RATSNEST: m_rbNetColorRatsnest->SetValue( true ); break;
1441 case NET_COLOR_MODE::OFF: m_rbNetColorOff->SetValue( true ); break;
1442 }
1443
1444 m_cbFlipBoard->SetValue( m_frame->GetCanvas()->GetView()->IsMirroredX() );
1445
1446 if( !m_isFpEditor )
1447 {
1448 if( PCBNEW_SETTINGS* cfg = m_frame->GetPcbNewSettings() )
1449 {
1450 if( !cfg->m_Display.m_ShowGlobalRatsnest )
1451 m_rbRatsnestNone->SetValue( true );
1452 else if( cfg->m_Display.m_RatsnestMode == RATSNEST_MODE::ALL )
1453 m_rbRatsnestAllLayers->SetValue( true );
1454 else
1455 m_rbRatsnestVisLayers->SetValue( true );
1456
1457 wxASSERT( m_objectSettingsMap.count( LAYER_RATSNEST ) );
1459 ratsnest->ctl_visibility->SetValue( cfg->m_Display.m_ShowGlobalRatsnest );
1460 }
1461 }
1462}
1463
1464
1465std::vector<LAYER_PRESET> APPEARANCE_CONTROLS::GetUserLayerPresets() const
1466{
1467 std::vector<LAYER_PRESET> ret;
1468
1469 for( const std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
1470 {
1471 if( !pair.second.readOnly )
1472 ret.emplace_back( pair.second );
1473 }
1474
1475 return ret;
1476}
1477
1478
1479void APPEARANCE_CONTROLS::SetUserLayerPresets( std::vector<LAYER_PRESET>& aPresetList )
1480{
1481 // Reset to defaults
1483
1484 for( const LAYER_PRESET& preset : aPresetList )
1485 {
1486 if( m_layerPresets.count( preset.name ) )
1487 continue;
1488
1489 m_layerPresets[preset.name] = preset;
1490
1491 m_presetMRU.Add( preset.name );
1492 }
1493
1495}
1496
1497
1499{
1500 m_layerPresets.clear();
1501
1502 // Load the read-only defaults
1503 for( const LAYER_PRESET& preset : { presetAllLayers,
1509 presetBack,
1511 {
1512 m_layerPresets[preset.name] = preset;
1513 m_layerPresets[preset.name].readOnly = true;
1514 }
1515}
1516
1517
1518void APPEARANCE_CONTROLS::ApplyLayerPreset( const wxString& aPresetName )
1519{
1520 updateLayerPresetSelection( aPresetName );
1521
1522 wxCommandEvent dummy;
1524}
1525
1526
1528{
1529 if( m_layerPresets.count( aPreset.name ) )
1531 else
1532 m_currentPreset = nullptr;
1533
1535 : nullptr;
1536
1538 doApplyLayerPreset( aPreset );
1539}
1540
1541
1542std::vector<VIEWPORT> APPEARANCE_CONTROLS::GetUserViewports() const
1543{
1544 std::vector<VIEWPORT> ret;
1545
1546 for( const std::pair<const wxString, VIEWPORT>& pair : m_viewports )
1547 ret.emplace_back( pair.second );
1548
1549 return ret;
1550}
1551
1552
1553void APPEARANCE_CONTROLS::SetUserViewports( std::vector<VIEWPORT>& aViewportList )
1554{
1555 m_viewports.clear();
1556
1557 for( const VIEWPORT& viewport : aViewportList )
1558 {
1559 if( m_viewports.count( viewport.name ) )
1560 continue;
1561
1562 m_viewports[viewport.name] = viewport;
1563
1564 m_viewportMRU.Add( viewport.name );
1565 }
1566
1568}
1569
1570
1571void APPEARANCE_CONTROLS::ApplyViewport( const wxString& aViewportName )
1572{
1573 updateViewportSelection( aViewportName );
1574
1575 wxCommandEvent dummy;
1577}
1578
1579
1581{
1582 updateViewportSelection( aViewport.name );
1583 doApplyViewport( aViewport );
1584}
1585
1586
1588{
1589 BOARD* board = m_frame->GetBoard();
1590 LSET enabled = board->GetEnabledLayers();
1591 LSET visible = getVisibleLayers();
1592
1593 COLOR_SETTINGS* theme = m_frame->GetColorSettings();
1594 COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
1595 bool readOnly = theme->IsReadOnly();
1596
1598
1599#ifdef __WXMAC__
1600 wxSizerItem* m_windowLayersSizerItem = m_panelLayersSizer->GetItem( m_windowLayers );
1601 m_windowLayersSizerItem->SetFlag( m_windowLayersSizerItem->GetFlag() & ~wxTOP );
1602#endif
1603
1604 auto appendLayer =
1605 [&]( std::unique_ptr<APPEARANCE_SETTING>& aSetting )
1606 {
1607 int layer = aSetting->id;
1608
1609 wxPanel* panel = new wxPanel( m_windowLayers, layer );
1610 wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
1611 panel->SetSizer( sizer );
1612
1613 panel->SetBackgroundColour( m_layerPanelColour );
1614
1615 aSetting->visible = visible[layer];
1616
1617 // TODO(JE) consider restyling this indicator
1618 INDICATOR_ICON* indicator = new INDICATOR_ICON( panel, *m_iconProvider,
1620
1621 COLOR_SWATCH* swatch = new COLOR_SWATCH( panel, COLOR4D::UNSPECIFIED, layer, bgColor,
1622 theme->GetColor( layer ), SWATCH_SMALL );
1623 swatch->SetToolTip( _( "Double click or middle click for color change, right click for menu" ) );
1624
1625 BITMAP_TOGGLE* btn_visible = new BITMAP_TOGGLE( panel, layer,
1628 aSetting->visible );
1629 btn_visible->SetToolTip( _( "Show or hide this layer" ) );
1630
1631 wxStaticText* label = new wxStaticText( panel, layer, aSetting->label );
1632 label->Wrap( -1 );
1633 label->SetToolTip( aSetting->tooltip );
1634
1635 sizer->AddSpacer( 1 );
1636 sizer->Add( indicator, 0, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1637 sizer->AddSpacer( 5 );
1638 sizer->Add( swatch, 0, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1639 sizer->AddSpacer( 6 );
1640 sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1641 sizer->AddSpacer( 5 );
1642 sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1643
1644 m_layersOuterSizer->Add( panel, 0, wxEXPAND, 0 );
1645
1646 aSetting->ctl_panel = panel;
1647 aSetting->ctl_indicator = indicator;
1648 aSetting->ctl_visibility = btn_visible;
1649 aSetting->ctl_color = swatch;
1650 aSetting->ctl_text = label;
1651
1652 panel->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1653 indicator->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1654 swatch->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1655 label->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1656
1657 btn_visible->Bind( TOGGLE_CHANGED,
1658 [&]( wxCommandEvent& aEvent )
1659 {
1660 wxObject* btn = aEvent.GetEventObject();
1661 int layerId = static_cast<wxWindow*>( btn )->GetId();
1662
1663 onLayerVisibilityToggled( static_cast<PCB_LAYER_ID>( layerId ) );
1664 } );
1665
1666 swatch->Bind( COLOR_SWATCH_CHANGED, &APPEARANCE_CONTROLS::OnColorSwatchChanged, this );
1667 swatch->SetReadOnlyCallback( std::bind( &APPEARANCE_CONTROLS::onReadOnlySwatch, this ) );
1668 swatch->SetReadOnly( readOnly );
1669
1670 panel->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1671 indicator->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1672 swatch->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1673 btn_visible->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1674 label->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1675 };
1676
1677 auto updateLayer =
1678 [&]( std::unique_ptr<APPEARANCE_SETTING>& aSetting )
1679 {
1680 int layer = aSetting->id;
1681 aSetting->visible = visible[layer];
1682 aSetting->ctl_panel->Show();
1683 aSetting->ctl_panel->SetId( layer );
1684 aSetting->ctl_indicator->SetWindowID( layer );
1685 aSetting->ctl_color->SetWindowID( layer );
1686 aSetting->ctl_color->SetSwatchColor( theme->GetColor( layer ), false );
1687 aSetting->ctl_visibility->SetWindowID( layer );
1688 aSetting->ctl_text->SetLabelText( aSetting->label );
1689 aSetting->ctl_text->SetId( layer );
1690 aSetting->ctl_text->SetToolTip( aSetting->tooltip );
1691 };
1692
1693 // technical layers are shown in this order:
1694 // Because they are static, wxGetTranslation must be explicitly
1695 // called for tooltips.
1696 static const struct {
1697 PCB_LAYER_ID layerId;
1698 wxString tooltip;
1699 } non_cu_seq[] = {
1700 { F_Adhes, _HKI( "Adhesive on board's front" ) },
1701 { B_Adhes, _HKI( "Adhesive on board's back" ) },
1702 { F_Paste, _HKI( "Solder paste on board's front" ) },
1703 { B_Paste, _HKI( "Solder paste on board's back" ) },
1704 { F_SilkS, _HKI( "Silkscreen on board's front" ) },
1705 { B_SilkS, _HKI( "Silkscreen on board's back" ) },
1706 { F_Mask, _HKI( "Solder mask on board's front" ) },
1707 { B_Mask, _HKI( "Solder mask on board's back" ) },
1708 { Dwgs_User, _HKI( "Explanatory drawings" ) },
1709 { Cmts_User, _HKI( "Explanatory comments" ) },
1710 { Eco1_User, _HKI( "User defined meaning" ) },
1711 { Eco2_User, _HKI( "User defined meaning" ) },
1712 { Edge_Cuts, _HKI( "Board's perimeter definition" ) },
1713 { Margin, _HKI( "Board's edge setback outline" ) },
1714 { F_CrtYd, _HKI( "Footprint courtyards on board's front" ) },
1715 { B_CrtYd, _HKI( "Footprint courtyards on board's back" ) },
1716 { F_Fab, _HKI( "Footprint assembly on board's front" ) },
1717 { B_Fab, _HKI( "Footprint assembly on board's back" ) },
1718 { User_1, _HKI( "User defined layer 1" ) },
1719 { User_2, _HKI( "User defined layer 2" ) },
1720 { User_3, _HKI( "User defined layer 3" ) },
1721 { User_4, _HKI( "User defined layer 4" ) },
1722 { User_5, _HKI( "User defined layer 5" ) },
1723 { User_6, _HKI( "User defined layer 6" ) },
1724 { User_7, _HKI( "User defined layer 7" ) },
1725 { User_8, _HKI( "User defined layer 8" ) },
1726 { User_9, _HKI( "User defined layer 9" ) },
1727 { User_10, _HKI( "User defined layer 10" ) },
1728 { User_11, _HKI( "User defined layer 11" ) },
1729 { User_12, _HKI( "User defined layer 12" ) },
1730 { User_13, _HKI( "User defined layer 13" ) },
1731 { User_14, _HKI( "User defined layer 14" ) },
1732 { User_15, _HKI( "User defined layer 15" ) },
1733 { User_16, _HKI( "User defined layer 16" ) },
1734 { User_17, _HKI( "User defined layer 17" ) },
1735 { User_18, _HKI( "User defined layer 18" ) },
1736 { User_19, _HKI( "User defined layer 19" ) },
1737 { User_20, _HKI( "User defined layer 20" ) },
1738 { User_21, _HKI( "User defined layer 21" ) },
1739 { User_22, _HKI( "User defined layer 22" ) },
1740 { User_23, _HKI( "User defined layer 23" ) },
1741 { User_24, _HKI( "User defined layer 24" ) },
1742 { User_25, _HKI( "User defined layer 25" ) },
1743 { User_26, _HKI( "User defined layer 26" ) },
1744 { User_27, _HKI( "User defined layer 27" ) },
1745 { User_28, _HKI( "User defined layer 28" ) },
1746 { User_29, _HKI( "User defined layer 29" ) },
1747 { User_30, _HKI( "User defined layer 30" ) },
1748 { User_31, _HKI( "User defined layer 31" ) },
1749 { User_32, _HKI( "User defined layer 32" ) },
1750 { User_33, _HKI( "User defined layer 33" ) },
1751 { User_34, _HKI( "User defined layer 34" ) },
1752 { User_35, _HKI( "User defined layer 35" ) },
1753 { User_36, _HKI( "User defined layer 36" ) },
1754 { User_37, _HKI( "User defined layer 37" ) },
1755 { User_38, _HKI( "User defined layer 38" ) },
1756 { User_39, _HKI( "User defined layer 39" ) },
1757 { User_40, _HKI( "User defined layer 40" ) },
1758 { User_41, _HKI( "User defined layer 41" ) },
1759 { User_42, _HKI( "User defined layer 42" ) },
1760 { User_43, _HKI( "User defined layer 43" ) },
1761 { User_44, _HKI( "User defined layer 44" ) },
1762 { User_45, _HKI( "User defined layer 45" ) },
1763 };
1764
1765 // There is a spacer added to the end of the list that we need to remove and re-add
1766 // after possibly adding additional layers
1767 if( m_layersOuterSizer->GetItemCount() > 0 )
1768 {
1769 m_layersOuterSizer->Detach( m_layersOuterSizer->GetItemCount() - 1 );
1770 }
1771 // Otherwise, this is the first time we are updating the control, so we need to attach
1772 // the handler
1773 else
1774 {
1775 // Add right click handling to show the context menu when clicking to the free area in
1776 // m_windowLayers (below the layer items)
1777 m_windowLayers->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1778 }
1779
1780 std::size_t total_layers = enabled.CuStack().size();
1781
1782 for( const auto& entry : non_cu_seq )
1783 {
1784 if( enabled[entry.layerId] )
1785 total_layers++;
1786 }
1787
1788 // Adds layers to the panel until we have enough to hold our total count
1789 while( total_layers > m_layerSettings.size() )
1790 m_layerSettings.push_back( std::make_unique<APPEARANCE_SETTING>() );
1791
1792 // We never delete layers from the panel, only hide them. This saves us
1793 // having to recreate the (possibly) later with minimal overhead
1794 for( std::size_t ii = total_layers; ii < m_layerSettings.size(); ++ii )
1795 {
1796 if( m_layerSettings[ii]->ctl_panel )
1797 m_layerSettings[ii]->ctl_panel->Show( false );
1798 }
1799
1800 auto layer_it = m_layerSettings.begin();
1801
1802 // show all coppers first, with front on top, back on bottom, then technical layers
1803 for( PCB_LAYER_ID layer : enabled.CuStack() )
1804 {
1805 wxString dsc;
1806
1807 switch( layer )
1808 {
1809 case F_Cu: dsc = _( "Front copper layer" ); break;
1810 case B_Cu: dsc = _( "Back copper layer" ); break;
1811 default: dsc = _( "Inner copper layer" ); break;
1812 }
1813
1814 std::unique_ptr<APPEARANCE_SETTING>& setting = *layer_it;
1815
1816 setting->label = board->GetLayerName( layer );
1817 setting->id = layer;
1818 setting->tooltip = dsc;
1819
1820 if( setting->ctl_panel == nullptr )
1821 appendLayer( setting );
1822 else
1823 updateLayer( setting );
1824
1825 m_layerSettingsMap[layer] = setting.get();
1826
1827 if( !isLayerEnabled( layer ) )
1828 {
1829 setting->ctl_text->Disable();
1830 setting->ctl_color->SetToolTip( wxEmptyString );
1831 }
1832
1833 ++layer_it;
1834 }
1835
1836 for( const auto& entry : non_cu_seq )
1837 {
1838 PCB_LAYER_ID layer = entry.layerId;
1839
1840 if( !enabled[layer] )
1841 continue;
1842
1843 std::unique_ptr<APPEARANCE_SETTING>& setting = *layer_it;
1844
1845 if( m_isFpEditor )
1846 {
1847 wxString canonicalName = LSET::Name( static_cast<PCB_LAYER_ID>( layer ) );
1848
1849 if( cfg->m_DesignSettings.m_UserLayerNames.contains( canonicalName.ToStdString() ) )
1850 setting->label = cfg->m_DesignSettings.m_UserLayerNames[canonicalName.ToStdString()];
1851 else
1852 setting->label = board->GetStandardLayerName( layer );
1853 }
1854 else
1855 {
1856 setting->label = board->GetLayerName( layer );
1857 }
1858
1859 setting->id = layer;
1860 // Because non_cu_seq is created static, we must explicitly call wxGetTranslation for
1861 // texts which are internationalized
1862 setting->tooltip = wxGetTranslation( entry.tooltip );
1863
1864 if( setting->ctl_panel == nullptr )
1865 appendLayer( setting );
1866 else
1867 updateLayer( setting );
1868
1869 m_layerSettingsMap[layer] = setting.get();
1870
1871 if( !isLayerEnabled( layer ) )
1872 {
1873 setting->ctl_text->Disable();
1874 setting->ctl_color->SetToolTip( wxEmptyString );
1875 }
1876
1877 ++layer_it;
1878 }
1879
1880 m_layersOuterSizer->AddSpacer( 10 );
1881 m_windowLayers->SetBackgroundColour( m_layerPanelColour );
1882 m_windowLayers->FitInside(); // Updates virtual size to fit subwindows, also auto-layouts.
1883
1884 m_paneLayerDisplayOptions->SetLabel( _( "Layer Display Options" ) );
1885
1886 int hotkey = PCB_ACTIONS::highContrastModeCycle.GetHotKey();
1887 wxString msg;
1888
1889 if( hotkey )
1890 msg = wxString::Format( _( "Inactive layers (%s):" ), KeyNameFromKeyCode( hotkey ) );
1891 else
1892 msg = _( "Inactive layers:" );
1893
1894 m_inactiveLayersLabel->SetLabel( msg );
1895
1896 m_rbHighContrastNormal->SetLabel( _( "Normal" ) );
1897 m_rbHighContrastNormal->SetToolTip( _( "Inactive layers will be shown in full color" ) );
1898
1899 m_rbHighContrastDim->SetLabel( _( "Dim" ) );
1900 m_rbHighContrastDim->SetToolTip( _( "Inactive layers will be dimmed" ) );
1901
1902 m_rbHighContrastOff->SetLabel( _( "Hide" ) );
1903 m_rbHighContrastOff->SetToolTip( _( "Inactive layers will be hidden" ) );
1904
1905 m_cbFlipBoard->SetLabel( _( "Flip board view" ) );
1906}
1907
1908
1910{
1911 delete m_layerContextMenu;
1912 m_layerContextMenu = new wxMenu;
1913
1914 KIUI::AddMenuItem( m_layerContextMenu, ID_SHOW_ALL_COPPER_LAYERS, _( "Show All Copper Layers" ),
1916 KIUI::AddMenuItem( m_layerContextMenu, ID_HIDE_ALL_COPPER_LAYERS, _( "Hide All Copper Layers" ),
1918
1919 m_layerContextMenu->AppendSeparator();
1920
1921 KIUI::AddMenuItem( m_layerContextMenu, ID_HIDE_ALL_BUT_ACTIVE, _( "Hide All Layers But Active" ),
1923
1924 m_layerContextMenu->AppendSeparator();
1925
1926 KIUI::AddMenuItem( m_layerContextMenu, ID_SHOW_ALL_NON_COPPER, _( "Show All Non Copper Layers" ),
1928
1929 KIUI::AddMenuItem( m_layerContextMenu, ID_HIDE_ALL_NON_COPPER, _( "Hide All Non Copper Layers" ),
1931
1932 m_layerContextMenu->AppendSeparator();
1933
1936
1939
1940 m_layerContextMenu->AppendSeparator();
1941
1942 KIUI::AddMenuItem( m_layerContextMenu, ID_PRESET_FRONT_ASSEMBLY, _( "Show Only Front Assembly Layers" ),
1944
1945 KIUI::AddMenuItem( m_layerContextMenu, ID_PRESET_FRONT, _( "Show Only Front Layers" ),
1947
1948 // Only show the internal layer option if internal layers are enabled
1949 if( m_frame->GetBoard()->GetCopperLayerCount() > 2 )
1950 {
1951 KIUI::AddMenuItem( m_layerContextMenu, ID_PRESET_INNER_COPPER, _( "Show Only Inner Layers" ),
1953 }
1954
1955 KIUI::AddMenuItem( m_layerContextMenu, ID_PRESET_BACK, _( "Show Only Back Layers" ),
1957
1958 KIUI::AddMenuItem( m_layerContextMenu, ID_PRESET_BACK_ASSEMBLY, _( "Show Only Back Assembly Layers" ),
1960}
1961
1962
1963void APPEARANCE_CONTROLS::OnLayerContextMenu( wxCommandEvent& aEvent )
1964{
1965 BOARD* board = m_frame->GetBoard();
1966 LSET visible = getVisibleLayers();
1967
1968 PCB_LAYER_ID current = m_frame->GetActiveLayer();
1969
1970 // The new preset. We keep the visibility state of objects:
1971 LAYER_PRESET preset;
1973
1974 switch( aEvent.GetId() )
1975 {
1977 preset.layers = presetNoLayers.layers;
1978 ApplyLayerPreset( preset );
1979 return;
1980
1982 preset.layers = presetAllLayers.layers;
1983 ApplyLayerPreset( preset );
1984 return;
1985
1987 visible |= presetAllCopper.layers;
1988 setVisibleLayers( visible );
1989 break;
1990
1992 preset.layers = presetNoLayers.layers | LSET( { current } );
1993 ApplyLayerPreset( preset );
1994 break;
1995
1997 visible &= ~presetAllCopper.layers;
1998
1999 if( !visible.test( current ) && visible.count() > 0 )
2000 m_frame->SetActiveLayer( *visible.Seq().begin() );
2001
2002 setVisibleLayers( visible );
2003 break;
2004
2006 visible &= presetAllCopper.layers;
2007
2008 if( !visible.test( current ) && visible.count() > 0 )
2009 m_frame->SetActiveLayer( *visible.Seq().begin() );
2010
2011 setVisibleLayers( visible );
2012 break;
2013
2015 visible |= ~presetAllCopper.layers;
2016
2017 setVisibleLayers( visible );
2018 break;
2019
2021 preset.layers = presetFrontAssembly.layers;
2022 ApplyLayerPreset( preset );
2023 return;
2024
2025 case ID_PRESET_FRONT:
2026 preset.layers = presetFront.layers;
2027 ApplyLayerPreset( preset );
2028 return;
2029
2031 preset.layers = presetInnerCopper.layers;
2032 ApplyLayerPreset( preset );
2033 return;
2034
2035 case ID_PRESET_BACK:
2036 preset.layers = presetBack.layers;
2037 ApplyLayerPreset( preset );
2038 return;
2039
2041 preset.layers = presetBackAssembly.layers;
2042 ApplyLayerPreset( preset );
2043 return;
2044 }
2045
2048
2049 if( !m_isFpEditor )
2050 m_frame->GetCanvas()->SyncLayersVisibility( board );
2051
2052 m_frame->GetCanvas()->Refresh();
2053}
2054
2055
2057{
2058 return m_notebook->GetSelection();
2059}
2060
2061
2063{
2064 size_t max = m_notebook->GetPageCount();
2065
2066 if( aTab >= 0 && static_cast<size_t>( aTab ) < max )
2067 m_notebook->SetSelection( aTab );
2068}
2069
2070
2072{
2073 COLOR_SETTINGS* theme = m_frame->GetColorSettings();
2074 bool readOnly = theme->IsReadOnly();
2075 LSET visible = getVisibleLayers();
2076 GAL_SET objects = getVisibleObjects();
2077
2078 Freeze();
2079
2080 for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_layerSettings )
2081 {
2082 int layer = setting->id;
2083
2084 if( setting->ctl_visibility )
2085 setting->ctl_visibility->SetValue( visible[layer] );
2086
2087 if( setting->ctl_color )
2088 {
2089 const COLOR4D& color = theme->GetColor( layer );
2090 setting->ctl_color->SetSwatchColor( color, false );
2091 setting->ctl_color->SetReadOnly( readOnly );
2092 }
2093 }
2094
2095 for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
2096 {
2097 GAL_LAYER_ID layer = static_cast<GAL_LAYER_ID>( setting->id );
2098
2099 if( setting->ctl_visibility )
2100 setting->ctl_visibility->SetValue( objects.Contains( layer ) );
2101
2102 if( setting->ctl_color )
2103 {
2104 const COLOR4D& color = theme->GetColor( layer );
2105 setting->ctl_color->SetSwatchColor( color, false );
2106 setting->ctl_color->SetReadOnly( readOnly );
2107 }
2108 }
2109
2110 // Update indicators and panel background colors
2112
2113 Thaw();
2114
2115 m_windowLayers->Refresh();
2116}
2117
2118
2119void APPEARANCE_CONTROLS::onLayerLeftClick( wxMouseEvent& aEvent )
2120{
2121 wxWindow* eventSource = static_cast<wxWindow*>( aEvent.GetEventObject() );
2122
2123 PCB_LAYER_ID layer = ToLAYER_ID( eventSource->GetId() );
2124
2125 if( !isLayerEnabled( layer ) )
2126 return;
2127
2128 m_frame->SetActiveLayer( layer );
2129 passOnFocus();
2130}
2131
2132
2133void APPEARANCE_CONTROLS::rightClickHandler( wxMouseEvent& aEvent )
2134{
2135 wxASSERT( m_layerContextMenu );
2136 PopupMenu( m_layerContextMenu );
2137 passOnFocus();
2138};
2139
2140
2142{
2143 LSET visibleLayers = getVisibleLayers();
2144
2145 visibleLayers.set( aLayer, !visibleLayers.test( aLayer ) );
2146 setVisibleLayers( visibleLayers );
2147 m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, visibleLayers.test( aLayer ) );
2148
2150 m_frame->GetCanvas()->Refresh();
2151}
2152
2153
2154void APPEARANCE_CONTROLS::onObjectVisibilityChanged( GAL_LAYER_ID aLayer, bool isVisible, bool isFinal )
2155{
2156 // Special-case controls
2157 switch( aLayer )
2158 {
2159 case LAYER_RATSNEST:
2160 {
2161 // don't touch the layers. ratsnest is enabled on per-item basis.
2162 m_frame->GetCanvas()->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
2163 m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, true );
2164
2165 if( m_frame->IsType( FRAME_PCB_EDITOR ) )
2166 {
2167 m_frame->GetPcbNewSettings()->m_Display.m_ShowGlobalRatsnest = isVisible;
2168 m_frame->GetBoard()->SetElementVisibility( aLayer, isVisible );
2169 m_frame->OnDisplayOptionsChanged();
2170 m_frame->GetCanvas()->RedrawRatsnest();
2171 }
2172
2173 break;
2174 }
2175
2176 case LAYER_GRID:
2177 m_frame->SetGridVisibility( isVisible );
2178 m_frame->GetCanvas()->Refresh();
2180 break;
2181
2182 case LAYER_FP_TEXT:
2183 // Because Footprint Text is a meta-control that also can disable values/references,
2184 // drag them along here so that the user is less likely to be confused.
2185 if( isFinal )
2186 {
2187 // Should only trigger when you actually click the Footprint Text button
2188 // Otherwise it goes into infinite recursive loop with the following case section
2190 onObjectVisibilityChanged( LAYER_FP_VALUES, isVisible, false );
2191 m_objectSettingsMap[LAYER_FP_REFERENCES]->ctl_visibility->SetValue( isVisible );
2192 m_objectSettingsMap[LAYER_FP_VALUES]->ctl_visibility->SetValue( isVisible );
2193 }
2194 break;
2195
2197 case LAYER_FP_VALUES:
2198 // In case that user changes Footprint Value/References when the Footprint Text
2199 // meta-control is disabled, we should put it back on.
2200 if( isVisible )
2201 {
2202 onObjectVisibilityChanged( LAYER_FP_TEXT, isVisible, false );
2203 m_objectSettingsMap[LAYER_FP_TEXT]->ctl_visibility->SetValue( isVisible );
2204 }
2205 break;
2206
2207 default:
2208 break;
2209 }
2210
2211 GAL_SET visible = getVisibleObjects();
2212
2213 if( visible.Contains( aLayer ) != isVisible )
2214 {
2215 visible.set( aLayer, isVisible );
2216 setVisibleObjects( visible );
2217 m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, isVisible );
2219 }
2220
2221 if( isFinal )
2222 {
2223 m_frame->GetCanvas()->Refresh();
2224 passOnFocus();
2225 }
2226}
2227
2228
2230{
2231 COLOR_SETTINGS* theme = m_frame->GetColorSettings();
2232 COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
2233 GAL_SET visible = getVisibleObjects();
2234 int swatchWidth = m_windowObjects->ConvertDialogToPixels( wxSize( 8, 0 ) ).x;
2235 int labelWidth = 0;
2236
2237 int btnWidth = m_visibleBitmapBundle.GetPreferredLogicalSizeFor( m_windowObjects ).x;
2238
2239 m_objectSettings.clear();
2240 m_objectsOuterSizer->Clear( true );
2241 m_objectsOuterSizer->AddSpacer( 5 );
2242
2243 auto appendObject =
2244 [&]( const std::unique_ptr<APPEARANCE_SETTING>& aSetting )
2245 {
2246 wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
2247 int layer = aSetting->id;
2248
2249 aSetting->visible = visible.Contains( ToGalLayer( layer ) );
2250 COLOR4D color = theme->GetColor( layer );
2251 COLOR4D defColor = theme->GetDefaultColor( layer );
2252
2253 if( color != COLOR4D::UNSPECIFIED || defColor != COLOR4D::UNSPECIFIED )
2254 {
2255 COLOR_SWATCH* swatch = new COLOR_SWATCH( m_windowObjects, color, layer,
2256 bgColor, defColor, SWATCH_SMALL );
2257 swatch->SetToolTip( _( "Left double click or middle click for color change, "
2258 "right click for menu" ) );
2259
2260 sizer->Add( swatch, 0, wxALIGN_CENTER_VERTICAL, 0 );
2261 aSetting->ctl_color = swatch;
2262
2263 swatch->Bind( COLOR_SWATCH_CHANGED, &APPEARANCE_CONTROLS::OnColorSwatchChanged, this );
2264
2265 swatch->SetReadOnlyCallback( std::bind( &APPEARANCE_CONTROLS::onReadOnlySwatch, this ) );
2266 }
2267 else
2268 {
2269 sizer->AddSpacer( swatchWidth );
2270 }
2271
2272 BITMAP_TOGGLE* btn_visible = nullptr;
2273 wxString tip;
2274
2275 if( aSetting->can_control_visibility )
2276 {
2277 btn_visible = new BITMAP_TOGGLE( m_windowObjects, layer,
2280 aSetting->visible );
2281
2282 tip.Printf( _( "Show or hide %s" ), aSetting->label.Lower() );
2283 btn_visible->SetToolTip( tip );
2284
2285 aSetting->ctl_visibility = btn_visible;
2286
2287 btn_visible->Bind( TOGGLE_CHANGED,
2288 [&]( wxCommandEvent& aEvent )
2289 {
2290 int id = static_cast<wxWindow*>( aEvent.GetEventObject() )->GetId();
2291 bool isVisible = aEvent.GetInt();
2292 onObjectVisibilityChanged( ToGalLayer( id ), isVisible, true );
2293 } );
2294 }
2295
2296 sizer->AddSpacer( 5 );
2297
2298 wxStaticText* label = new wxStaticText( m_windowObjects, layer, aSetting->label );
2299 label->Wrap( -1 );
2300 label->SetToolTip( aSetting->tooltip );
2301
2302 if( aSetting->can_control_opacity )
2303 {
2304 label->SetMinSize( wxSize( labelWidth, -1 ) );
2305#ifdef __WXMAC__
2306 if( btn_visible )
2307 sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, 10 );
2308 else
2309 sizer->AddSpacer( btnWidth );
2310
2311 sizer->AddSpacer( 5 );
2312 sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, 10 );
2313#else
2314 if( btn_visible )
2315 sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL, 0 );
2316 else
2317 sizer->AddSpacer( btnWidth );
2318
2319 sizer->AddSpacer( 5 );
2320 sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL, 0 );
2321#endif
2322
2323 wxSlider* slider = new wxSlider( m_windowObjects, wxID_ANY, 100, 0, 100,
2324 wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL );
2325#ifdef __WXMAC__
2326 slider->SetMinSize( wxSize( 80, 16 ) );
2327#else
2328 slider->SetMinSize( wxSize( 80, -1 ) );
2329#endif
2330
2331 tip.Printf( _( "Set opacity of %s" ), aSetting->label.Lower() );
2332 slider->SetToolTip( tip );
2333
2334 sizer->Add( slider, 1, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 5 );
2335 aSetting->ctl_opacity = slider;
2336
2337 auto opacitySliderHandler =
2338 [this, layer]( wxCommandEvent& aEvent )
2339 {
2340 wxSlider* ctrl = static_cast<wxSlider*>( aEvent.GetEventObject() );
2341 int value = ctrl->GetValue();
2342 onObjectOpacitySlider( layer, value / 100.0f );
2343 };
2344
2345 slider->Bind( wxEVT_SCROLL_CHANGED, opacitySliderHandler );
2346 slider->Bind( wxEVT_SCROLL_THUMBTRACK, opacitySliderHandler );
2347 slider->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS::OnSetFocus, this );
2348 }
2349 else
2350 {
2351 if( btn_visible )
2352 sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL, 0 );
2353 else
2354 sizer->AddSpacer( btnWidth );
2355
2356 sizer->AddSpacer( 5 );
2357 sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL, 0 );
2358 }
2359
2360 aSetting->ctl_text = label;
2361 m_objectsOuterSizer->Add( sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, 5 );
2362
2363 if( !aSetting->can_control_opacity )
2364 m_objectsOuterSizer->AddSpacer( 2 );
2365 };
2366
2367 for( const APPEARANCE_SETTING& s_setting : s_objectSettings )
2368 {
2369 if( m_isFpEditor && !s_allowedInFpEditor.count( s_setting.id ) )
2370 continue;
2371
2372 m_objectSettings.emplace_back( std::make_unique<APPEARANCE_SETTING>( s_setting ) );
2373
2374 std::unique_ptr<APPEARANCE_SETTING>& setting = m_objectSettings.back();
2375
2376 // Because s_render_rows is created static, we must explicitly call wxGetTranslation
2377 // for texts which are internationalized (tool tips and item names)
2378 setting->tooltip = wxGetTranslation( s_setting.tooltip );
2379 setting->label = wxGetTranslation( s_setting.label );
2380
2381 if( setting->can_control_opacity )
2382 {
2383 int width = m_windowObjects->GetTextExtent( setting->label ).x + 5;
2384 labelWidth = std::max( labelWidth, width );
2385 }
2386
2387 if( !s_setting.spacer )
2388 m_objectSettingsMap[ToGalLayer( setting->id )] = setting.get();
2389 }
2390
2391 for( const std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
2392 {
2393 if( setting->spacer )
2394 m_objectsOuterSizer->AddSpacer( m_pointSize / 2 );
2395 else
2396 appendObject( setting );
2397 }
2398
2399 m_objectsOuterSizer->Layout();
2400}
2401
2402
2404{
2405 GAL_SET visible = getVisibleObjects();
2406
2407 const PCB_DISPLAY_OPTIONS& opts = m_frame->GetDisplayOptions();
2408
2409 for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
2410 {
2411 if( setting->spacer )
2412 continue;
2413
2414 GAL_LAYER_ID layer = ToGalLayer( setting->id );
2415
2416 if( setting->ctl_visibility )
2417 setting->ctl_visibility->SetValue( visible.Contains( layer ) );
2418
2419 if( setting->ctl_color )
2420 {
2421 COLOR4D color = m_frame->GetColorSettings()->GetColor( setting->id );
2422 setting->ctl_color->SetSwatchColor( color, false );
2423 }
2424 }
2425
2426 wxASSERT( m_objectSettingsMap.count( LAYER_TRACKS )
2432
2433 m_objectSettingsMap[LAYER_TRACKS]->ctl_opacity->SetValue( opts.m_TrackOpacity * 100 );
2434 m_objectSettingsMap[LAYER_VIAS]->ctl_opacity->SetValue( opts.m_ViaOpacity * 100 );
2435 m_objectSettingsMap[LAYER_PADS]->ctl_opacity->SetValue( opts.m_PadOpacity * 100 );
2436 m_objectSettingsMap[LAYER_ZONES]->ctl_opacity->SetValue( opts.m_ZoneOpacity * 100 );
2437 m_objectSettingsMap[LAYER_DRAW_BITMAPS]->ctl_opacity->SetValue( opts.m_ImageOpacity * 100 );
2438 m_objectSettingsMap[LAYER_FILLED_SHAPES]->ctl_opacity->SetValue( opts.m_FilledShapeOpacity * 100 );
2439}
2440
2441
2442void APPEARANCE_CONTROLS::buildNetClassMenu( wxMenu& aMenu, bool isDefaultClass,
2443 const wxString& aName )
2444{
2445 BOARD* board = m_frame->GetBoard();
2446 std::shared_ptr<NET_SETTINGS>& netSettings = board->GetDesignSettings().m_NetSettings;
2447
2448 if( !isDefaultClass)
2449 {
2450 aMenu.Append( new wxMenuItem( &aMenu, ID_SET_NET_COLOR, _( "Set Netclass Color" ),
2451 wxEmptyString, wxITEM_NORMAL ) );
2452
2453 wxMenuItem* schematicColor = new wxMenuItem( &aMenu, ID_USE_SCHEMATIC_NET_COLOR,
2454 _( "Use Color from Schematic" ),
2455 wxEmptyString, wxITEM_NORMAL );
2456 std::shared_ptr<NETCLASS> nc = netSettings->GetNetClassByName( aName );
2457 const KIGFX::COLOR4D ncColor = nc->GetSchematicColor();
2458 aMenu.Append( schematicColor );
2459
2460 if( ncColor == KIGFX::COLOR4D::UNSPECIFIED )
2461 schematicColor->Enable( false );
2462
2463 aMenu.Append( new wxMenuItem( &aMenu, ID_CLEAR_NET_COLOR, _( "Clear Netclass Color" ),
2464 wxEmptyString, wxITEM_NORMAL ) );
2465 aMenu.AppendSeparator();
2466 }
2467
2468 wxString name = UnescapeString( aName );
2469
2470 aMenu.Append( new wxMenuItem( &aMenu, ID_HIGHLIGHT_NET,
2471 wxString::Format( _( "Highlight Nets in %s" ), name ),
2472 wxEmptyString, wxITEM_NORMAL ) );
2473 aMenu.Append( new wxMenuItem( &aMenu, ID_SELECT_NET,
2474 wxString::Format( _( "Select Tracks and Vias in %s" ), name ),
2475 wxEmptyString, wxITEM_NORMAL ) );
2476 aMenu.Append( new wxMenuItem( &aMenu, ID_DESELECT_NET,
2477 wxString::Format( _( "Unselect Tracks and Vias in %s" ), name ),
2478 wxEmptyString, wxITEM_NORMAL ) );
2479
2480 aMenu.AppendSeparator();
2481
2482 aMenu.Append( new wxMenuItem( &aMenu, ID_SHOW_ALL_NETS, _( "Show All Netclasses" ),
2483 wxEmptyString, wxITEM_NORMAL ) );
2484 aMenu.Append( new wxMenuItem( &aMenu, ID_HIDE_OTHER_NETS, _( "Hide All Other Netclasses" ),
2485 wxEmptyString, wxITEM_NORMAL ) );
2486
2487 aMenu.Bind( wxEVT_COMMAND_MENU_SELECTED, &APPEARANCE_CONTROLS::onNetclassContextMenu, this );
2488
2489}
2490
2491
2493{
2494 BOARD* board = m_frame->GetBoard();
2495 COLOR_SETTINGS* theme = m_frame->GetColorSettings();
2496 COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
2497
2498 // If the board isn't fully loaded, we can't yet rebuild
2499 if( !board->GetProject() )
2500 return;
2501
2502 m_staticTextNets->SetLabel( _( "Nets" ) );
2503 m_staticTextNetClasses->SetLabel( _( "Net Classes" ) );
2504
2505 std::shared_ptr<NET_SETTINGS>& netSettings = board->GetDesignSettings().m_NetSettings;
2506
2507 const std::set<wxString>& hiddenClasses = m_frame->Prj().GetLocalSettings().m_HiddenNetclasses;
2508
2509 m_netclassOuterSizer->Clear( true );
2510
2511 auto appendNetclass =
2512 [&]( int aId, const std::shared_ptr<NETCLASS>& aClass, bool isDefaultClass = false )
2513 {
2514 wxString name = aClass->GetName();
2515
2516 m_netclassSettings.emplace_back( std::make_unique<APPEARANCE_SETTING>() );
2517 APPEARANCE_SETTING* setting = m_netclassSettings.back().get();
2518 m_netclassSettingsMap[name] = setting;
2519
2520 setting->ctl_panel = new wxPanel( m_netclassScrolledWindow, aId );
2521 wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
2522 setting->ctl_panel->SetSizer( sizer );
2523
2524 COLOR4D color = netSettings->HasNetclass( name )
2525 ? netSettings->GetNetClassByName( name )->GetPcbColor()
2527
2528 setting->ctl_color = new COLOR_SWATCH( setting->ctl_panel, color, aId, bgColor,
2530 setting->ctl_color->SetToolTip( _( "Left double click or middle click for color "
2531 "change, right click for menu" ) );
2532
2533 setting->ctl_color->Bind( COLOR_SWATCH_CHANGED,
2535
2536 // Default netclass can't have an override color
2537 if( isDefaultClass )
2538 setting->ctl_color->Hide();
2539
2540 setting->ctl_visibility = new BITMAP_TOGGLE( setting->ctl_panel, aId,
2543 !hiddenClasses.count( name ) );
2544
2545 wxString tip;
2546 tip.Printf( _( "Show or hide ratsnest for nets in %s" ), name );
2547 setting->ctl_visibility->SetToolTip( tip );
2548
2549 setting->ctl_text = new wxStaticText( setting->ctl_panel, aId, name );
2550 setting->ctl_text->Wrap( -1 );
2551
2552 int flags = wxALIGN_CENTER_VERTICAL;
2553
2554 sizer->Add( setting->ctl_color, 0, flags | wxRESERVE_SPACE_EVEN_IF_HIDDEN, 5 );
2555 sizer->AddSpacer( 7 );
2556 sizer->Add( setting->ctl_visibility, 0, flags, 5 );
2557 sizer->AddSpacer( 3 );
2558 sizer->Add( setting->ctl_text, 1, flags, 5 );
2559
2560 m_netclassOuterSizer->Add( setting->ctl_panel, 0, wxEXPAND, 5 );
2561 m_netclassOuterSizer->AddSpacer( 2 );
2562
2563 setting->ctl_visibility->Bind( TOGGLE_CHANGED,
2565 this );
2566
2567 auto menuHandler =
2568 [&, name, isDefaultClass]( wxMouseEvent& aEvent )
2569 {
2570 wxMenu menu;
2571 buildNetClassMenu( menu, isDefaultClass, name );
2572
2574 PopupMenu( &menu );
2575 };
2576
2577 setting->ctl_panel->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2578 setting->ctl_visibility->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2579 setting->ctl_color->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2580 setting->ctl_text->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2581 };
2582
2583 std::vector<wxString> names;
2584
2585 for( const auto& [name, netclass] : netSettings->GetNetclasses() )
2586 names.emplace_back( name );
2587
2588 std::sort( names.begin(), names.end() );
2589
2590 m_netclassIdMap.clear();
2591
2592 int idx = wxID_HIGHEST;
2593
2594 m_netclassIdMap[idx] = netSettings->GetDefaultNetclass()->GetName();
2595 appendNetclass( idx++, netSettings->GetDefaultNetclass(), true );
2596
2597 for( const wxString& name : names )
2598 {
2599 m_netclassIdMap[idx] = name;
2600 appendNetclass( idx++, netSettings->GetNetclasses().at( name ) );
2601 }
2602
2603 int hotkey;
2604 wxString msg;
2605
2606 m_paneNetDisplayOptions->SetLabel( _( "Net Display Options" ) );
2607
2608 hotkey = PCB_ACTIONS::netColorModeCycle.GetHotKey();
2609
2610 if( hotkey )
2611 msg = wxString::Format( _( "Net colors (%s):" ), KeyNameFromKeyCode( hotkey ) );
2612 else
2613 msg = _( "Net colors:" );
2614
2615 m_txtNetDisplayTitle->SetLabel( msg );
2616 m_txtNetDisplayTitle->SetToolTip( _( "Choose when to show net and netclass colors" ) );
2617
2618 m_rbNetColorAll->SetLabel( _( "All" ) );
2619 m_rbNetColorAll->SetToolTip( _( "Net and netclass colors are shown on all copper items" ) );
2620
2621 m_rbNetColorRatsnest->SetLabel( _( "Ratsnest" ) );
2622 m_rbNetColorRatsnest->SetToolTip( _( "Net and netclass colors are shown on the ratsnest only" ) );
2623
2624 m_rbNetColorOff->SetLabel( _( "None" ) );
2625 m_rbNetColorOff->SetToolTip( _( "Net and netclass colors are not shown" ) );
2626
2627 hotkey = PCB_ACTIONS::ratsnestModeCycle.GetHotKey();
2628
2629 if( hotkey )
2630 msg = wxString::Format( _( "Ratsnest display (%s):" ), KeyNameFromKeyCode( hotkey ) );
2631 else
2632 msg = _( "Ratsnest display:" );
2633
2634 m_txtRatsnestVisibility->SetLabel( msg );
2635 m_txtRatsnestVisibility->SetToolTip( _( "Choose which ratsnest lines to display" ) );
2636
2637 m_rbRatsnestAllLayers->SetLabel( _( "All" ) );
2638 m_rbRatsnestAllLayers->SetToolTip( _( "Show ratsnest lines to items on all layers" ) );
2639
2640 m_rbRatsnestVisLayers->SetLabel( _( "Visible layers" ) );
2641 m_rbRatsnestVisLayers->SetToolTip( _( "Show ratsnest lines to items on visible layers" ) );
2642
2643 m_rbRatsnestNone->SetLabel( _( "None" ) );
2644 m_rbRatsnestNone->SetToolTip( _( "Hide all ratsnest lines" ) );
2645
2646 m_netclassOuterSizer->Layout();
2647
2648 m_netsTable->Rebuild();
2649 m_panelNets->GetSizer()->Layout();
2650}
2651
2652
2654{
2655 m_viewportsLabel->SetLabel( wxString::Format( _( "Presets (%s+Tab):" ),
2657
2658 m_cbLayerPresets->Clear();
2659
2660 if( aReset )
2661 m_presetMRU.clear();
2662
2663 // Build the layers preset list.
2664 // By default, the presetAllLayers will be selected
2665 int idx = 0;
2666 int default_idx = 0;
2667 std::vector<std::pair<wxString, void*>> userPresets;
2668
2669 // m_layerPresets is alphabetical: m_presetMRU should also be alphabetical, but m_cbLayerPresets
2670 // is split into build-in and user sections.
2671 for( auto& [name, preset] : m_layerPresets )
2672 {
2673 const wxString translatedName = wxGetTranslation( name );
2674 void* userData = static_cast<void*>( &preset );
2675
2676 if( preset.readOnly )
2677 m_cbLayerPresets->Append( translatedName, userData );
2678 else
2679 userPresets.push_back( { name, userData } );
2680
2681 if( aReset )
2682 m_presetMRU.push_back( translatedName );
2683
2684 if( name == presetAllLayers.name )
2685 default_idx = idx;
2686
2687 idx++;
2688 }
2689
2690 if( !userPresets.empty() )
2691 {
2692 m_cbLayerPresets->Append( wxT( "---" ) );
2693
2694 for( auto& [name, userData] : userPresets )
2695 m_cbLayerPresets->Append( name, userData );
2696 }
2697
2698 m_cbLayerPresets->Append( wxT( "---" ) );
2699 m_cbLayerPresets->Append( _( "Save preset..." ) );
2700 m_cbLayerPresets->Append( _( "Delete preset..." ) );
2701
2702 // At least the built-in presets should always be present
2703 wxASSERT( !m_layerPresets.empty() );
2704
2705 if( aReset )
2706 {
2707 // Default preset: all layers
2708 m_cbLayerPresets->SetSelection( default_idx );
2710 }
2711}
2712
2713
2715{
2716 LSET visibleLayers = getVisibleLayers();
2717 GAL_SET visibleObjects = getVisibleObjects();
2718 bool flipBoard = m_cbFlipBoard->GetValue();
2719
2720 auto it = std::find_if( m_layerPresets.begin(), m_layerPresets.end(),
2721 [&]( const std::pair<const wxString, LAYER_PRESET>& aPair )
2722 {
2723 return ( aPair.second.layers == visibleLayers
2724 && aPair.second.renderLayers == visibleObjects
2725 && aPair.second.flipBoard == flipBoard );
2726 } );
2727
2728 if( it != m_layerPresets.end() )
2729 {
2730 // Select the right m_cbLayersPresets item.
2731 // but these items are translated if they are predefined items.
2732 bool do_translate = it->second.readOnly;
2733 wxString text = do_translate ? wxGetTranslation( it->first ) : it->first;
2734
2735 m_cbLayerPresets->SetStringSelection( text );
2736 }
2737 else
2738 {
2739 m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator
2740 }
2741
2742 m_currentPreset = static_cast<LAYER_PRESET*>( m_cbLayerPresets->GetClientData( m_cbLayerPresets->GetSelection() ) );
2743}
2744
2745
2747{
2748 // look at m_layerPresets to know if aName is a read only preset, or a user preset.
2749 // Read only presets have translated names in UI, so we have to use
2750 // a translated name in UI selection.
2751 // But for a user preset name we should search for aName (not translated)
2752 wxString ui_label = aName;
2753
2754 for( std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
2755 {
2756 if( pair.first != aName )
2757 continue;
2758
2759 if( pair.second.readOnly == true )
2760 ui_label = wxGetTranslation( aName );
2761
2762 break;
2763 }
2764
2765 int idx = m_cbLayerPresets->FindString( ui_label );
2766
2767 if( idx >= 0 && m_cbLayerPresets->GetSelection() != idx )
2768 {
2769 m_cbLayerPresets->SetSelection( idx );
2770 m_currentPreset = static_cast<LAYER_PRESET*>( m_cbLayerPresets->GetClientData( idx ) );
2771 }
2772 else if( idx < 0 )
2773 {
2774 m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator
2775 }
2776}
2777
2778
2779void APPEARANCE_CONTROLS::onLayerPresetChanged( wxCommandEvent& aEvent )
2780{
2781 int count = m_cbLayerPresets->GetCount();
2782 int index = m_cbLayerPresets->GetSelection();
2783
2784 auto resetSelection =
2785 [&]()
2786 {
2787 if( m_currentPreset )
2788 m_cbLayerPresets->SetStringSelection( m_currentPreset->name );
2789 else
2790 m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 );
2791 };
2792
2793 if( index == count - 2 )
2794 {
2795 // Save current state to new preset
2796 wxString name;
2797
2800
2801 wxTextEntryDialog dlg( wxGetTopLevelParent( this ), _( "Layer preset name:" ),
2802 _( "Save Layer Preset" ), name );
2803
2804 if( dlg.ShowModal() != wxID_OK )
2805 {
2806 resetSelection();
2807 return;
2808 }
2809
2810 name = dlg.GetValue();
2811 bool exists = m_layerPresets.count( name );
2812
2813 if( !exists )
2814 {
2816 UNSELECTED_LAYER, m_cbFlipBoard->GetValue() );
2817 }
2818
2819 LAYER_PRESET* preset = &m_layerPresets[name];
2820
2821 if( !exists )
2822 {
2824 index = m_cbLayerPresets->FindString( name );
2825 }
2826 else if( preset->readOnly )
2827 {
2828 wxMessageBox( _( "Default presets cannot be modified.\nPlease use a different name." ),
2829 _( "Error" ), wxOK | wxICON_ERROR, wxGetTopLevelParent( this ) );
2830 resetSelection();
2831 return;
2832 }
2833 else
2834 {
2835 // Ask the user if they want to overwrite the existing preset
2836 if( !IsOK( wxGetTopLevelParent( this ), _( "Overwrite existing preset?" ) ) )
2837 {
2838 resetSelection();
2839 return;
2840 }
2841
2842 preset->layers = getVisibleLayers();
2843 preset->renderLayers = getVisibleObjects();
2844 preset->flipBoard = m_cbFlipBoard->GetValue();
2845
2846 index = m_cbLayerPresets->FindString( name );
2847
2848 if( m_presetMRU.Index( name ) != wxNOT_FOUND )
2849 m_presetMRU.Remove( name );
2850 }
2851
2852 m_currentPreset = preset;
2853 m_cbLayerPresets->SetSelection( index );
2854 m_presetMRU.Insert( name, 0 );
2855
2856 return;
2857 }
2858 else if( index == count - 1 )
2859 {
2860 // Delete a preset
2861 wxArrayString headers;
2862 std::vector<wxArrayString> items;
2863
2864 headers.Add( _( "Presets" ) );
2865
2866 for( std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
2867 {
2868 if( !pair.second.readOnly )
2869 {
2870 wxArrayString item;
2871 item.Add( pair.first );
2872 items.emplace_back( item );
2873 }
2874 }
2875
2876 EDA_LIST_DIALOG dlg( m_frame, _( "Delete Preset" ), headers, items );
2877 dlg.SetListLabel( _( "Select preset:" ) );
2878
2879 if( dlg.ShowModal() == wxID_OK )
2880 {
2881 wxString presetName = dlg.GetTextSelection();
2882 int idx = m_cbLayerPresets->FindString( presetName );
2883
2884 if( idx != wxNOT_FOUND )
2885 {
2886 m_layerPresets.erase( presetName );
2887
2888 m_cbLayerPresets->Delete( idx );
2889 m_currentPreset = nullptr;
2890 }
2891
2892 if( m_presetMRU.Index( presetName ) != wxNOT_FOUND )
2893 m_presetMRU.Remove( presetName );
2894 }
2895
2896 resetSelection();
2897 return;
2898 }
2899 else if( m_cbLayerPresets->GetString( index ) == wxT( "---" ) )
2900 {
2901 // Separator: reject the selection
2902 resetSelection();
2903 return;
2904 }
2905
2906 // Store the objects visibility settings if the preset is not a user preset,
2907 // to be reused when selecting a new built-in layer preset, even if a previous
2908 // user preset has changed the object visibility
2909 if( !m_currentPreset || m_currentPreset->readOnly )
2910 {
2911 m_lastBuiltinPreset.renderLayers = getVisibleObjects();
2912 }
2913
2914 LAYER_PRESET* preset = static_cast<LAYER_PRESET*>( m_cbLayerPresets->GetClientData( index ) );
2915 m_currentPreset = preset;
2916
2917 m_lastSelectedUserPreset = ( !preset || preset->readOnly ) ? nullptr : preset;
2918
2919 if( preset )
2920 {
2921 // Change board layers visibility, but do not change objects visibility
2922 LAYER_PRESET curr_layers_choice = *preset;
2923
2924 // For predefined presets that do not manage objects visibility, use
2925 // the objects visibility settings of the last used predefined preset.
2926 if( curr_layers_choice.readOnly )
2927 curr_layers_choice.renderLayers = m_lastBuiltinPreset.renderLayers;
2928
2929 doApplyLayerPreset( curr_layers_choice );
2930 }
2931
2932 if( !m_currentPreset->name.IsEmpty() )
2933 {
2934 const wxString translatedName = wxGetTranslation( m_currentPreset->name );
2935
2936 if( m_presetMRU.Index( translatedName ) != wxNOT_FOUND )
2937 m_presetMRU.Remove( translatedName );
2938
2939 m_presetMRU.Insert( translatedName, 0 );
2940 }
2941
2942 passOnFocus();
2943}
2944
2945
2947{
2948 BOARD* board = m_frame->GetBoard();
2949 KIGFX::PCB_VIEW* view = m_frame->GetCanvas()->GetView();
2950
2951 setVisibleLayers( aPreset.layers );
2953
2954 // If the preset doesn't have an explicit active layer to restore, we can at least
2955 // force the active layer to be something in the preset's layer set
2956 PCB_LAYER_ID activeLayer = UNSELECTED_LAYER;
2957
2958 if( aPreset.activeLayer != UNSELECTED_LAYER )
2959 activeLayer = aPreset.activeLayer;
2960 else if( aPreset.layers.any() && !aPreset.layers.test( m_frame->GetActiveLayer() ) )
2961 activeLayer = *aPreset.layers.Seq().begin();
2962
2963 LSET boardLayers = board->GetLayerSet();
2964
2965 if( activeLayer != UNSELECTED_LAYER && boardLayers.Contains( activeLayer ) )
2966 m_frame->SetActiveLayer( activeLayer );
2967
2968 if( !m_isFpEditor )
2969 m_frame->GetCanvas()->SyncLayersVisibility( board );
2970
2971 if( aPreset.flipBoard != view->IsMirroredX() )
2972 {
2973 view->SetMirror( !view->IsMirroredX(), view->IsMirroredY() );
2974 view->RecacheAllItems();
2975 }
2976
2977 m_frame->GetCanvas()->Refresh();
2978
2981}
2982
2983
2985{
2986 m_viewportsLabel->SetLabel( wxString::Format( _( "Viewports (%s+Tab):" ),
2988
2989 m_cbViewports->Clear();
2990
2991 for( std::pair<const wxString, VIEWPORT>& pair : m_viewports )
2992 m_cbViewports->Append( pair.first, static_cast<void*>( &pair.second ) );
2993
2994 m_cbViewports->Append( wxT( "---" ) );
2995 m_cbViewports->Append( _( "Save viewport..." ) );
2996 m_cbViewports->Append( _( "Delete viewport..." ) );
2997
2998 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 );
2999 m_lastSelectedViewport = nullptr;
3000}
3001
3002
3004{
3005 int idx = m_cbViewports->FindString( aName );
3006
3007 if( idx >= 0 && idx < (int)m_cbViewports->GetCount() - 3 /* separator */ )
3008 {
3009 m_cbViewports->SetSelection( idx );
3010 m_lastSelectedViewport = static_cast<VIEWPORT*>( m_cbViewports->GetClientData( idx ) );
3011 }
3012 else if( idx < 0 )
3013 {
3014 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 ); // separator
3015 m_lastSelectedViewport = nullptr;
3016 }
3017}
3018
3019
3020void APPEARANCE_CONTROLS::onViewportChanged( wxCommandEvent& aEvent )
3021{
3022 int count = m_cbViewports->GetCount();
3023 int index = m_cbViewports->GetSelection();
3024
3025 if( index >= 0 && index < count - 3 )
3026 {
3027 VIEWPORT* viewport = static_cast<VIEWPORT*>( m_cbViewports->GetClientData( index ) );
3028
3029 wxCHECK( viewport, /* void */ );
3030
3031 doApplyViewport( *viewport );
3032
3033 if( !viewport->name.IsEmpty() )
3034 {
3035 if( m_viewportMRU.Index( viewport->name ) != wxNOT_FOUND )
3036 m_viewportMRU.Remove( viewport->name );
3037
3038 m_viewportMRU.Insert( viewport->name, 0 );
3039 }
3040 }
3041 else if( index == count - 2 )
3042 {
3043 // Save current state to new preset
3044 wxString name;
3045
3046 wxTextEntryDialog dlg( wxGetTopLevelParent( this ), _( "Viewport name:" ), _( "Save Viewport" ), name );
3047
3048 if( dlg.ShowModal() != wxID_OK )
3049 {
3051 m_cbViewports->SetStringSelection( m_lastSelectedViewport->name );
3052 else
3053 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 );
3054
3055 return;
3056 }
3057
3058 name = dlg.GetValue();
3059 bool exists = m_viewports.count( name );
3060
3061 if( !exists )
3062 {
3063 m_viewports[name] = VIEWPORT( name, m_frame->GetCanvas()->GetView()->GetViewport() );
3064
3065 index = m_cbViewports->Insert( name, index-1, static_cast<void*>( &m_viewports[name] ) );
3066 }
3067 else
3068 {
3069 m_viewports[name].rect = m_frame->GetCanvas()->GetView()->GetViewport();
3070 index = m_cbViewports->FindString( name );
3071
3072 if( m_viewportMRU.Index( name ) != wxNOT_FOUND )
3073 m_viewportMRU.Remove( name );
3074 }
3075
3076 m_cbViewports->SetSelection( index );
3077 m_viewportMRU.Insert( name, 0 );
3078
3079 return;
3080 }
3081 else if( index == count - 1 )
3082 {
3083 // Delete an existing viewport
3084 wxArrayString headers;
3085 std::vector<wxArrayString> items;
3086
3087 headers.Add( _( "Viewports" ) );
3088
3089 for( std::pair<const wxString, VIEWPORT>& pair : m_viewports )
3090 {
3091 wxArrayString item;
3092 item.Add( pair.first );
3093 items.emplace_back( item );
3094 }
3095
3096 EDA_LIST_DIALOG dlg( m_frame, _( "Delete Viewport" ), headers, items );
3097 dlg.SetListLabel( _( "Select viewport:" ) );
3098
3099 if( dlg.ShowModal() == wxID_OK )
3100 {
3101 wxString viewportName = dlg.GetTextSelection();
3102 int idx = m_cbViewports->FindString( viewportName );
3103
3104 if( idx != wxNOT_FOUND )
3105 {
3106 m_viewports.erase( viewportName );
3107 m_cbViewports->Delete( idx );
3108 }
3109
3110 if( m_viewportMRU.Index( viewportName ) != wxNOT_FOUND )
3111 m_viewportMRU.Remove( viewportName );
3112 }
3113
3115 m_cbViewports->SetStringSelection( m_lastSelectedViewport->name );
3116 else
3117 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 );
3118
3119 return;
3120 }
3121
3122 passOnFocus();
3123}
3124
3125
3127{
3128 m_frame->GetCanvas()->GetView()->SetViewport( aViewport.rect );
3129 m_frame->GetCanvas()->Refresh();
3130}
3131
3132
3133void APPEARANCE_CONTROLS::OnColorSwatchChanged( wxCommandEvent& aEvent )
3134{
3135 COLOR_SWATCH* swatch = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
3136 COLOR4D newColor = swatch->GetSwatchColor();
3137 int layer = swatch->GetId();
3138
3139 COLOR_SETTINGS* cs = m_frame->GetColorSettings();
3140
3141 cs->SetColor( layer, newColor );
3142 m_frame->GetSettingsManager()->SaveColorSettings( cs, "board" );
3143
3144 m_frame->GetCanvas()->UpdateColors();
3145
3146 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
3147 view->UpdateLayerColor( layer );
3148 view->UpdateLayerColor( GetNetnameLayer( layer ) );
3149
3150 if( IsCopperLayer( layer ) )
3151 {
3152 view->UpdateLayerColor( ZONE_LAYER_FOR( layer ) );
3153 view->UpdateLayerColor( VIA_COPPER_LAYER_FOR( layer ) );
3154 view->UpdateLayerColor( PAD_COPPER_LAYER_FOR( layer ) );
3155 view->UpdateLayerColor( CLEARANCE_LAYER_FOR( layer ) );
3156 }
3157
3158 // Update the bitmap of the layer box
3159 if( m_frame->IsType( FRAME_PCB_EDITOR ) )
3160 static_cast<PCB_EDIT_FRAME*>( m_frame )->ReCreateLayerBox( false );
3161
3162 m_frame->GetCanvas()->Refresh();
3163
3164 if( layer == LAYER_PCB_BACKGROUND )
3165 m_frame->SetDrawBgColor( newColor );
3166
3167 passOnFocus();
3168}
3169
3170
3171void APPEARANCE_CONTROLS::onObjectOpacitySlider( int aLayer, float aOpacity )
3172{
3173 PCB_DISPLAY_OPTIONS options = m_frame->GetDisplayOptions();
3174
3175 switch( aLayer )
3176 {
3177 case static_cast<int>( LAYER_TRACKS ): options.m_TrackOpacity = aOpacity; break;
3178 case static_cast<int>( LAYER_VIAS ): options.m_ViaOpacity = aOpacity; break;
3179 case static_cast<int>( LAYER_PADS ): options.m_PadOpacity = aOpacity; break;
3180 case static_cast<int>( LAYER_ZONES ): options.m_ZoneOpacity = aOpacity; break;
3181 case static_cast<int>( LAYER_DRAW_BITMAPS ): options.m_ImageOpacity = aOpacity; break;
3182 case static_cast<int>( LAYER_FILLED_SHAPES ): options.m_FilledShapeOpacity = aOpacity; break;
3183 default: return;
3184 }
3185
3186 m_frame->SetDisplayOptions( options );
3187 passOnFocus();
3188}
3189
3190
3191void APPEARANCE_CONTROLS::onNetContextMenu( wxCommandEvent& aEvent )
3192{
3193 wxASSERT( m_netsGrid->GetSelectedRows().size() == 1 );
3194
3195 int row = m_netsGrid->GetSelectedRows()[0];
3196 NET_GRID_ENTRY& net = m_netsTable->GetEntry( row );
3197
3198 m_netsGrid->ClearSelection();
3199
3200 switch( aEvent.GetId() )
3201 {
3202 case ID_SET_NET_COLOR:
3203 {
3204 wxGridCellEditor* editor = m_netsGrid->GetCellEditor( row, NET_GRID_TABLE::COL_COLOR );
3205 editor->BeginEdit( row, NET_GRID_TABLE::COL_COLOR, m_netsGrid );
3206 break;
3207 }
3208
3209 case ID_CLEAR_NET_COLOR:
3210 m_netsGrid->SetCellValue( row, NET_GRID_TABLE::COL_COLOR, wxS( "rgba(0,0,0,0)" ) );
3211 break;
3212
3213 case ID_HIGHLIGHT_NET:
3214 m_frame->GetToolManager()->RunAction( PCB_ACTIONS::highlightNet, net.code );
3215 m_frame->GetCanvas()->Refresh();
3216 break;
3217
3218 case ID_SELECT_NET:
3219 m_frame->GetToolManager()->RunAction( PCB_ACTIONS::selectNet, net.code );
3220 m_frame->GetCanvas()->Refresh();
3221 break;
3222
3223 case ID_DESELECT_NET:
3224 m_frame->GetToolManager()->RunAction( PCB_ACTIONS::deselectNet, net.code );
3225 m_frame->GetCanvas()->Refresh();
3226 break;
3227
3228 case ID_SHOW_ALL_NETS:
3229 m_netsTable->ShowAllNets();
3230 break;
3231
3232 case ID_HIDE_OTHER_NETS:
3233 m_netsTable->HideOtherNets( net );
3234 break;
3235
3236 default:
3237 break;
3238 }
3239
3240 passOnFocus();
3241}
3242
3243
3245{
3246 wxString className = netclassNameFromEvent( aEvent );
3247 bool show = aEvent.GetInt();
3248 showNetclass( className, show );
3249 passOnFocus();
3250}
3251
3252
3253void APPEARANCE_CONTROLS::showNetclass( const wxString& aClassName, bool aShow )
3254{
3256
3257 for( NETINFO_ITEM* net : m_frame->GetBoard()->GetNetInfo() )
3258 {
3259 if( net->GetNetClass()->ContainsNetclassWithName( aClassName ) )
3260 {
3261 m_frame->GetToolManager()->RunAction( aShow ? PCB_ACTIONS::showNetInRatsnest
3263 net->GetNetCode() );
3264
3265 int row = m_netsTable->GetRowByNetcode( net->GetNetCode() );
3266
3267 if( row >= 0 )
3268 m_netsTable->SetValueAsBool( row, NET_GRID_TABLE::COL_VISIBILITY, aShow );
3269 }
3270 }
3271
3272 PROJECT_LOCAL_SETTINGS& localSettings = m_frame->Prj().GetLocalSettings();
3273
3274 if( !aShow )
3275 localSettings.m_HiddenNetclasses.insert( aClassName );
3276 else
3277 localSettings.m_HiddenNetclasses.erase( aClassName );
3278
3279 m_netsGrid->ForceRefresh();
3280 m_frame->GetCanvas()->RedrawRatsnest();
3281 m_frame->GetCanvas()->Refresh();
3283}
3284
3285
3287{
3288 COLOR_SWATCH* swatch = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
3289 wxString netclassName = netclassNameFromEvent( aEvent );
3290
3291 BOARD* board = m_frame->GetBoard();
3292 std::shared_ptr<NET_SETTINGS>& netSettings = board->GetDesignSettings().m_NetSettings;
3293 std::shared_ptr<NETCLASS> nc = netSettings->GetNetClassByName( netclassName );
3294
3295 nc->SetPcbColor( swatch->GetSwatchColor() );
3296 netSettings->RecomputeEffectiveNetclasses();
3297
3298 m_frame->GetCanvas()->GetView()->UpdateAllLayersColor();
3299 m_frame->GetCanvas()->RedrawRatsnest();
3300 m_frame->GetCanvas()->Refresh();
3301}
3302
3303
3305{
3306 COLOR_SWATCH* s = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
3307 int classId = s->GetId();
3308
3309 wxASSERT( m_netclassIdMap.count( classId ) );
3310 return m_netclassIdMap.at( classId );
3311}
3312
3313
3314void APPEARANCE_CONTROLS::onNetColorMode( wxCommandEvent& aEvent )
3315{
3316 PCB_DISPLAY_OPTIONS options = m_frame->GetDisplayOptions();
3317
3318 if( m_rbNetColorAll->GetValue() )
3320 else if( m_rbNetColorRatsnest->GetValue() )
3322 else
3324
3325 m_frame->SetDisplayOptions( options );
3326 m_frame->GetCanvas()->GetView()->UpdateAllLayersColor();
3327 passOnFocus();
3328}
3329
3330
3331void APPEARANCE_CONTROLS::onRatsnestMode( wxCommandEvent& aEvent )
3332{
3333 if( PCBNEW_SETTINGS* cfg = m_frame->GetPcbNewSettings() )
3334 {
3335 if( m_rbRatsnestAllLayers->GetValue() )
3336 {
3337 cfg->m_Display.m_ShowGlobalRatsnest = true;
3338 cfg->m_Display.m_RatsnestMode = RATSNEST_MODE::ALL;
3339 }
3340 else if( m_rbRatsnestVisLayers->GetValue() )
3341 {
3342 cfg->m_Display.m_ShowGlobalRatsnest = true;
3343 cfg->m_Display.m_RatsnestMode = RATSNEST_MODE::VISIBLE;
3344 }
3345 else
3346 {
3347 cfg->m_Display.m_ShowGlobalRatsnest = false;
3348 }
3349 }
3350
3351 if( PCB_EDIT_FRAME* editframe = dynamic_cast<PCB_EDIT_FRAME*>( m_frame ) )
3352 {
3353 if( PCBNEW_SETTINGS* cfg = m_frame->GetPcbNewSettings() )
3354 editframe->SetElementVisibility( LAYER_RATSNEST, cfg->m_Display.m_ShowGlobalRatsnest );
3355
3356 editframe->OnDisplayOptionsChanged();
3357 editframe->GetCanvas()->RedrawRatsnest();
3358 editframe->GetCanvas()->Refresh();
3359 }
3360
3361 passOnFocus();
3362}
3363
3364
3366{
3367 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
3369 static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
3370
3371 BOARD* board = m_frame->GetBoard();
3372 std::shared_ptr<NET_SETTINGS>& netSettings = board->GetDesignSettings().m_NetSettings;
3373 APPEARANCE_SETTING* setting = nullptr;
3374
3376
3377 if( it != m_netclassSettingsMap.end() )
3378 setting = it->second;
3379
3380 auto runOnNetsOfClass =
3381 [&]( const wxString& netClassName, std::function<void( NETINFO_ITEM* )> aFunction )
3382 {
3383 for( NETINFO_ITEM* net : board->GetNetInfo() )
3384 {
3385 if( net->GetNetClass()->ContainsNetclassWithName( netClassName ) )
3386 aFunction( net );
3387 }
3388 };
3389
3390 switch( aEvent.GetId() )
3391 {
3392 case ID_SET_NET_COLOR:
3393 {
3394 if( setting )
3395 {
3396 setting->ctl_color->GetNewSwatchColor();
3397
3398 COLOR4D color = setting->ctl_color->GetSwatchColor();
3399
3400 if( color != COLOR4D::UNSPECIFIED )
3401 {
3402 netSettings->GetNetClassByName( m_contextMenuNetclass )->SetPcbColor( color );
3403 netSettings->RecomputeEffectiveNetclasses();
3404 }
3405
3406 view->UpdateAllLayersColor();
3407 }
3408
3409 break;
3410 }
3411
3412 case ID_CLEAR_NET_COLOR:
3413 {
3414 if( setting )
3415 {
3416 setting->ctl_color->SetSwatchColor( COLOR4D( 0, 0, 0, 0 ), true );
3417
3418 netSettings->GetNetClassByName( m_contextMenuNetclass )->SetPcbColor( COLOR4D::UNSPECIFIED );
3419 netSettings->RecomputeEffectiveNetclasses();
3420
3421 view->UpdateAllLayersColor();
3422 }
3423
3424 break;
3425 }
3426
3428 {
3429 if( setting )
3430 {
3431 std::shared_ptr<NETCLASS> nc = netSettings->GetNetClassByName( m_contextMenuNetclass );
3432 const KIGFX::COLOR4D ncColor = nc->GetSchematicColor();
3433
3434 setting->ctl_color->SetSwatchColor( ncColor, true );
3435
3436 netSettings->GetNetClassByName( m_contextMenuNetclass )->SetPcbColor( ncColor );
3437 netSettings->RecomputeEffectiveNetclasses();
3438
3439 view->UpdateAllLayersColor();
3440 }
3441
3442 break;
3443 }
3444
3445 case ID_HIGHLIGHT_NET:
3446 {
3447 if( !m_contextMenuNetclass.IsEmpty() )
3448 {
3449 runOnNetsOfClass( m_contextMenuNetclass,
3450 [&]( NETINFO_ITEM* aItem )
3451 {
3452 static bool first = true;
3453 int code = aItem->GetNetCode();
3454
3455 if( first )
3456 {
3457 board->SetHighLightNet( code );
3458 rs->SetHighlight( true, code );
3459 first = false;
3460 }
3461 else
3462 {
3463 board->SetHighLightNet( code, true );
3464 rs->SetHighlight( true, code, true );
3465 }
3466 } );
3467
3468 view->UpdateAllLayersColor();
3469 board->HighLightON();
3470 }
3471
3472 break;
3473 }
3474
3475 case ID_SELECT_NET:
3476 case ID_DESELECT_NET:
3477 {
3478 if( !m_contextMenuNetclass.IsEmpty() )
3479 {
3480 TOOL_MANAGER* toolMgr = m_frame->GetToolManager();
3481 TOOL_ACTION& action = aEvent.GetId() == ID_SELECT_NET ? PCB_ACTIONS::selectNet
3483
3484 runOnNetsOfClass( m_contextMenuNetclass,
3485 [&]( NETINFO_ITEM* aItem )
3486 {
3487 toolMgr->RunAction( action, aItem->GetNetCode() );
3488 } );
3489 }
3490 break;
3491 }
3492
3493
3494 case ID_SHOW_ALL_NETS:
3495 {
3497 wxASSERT( m_netclassSettingsMap.count( NETCLASS::Default ) );
3498 m_netclassSettingsMap.at( NETCLASS::Default )->ctl_visibility->SetValue( true );
3499
3500 for( const auto& [name, netclass] : netSettings->GetNetclasses() )
3501 {
3502 showNetclass( name );
3503
3504 if( m_netclassSettingsMap.count( name ) )
3505 m_netclassSettingsMap.at( name )->ctl_visibility->SetValue( true );
3506 }
3507
3508 break;
3509 }
3510
3511 case ID_HIDE_OTHER_NETS:
3512 {
3513 bool showDefault = m_contextMenuNetclass == NETCLASS::Default;
3514 showNetclass( NETCLASS::Default, showDefault );
3515 wxASSERT( m_netclassSettingsMap.count( NETCLASS::Default ) );
3516 m_netclassSettingsMap.at( NETCLASS::Default )->ctl_visibility->SetValue( showDefault );
3517
3518 for( const auto& [name, netclass] : netSettings->GetNetclasses() )
3519 {
3520 bool show = ( name == m_contextMenuNetclass );
3521
3522 showNetclass( name, show );
3523
3524 if( m_netclassSettingsMap.count( name ) )
3525 m_netclassSettingsMap.at( name )->ctl_visibility->SetValue( show );
3526 }
3527
3528 break;
3529 }
3530
3531 default:
3532 break;
3533 }
3534
3535 m_frame->GetCanvas()->RedrawRatsnest();
3536 m_frame->GetCanvas()->Refresh();
3537
3538 m_contextMenuNetclass.clear();
3539}
3540
3541
3543{
3544 m_focusOwner->SetFocus();
3545}
3546
3547
3549{
3550 WX_INFOBAR* infobar = m_frame->GetInfoBar();
3551
3552 wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY, _( "Open Preferences" ), wxEmptyString );
3553
3554 button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
3555 [&]( wxHyperlinkEvent& aEvent )
3556 {
3557 m_frame->ShowPreferences( wxEmptyString, wxEmptyString );
3558 } ) );
3559
3560 infobar->RemoveAllButtons();
3561 infobar->AddButton( button );
3562 infobar->AddCloseButton();
3563
3564 infobar->ShowMessageFor( _( "The current color theme is read-only. Create a new theme in Preferences to "
3565 "enable color editing." ),
3566 10000, wxICON_INFORMATION );
3567}
3568
3569
3574
3575
int index
const char * name
static std::set< int > s_allowedInFpEditor
These GAL layers are shown in the Objects tab in the footprint editor.
#define RR
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition bitmap.cpp:104
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:110
@ show_all_back_layers
@ show_front_assembly_layers
@ show_back_assembly_layers
@ show_all_front_layers
@ options_generic_16
@ show_no_copper_layers
@ show_all_layers
@ show_all_copper_layers
HIGH_CONTRAST_MODE
Determine how inactive layers should be displayed.
@ NORMAL
Inactive layers are shown normally (no high-contrast mode)
@ HIDDEN
Inactive layers are hidden.
@ DIMMED
Inactive layers are dimmed (old high-contrast mode)
@ RATSNEST
Net/netclass colors are shown on ratsnest lines only.
@ ALL
Net/netclass colors are shown on all net copper.
@ OFF
Net (and netclass) colors are not shown.
@ VISIBLE
Ratsnest lines are drawn to items on visible layers only.
@ ALL
Ratsnest lines are drawn to items on all layers (default)
static TOOL_ACTION highContrastModeCycle
Definition actions.h:156
APPEARANCE_CONTROLS_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxTAB_TRAVERSAL, const wxString &name=wxEmptyString)
wxScrolledWindow * m_netclassScrolledWindow
void OnBoardNetSettingsChanged(BOARD &aBoard) override
void doApplyLayerPreset(const LAYER_PRESET &aPreset)
std::map< PCB_LAYER_ID, APPEARANCE_SETTING * > m_layerSettingsMap
wxStaticText * m_inactiveLayersLabel
std::map< GAL_LAYER_ID, APPEARANCE_SETTING * > m_objectSettingsMap
void ApplyLayerPreset(const wxString &aPresetName)
static LAYER_PRESET m_lastBuiltinPreset
wxRadioButton * m_rbHighContrastNormal
void onObjectVisibilityChanged(GAL_LAYER_ID aLayer, bool isVisible, bool isFinal)
static LAYER_PRESET presetFrontAssembly
void OnBoardItemAdded(BOARD &aBoard, BOARD_ITEM *aItem) override
static LAYER_PRESET presetBackAssembly
void OnNetGridClick(wxGridEvent &event) override
void setVisibleObjects(GAL_SET aObjects)
wxRadioButton * m_rbRatsnestNone
WX_COLLAPSIBLE_PANE * m_paneLayerDisplayOptions
void buildNetClassMenu(wxMenu &aMenu, bool isDefaultClass, const wxString &aName)
void onLayerVisibilityToggled(PCB_LAYER_ID aLayer)
void onLayerPresetChanged(wxCommandEvent &aEvent) override
wxBitmapBundle m_visibleBitmapBundle
void OnBoardItemRemoved(BOARD &aBoard, BOARD_ITEM *aItem) override
wxRadioButton * m_rbRatsnestVisLayers
wxRadioButton * m_rbNetColorAll
bool doesBoardItemNeedRebuild(BOARD_ITEM *aBoardItem)
void SetUserLayerPresets(std::vector< LAYER_PRESET > &aPresetList)
std::vector< LAYER_PRESET > GetUserLayerPresets() const
Update the current layer presets from those saved in the project file.
static LAYER_PRESET presetInnerCopper
void updateViewportSelection(const wxString &aName)
std::map< wxString, VIEWPORT > m_viewports
void onViewportChanged(wxCommandEvent &aEvent) override
NET_GRID_TABLE * m_netsTable
std::vector< std::unique_ptr< APPEARANCE_SETTING > > m_layerSettings
std::vector< std::unique_ptr< APPEARANCE_SETTING > > m_objectSettings
void onObjectOpacitySlider(int aLayer, float aOpacity)
bool isLayerEnabled(PCB_LAYER_ID aLayer) const
void setVisibleLayers(const LSET &aLayers)
wxRadioButton * m_rbRatsnestAllLayers
wxSize GetBestSize() const
Update the panel contents from the application and board models.
LAYER_PRESET * m_lastSelectedUserPreset
wxString m_contextMenuNetclass
The name of the netclass that was right-clicked.
wxRadioButton * m_rbNetColorRatsnest
void rebuildLayerPresetsWidget(bool aReset)
void onRatsnestMode(wxCommandEvent &aEvent)
wxRadioButton * m_rbNetColorOff
static LAYER_PRESET presetFront
void doApplyViewport(const VIEWPORT &aViewport)
static const APPEARANCE_SETTING s_objectSettings[]
Template for object appearance settings.
void OnNetGridMouseEvent(wxMouseEvent &aEvent)
WX_COLLAPSIBLE_PANE * m_paneNetDisplayOptions
void OnNotebookPageChanged(wxNotebookEvent &event) override
int GetTabIndex() const
Set the current notebook tab.
void onNetclassVisibilityChanged(wxCommandEvent &aEvent)
void OnBoardItemsRemoved(BOARD &aBoard, std::vector< BOARD_ITEM * > &aItems) override
void onNetContextMenu(wxCommandEvent &aEvent)
void OnColorSwatchChanged(wxCommandEvent &aEvent)
void updateLayerPresetSelection(const wxString &aName)
ROW_ICON_PROVIDER * m_iconProvider
std::map< wxString, LAYER_PRESET > m_layerPresets
static LAYER_PRESET presetBack
void RefreshCollapsiblePanes()
Function to force a redraw of the collapsible panes in this control.
static LAYER_PRESET presetNoLayers
void idleFocusHandler(wxIdleEvent &aEvent)
void rightClickHandler(wxMouseEvent &aEvent)
wxBitmapBundle m_notVisibileBitmapBundle
void OnNetGridRightClick(wxGridEvent &event) override
void OnBoardItemsChanged(BOARD &aBoard, std::vector< BOARD_ITEM * > &aItems) override
void UpdateDisplayOptions()
Return a list of the layer presets created by the user.
std::vector< std::unique_ptr< APPEARANCE_SETTING > > m_netclassSettings
wxRadioButton * m_rbHighContrastOff
void OnBoardCompositeUpdate(BOARD &aBoard, std::vector< BOARD_ITEM * > &aAddedItems, std::vector< BOARD_ITEM * > &aRemovedItems, std::vector< BOARD_ITEM * > &aChangedItems) override
Update the colors on all the widgets from the new chosen color theme.
void OnBoardItemsAdded(BOARD &aBoard, std::vector< BOARD_ITEM * > &aItems) override
void OnColorThemeChanged()
Respond to change in OS's DarkMode.
LAYER_PRESET * m_currentPreset
std::map< wxString, APPEARANCE_SETTING * > m_netclassSettingsMap
void OnSetFocus(wxFocusEvent &aEvent) override
void OnLanguageChanged(wxCommandEvent &aEvent)
static LAYER_PRESET presetAllCopper
void SetUserViewports(std::vector< VIEWPORT > &aPresetList)
wxRadioButton * m_rbHighContrastDim
void OnSize(wxSizeEvent &aEvent) override
wxString netclassNameFromEvent(wxEvent &aEvent)
wxGridCellCoords m_hoveredCell
Grid cell that is being hovered over, for tooltips.
void showNetclass(const wxString &aClassName, bool aShow=true)
wxStaticText * m_txtRatsnestVisibility
void onLayerLeftClick(wxMouseEvent &aEvent)
std::vector< VIEWPORT > GetUserViewports() const
Update the current viewports from those saved in the project file.
std::map< int, wxString > m_netclassIdMap
Stores wxIDs for each netclass for control event mapping.
void OnLayerContextMenu(wxCommandEvent &aEvent)
Return the index of the current tab (0-2).
void onNetColorMode(wxCommandEvent &aEvent)
void OnNetVisibilityChanged(int aNetCode, bool aVisibility)
Notifies the panel when a net has been hidden or shown via the external tool.
void OnDarkModeToggle()
Update the widget when the active board layer is changed.
static LAYER_PRESET presetAllLayers
void onNetclassContextMenu(wxCommandEvent &aEvent)
wxStaticText * m_txtNetDisplayTitle
wxStaticLine * m_layerDisplaySeparator
APPEARANCE_CONTROLS(PCB_BASE_FRAME *aParent, wxWindow *aFocusOwner, bool aFpEditor=false)
void SetObjectVisible(GAL_LAYER_ID aLayer, bool isVisible=true)
void OnNetGridDoubleClick(wxGridEvent &event) override
void SetLayerVisible(int aLayer, bool isVisible)
void OnBoardItemChanged(BOARD &aBoard, BOARD_ITEM *aItem) override
void onNetclassColorChanged(wxCommandEvent &aEvent)
void ApplyViewport(const wxString &aPresetName)
GRID_BITMAP_TOGGLE_RENDERER * m_toggleGridRenderer
BASE_SET & set(size_t pos)
Definition base_set.h:116
A checkbox control except with custom bitmaps for the checked and unchecked states.
void SetValue(bool aValue)
Set the checkbox state.
std::shared_ptr< NET_SETTINGS > m_NetSettings
std::map< std::string, wxString > m_UserLayerNames
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:83
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:322
const NETINFO_LIST & GetNetInfo() const
Definition board.h:996
static wxString GetStandardLayerName(PCB_LAYER_ID aLayerId)
Return an "English Standard" name of a PCB layer when given aLayerNumber.
Definition board.h:901
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition board.h:680
void SetHighLightNet(int aNetCode, bool aMulti=false)
Select the netcode to be highlighted.
Definition board.cpp:3259
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition board.cpp:730
PROJECT * GetProject() const
Definition board.h:579
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1084
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition board.cpp:969
void HighLightON(bool aValue=true)
Enable or disable net highlighting.
Definition board.cpp:3272
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:402
Color settings are a bit different than most of the settings objects in that there can be more than o...
void SetColor(int aLayer, const COLOR4D &aColor)
COLOR4D GetColor(int aLayer) const
COLOR4D GetDefaultColor(int aLayer)
A simple color swatch of the kind used to set layer colors.
void SetSwatchColor(const KIGFX::COLOR4D &aColor, bool aSendEvent)
Set the current swatch color directly.
void GetNewSwatchColor()
Prompt for a new colour, using the colour picker dialog.
KIGFX::COLOR4D GetSwatchColor() const
void SetReadOnlyCallback(std::function< void()> aCallback)
Register a handler for when the user tries to interact with a read-only swatch.
void SetReadOnly(bool aReadOnly=true)
int ShowModal() override
Class to handle configuration and automatic determination of the DPI scale to use for canvases.
double GetScaleFactor() const override
Get the DPI scale from all known sources in order:
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h: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:403
bool Contains(GAL_LAYER_ID aPos)
Definition layer_ids.h:437
GAL_SET & set()
Definition layer_ids.h:419
static GAL_SET DefaultVisible()
Definition lset.cpp:786
A toggle button renderer for a wxGrid, similar to BITMAP_TOGGLE.
A text renderer that can unescape text for display This is useful where it's desired to keep the unde...
Represent a row indicator icon for use in places like the layer widget.
void SetIndicatorState(ICON_ID aIconId)
Set the row indicator to the given state.
bool IsReadOnly() const
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:105
bool SetFromWxString(const wxString &aColorString)
Set color values by parsing a string using wxColour::Set().
Definition color4d.cpp:131
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:402
PCB specific render settings.
Definition pcb_painter.h:82
std::set< int > & GetHiddenNets()
std::map< int, KIGFX::COLOR4D > & GetNetColorMap()
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
void SetHighlight(bool aEnabled, int aNetcode=-1, bool aMulti=false)
Turns on/off highlighting.
An abstract base class for deriving all objects that can be added to a VIEW.
Definition view_item.h:86
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:66
void SetMirror(bool aMirrorX, bool aMirrorY)
Control the mirroring of the VIEW.
Definition view.cpp:558
void UpdateAllLayersColor()
Apply the new coloring scheme to all layers.
Definition view.cpp:776
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:1462
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:755
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:1582
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static const LSET & FrontMask()
Return a mask holding all technical layers and the external CU layer on front side.
Definition lset.cpp:722
static const LSET & BackAssembly()
Return a complete set of all bottom assembly layers which is all B_SilkS and B_Mask.
Definition lset.cpp:570
static const LSET & BackMask()
Return a mask holding all technical layers and the external CU layer on back side.
Definition lset.cpp:729
static const LSET & FrontAssembly()
Return a complete set of all top assembly layers which is all F_SilkS and F_Mask.
Definition lset.cpp:563
LSEQ CuStack() const
Return a sequence of copper layers in starting from the front/top and extending to the back/bottom.
Definition lset.cpp:263
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition lset.cpp:313
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition lset.cpp:599
static const LSET & AllLayersMask()
Definition lset.cpp:641
static const LSET & InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
Definition lset.cpp:577
static wxString Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Definition lset.cpp:188
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
Definition lset.h:63
static const char Default[]
the name of the default NETCLASS
Definition netclass.h: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:238
void SetValue(int aRow, int aCol, const wxString &aValue) override
void SetValueAsCustom(int aRow, int aCol, const wxString &aTypeName, void *aValue) override
std::vector< NET_GRID_ENTRY > m_nets
void updateNetColor(const NET_GRID_ENTRY &aNet)
NET_GRID_ENTRY & GetEntry(int aRow)
void SetValueAsBool(int aRow, int aCol, bool aValue) override
void * GetValueAsCustom(int aRow, int aCol, const wxString &aTypeName) override
NET_GRID_TABLE(PCB_BASE_FRAME *aFrame, wxColor aBackgroundColor)
void updateNetVisibility(const NET_GRID_ENTRY &aNet)
wxString GetValue(int aRow, int aCol) override
wxGridCellAttr * m_labelAttr
PCB_BASE_FRAME * m_frame
void HideOtherNets(const NET_GRID_ENTRY &aNet)
wxGridCellAttr * m_defaultAttr
bool GetValueAsBool(int aRow, int aCol) override
wxGridCellAttr * GetAttr(int aRow, int aCol, wxGridCellAttr::wxAttrKind) override
static void * ColorToVoid(COLOR4D &aColor)
int GetRowByNetcode(int aCode) const
wxString GetTypeName(int aRow, int aCol) override
static COLOR4D VoidToColor(void *aColor)
Definition pad.h:55
static TOOL_ACTION highlightNet
static TOOL_ACTION hideNetInRatsnest
static TOOL_ACTION showNetInRatsnest
static TOOL_ACTION showNetInspector
static TOOL_ACTION ratsnestModeCycle
static TOOL_ACTION netColorModeCycle
static TOOL_ACTION selectNet
Select all connections belonging to a single net.
Definition pcb_actions.h:82
static TOOL_ACTION flipBoard
static TOOL_ACTION deselectNet
Remove all connections belonging to a single net from the active selection.
Definition pcb_actions.h:85
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
double m_TrackOpacity
Opacity override for all tracks.
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:259
This file is part of the common library.
#define _(s)
#define VIEWPORT_SWITCH_KEY
#define PRESET_SWITCH_KEY
@ FRAME_PCB_EDITOR
Definition frame_type.h:42
wxString KeyNameFromKeyCode(int aKeycode, bool *aIsFound)
Return the key name from the key code.
GAL_LAYER_ID ToGalLayer(int aInteger)
Definition layer_ids.h:382
int GetNetnameLayer(int aLayer)
Return a netname layer corresponding to the given layer.
Definition layer_ids.h:854
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition layer_ids.h:677
GAL_LAYER_ID
GAL layers are "virtual" layers, i.e.
Definition layer_ids.h:228
@ LAYER_GRID
Definition layer_ids.h:254
@ LAYER_POINTS
PCB reference/manual snap points visibility.
Definition layer_ids.h:321
@ GAL_LAYER_ID_START
Definition layer_ids.h:229
@ LAYER_LOCKED_ITEM_SHADOW
Shadow layer for locked items.
Definition layer_ids.h:307
@ LAYER_FILLED_SHAPES
Copper graphic shape opacity/visibility (color ignored).
Definition layer_ids.h:313
@ LAYER_CONFLICTS_SHADOW
Shadow layer for items flagged conflicting.
Definition layer_ids.h:310
@ LAYER_FOOTPRINTS_FR
Show footprints on front.
Definition layer_ids.h:259
@ LAYER_DRAWINGSHEET
Sheet frame and title block.
Definition layer_ids.h:278
@ LAYER_DRAW_BITMAPS
Draw images.
Definition layer_ids.h:284
@ LAYER_FP_REFERENCES
Show footprints references (when texts are visible).
Definition layer_ids.h:266
@ LAYER_BOARD_OUTLINE_AREA
PCB board outline.
Definition layer_ids.h:318
@ LAYER_DRC_EXCLUSION
Layer for DRC markers which have been individually excluded.
Definition layer_ids.h:304
@ LAYER_PCB_BACKGROUND
PCB background color.
Definition layer_ids.h:281
@ LAYER_ZONES
Control for copper zone opacity/visibility (color ignored).
Definition layer_ids.h:295
@ LAYER_PADS
Meta control for all pads opacity/visibility (color ignored).
Definition layer_ids.h:292
@ LAYER_DRC_WARNING
Layer for DRC markers with #SEVERITY_WARNING.
Definition layer_ids.h:301
@ LAYER_TRACKS
Definition layer_ids.h:267
@ LAYER_RATSNEST
Definition layer_ids.h:253
@ LAYER_ZONE_START
Virtual layers for stacking zones and tracks on a given copper layer.
Definition layer_ids.h:333
@ LAYER_FP_TEXT
Definition layer_ids.h:240
@ LAYER_FOOTPRINTS_BK
Show footprints on back.
Definition layer_ids.h:260
@ LAYER_ANCHOR
Anchor of items having an anchor point (texts, footprints).
Definition layer_ids.h:248
@ LAYER_FP_VALUES
Show footprints values (when texts are visible).
Definition layer_ids.h:263
@ LAYER_DRC_ERROR
Layer for DRC markers with #SEVERITY_ERROR.
Definition layer_ids.h:277
@ LAYER_VIAS
Meta control for all vias opacity/visibility.
Definition layer_ids.h:232
#define CLEARANCE_LAYER_FOR(boardLayer)
Definition layer_ids.h:371
#define VIA_COPPER_LAYER_FOR(boardLayer)
Definition layer_ids.h:370
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:368
#define PAD_COPPER_LAYER_FOR(boardLayer)
Definition layer_ids.h:369
#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:364
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition lset.cpp:754
@ ALL
All except INITIAL_ADD.
Definition view_item.h:59
@ TARGET_NONCACHED
Auxiliary rendering target (noncached)
Definition definitions.h:38
KICOMMON_API wxFont GetInfoFont(wxWindow *aWindow)
KICOMMON_API wxMenuItem * AddMenuItem(wxMenu *aMenu, int aId, const wxString &aText, const wxBitmapBundle &aImage, wxItemKind aType=wxITEM_NORMAL)
Create and insert a menu item with an icon into aMenu.
const int c_IndicatorSizeDIP
Definition ui_common.h:52
#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:110