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 wxPanel* panel = new wxPanel( m_windowObjects, wxID_ANY );
2248 wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
2249 panel->SetSizer( sizer );
2250 int layer = aSetting->id;
2251
2252 aSetting->visible = visible.Contains( ToGalLayer( layer ) );
2253 COLOR4D color = theme->GetColor( layer );
2254 COLOR4D defColor = theme->GetDefaultColor( layer );
2255
2256 if( color != COLOR4D::UNSPECIFIED || defColor != COLOR4D::UNSPECIFIED )
2257 {
2258 COLOR_SWATCH* swatch = new COLOR_SWATCH( panel, color, layer,
2259 bgColor, defColor, SWATCH_SMALL );
2260 swatch->SetToolTip( _( "Left double click or middle click for color change, "
2261 "right click for menu" ) );
2262
2263 sizer->Add( swatch, 0, wxALIGN_CENTER_VERTICAL, 0 );
2264 aSetting->ctl_color = swatch;
2265
2266 swatch->Bind( COLOR_SWATCH_CHANGED, &APPEARANCE_CONTROLS::OnColorSwatchChanged, this );
2267
2268 swatch->SetReadOnlyCallback( std::bind( &APPEARANCE_CONTROLS::onReadOnlySwatch, this ) );
2269 }
2270 else
2271 {
2272 sizer->AddSpacer( swatchWidth );
2273 }
2274
2275 BITMAP_TOGGLE* btn_visible = nullptr;
2276 wxString tip;
2277
2278 if( aSetting->can_control_visibility )
2279 {
2280 btn_visible = new BITMAP_TOGGLE( panel, layer,
2283 aSetting->visible );
2284
2285 tip.Printf( _( "Show or hide %s" ), aSetting->label.Lower() );
2286 btn_visible->SetToolTip( tip );
2287
2288 aSetting->ctl_visibility = btn_visible;
2289
2290 btn_visible->Bind( TOGGLE_CHANGED,
2291 [&]( wxCommandEvent& aEvent )
2292 {
2293 int id = static_cast<wxWindow*>( aEvent.GetEventObject() )->GetId();
2294 bool isVisible = aEvent.GetInt();
2295 onObjectVisibilityChanged( ToGalLayer( id ), isVisible, true );
2296 } );
2297 }
2298
2299 sizer->AddSpacer( 5 );
2300
2301 wxStaticText* label = new wxStaticText( panel, layer, aSetting->label );
2302 label->Wrap( -1 );
2303 label->SetToolTip( aSetting->tooltip );
2304
2305 if( aSetting->can_control_opacity )
2306 {
2307 label->SetMinSize( wxSize( labelWidth, -1 ) );
2308#ifdef __WXMAC__
2309 if( btn_visible )
2310 sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, 10 );
2311 else
2312 sizer->AddSpacer( btnWidth );
2313
2314 sizer->AddSpacer( 5 );
2315 sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, 10 );
2316#else
2317 if( btn_visible )
2318 sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL, 0 );
2319 else
2320 sizer->AddSpacer( btnWidth );
2321
2322 sizer->AddSpacer( 5 );
2323 sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL, 0 );
2324#endif
2325
2326 wxSlider* slider = new wxSlider( panel, wxID_ANY, 100, 0, 100,
2327 wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL );
2328#ifdef __WXMAC__
2329 slider->SetMinSize( wxSize( 80, 16 ) );
2330#else
2331 slider->SetMinSize( wxSize( 80, -1 ) );
2332#endif
2333
2334 tip.Printf( _( "Set opacity of %s" ), aSetting->label.Lower() );
2335 slider->SetToolTip( tip );
2336
2337 sizer->Add( slider, 1, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 5 );
2338 aSetting->ctl_opacity = slider;
2339
2340 auto opacitySliderHandler =
2341 [this, layer]( wxCommandEvent& aEvent )
2342 {
2343 wxSlider* ctrl = static_cast<wxSlider*>( aEvent.GetEventObject() );
2344 int value = ctrl->GetValue();
2345 onObjectOpacitySlider( layer, value / 100.0f );
2346 };
2347
2348 slider->Bind( wxEVT_SCROLL_CHANGED, opacitySliderHandler );
2349 slider->Bind( wxEVT_SCROLL_THUMBTRACK, opacitySliderHandler );
2350 slider->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS::OnSetFocus, this );
2351 }
2352 else
2353 {
2354 if( btn_visible )
2355 sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL, 0 );
2356 else
2357 sizer->AddSpacer( btnWidth );
2358
2359 sizer->AddSpacer( 5 );
2360 sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL, 0 );
2361 }
2362
2363 aSetting->ctl_text = label;
2364 m_objectsOuterSizer->Add( panel, 0, wxEXPAND | wxLEFT | wxRIGHT, 5 );
2365
2366 if( !aSetting->can_control_opacity )
2367 m_objectsOuterSizer->AddSpacer( 2 );
2368 };
2369
2370 for( const APPEARANCE_SETTING& s_setting : s_objectSettings )
2371 {
2372 if( m_isFpEditor && !s_allowedInFpEditor.count( s_setting.id ) )
2373 continue;
2374
2375 m_objectSettings.emplace_back( std::make_unique<APPEARANCE_SETTING>( s_setting ) );
2376
2377 std::unique_ptr<APPEARANCE_SETTING>& setting = m_objectSettings.back();
2378
2379 // Because s_render_rows is created static, we must explicitly call wxGetTranslation
2380 // for texts which are internationalized (tool tips and item names)
2381 setting->tooltip = wxGetTranslation( s_setting.tooltip );
2382 setting->label = wxGetTranslation( s_setting.label );
2383
2384 if( setting->can_control_opacity )
2385 {
2386 int width = m_windowObjects->GetTextExtent( setting->label ).x + 5;
2387 labelWidth = std::max( labelWidth, width );
2388 }
2389
2390 if( !s_setting.spacer )
2391 m_objectSettingsMap[ToGalLayer( setting->id )] = setting.get();
2392 }
2393
2394 for( const std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
2395 {
2396 if( setting->spacer )
2397 m_objectsOuterSizer->AddSpacer( m_pointSize / 2 );
2398 else
2399 appendObject( setting );
2400 }
2401
2402 m_objectsOuterSizer->Layout();
2403 m_windowObjects->FitInside();
2404}
2405
2406
2408{
2409 GAL_SET visible = getVisibleObjects();
2410
2411 const PCB_DISPLAY_OPTIONS& opts = m_frame->GetDisplayOptions();
2412
2413 for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
2414 {
2415 if( setting->spacer )
2416 continue;
2417
2418 GAL_LAYER_ID layer = ToGalLayer( setting->id );
2419
2420 if( setting->ctl_visibility )
2421 setting->ctl_visibility->SetValue( visible.Contains( layer ) );
2422
2423 if( setting->ctl_color )
2424 {
2425 COLOR4D color = m_frame->GetColorSettings()->GetColor( setting->id );
2426 setting->ctl_color->SetSwatchColor( color, false );
2427 }
2428 }
2429
2430 wxASSERT( m_objectSettingsMap.count( LAYER_TRACKS )
2436
2437 m_objectSettingsMap[LAYER_TRACKS]->ctl_opacity->SetValue( opts.m_TrackOpacity * 100 );
2438 m_objectSettingsMap[LAYER_VIAS]->ctl_opacity->SetValue( opts.m_ViaOpacity * 100 );
2439 m_objectSettingsMap[LAYER_PADS]->ctl_opacity->SetValue( opts.m_PadOpacity * 100 );
2440 m_objectSettingsMap[LAYER_ZONES]->ctl_opacity->SetValue( opts.m_ZoneOpacity * 100 );
2441 m_objectSettingsMap[LAYER_DRAW_BITMAPS]->ctl_opacity->SetValue( opts.m_ImageOpacity * 100 );
2442 m_objectSettingsMap[LAYER_FILLED_SHAPES]->ctl_opacity->SetValue( opts.m_FilledShapeOpacity * 100 );
2443}
2444
2445
2446void APPEARANCE_CONTROLS::buildNetClassMenu( wxMenu& aMenu, bool isDefaultClass,
2447 const wxString& aName )
2448{
2449 BOARD* board = m_frame->GetBoard();
2450 std::shared_ptr<NET_SETTINGS>& netSettings = board->GetDesignSettings().m_NetSettings;
2451
2452 if( !isDefaultClass)
2453 {
2454 aMenu.Append( new wxMenuItem( &aMenu, ID_SET_NET_COLOR, _( "Set Netclass Color" ),
2455 wxEmptyString, wxITEM_NORMAL ) );
2456
2457 wxMenuItem* schematicColor = new wxMenuItem( &aMenu, ID_USE_SCHEMATIC_NET_COLOR,
2458 _( "Use Color from Schematic" ),
2459 wxEmptyString, wxITEM_NORMAL );
2460 std::shared_ptr<NETCLASS> nc = netSettings->GetNetClassByName( aName );
2461 const KIGFX::COLOR4D ncColor = nc->GetSchematicColor();
2462 aMenu.Append( schematicColor );
2463
2464 if( ncColor == KIGFX::COLOR4D::UNSPECIFIED )
2465 schematicColor->Enable( false );
2466
2467 aMenu.Append( new wxMenuItem( &aMenu, ID_CLEAR_NET_COLOR, _( "Clear Netclass Color" ),
2468 wxEmptyString, wxITEM_NORMAL ) );
2469 aMenu.AppendSeparator();
2470 }
2471
2472 wxString name = UnescapeString( aName );
2473
2474 aMenu.Append( new wxMenuItem( &aMenu, ID_HIGHLIGHT_NET,
2475 wxString::Format( _( "Highlight Nets in %s" ), name ),
2476 wxEmptyString, wxITEM_NORMAL ) );
2477 aMenu.Append( new wxMenuItem( &aMenu, ID_SELECT_NET,
2478 wxString::Format( _( "Select Tracks and Vias in %s" ), name ),
2479 wxEmptyString, wxITEM_NORMAL ) );
2480 aMenu.Append( new wxMenuItem( &aMenu, ID_DESELECT_NET,
2481 wxString::Format( _( "Unselect Tracks and Vias in %s" ), name ),
2482 wxEmptyString, wxITEM_NORMAL ) );
2483
2484 aMenu.AppendSeparator();
2485
2486 aMenu.Append( new wxMenuItem( &aMenu, ID_SHOW_ALL_NETS, _( "Show All Netclasses" ),
2487 wxEmptyString, wxITEM_NORMAL ) );
2488 aMenu.Append( new wxMenuItem( &aMenu, ID_HIDE_OTHER_NETS, _( "Hide All Other Netclasses" ),
2489 wxEmptyString, wxITEM_NORMAL ) );
2490
2491 aMenu.Bind( wxEVT_COMMAND_MENU_SELECTED, &APPEARANCE_CONTROLS::onNetclassContextMenu, this );
2492
2493}
2494
2495
2497{
2498 BOARD* board = m_frame->GetBoard();
2499 COLOR_SETTINGS* theme = m_frame->GetColorSettings();
2500 COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
2501
2502 // If the board isn't fully loaded, we can't yet rebuild
2503 if( !board->GetProject() )
2504 return;
2505
2506 m_staticTextNets->SetLabel( _( "Nets" ) );
2507 m_staticTextNetClasses->SetLabel( _( "Net Classes" ) );
2508
2509 std::shared_ptr<NET_SETTINGS>& netSettings = board->GetDesignSettings().m_NetSettings;
2510
2511 const std::set<wxString>& hiddenClasses = m_frame->Prj().GetLocalSettings().m_HiddenNetclasses;
2512
2513 m_netclassOuterSizer->Clear( true );
2514
2515 auto appendNetclass =
2516 [&]( int aId, const std::shared_ptr<NETCLASS>& aClass, bool isDefaultClass = false )
2517 {
2518 wxString name = aClass->GetName();
2519
2520 m_netclassSettings.emplace_back( std::make_unique<APPEARANCE_SETTING>() );
2521 APPEARANCE_SETTING* setting = m_netclassSettings.back().get();
2522 m_netclassSettingsMap[name] = setting;
2523
2524 setting->ctl_panel = new wxPanel( m_netclassScrolledWindow, aId );
2525 wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
2526 setting->ctl_panel->SetSizer( sizer );
2527
2528 COLOR4D color = netSettings->HasNetclass( name )
2529 ? netSettings->GetNetClassByName( name )->GetPcbColor()
2531
2532 setting->ctl_color = new COLOR_SWATCH( setting->ctl_panel, color, aId, bgColor,
2534 setting->ctl_color->SetToolTip( _( "Left double click or middle click for color "
2535 "change, right click for menu" ) );
2536
2537 setting->ctl_color->Bind( COLOR_SWATCH_CHANGED,
2539
2540 // Default netclass can't have an override color
2541 if( isDefaultClass )
2542 setting->ctl_color->Hide();
2543
2544 setting->ctl_visibility = new BITMAP_TOGGLE( setting->ctl_panel, aId,
2547 !hiddenClasses.count( name ) );
2548
2549 wxString tip;
2550 tip.Printf( _( "Show or hide ratsnest for nets in %s" ), name );
2551 setting->ctl_visibility->SetToolTip( tip );
2552
2553 setting->ctl_text = new wxStaticText( setting->ctl_panel, aId, name );
2554 setting->ctl_text->Wrap( -1 );
2555
2556 int flags = wxALIGN_CENTER_VERTICAL;
2557
2558 sizer->Add( setting->ctl_color, 0, flags | wxRESERVE_SPACE_EVEN_IF_HIDDEN, 5 );
2559 sizer->AddSpacer( 7 );
2560 sizer->Add( setting->ctl_visibility, 0, flags, 5 );
2561 sizer->AddSpacer( 3 );
2562 sizer->Add( setting->ctl_text, 1, flags, 5 );
2563
2564 m_netclassOuterSizer->Add( setting->ctl_panel, 0, wxEXPAND, 5 );
2565 m_netclassOuterSizer->AddSpacer( 2 );
2566
2567 setting->ctl_visibility->Bind( TOGGLE_CHANGED,
2569 this );
2570
2571 auto menuHandler =
2572 [&, name, isDefaultClass]( wxMouseEvent& aEvent )
2573 {
2574 wxMenu menu;
2575 buildNetClassMenu( menu, isDefaultClass, name );
2576
2578 PopupMenu( &menu );
2579 };
2580
2581 setting->ctl_panel->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2582 setting->ctl_visibility->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2583 setting->ctl_color->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2584 setting->ctl_text->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2585 };
2586
2587 std::vector<wxString> names;
2588
2589 for( const auto& [name, netclass] : netSettings->GetNetclasses() )
2590 names.emplace_back( name );
2591
2592 std::sort( names.begin(), names.end() );
2593
2594 m_netclassIdMap.clear();
2595
2596 int idx = wxID_HIGHEST;
2597
2598 m_netclassIdMap[idx] = netSettings->GetDefaultNetclass()->GetName();
2599 appendNetclass( idx++, netSettings->GetDefaultNetclass(), true );
2600
2601 for( const wxString& name : names )
2602 {
2603 m_netclassIdMap[idx] = name;
2604 appendNetclass( idx++, netSettings->GetNetclasses().at( name ) );
2605 }
2606
2607 int hotkey;
2608 wxString msg;
2609
2610 m_paneNetDisplayOptions->SetLabel( _( "Net Display Options" ) );
2611
2612 hotkey = PCB_ACTIONS::netColorModeCycle.GetHotKey();
2613
2614 if( hotkey )
2615 msg = wxString::Format( _( "Net colors (%s):" ), KeyNameFromKeyCode( hotkey ) );
2616 else
2617 msg = _( "Net colors:" );
2618
2619 m_txtNetDisplayTitle->SetLabel( msg );
2620 m_txtNetDisplayTitle->SetToolTip( _( "Choose when to show net and netclass colors" ) );
2621
2622 m_rbNetColorAll->SetLabel( _( "All" ) );
2623 m_rbNetColorAll->SetToolTip( _( "Net and netclass colors are shown on all copper items" ) );
2624
2625 m_rbNetColorRatsnest->SetLabel( _( "Ratsnest" ) );
2626 m_rbNetColorRatsnest->SetToolTip( _( "Net and netclass colors are shown on the ratsnest only" ) );
2627
2628 m_rbNetColorOff->SetLabel( _( "None" ) );
2629 m_rbNetColorOff->SetToolTip( _( "Net and netclass colors are not shown" ) );
2630
2631 hotkey = PCB_ACTIONS::ratsnestModeCycle.GetHotKey();
2632
2633 if( hotkey )
2634 msg = wxString::Format( _( "Ratsnest display (%s):" ), KeyNameFromKeyCode( hotkey ) );
2635 else
2636 msg = _( "Ratsnest display:" );
2637
2638 m_txtRatsnestVisibility->SetLabel( msg );
2639 m_txtRatsnestVisibility->SetToolTip( _( "Choose which ratsnest lines to display" ) );
2640
2641 m_rbRatsnestAllLayers->SetLabel( _( "All" ) );
2642 m_rbRatsnestAllLayers->SetToolTip( _( "Show ratsnest lines to items on all layers" ) );
2643
2644 m_rbRatsnestVisLayers->SetLabel( _( "Visible layers" ) );
2645 m_rbRatsnestVisLayers->SetToolTip( _( "Show ratsnest lines to items on visible layers" ) );
2646
2647 m_rbRatsnestNone->SetLabel( _( "None" ) );
2648 m_rbRatsnestNone->SetToolTip( _( "Hide all ratsnest lines" ) );
2649
2650 m_netclassOuterSizer->Layout();
2651
2652 m_netsTable->Rebuild();
2653 m_panelNets->GetSizer()->Layout();
2654}
2655
2656
2658{
2659 m_viewportsLabel->SetLabel( wxString::Format( _( "Presets (%s+Tab):" ),
2661
2662 m_cbLayerPresets->Clear();
2663
2664 if( aReset )
2665 m_presetMRU.clear();
2666
2667 // Build the layers preset list.
2668 // By default, the presetAllLayers will be selected
2669 int idx = 0;
2670 int default_idx = 0;
2671 std::vector<std::pair<wxString, void*>> userPresets;
2672
2673 // m_layerPresets is alphabetical: m_presetMRU should also be alphabetical, but m_cbLayerPresets
2674 // is split into build-in and user sections.
2675 for( auto& [name, preset] : m_layerPresets )
2676 {
2677 const wxString translatedName = wxGetTranslation( name );
2678 void* userData = static_cast<void*>( &preset );
2679
2680 if( preset.readOnly )
2681 m_cbLayerPresets->Append( translatedName, userData );
2682 else
2683 userPresets.push_back( { name, userData } );
2684
2685 if( aReset )
2686 m_presetMRU.push_back( translatedName );
2687
2688 if( name == presetAllLayers.name )
2689 default_idx = idx;
2690
2691 idx++;
2692 }
2693
2694 if( !userPresets.empty() )
2695 {
2696 m_cbLayerPresets->Append( wxT( "---" ) );
2697
2698 for( auto& [name, userData] : userPresets )
2699 m_cbLayerPresets->Append( name, userData );
2700 }
2701
2702 m_cbLayerPresets->Append( wxT( "---" ) );
2703 m_cbLayerPresets->Append( _( "Save preset..." ) );
2704 m_cbLayerPresets->Append( _( "Delete preset..." ) );
2705
2706 // At least the built-in presets should always be present
2707 wxASSERT( !m_layerPresets.empty() );
2708
2709 if( aReset )
2710 {
2711 // Default preset: all layers
2712 m_cbLayerPresets->SetSelection( default_idx );
2714 }
2715}
2716
2717
2719{
2720 LSET visibleLayers = getVisibleLayers();
2721 GAL_SET visibleObjects = getVisibleObjects();
2722 bool flipBoard = m_cbFlipBoard->GetValue();
2723
2724 auto it = std::find_if( m_layerPresets.begin(), m_layerPresets.end(),
2725 [&]( const std::pair<const wxString, LAYER_PRESET>& aPair )
2726 {
2727 return ( aPair.second.layers == visibleLayers
2728 && aPair.second.renderLayers == visibleObjects
2729 && aPair.second.flipBoard == flipBoard );
2730 } );
2731
2732 if( it != m_layerPresets.end() )
2733 {
2734 // Select the right m_cbLayersPresets item.
2735 // but these items are translated if they are predefined items.
2736 bool do_translate = it->second.readOnly;
2737 wxString text = do_translate ? wxGetTranslation( it->first ) : it->first;
2738
2739 m_cbLayerPresets->SetStringSelection( text );
2740 }
2741 else
2742 {
2743 m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator
2744 }
2745
2746 m_currentPreset = static_cast<LAYER_PRESET*>( m_cbLayerPresets->GetClientData( m_cbLayerPresets->GetSelection() ) );
2747}
2748
2749
2751{
2752 // look at m_layerPresets to know if aName is a read only preset, or a user preset.
2753 // Read only presets have translated names in UI, so we have to use
2754 // a translated name in UI selection.
2755 // But for a user preset name we should search for aName (not translated)
2756 wxString ui_label = aName;
2757
2758 for( std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
2759 {
2760 if( pair.first != aName )
2761 continue;
2762
2763 if( pair.second.readOnly == true )
2764 ui_label = wxGetTranslation( aName );
2765
2766 break;
2767 }
2768
2769 int idx = m_cbLayerPresets->FindString( ui_label );
2770
2771 if( idx >= 0 && m_cbLayerPresets->GetSelection() != idx )
2772 {
2773 m_cbLayerPresets->SetSelection( idx );
2774 m_currentPreset = static_cast<LAYER_PRESET*>( m_cbLayerPresets->GetClientData( idx ) );
2775 }
2776 else if( idx < 0 )
2777 {
2778 m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator
2779 }
2780}
2781
2782
2783void APPEARANCE_CONTROLS::onLayerPresetChanged( wxCommandEvent& aEvent )
2784{
2785 int count = m_cbLayerPresets->GetCount();
2786 int index = m_cbLayerPresets->GetSelection();
2787
2788 auto resetSelection =
2789 [&]()
2790 {
2791 if( m_currentPreset )
2792 m_cbLayerPresets->SetStringSelection( m_currentPreset->name );
2793 else
2794 m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 );
2795 };
2796
2797 if( index == count - 2 )
2798 {
2799 // Save current state to new preset
2800 wxString name;
2801
2804
2805 wxTextEntryDialog dlg( wxGetTopLevelParent( this ), _( "Layer preset name:" ),
2806 _( "Save Layer Preset" ), name );
2807
2808 if( dlg.ShowModal() != wxID_OK )
2809 {
2810 resetSelection();
2811 return;
2812 }
2813
2814 name = dlg.GetValue();
2815 bool exists = m_layerPresets.count( name );
2816
2817 if( !exists )
2818 {
2820 UNSELECTED_LAYER, m_cbFlipBoard->GetValue() );
2821 }
2822
2823 LAYER_PRESET* preset = &m_layerPresets[name];
2824
2825 if( !exists )
2826 {
2828 index = m_cbLayerPresets->FindString( name );
2829 }
2830 else if( preset->readOnly )
2831 {
2832 wxMessageBox( _( "Default presets cannot be modified.\nPlease use a different name." ),
2833 _( "Error" ), wxOK | wxICON_ERROR, wxGetTopLevelParent( this ) );
2834 resetSelection();
2835 return;
2836 }
2837 else
2838 {
2839 // Ask the user if they want to overwrite the existing preset
2840 if( !IsOK( wxGetTopLevelParent( this ), _( "Overwrite existing preset?" ) ) )
2841 {
2842 resetSelection();
2843 return;
2844 }
2845
2846 preset->layers = getVisibleLayers();
2847 preset->renderLayers = getVisibleObjects();
2848 preset->flipBoard = m_cbFlipBoard->GetValue();
2849
2850 index = m_cbLayerPresets->FindString( name );
2851
2852 if( m_presetMRU.Index( name ) != wxNOT_FOUND )
2853 m_presetMRU.Remove( name );
2854 }
2855
2856 m_currentPreset = preset;
2857 m_cbLayerPresets->SetSelection( index );
2858 m_presetMRU.Insert( name, 0 );
2859
2860 return;
2861 }
2862 else if( index == count - 1 )
2863 {
2864 // Delete a preset
2865 wxArrayString headers;
2866 std::vector<wxArrayString> items;
2867
2868 headers.Add( _( "Presets" ) );
2869
2870 for( std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
2871 {
2872 if( !pair.second.readOnly )
2873 {
2874 wxArrayString item;
2875 item.Add( pair.first );
2876 items.emplace_back( item );
2877 }
2878 }
2879
2880 EDA_LIST_DIALOG dlg( m_frame, _( "Delete Preset" ), headers, items );
2881 dlg.SetListLabel( _( "Select preset:" ) );
2882
2883 if( dlg.ShowModal() == wxID_OK )
2884 {
2885 wxString presetName = dlg.GetTextSelection();
2886 int idx = m_cbLayerPresets->FindString( presetName );
2887
2888 if( idx != wxNOT_FOUND )
2889 {
2890 m_layerPresets.erase( presetName );
2891
2892 m_cbLayerPresets->Delete( idx );
2893 m_currentPreset = nullptr;
2894 }
2895
2896 if( m_presetMRU.Index( presetName ) != wxNOT_FOUND )
2897 m_presetMRU.Remove( presetName );
2898 }
2899
2900 resetSelection();
2901 return;
2902 }
2903 else if( m_cbLayerPresets->GetString( index ) == wxT( "---" ) )
2904 {
2905 // Separator: reject the selection
2906 resetSelection();
2907 return;
2908 }
2909
2910 // Store the objects visibility settings if the preset is not a user preset,
2911 // to be reused when selecting a new built-in layer preset, even if a previous
2912 // user preset has changed the object visibility
2913 if( !m_currentPreset || m_currentPreset->readOnly )
2914 {
2915 m_lastBuiltinPreset.renderLayers = getVisibleObjects();
2916 }
2917
2918 LAYER_PRESET* preset = static_cast<LAYER_PRESET*>( m_cbLayerPresets->GetClientData( index ) );
2919 m_currentPreset = preset;
2920
2921 m_lastSelectedUserPreset = ( !preset || preset->readOnly ) ? nullptr : preset;
2922
2923 if( preset )
2924 {
2925 // Change board layers visibility, but do not change objects visibility
2926 LAYER_PRESET curr_layers_choice = *preset;
2927
2928 // For predefined presets that do not manage objects visibility, use
2929 // the objects visibility settings of the last used predefined preset.
2930 if( curr_layers_choice.readOnly )
2931 curr_layers_choice.renderLayers = m_lastBuiltinPreset.renderLayers;
2932
2933 doApplyLayerPreset( curr_layers_choice );
2934 }
2935
2936 if( !m_currentPreset->name.IsEmpty() )
2937 {
2938 const wxString translatedName = wxGetTranslation( m_currentPreset->name );
2939
2940 if( m_presetMRU.Index( translatedName ) != wxNOT_FOUND )
2941 m_presetMRU.Remove( translatedName );
2942
2943 m_presetMRU.Insert( translatedName, 0 );
2944 }
2945
2946 passOnFocus();
2947}
2948
2949
2951{
2952 BOARD* board = m_frame->GetBoard();
2953 KIGFX::PCB_VIEW* view = m_frame->GetCanvas()->GetView();
2954
2955 setVisibleLayers( aPreset.layers );
2957
2958 // If the preset doesn't have an explicit active layer to restore, we can at least
2959 // force the active layer to be something in the preset's layer set
2960 PCB_LAYER_ID activeLayer = UNSELECTED_LAYER;
2961
2962 if( aPreset.activeLayer != UNSELECTED_LAYER )
2963 activeLayer = aPreset.activeLayer;
2964 else if( aPreset.layers.any() && !aPreset.layers.test( m_frame->GetActiveLayer() ) )
2965 activeLayer = *aPreset.layers.Seq().begin();
2966
2967 LSET boardLayers = board->GetLayerSet();
2968
2969 if( activeLayer != UNSELECTED_LAYER && boardLayers.Contains( activeLayer ) )
2970 m_frame->SetActiveLayer( activeLayer );
2971
2972 if( !m_isFpEditor )
2973 m_frame->GetCanvas()->SyncLayersVisibility( board );
2974
2975 if( aPreset.flipBoard != view->IsMirroredX() )
2976 {
2977 view->SetMirror( !view->IsMirroredX(), view->IsMirroredY() );
2978 view->RecacheAllItems();
2979 }
2980
2981 m_frame->GetCanvas()->Refresh();
2982
2985}
2986
2987
2989{
2990 m_viewportsLabel->SetLabel( wxString::Format( _( "Viewports (%s+Tab):" ),
2992
2993 m_cbViewports->Clear();
2994
2995 for( std::pair<const wxString, VIEWPORT>& pair : m_viewports )
2996 m_cbViewports->Append( pair.first, static_cast<void*>( &pair.second ) );
2997
2998 m_cbViewports->Append( wxT( "---" ) );
2999 m_cbViewports->Append( _( "Save viewport..." ) );
3000 m_cbViewports->Append( _( "Delete viewport..." ) );
3001
3002 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 );
3003 m_lastSelectedViewport = nullptr;
3004}
3005
3006
3008{
3009 int idx = m_cbViewports->FindString( aName );
3010
3011 if( idx >= 0 && idx < (int)m_cbViewports->GetCount() - 3 /* separator */ )
3012 {
3013 m_cbViewports->SetSelection( idx );
3014 m_lastSelectedViewport = static_cast<VIEWPORT*>( m_cbViewports->GetClientData( idx ) );
3015 }
3016 else if( idx < 0 )
3017 {
3018 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 ); // separator
3019 m_lastSelectedViewport = nullptr;
3020 }
3021}
3022
3023
3024void APPEARANCE_CONTROLS::onViewportChanged( wxCommandEvent& aEvent )
3025{
3026 int count = m_cbViewports->GetCount();
3027 int index = m_cbViewports->GetSelection();
3028
3029 if( index >= 0 && index < count - 3 )
3030 {
3031 VIEWPORT* viewport = static_cast<VIEWPORT*>( m_cbViewports->GetClientData( index ) );
3032
3033 wxCHECK( viewport, /* void */ );
3034
3035 doApplyViewport( *viewport );
3036
3037 if( !viewport->name.IsEmpty() )
3038 {
3039 if( m_viewportMRU.Index( viewport->name ) != wxNOT_FOUND )
3040 m_viewportMRU.Remove( viewport->name );
3041
3042 m_viewportMRU.Insert( viewport->name, 0 );
3043 }
3044 }
3045 else if( index == count - 2 )
3046 {
3047 // Save current state to new preset
3048 wxString name;
3049
3050 wxTextEntryDialog dlg( wxGetTopLevelParent( this ), _( "Viewport name:" ), _( "Save Viewport" ), name );
3051
3052 if( dlg.ShowModal() != wxID_OK )
3053 {
3055 m_cbViewports->SetStringSelection( m_lastSelectedViewport->name );
3056 else
3057 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 );
3058
3059 return;
3060 }
3061
3062 name = dlg.GetValue();
3063 bool exists = m_viewports.count( name );
3064
3065 if( !exists )
3066 {
3067 m_viewports[name] = VIEWPORT( name, m_frame->GetCanvas()->GetView()->GetViewport() );
3068
3069 index = m_cbViewports->Insert( name, index-1, static_cast<void*>( &m_viewports[name] ) );
3070 }
3071 else
3072 {
3073 m_viewports[name].rect = m_frame->GetCanvas()->GetView()->GetViewport();
3074 index = m_cbViewports->FindString( name );
3075
3076 if( m_viewportMRU.Index( name ) != wxNOT_FOUND )
3077 m_viewportMRU.Remove( name );
3078 }
3079
3080 m_cbViewports->SetSelection( index );
3081 m_viewportMRU.Insert( name, 0 );
3082
3083 return;
3084 }
3085 else if( index == count - 1 )
3086 {
3087 // Delete an existing viewport
3088 wxArrayString headers;
3089 std::vector<wxArrayString> items;
3090
3091 headers.Add( _( "Viewports" ) );
3092
3093 for( std::pair<const wxString, VIEWPORT>& pair : m_viewports )
3094 {
3095 wxArrayString item;
3096 item.Add( pair.first );
3097 items.emplace_back( item );
3098 }
3099
3100 EDA_LIST_DIALOG dlg( m_frame, _( "Delete Viewport" ), headers, items );
3101 dlg.SetListLabel( _( "Select viewport:" ) );
3102
3103 if( dlg.ShowModal() == wxID_OK )
3104 {
3105 wxString viewportName = dlg.GetTextSelection();
3106 int idx = m_cbViewports->FindString( viewportName );
3107
3108 if( idx != wxNOT_FOUND )
3109 {
3110 m_viewports.erase( viewportName );
3111 m_cbViewports->Delete( idx );
3112 }
3113
3114 if( m_viewportMRU.Index( viewportName ) != wxNOT_FOUND )
3115 m_viewportMRU.Remove( viewportName );
3116 }
3117
3119 m_cbViewports->SetStringSelection( m_lastSelectedViewport->name );
3120 else
3121 m_cbViewports->SetSelection( m_cbViewports->GetCount() - 3 );
3122
3123 return;
3124 }
3125
3126 passOnFocus();
3127}
3128
3129
3131{
3132 m_frame->GetCanvas()->GetView()->SetViewport( aViewport.rect );
3133 m_frame->GetCanvas()->Refresh();
3134}
3135
3136
3137void APPEARANCE_CONTROLS::OnColorSwatchChanged( wxCommandEvent& aEvent )
3138{
3139 COLOR_SWATCH* swatch = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
3140 COLOR4D newColor = swatch->GetSwatchColor();
3141 int layer = swatch->GetId();
3142
3143 COLOR_SETTINGS* cs = m_frame->GetColorSettings();
3144
3145 cs->SetColor( layer, newColor );
3146 m_frame->GetSettingsManager()->SaveColorSettings( cs, "board" );
3147
3148 m_frame->GetCanvas()->UpdateColors();
3149
3150 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
3151 view->UpdateLayerColor( layer );
3152 view->UpdateLayerColor( GetNetnameLayer( layer ) );
3153
3154 if( IsCopperLayer( layer ) )
3155 {
3156 view->UpdateLayerColor( ZONE_LAYER_FOR( layer ) );
3157 view->UpdateLayerColor( VIA_COPPER_LAYER_FOR( layer ) );
3158 view->UpdateLayerColor( PAD_COPPER_LAYER_FOR( layer ) );
3159 view->UpdateLayerColor( CLEARANCE_LAYER_FOR( layer ) );
3160 }
3161
3162 // Update the bitmap of the layer box
3163 if( m_frame->IsType( FRAME_PCB_EDITOR ) )
3164 static_cast<PCB_EDIT_FRAME*>( m_frame )->ReCreateLayerBox( false );
3165
3166 m_frame->GetCanvas()->Refresh();
3167
3168 if( layer == LAYER_PCB_BACKGROUND )
3169 m_frame->SetDrawBgColor( newColor );
3170
3171 passOnFocus();
3172}
3173
3174
3175void APPEARANCE_CONTROLS::onObjectOpacitySlider( int aLayer, float aOpacity )
3176{
3177 PCB_DISPLAY_OPTIONS options = m_frame->GetDisplayOptions();
3178
3179 switch( aLayer )
3180 {
3181 case static_cast<int>( LAYER_TRACKS ): options.m_TrackOpacity = aOpacity; break;
3182 case static_cast<int>( LAYER_VIAS ): options.m_ViaOpacity = aOpacity; break;
3183 case static_cast<int>( LAYER_PADS ): options.m_PadOpacity = aOpacity; break;
3184 case static_cast<int>( LAYER_ZONES ): options.m_ZoneOpacity = aOpacity; break;
3185 case static_cast<int>( LAYER_DRAW_BITMAPS ): options.m_ImageOpacity = aOpacity; break;
3186 case static_cast<int>( LAYER_FILLED_SHAPES ): options.m_FilledShapeOpacity = aOpacity; break;
3187 default: return;
3188 }
3189
3190 m_frame->SetDisplayOptions( options );
3191 passOnFocus();
3192}
3193
3194
3195void APPEARANCE_CONTROLS::onNetContextMenu( wxCommandEvent& aEvent )
3196{
3197 wxASSERT( m_netsGrid->GetSelectedRows().size() == 1 );
3198
3199 int row = m_netsGrid->GetSelectedRows()[0];
3200 NET_GRID_ENTRY& net = m_netsTable->GetEntry( row );
3201
3202 m_netsGrid->ClearSelection();
3203
3204 switch( aEvent.GetId() )
3205 {
3206 case ID_SET_NET_COLOR:
3207 {
3208 wxGridCellEditor* editor = m_netsGrid->GetCellEditor( row, NET_GRID_TABLE::COL_COLOR );
3209 editor->BeginEdit( row, NET_GRID_TABLE::COL_COLOR, m_netsGrid );
3210 break;
3211 }
3212
3213 case ID_CLEAR_NET_COLOR:
3214 m_netsGrid->SetCellValue( row, NET_GRID_TABLE::COL_COLOR, wxS( "rgba(0,0,0,0)" ) );
3215 break;
3216
3217 case ID_HIGHLIGHT_NET:
3218 m_frame->GetToolManager()->RunAction( PCB_ACTIONS::highlightNet, net.code );
3219 m_frame->GetCanvas()->Refresh();
3220 break;
3221
3222 case ID_SELECT_NET:
3223 m_frame->GetToolManager()->RunAction( PCB_ACTIONS::selectNet, net.code );
3224 m_frame->GetCanvas()->Refresh();
3225 break;
3226
3227 case ID_DESELECT_NET:
3228 m_frame->GetToolManager()->RunAction( PCB_ACTIONS::deselectNet, net.code );
3229 m_frame->GetCanvas()->Refresh();
3230 break;
3231
3232 case ID_SHOW_ALL_NETS:
3233 m_netsTable->ShowAllNets();
3234 break;
3235
3236 case ID_HIDE_OTHER_NETS:
3237 m_netsTable->HideOtherNets( net );
3238 break;
3239
3240 default:
3241 break;
3242 }
3243
3244 passOnFocus();
3245}
3246
3247
3249{
3250 wxString className = netclassNameFromEvent( aEvent );
3251 bool show = aEvent.GetInt();
3252 showNetclass( className, show );
3253 passOnFocus();
3254}
3255
3256
3257void APPEARANCE_CONTROLS::showNetclass( const wxString& aClassName, bool aShow )
3258{
3260
3261 for( NETINFO_ITEM* net : m_frame->GetBoard()->GetNetInfo() )
3262 {
3263 if( net->GetNetClass()->ContainsNetclassWithName( aClassName ) )
3264 {
3265 m_frame->GetToolManager()->RunAction( aShow ? PCB_ACTIONS::showNetInRatsnest
3267 net->GetNetCode() );
3268
3269 int row = m_netsTable->GetRowByNetcode( net->GetNetCode() );
3270
3271 if( row >= 0 )
3272 m_netsTable->SetValueAsBool( row, NET_GRID_TABLE::COL_VISIBILITY, aShow );
3273 }
3274 }
3275
3276 PROJECT_LOCAL_SETTINGS& localSettings = m_frame->Prj().GetLocalSettings();
3277
3278 if( !aShow )
3279 localSettings.m_HiddenNetclasses.insert( aClassName );
3280 else
3281 localSettings.m_HiddenNetclasses.erase( aClassName );
3282
3283 m_netsGrid->ForceRefresh();
3284 m_frame->GetCanvas()->RedrawRatsnest();
3285 m_frame->GetCanvas()->Refresh();
3287}
3288
3289
3291{
3292 COLOR_SWATCH* swatch = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
3293 wxString netclassName = netclassNameFromEvent( aEvent );
3294
3295 BOARD* board = m_frame->GetBoard();
3296 std::shared_ptr<NET_SETTINGS>& netSettings = board->GetDesignSettings().m_NetSettings;
3297 std::shared_ptr<NETCLASS> nc = netSettings->GetNetClassByName( netclassName );
3298
3299 nc->SetPcbColor( swatch->GetSwatchColor() );
3300 netSettings->RecomputeEffectiveNetclasses();
3301
3302 m_frame->GetCanvas()->GetView()->UpdateAllLayersColor();
3303 m_frame->GetCanvas()->RedrawRatsnest();
3304 m_frame->GetCanvas()->Refresh();
3305}
3306
3307
3309{
3310 COLOR_SWATCH* s = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
3311 int classId = s->GetId();
3312
3313 wxASSERT( m_netclassIdMap.count( classId ) );
3314 return m_netclassIdMap.at( classId );
3315}
3316
3317
3318void APPEARANCE_CONTROLS::onNetColorMode( wxCommandEvent& aEvent )
3319{
3320 PCB_DISPLAY_OPTIONS options = m_frame->GetDisplayOptions();
3321
3322 if( m_rbNetColorAll->GetValue() )
3324 else if( m_rbNetColorRatsnest->GetValue() )
3326 else
3328
3329 m_frame->SetDisplayOptions( options );
3330 m_frame->GetCanvas()->GetView()->UpdateAllLayersColor();
3331 passOnFocus();
3332}
3333
3334
3335void APPEARANCE_CONTROLS::onRatsnestMode( wxCommandEvent& aEvent )
3336{
3337 if( PCBNEW_SETTINGS* cfg = m_frame->GetPcbNewSettings() )
3338 {
3339 if( m_rbRatsnestAllLayers->GetValue() )
3340 {
3341 cfg->m_Display.m_ShowGlobalRatsnest = true;
3342 cfg->m_Display.m_RatsnestMode = RATSNEST_MODE::ALL;
3343 }
3344 else if( m_rbRatsnestVisLayers->GetValue() )
3345 {
3346 cfg->m_Display.m_ShowGlobalRatsnest = true;
3347 cfg->m_Display.m_RatsnestMode = RATSNEST_MODE::VISIBLE;
3348 }
3349 else
3350 {
3351 cfg->m_Display.m_ShowGlobalRatsnest = false;
3352 }
3353 }
3354
3355 if( PCB_EDIT_FRAME* editframe = dynamic_cast<PCB_EDIT_FRAME*>( m_frame ) )
3356 {
3357 if( PCBNEW_SETTINGS* cfg = m_frame->GetPcbNewSettings() )
3358 editframe->SetElementVisibility( LAYER_RATSNEST, cfg->m_Display.m_ShowGlobalRatsnest );
3359
3360 editframe->OnDisplayOptionsChanged();
3361 editframe->GetCanvas()->RedrawRatsnest();
3362 editframe->GetCanvas()->Refresh();
3363 }
3364
3365 passOnFocus();
3366}
3367
3368
3370{
3371 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
3373 static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
3374
3375 BOARD* board = m_frame->GetBoard();
3376 std::shared_ptr<NET_SETTINGS>& netSettings = board->GetDesignSettings().m_NetSettings;
3377 APPEARANCE_SETTING* setting = nullptr;
3378
3380
3381 if( it != m_netclassSettingsMap.end() )
3382 setting = it->second;
3383
3384 auto runOnNetsOfClass =
3385 [&]( const wxString& netClassName, std::function<void( NETINFO_ITEM* )> aFunction )
3386 {
3387 for( NETINFO_ITEM* net : board->GetNetInfo() )
3388 {
3389 if( net->GetNetClass()->ContainsNetclassWithName( netClassName ) )
3390 aFunction( net );
3391 }
3392 };
3393
3394 switch( aEvent.GetId() )
3395 {
3396 case ID_SET_NET_COLOR:
3397 {
3398 if( setting )
3399 {
3400 setting->ctl_color->GetNewSwatchColor();
3401
3402 COLOR4D color = setting->ctl_color->GetSwatchColor();
3403
3404 if( color != COLOR4D::UNSPECIFIED )
3405 {
3406 netSettings->GetNetClassByName( m_contextMenuNetclass )->SetPcbColor( color );
3407 netSettings->RecomputeEffectiveNetclasses();
3408 }
3409
3410 view->UpdateAllLayersColor();
3411 }
3412
3413 break;
3414 }
3415
3416 case ID_CLEAR_NET_COLOR:
3417 {
3418 if( setting )
3419 {
3420 setting->ctl_color->SetSwatchColor( COLOR4D( 0, 0, 0, 0 ), true );
3421
3422 netSettings->GetNetClassByName( m_contextMenuNetclass )->SetPcbColor( COLOR4D::UNSPECIFIED );
3423 netSettings->RecomputeEffectiveNetclasses();
3424
3425 view->UpdateAllLayersColor();
3426 }
3427
3428 break;
3429 }
3430
3432 {
3433 if( setting )
3434 {
3435 std::shared_ptr<NETCLASS> nc = netSettings->GetNetClassByName( m_contextMenuNetclass );
3436 const KIGFX::COLOR4D ncColor = nc->GetSchematicColor();
3437
3438 setting->ctl_color->SetSwatchColor( ncColor, true );
3439
3440 netSettings->GetNetClassByName( m_contextMenuNetclass )->SetPcbColor( ncColor );
3441 netSettings->RecomputeEffectiveNetclasses();
3442
3443 view->UpdateAllLayersColor();
3444 }
3445
3446 break;
3447 }
3448
3449 case ID_HIGHLIGHT_NET:
3450 {
3451 if( !m_contextMenuNetclass.IsEmpty() )
3452 {
3453 runOnNetsOfClass( m_contextMenuNetclass,
3454 [&]( NETINFO_ITEM* aItem )
3455 {
3456 static bool first = true;
3457 int code = aItem->GetNetCode();
3458
3459 if( first )
3460 {
3461 board->SetHighLightNet( code );
3462 rs->SetHighlight( true, code );
3463 first = false;
3464 }
3465 else
3466 {
3467 board->SetHighLightNet( code, true );
3468 rs->SetHighlight( true, code, true );
3469 }
3470 } );
3471
3472 view->UpdateAllLayersColor();
3473 board->HighLightON();
3474 }
3475
3476 break;
3477 }
3478
3479 case ID_SELECT_NET:
3480 case ID_DESELECT_NET:
3481 {
3482 if( !m_contextMenuNetclass.IsEmpty() )
3483 {
3484 TOOL_MANAGER* toolMgr = m_frame->GetToolManager();
3485 TOOL_ACTION& action = aEvent.GetId() == ID_SELECT_NET ? PCB_ACTIONS::selectNet
3487
3488 runOnNetsOfClass( m_contextMenuNetclass,
3489 [&]( NETINFO_ITEM* aItem )
3490 {
3491 toolMgr->RunAction( action, aItem->GetNetCode() );
3492 } );
3493 }
3494 break;
3495 }
3496
3497
3498 case ID_SHOW_ALL_NETS:
3499 {
3501 wxASSERT( m_netclassSettingsMap.count( NETCLASS::Default ) );
3502 m_netclassSettingsMap.at( NETCLASS::Default )->ctl_visibility->SetValue( true );
3503
3504 for( const auto& [name, netclass] : netSettings->GetNetclasses() )
3505 {
3506 showNetclass( name );
3507
3508 if( m_netclassSettingsMap.count( name ) )
3509 m_netclassSettingsMap.at( name )->ctl_visibility->SetValue( true );
3510 }
3511
3512 break;
3513 }
3514
3515 case ID_HIDE_OTHER_NETS:
3516 {
3517 bool showDefault = m_contextMenuNetclass == NETCLASS::Default;
3518 showNetclass( NETCLASS::Default, showDefault );
3519 wxASSERT( m_netclassSettingsMap.count( NETCLASS::Default ) );
3520 m_netclassSettingsMap.at( NETCLASS::Default )->ctl_visibility->SetValue( showDefault );
3521
3522 for( const auto& [name, netclass] : netSettings->GetNetclasses() )
3523 {
3524 bool show = ( name == m_contextMenuNetclass );
3525
3526 showNetclass( name, show );
3527
3528 if( m_netclassSettingsMap.count( name ) )
3529 m_netclassSettingsMap.at( name )->ctl_visibility->SetValue( show );
3530 }
3531
3532 break;
3533 }
3534
3535 default:
3536 break;
3537 }
3538
3539 m_frame->GetCanvas()->RedrawRatsnest();
3540 m_frame->GetCanvas()->Refresh();
3541
3542 m_contextMenuNetclass.clear();
3543}
3544
3545
3547{
3548 m_focusOwner->SetFocus();
3549}
3550
3551
3553{
3554 WX_INFOBAR* infobar = m_frame->GetInfoBar();
3555
3556 wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY, _( "Open Preferences" ), wxEmptyString );
3557
3558 button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
3559 [&]( wxHyperlinkEvent& aEvent )
3560 {
3561 m_frame->ShowPreferences( wxEmptyString, wxEmptyString );
3562 } ) );
3563
3564 infobar->RemoveAllButtons();
3565 infobar->AddButton( button );
3566 infobar->AddCloseButton();
3567
3568 infobar->ShowMessageFor( _( "The current color theme is read-only. Create a new theme in Preferences to "
3569 "enable color editing." ),
3570 10000, wxICON_INFORMATION );
3571}
3572
3573
3578
3579
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:3281
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition board.cpp:729
PROJECT * GetProject() const
Definition board.h:579
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1083
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition board.cpp:968
void HighLightON(bool aValue=true)
Enable or disable net highlighting.
Definition board.cpp:3294
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:563
void UpdateAllLayersColor()
Apply the new coloring scheme to all layers.
Definition view.cpp:783
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:1469
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:762
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:1600
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