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