KiCad PCB EDA Suite
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 <jon@craftyjon.com>
5  * Copyright (C) 2021 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>
25 #include <board_design_settings.h>
26 #include <dialog_helpers.h>
27 #include <footprint_edit_frame.h>
28 #include <menus_helpers.h>
29 #include <pcb_display_options.h>
30 #include <pcb_edit_frame.h>
31 #include <pcb_painter.h>
32 #include <pcbnew_settings.h>
34 #include <tool/tool_manager.h>
35 #include <tools/pcb_actions.h>
36 #include <widgets/bitmap_button.h>
37 #include <widgets/bitmap_toggle.h>
39 #include <widgets/color_swatch.h>
43 #include <widgets/indicator_icon.h>
44 #include <widgets/infobar.h>
45 #include <widgets/wx_grid.h>
46 #include <wx/bmpbuttn.h>
47 #include <wx/checkbox.h>
48 #include <wx/hyperlink.h>
49 #include <wx/radiobut.h>
50 #include <wx/sizer.h>
51 #include <wx/slider.h>
52 #include <wx/statline.h>
53 #include <wx/textdlg.h>
54 
55 
56 NET_GRID_TABLE::NET_GRID_TABLE( PCB_BASE_FRAME* aFrame, wxColor aBackgroundColor ) :
57  wxGridTableBase(),
58  m_frame( aFrame )
59 {
60  m_defaultAttr = new wxGridCellAttr;
61  m_defaultAttr->SetBackgroundColour( aBackgroundColor );
62 
63  m_labelAttr = new wxGridCellAttr;
64  m_labelAttr->SetRenderer( new GRID_CELL_ESCAPED_TEXT_RENDERER );
65  m_labelAttr->SetBackgroundColour( aBackgroundColor );
66 }
67 
68 
70 {
71  m_defaultAttr->DecRef();
72  m_labelAttr->DecRef();
73 }
74 
75 
76 wxGridCellAttr* NET_GRID_TABLE::GetAttr( int aRow, int aCol, wxGridCellAttr::wxAttrKind )
77 {
78  switch( aCol )
79  {
80  case COL_COLOR:
81  m_defaultAttr->IncRef();
82  return m_defaultAttr;
83 
84  case COL_VISIBILITY:
85  m_defaultAttr->IncRef();
86  return m_defaultAttr;
87 
88  case COL_LABEL:
89  m_labelAttr->IncRef();
90  return m_labelAttr;
91 
92  default:
93  wxFAIL;
94  return nullptr;
95  }
96 }
97 
98 
99 wxString NET_GRID_TABLE::GetValue( int aRow, int aCol )
100 {
101  wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
102 
103  switch( aCol )
104  {
105  case COL_COLOR:
106  return m_nets[aRow].color.ToWxString( wxC2S_CSS_SYNTAX );
107 
108  case COL_VISIBILITY:
109  return m_nets[aRow].visible ? "1" : "0";
110 
111  case COL_LABEL:
112  return m_nets[aRow].name;
113 
114  default:
115  return wxEmptyString;
116  }
117 }
118 
119 
120 void NET_GRID_TABLE::SetValue( int aRow, int aCol, const wxString& aValue )
121 {
122  wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
123 
124  NET_GRID_ENTRY& net = m_nets[aRow];
125 
126  switch( aCol )
127  {
128  case COL_COLOR:
129  net.color.SetFromWxString( aValue );
130  updateNetColor( net );
131  break;
132 
133  case COL_VISIBILITY:
134  net.visible = ( aValue != "0" );
135  updateNetVisibility( net );
136  break;
137 
138  case COL_LABEL:
139  net.name = aValue;
140  break;
141 
142  default:
143  break;
144  }
145 }
146 
147 
148 wxString NET_GRID_TABLE::GetTypeName( int aRow, int aCol )
149 {
150  switch( aCol )
151  {
152  case COL_COLOR:
153  return wxT( "COLOR4D" );
154 
155  case COL_VISIBILITY:
156  return wxGRID_VALUE_BOOL;
157 
158  case COL_LABEL:
159  default:
160  return wxGRID_VALUE_STRING;
161  }
162 }
163 
164 
165 bool NET_GRID_TABLE::GetValueAsBool( int aRow, int aCol )
166 {
167  wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
168  wxASSERT( aCol == COL_VISIBILITY );
169 
170  return m_nets[aRow].visible;
171 }
172 
173 
174 void NET_GRID_TABLE::SetValueAsBool( int aRow, int aCol, bool aValue )
175 {
176  wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
177  wxASSERT( aCol == COL_VISIBILITY );
178 
179  m_nets[aRow].visible = aValue;
180  updateNetVisibility( m_nets[aRow] );
181 }
182 
183 
184 void* NET_GRID_TABLE::GetValueAsCustom( int aRow, int aCol, const wxString& aTypeName )
185 {
186  wxASSERT( aCol == COL_COLOR );
187  wxASSERT( aTypeName == wxT( "COLOR4D" ) );
188  wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
189 
190  return ColorToVoid( m_nets[aRow].color );
191 }
192 
193 
194 void NET_GRID_TABLE::SetValueAsCustom( int aRow, int aCol, const wxString& aTypeName, void* aValue )
195 {
196  wxASSERT( aCol == COL_COLOR );
197  wxASSERT( aTypeName == wxT( "COLOR4D" ) );
198  wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
199 
200  m_nets[aRow].color = VoidToColor( aValue );
201  updateNetColor( m_nets[aRow] );
202 
203  if( GetView() )
204  {
205  wxGridTableMessage msg( this, wxGRIDTABLE_REQUEST_VIEW_GET_VALUES );
206  GetView()->ProcessTableMessage( msg );
207  }
208 }
209 
210 
212 {
213  wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
214  return m_nets[aRow];
215 }
216 
217 
218 int NET_GRID_TABLE::GetRowByNetcode( int aCode ) const
219 {
220  auto it = std::find_if( m_nets.cbegin(), m_nets.cend(),
221  [aCode]( const NET_GRID_ENTRY& aEntry )
222  {
223  return aEntry.code == aCode;
224  } );
225 
226  if( it == m_nets.cend() )
227  return -1;
228 
229  return std::distance( m_nets.cbegin(), it );
230 }
231 
232 
234 {
235  BOARD* board = m_frame->GetBoard();
236  const NETNAMES_MAP& nets = board->GetNetInfo().NetsByName();
237 
238  KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>(
240 
241  std::set<int>& hiddenNets = rs->GetHiddenNets();
242  std::map<int, KIGFX::COLOR4D>& netColors = rs->GetNetColorMap();
243 
244  int deleted = m_nets.size();
245  m_nets.clear();
246 
247  if( GetView() )
248  {
249  wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, 0, deleted );
250  GetView()->ProcessTableMessage( msg );
251  }
252 
253  for( const std::pair<const wxString, NETINFO_ITEM*>& pair : nets )
254  {
255  int netCode = pair.second->GetNetCode();
256 
257  if( netCode > 0 && !pair.first.StartsWith( "unconnected-(" ) )
258  {
259  COLOR4D color = netColors.count( netCode ) ? netColors.at( netCode ) :
260  COLOR4D::UNSPECIFIED;
261 
262  bool visible = hiddenNets.count( netCode ) == 0;
263 
264  m_nets.emplace_back( NET_GRID_ENTRY( netCode, pair.first, color, visible ) );
265  }
266  }
267 
268  // TODO(JE) move to ::Compare so we can re-sort easily
269  std::sort( m_nets.begin(), m_nets.end(),
270  []( const NET_GRID_ENTRY& a, const NET_GRID_ENTRY& b )
271  {
272  return a.name < b.name;
273  } );
274 
275  if( GetView() )
276  {
277  wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_nets.size() );
278  GetView()->ProcessTableMessage( msg );
279  }
280 }
281 
282 
284 {
285  for( NET_GRID_ENTRY& net : m_nets )
286  {
287  net.visible = true;
288  updateNetVisibility( net );
289  }
290 
291  if( GetView() )
292  GetView()->ForceRefresh();
293 }
294 
295 
297 {
298  for( NET_GRID_ENTRY& net : m_nets )
299  {
300  net.visible = ( net.code == aNet.code );
301  updateNetVisibility( net );
302  }
303 
304  if( GetView() )
305  GetView()->ForceRefresh();
306 }
307 
308 
310 {
312  m_frame->GetToolManager()->RunAction( action, true, static_cast<intptr_t>( aNet.code ) );
313 }
314 
315 
317 {
318  KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>(
320 
321  std::map<int, KIGFX::COLOR4D>& netColors = rs->GetNetColorMap();
322 
323  if( aNet.color != COLOR4D::UNSPECIFIED )
324  netColors[aNet.code] = aNet.color;
325  else
326  netColors.erase( aNet.code );
327 
330  m_frame->GetCanvas()->Refresh();
331 }
332 
333 
336 
337 #define RR APPEARANCE_CONTROLS::APPEARANCE_SETTING // Render Row abbreviation to reduce source width
338 
339  // text id tooltip opacity slider
340  RR( _( "Tracks" ), LAYER_TRACKS, _( "Show tracks" ), true ),
341  RR( _( "Vias" ), LAYER_VIAS, _( "Show all vias" ), true ),
342  RR( _( "Pads" ), LAYER_PADS, _( "Show all pads" ), true ),
343  RR( _( "Zones" ), LAYER_ZONES, _( "Show copper zones" ), true ),
344  RR(),
345  RR( _( "Footprints Front" ), LAYER_MOD_FR, _( "Show footprints that are on board's front" ) ),
346  RR( _( "Footprints Back" ), LAYER_MOD_BK, _( "Show footprints that are on board's back" ) ),
347  RR( _( "Through-hole Pads" ),LAYER_PADS_TH, _( "Show through-hole pads" ) ),
348  RR( _( "Values" ), LAYER_MOD_VALUES, _( "Show footprint values" ) ),
349  RR( _( "References" ), LAYER_MOD_REFERENCES, _( "Show footprint references" ) ),
350  RR( _( "Footprint Text" ), LAYER_MOD_TEXT_FR, _( "Show all footprint text" ) ),
351  RR( _( "Hidden Text" ), LAYER_MOD_TEXT_INVISIBLE, _( "Show footprint text marked as invisible" ) ),
352  RR(),
353  RR(),
354  RR( _( "Ratsnest" ), LAYER_RATSNEST, _( "Show unconnected nets as a ratsnest") ),
355  RR( _( "No-Connects" ), LAYER_NO_CONNECTS, _( "Show a marker on pads which have no net connected" ) ),
356  RR( _( "DRC Warnings" ), LAYER_DRC_WARNING, _( "DRC violations with a Warning severity" ) ),
357  RR( _( "DRC Errors" ), LAYER_DRC_ERROR, _( "DRC violations with an Error severity" ) ),
358  RR( _( "DRC Exclusions" ), LAYER_DRC_EXCLUSION, _( "DRC violations which have been individually excluded" ) ),
359  RR( _( "Anchors" ), LAYER_ANCHOR, _( "Show footprint and text origins as a cross" ) ),
360  RR( _( "Drawing Sheet" ), LAYER_DRAWINGSHEET, _( "Show drawing sheet borders and title block" ) ),
361  RR( _( "Grid" ), LAYER_GRID, _( "Show the (x,y) grid dots" ) )
362 };
363 
365 static std::set<int> s_allowedInFpEditor =
366  {
367  LAYER_TRACKS,
368  LAYER_VIAS,
369  LAYER_PADS,
370  LAYER_ZONES,
375  LAYER_GRID
376  };
377 
378 // These are the built-in layer presets that cannot be deleted
379 
381 
383 
384 LAYER_PRESET APPEARANCE_CONTROLS::presetAllCopper( _( "All Copper Layers" ),
385  LSET::AllCuMask().set( Edge_Cuts ) );
386 
387 LAYER_PRESET APPEARANCE_CONTROLS::presetInnerCopper( _( "Inner Copper Layers" ),
388  LSET::InternalCuMask().set( Edge_Cuts ) );
389 
391  LSET::FrontMask().set( Edge_Cuts ) );
392 
395 
397  LSET::BackMask().set( Edge_Cuts ) );
398 
401 
402 
404  bool aFpEditorMode ) :
405  APPEARANCE_CONTROLS_BASE( aParent ),
406  m_frame( aParent ),
407  m_focusOwner( aFocusOwner ),
408  m_board( nullptr ),
409  m_isFpEditor( aFpEditorMode ),
410  m_currentPreset( nullptr ),
411  m_lastSelectedUserPreset( nullptr ),
412  m_layerContextMenu( nullptr )
413 {
414  int indicatorSize = ConvertDialogToPixels( wxSize( 6, 6 ) ).x;
415  m_iconProvider = new ROW_ICON_PROVIDER( indicatorSize );
416  int pointSize = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ).GetPointSize();
417  int screenHeight = wxSystemSettings::GetMetric( wxSYS_SCREEN_Y );
418 
419  m_layerPanelColour = m_panelLayers->GetBackgroundColour().ChangeLightness( 110 );
420 
421  m_layersOuterSizer = new wxBoxSizer( wxVERTICAL );
422  m_windowLayers->SetSizer( m_layersOuterSizer );
423  m_windowLayers->SetScrollRate( 0, 5 );
424  m_windowLayers->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS::OnSetFocus, this );
425 
426  m_objectsOuterSizer = new wxBoxSizer( wxVERTICAL );
428  m_windowObjects->SetScrollRate( 0, 5 );
429  m_windowObjects->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS::OnSetFocus, this );
430 
431  createControls();
432 
435 
438 
439  m_txtNetFilter->SetHint( _( "Filter nets" ) );
440 
441  if( screenHeight <= 900 && pointSize >= indicatorSize )
442  pointSize = pointSize * 8 / 10;
443 
444  m_pointSize = pointSize;
445  wxFont font = m_notebook->GetFont();
446 
447 #ifdef __WXMAC__
448  font.SetPointSize( m_pointSize );
449  m_notebook->SetFont( font );
450 #endif
451 
452  auto setHighContrastMode =
453  [&]( HIGH_CONTRAST_MODE aMode )
454  {
456  opts.m_ContrastModeDisplay = aMode;
457 
458  m_frame->SetDisplayOptions( opts );
459  passOnFocus();
460  };
461 
462  m_rbHighContrastNormal->Bind( wxEVT_RADIOBUTTON,
463  [=]( wxCommandEvent& aEvent )
464  {
465  setHighContrastMode( HIGH_CONTRAST_MODE::NORMAL );
466  } );
467 
468  m_rbHighContrastDim->Bind( wxEVT_RADIOBUTTON,
469  [=]( wxCommandEvent& aEvent )
470  {
471  setHighContrastMode( HIGH_CONTRAST_MODE::DIMMED );
472  } );
473 
474  m_rbHighContrastOff->Bind( wxEVT_RADIOBUTTON,
475  [=]( wxCommandEvent& aEvent )
476  {
477  setHighContrastMode( HIGH_CONTRAST_MODE::HIDDEN );
478  } );
479 
480  m_cbLayerPresets->Bind( wxEVT_CHOICE, &APPEARANCE_CONTROLS::onLayerPresetChanged, this );
481 
482  m_btnNetInspector->Bind( wxEVT_BUTTON,
483  [&]( wxCommandEvent& aEvent )
484  {
486  passOnFocus();
487  } );
488 
489  m_btnConfigureNetClasses->Bind( wxEVT_BUTTON,
490  [&]( wxCommandEvent& aEvent )
491  {
492  // This panel should only be visible in the PCB_EDIT_FRAME anyway
493  if( PCB_EDIT_FRAME* editframe = dynamic_cast<PCB_EDIT_FRAME*>( m_frame ) )
494  editframe->ShowBoardSetupDialog( _( "Net Classes" ) );
495 
496  passOnFocus();
497  } );
498 
499  m_cbFlipBoard->SetValue( m_frame->GetCanvas()->GetView()->IsMirroredX() );
500  m_cbFlipBoard->Bind( wxEVT_CHECKBOX,
501  [&]( wxCommandEvent& aEvent )
502  {
504  } );
505 
508 
509  m_netsGrid->RegisterDataType( wxT( "bool" ), m_toggleGridRenderer, new wxGridCellBoolEditor );
510 
511  // TODO(JE) Update background color of swatch renderer when theme changes
512  m_netsGrid->RegisterDataType( wxT( "COLOR4D" ),
515 
516  m_netsTable = new NET_GRID_TABLE( m_frame, m_panelNets->GetBackgroundColour() );
517  m_netsGrid->SetTable( m_netsTable, true );
519 
520  m_netsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
521  m_netsGrid->SetSelectionForeground( m_netsGrid->GetDefaultCellTextColour() );
522  m_netsGrid->SetSelectionBackground( m_panelNets->GetBackgroundColour() );
523 
524  const int cellPadding = 6;
525 #ifdef __WXMAC__
526  const int rowHeightPadding = 5;
527 #else
528  const int rowHeightPadding = 3;
529 #endif
530 
531  wxSize size = ConvertDialogToPixels( SWATCH_SIZE_SMALL_DU );
532  m_netsGrid->SetColSize( NET_GRID_TABLE::COL_COLOR, size.x + cellPadding );
533 
534  size = KiBitmap( BITMAPS::visibility ).GetSize();
535  m_netsGrid->SetColSize( NET_GRID_TABLE::COL_VISIBILITY, size.x + cellPadding );
536 
537  m_netsGrid->SetDefaultCellFont( font );
538  m_netsGrid->SetDefaultRowSize( font.GetPixelSize().y + rowHeightPadding );
539 
540  m_netsGrid->GetGridWindow()->Bind( wxEVT_MOTION,
542 
543  // To handle middle click on color swatches
544  m_netsGrid->GetGridWindow()->Bind( wxEVT_MIDDLE_UP,
546 
547  m_netsGrid->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_DEFAULT );
548  m_netclassScrolledWindow->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_DEFAULT );
549 
550  if( m_isFpEditor )
551  m_notebook->RemovePage( 2 );
552 
554  rebuildObjects();
555  OnBoardChanged();
556 
557  // Grid visibility is loaded and set to the GAL before we are constructed
559 
560  Bind( wxEVT_COMMAND_MENU_SELECTED, &APPEARANCE_CONTROLS::OnLayerContextMenu, this,
562 }
563 
564 
566 {
567  delete m_iconProvider;
568 }
569 
570 
572 {
573  // Create layer display options
575  _( "Layer Display Options" ) );
577  m_paneLayerDisplayOptions->SetBackgroundColour( m_notebook->GetThemeBackgroundColour() );
578 
579  wxWindow* layerDisplayPane = m_paneLayerDisplayOptions->GetPane();
580 
581  wxBoxSizer* layerDisplayOptionsSizer;
582  layerDisplayOptionsSizer = new wxBoxSizer( wxVERTICAL );
583 
584  m_staticTextContrastModeTitle = new wxStaticText( layerDisplayPane, wxID_ANY,
585  _( "Inactive layers:" ), wxDefaultPosition,
586  wxDefaultSize, 0 );
587  m_staticTextContrastModeTitle->Wrap( -1 );
588  layerDisplayOptionsSizer->Add( m_staticTextContrastModeTitle, 0,
589  wxEXPAND | wxBOTTOM | wxLEFT, 2 );
590 
591  wxBoxSizer* contrastModeSizer;
592  contrastModeSizer = new wxBoxSizer( wxHORIZONTAL );
593 
594  m_rbHighContrastNormal = new wxRadioButton( layerDisplayPane, wxID_ANY, _( "Normal" ),
595  wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
596  m_rbHighContrastNormal->SetValue( true );
597  m_rbHighContrastNormal->SetToolTip( _( "Inactive layers will be shown in full color" ) );
598 
599  contrastModeSizer->Add( m_rbHighContrastNormal, 0, wxRIGHT, 4 );
600 
601  m_rbHighContrastDim = new wxRadioButton( layerDisplayPane, wxID_ANY, _( "Dim" ),
602  wxDefaultPosition, wxDefaultSize, 0 );
603  m_rbHighContrastDim->SetToolTip( _( "Inactive layers will be dimmed" ) );
604 
605  contrastModeSizer->Add( m_rbHighContrastDim, 0, wxRIGHT | wxLEFT, 10 );
606 
607  m_rbHighContrastOff = new wxRadioButton( layerDisplayPane, wxID_ANY, _( "Hide" ),
608  wxDefaultPosition, wxDefaultSize, 0 );
609  m_rbHighContrastOff->SetToolTip( _( "Inactive layers will be hidden" ) );
610 
611  contrastModeSizer->Add( m_rbHighContrastOff, 0, 0, 5 );
612 
613  layerDisplayOptionsSizer->Add( contrastModeSizer, 0, wxEXPAND, 5 );
614 
615  m_layerDisplaySeparator = new wxStaticLine( layerDisplayPane, wxID_ANY, wxDefaultPosition,
616  wxDefaultSize, wxLI_HORIZONTAL );
617  layerDisplayOptionsSizer->Add( m_layerDisplaySeparator, 0, wxEXPAND | wxTOP | wxBOTTOM, 5 );
618 
619  m_cbFlipBoard = new wxCheckBox( layerDisplayPane, wxID_ANY, _( "Flip board view" ),
620  wxDefaultPosition, wxDefaultSize, 0 );
621  layerDisplayOptionsSizer->Add( m_cbFlipBoard, 0, 0, 5 );
622 
623  layerDisplayPane->SetSizer( layerDisplayOptionsSizer );
624  layerDisplayPane->Layout();
625  layerDisplayOptionsSizer->Fit( layerDisplayPane );
626 
627  m_panelLayersSizer->Add( m_paneLayerDisplayOptions, 0, wxEXPAND | wxTOP, 5 );
628 
629  m_paneLayerDisplayOptions->Bind( WX_COLLAPSIBLE_PANE_CHANGED,
630  [&]( wxCommandEvent& aEvent )
631  {
632  Freeze();
633  m_panelLayers->Fit();
634  m_sizerOuter->Layout();
635  Thaw();
636  } );
637 
638  // Create net display options
639 
641  _( "Net Display Options" ) );
643  m_paneNetDisplayOptions->SetBackgroundColour( m_notebook->GetThemeBackgroundColour() );
644 
645  wxWindow* netDisplayPane = m_paneNetDisplayOptions->GetPane();
646  wxBoxSizer* netDisplayOptionsSizer = new wxBoxSizer( wxVERTICAL );
647 
649 
650  m_txtNetDisplayTitle = new wxStaticText( netDisplayPane, wxID_ANY, _( "Net colors:" ),
651  wxDefaultPosition, wxDefaultSize, 0 );
652  m_txtNetDisplayTitle->Wrap( -1 );
653  m_txtNetDisplayTitle->SetToolTip( _( "Choose when to show net and netclass colors" ) );
654 
655  netDisplayOptionsSizer->Add( m_txtNetDisplayTitle, 0, wxEXPAND | wxBOTTOM | wxLEFT, 2 );
656 
657  wxBoxSizer* netColorSizer = new wxBoxSizer( wxHORIZONTAL );
658 
659  m_rbNetColorAll = new wxRadioButton( netDisplayPane, wxID_ANY, _( "All" ), wxDefaultPosition,
660  wxDefaultSize, wxRB_GROUP );
661  m_rbNetColorAll->SetToolTip( _( "Net and netclass colors are shown on all copper items" ) );
662 
663  netColorSizer->Add( m_rbNetColorAll, 0, wxRIGHT, 10 );
664 
665  m_rbNetColorRatsnest = new wxRadioButton( netDisplayPane, wxID_ANY, _( "Ratsnest" ),
666  wxDefaultPosition, wxDefaultSize, 0 );
667  m_rbNetColorRatsnest->SetValue( true );
668  m_rbNetColorRatsnest->SetToolTip( _( "Net and netclass colors are shown on the ratsnest only" ) );
669 
670  netColorSizer->Add( m_rbNetColorRatsnest, 0, wxRIGHT, 4 );
671 
672  m_rbNetColorOff = new wxRadioButton( netDisplayPane, wxID_ANY, _( "None" ), wxDefaultPosition,
673  wxDefaultSize, 0 );
674  m_rbNetColorOff->SetToolTip( _( "Net and netclass colors are not shown" ) );
675 
676  netColorSizer->Add( m_rbNetColorOff, 0, 0, 5 );
677 
678  netDisplayOptionsSizer->Add( netColorSizer, 0, wxEXPAND | wxBOTTOM, 5 );
679 
681 
682  m_txtRatsnestVisibility = new wxStaticText( netDisplayPane, wxID_ANY, _( "Ratsnest display:" ),
683  wxDefaultPosition, wxDefaultSize, 0 );
684  m_txtRatsnestVisibility->Wrap( -1 );
685  m_txtRatsnestVisibility->SetToolTip( _( "Choose what ratsnest lines to display" ) );
686 
687  netDisplayOptionsSizer->Add( m_txtRatsnestVisibility, 0, wxEXPAND | wxBOTTOM | wxLEFT, 2 );
688 
689  wxBoxSizer* ratsnestDisplayModeSizer = new wxBoxSizer( wxHORIZONTAL );
690 
691  m_rbRatsnestAllLayers = new wxRadioButton( netDisplayPane, wxID_ANY, _( "All layers" ),
692  wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
693  m_rbRatsnestAllLayers->SetToolTip( _( "Ratsnest lines are shown to items on all layers" ) );
694  m_rbRatsnestAllLayers->SetValue( true );
695 
696  ratsnestDisplayModeSizer->Add( m_rbRatsnestAllLayers, 0, wxRIGHT, 10 );
697 
698  m_rbRatsnestVisibleLayers = new wxRadioButton( netDisplayPane, wxID_ANY, _( "Visible layers" ),
699  wxDefaultPosition, wxDefaultSize, 0 );
700  m_rbRatsnestVisibleLayers->SetToolTip( _( "Ratsnest lines are shown to items on visible layers" ) );
701 
702  ratsnestDisplayModeSizer->Add( m_rbRatsnestVisibleLayers, 0, wxRIGHT, 4 );
703 
704  netDisplayOptionsSizer->Add( ratsnestDisplayModeSizer, 0, wxEXPAND | wxBOTTOM, 5 );
705 
707 
708  netDisplayPane->SetSizer( netDisplayOptionsSizer );
709  netDisplayPane->Layout();
710  netDisplayOptionsSizer->Fit( netDisplayPane );
711 
712  m_netsTabOuterSizer->Add( m_paneNetDisplayOptions, 0, wxEXPAND | wxTOP, 5 );
713 
714  m_paneNetDisplayOptions->Bind( WX_COLLAPSIBLE_PANE_CHANGED,
715  [&]( wxCommandEvent& aEvent )
716  {
717  Freeze();
718  m_panelNetsAndClasses->Fit();
719  m_sizerOuter->Layout();
720  passOnFocus();
721  Thaw();
722  } );
723 
724  m_rbNetColorAll->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onNetColorModeChanged, this );
725  m_rbNetColorOff->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onNetColorModeChanged, this );
726  m_rbNetColorRatsnest->Bind( wxEVT_RADIOBUTTON,
728 
729  m_rbRatsnestAllLayers->Bind( wxEVT_RADIOBUTTON,
731  m_rbRatsnestVisibleLayers->Bind( wxEVT_RADIOBUTTON,
733 }
734 
735 
737 {
738  wxSize size( 220, 480 );
739  // TODO(JE) appropriate logic
740  return size;
741 }
742 
743 
744 void APPEARANCE_CONTROLS::OnNotebookPageChanged( wxNotebookEvent& aEvent )
745 {
746  // Work around wxMac issue where the notebook pages are blank
747 #ifdef __WXMAC__
748  int page = aEvent.GetSelection();
749 
750  if( page >= 0 )
751  m_notebook->ChangeSelection( static_cast<unsigned>( page ) );
752 #endif
753 
754 #ifndef __WXMSW__
755  // Because wxWidgets is broken and will send click events to children of the collapsible
756  // panes even if they are collapsed without this
757  Freeze();
758  m_panelLayers->Fit();
759  m_panelNetsAndClasses->Fit();
760  m_sizerOuter->Layout();
761  Thaw();
762 #endif
763 
764  Bind( wxEVT_IDLE, &APPEARANCE_CONTROLS::idleFocusHandler, this );
765 }
766 
767 
768 void APPEARANCE_CONTROLS::idleFocusHandler( wxIdleEvent& aEvent )
769 {
770  passOnFocus();
771  Unbind( wxEVT_IDLE, &APPEARANCE_CONTROLS::idleFocusHandler, this );
772 }
773 
774 
775 void APPEARANCE_CONTROLS::OnSetFocus( wxFocusEvent& aEvent )
776 {
777 #ifdef __WXMSW__
778  // In wxMSW, buttons won't process events unless they have focus, so we'll let it take the
779  // focus and give it back to the parent in the button event handler.
780  if( wxBitmapButton* btn = dynamic_cast<wxBitmapButton*>( aEvent.GetEventObject() ) )
781  {
782  wxCommandEvent evt( wxEVT_BUTTON );
783  wxPostEvent( btn, evt );
784  }
785 #endif
786 
787  passOnFocus();
788  aEvent.Skip();
789 }
790 
791 
792 void APPEARANCE_CONTROLS::OnSize( wxSizeEvent& aEvent )
793 {
794  aEvent.Skip();
795 }
796 
797 
798 void APPEARANCE_CONTROLS::OnNetGridClick( wxGridEvent& event )
799 {
800  int row = event.GetRow();
801  int col = event.GetCol();
802 
803  switch( col )
804  {
806  m_netsTable->SetValueAsBool( row, col, !m_netsTable->GetValueAsBool( row, col ) );
807  m_netsGrid->ForceRefresh();
808  break;
809 
810  default:
811  break;
812  }
813 }
814 
815 
817 {
818  int row = event.GetRow();
819  int col = event.GetCol();
820 
821  switch( col )
822  {
824  m_netsGrid->GetCellEditor( row, col )->BeginEdit( row, col, m_netsGrid );
825  break;
826 
827  default:
828  break;
829  }
830 }
831 
832 
834 {
835  m_netsGrid->SelectRow( event.GetRow() );
836 
837  wxString netName = m_netsGrid->GetCellValue( event.GetRow(), NET_GRID_TABLE::COL_LABEL );
838  wxMenu menu;
839 
840  menu.Append( new wxMenuItem( &menu, ID_SET_NET_COLOR,
841  _( "Set Net Color" ), wxEmptyString, wxITEM_NORMAL ) );
842  menu.Append( new wxMenuItem( &menu, ID_HIGHLIGHT_NET,
843  wxString::Format( _( "Highlight %s" ), netName ),
844  wxEmptyString, wxITEM_NORMAL ) );
845  menu.Append( new wxMenuItem( &menu, ID_SELECT_NET,
846  wxString::Format( _( "Select Tracks and Vias in %s" ), netName ),
847  wxEmptyString, wxITEM_NORMAL ) );
848  menu.Append( new wxMenuItem( &menu, ID_DESELECT_NET,
849  wxString::Format( _( "Unselect Tracks and Vias in %s" ), netName ),
850  wxEmptyString, wxITEM_NORMAL ) );
851 
852  menu.AppendSeparator();
853 
854  menu.Append( new wxMenuItem( &menu, ID_SHOW_ALL_NETS,
855  _( "Show All Nets" ), wxEmptyString, wxITEM_NORMAL ) );
856  menu.Append( new wxMenuItem( &menu, ID_HIDE_OTHER_NETS,
857  _( "Hide All Other Nets" ), wxEmptyString,
858  wxITEM_NORMAL ) );
859 
860  menu.Bind( wxEVT_COMMAND_MENU_SELECTED,
862 
863  PopupMenu( &menu );
864 }
865 
866 
867 void APPEARANCE_CONTROLS::OnNetGridMouseEvent( wxMouseEvent& aEvent )
868 {
869  wxPoint pos = m_netsGrid->CalcUnscrolledPosition( aEvent.GetPosition() );
870  wxGridCellCoords cell = m_netsGrid->XYToCell( pos );
871 
872  if( aEvent.Moving() || aEvent.Entering() )
873  {
874  aEvent.Skip();
875 
876  if( !cell )
877  {
878  m_netsGrid->GetGridWindow()->UnsetToolTip();
879  return;
880  }
881 
882  if( cell == m_hoveredCell )
883  return;
884 
885  m_hoveredCell = cell;
886 
887  NET_GRID_ENTRY& net = m_netsTable->GetEntry( cell.GetRow() );
888 
889  wxString name = net.name;
890  wxString showOrHide = net.visible ? _( "Click to hide ratsnest for %s" )
891  : _( "Click to show ratsnest for %s" );
892  wxString tip;
893 
894  if( cell.GetCol() == NET_GRID_TABLE::COL_VISIBILITY )
895  tip.Printf( showOrHide, name );
896  else if( cell.GetCol() == NET_GRID_TABLE::COL_COLOR )
897  tip = _( "Double click (or middle click) to change color; "
898  "right click for more actions" );
899 
900  m_netsGrid->GetGridWindow()->SetToolTip( tip );
901  }
902  else if( aEvent.Leaving() )
903  {
904  m_netsGrid->UnsetToolTip();
905  aEvent.Skip();
906  }
907  else if( aEvent.Dragging() )
908  {
909  // not allowed
910  CallAfter( [&]()
911  {
912  m_netsGrid->ClearSelection();
913  } );
914  }
915  else if( aEvent.ButtonUp( wxMOUSE_BTN_MIDDLE ) && !!cell )
916  {
917  int row = cell.GetRow();
918  int col = cell.GetCol();
919 
920  if(col == NET_GRID_TABLE::COL_COLOR )
921  m_netsGrid->GetCellEditor( row, col )->BeginEdit( row, col, m_netsGrid );
922 
923  aEvent.Skip();
924  }
925  else
926  {
927  aEvent.Skip();
928  }
929 }
930 
931 
933 {
934  Freeze();
935  rebuildLayers();
939  rebuildNets();
942 
944 
945  m_board = m_frame->GetBoard();
946 
947  if( m_board )
948  m_board->AddListener( this );
949 
950  Thaw();
951  Refresh();
952 }
953 
954 
956 {
958 }
959 
960 
961 void APPEARANCE_CONTROLS::OnNetVisibilityChanged( int aNetCode, bool aVisibility )
962 {
963  int row = m_netsTable->GetRowByNetcode( aNetCode );
964 
965  if( row >= 0 )
966  {
968  m_netsGrid->ForceRefresh();
969  }
970 }
971 
972 
974 {
975  return aBoardItem->Type() == PCB_NETINFO_T;
976 }
977 
978 
979 bool APPEARANCE_CONTROLS::doesBoardItemNeedRebuild( std::vector<BOARD_ITEM*>& aBoardItems )
980 {
981  bool rebuild = std::any_of( aBoardItems.begin(), aBoardItems.end(),
982  []( const BOARD_ITEM* a )
983  {
984  return a->Type() == PCB_NETINFO_T;
985  } );
986 
987 
988  return rebuild;
989 }
990 
991 
993 {
994  if( doesBoardItemNeedRebuild( aBoardItem ) )
996 }
997 
998 
999 void APPEARANCE_CONTROLS::OnBoardItemsAdded( BOARD& aBoard, std::vector<BOARD_ITEM*>& aBoardItems )
1000 {
1001  if( doesBoardItemNeedRebuild( aBoardItems ) )
1002  {
1004  }
1005 }
1006 
1007 
1009 {
1010  if( doesBoardItemNeedRebuild( aBoardItem ) )
1012 }
1013 
1014 
1016  BOARD& aBoard, std::vector<BOARD_ITEM*>& aBoardItems )
1017 {
1018  if( doesBoardItemNeedRebuild( aBoardItems ) )
1019  {
1021  }
1022 }
1023 
1024 
1026 {
1027  if( doesBoardItemNeedRebuild( aBoardItem ) )
1029 }
1030 
1031 
1033  BOARD& aBoard, std::vector<BOARD_ITEM*>& aBoardItems )
1034 {
1035  if( doesBoardItemNeedRebuild( aBoardItems ) )
1036  {
1038  }
1039 }
1040 
1041 
1043 {
1044  Freeze();
1045  rebuildNets();
1046  Thaw();
1047 }
1048 
1049 
1051 {
1054 }
1055 
1056 
1058 {
1059  for( const std::unique_ptr<APPEARANCE_SETTING>& setting : m_layerSettings )
1060  {
1061  setting->ctl_panel->SetBackgroundColour( m_layerPanelColour );
1062  setting->ctl_indicator->SetIndicatorState( ROW_ICON_PROVIDER::STATE::OFF );
1063  }
1064 
1065  wxChar r, g, b;
1066 
1067  r = m_layerPanelColour.Red();
1068  g = m_layerPanelColour.Green();
1069  b = m_layerPanelColour.Blue();
1070 
1071  if( r < 240 || g < 240 || b < 240 )
1072  {
1073  r = wxChar( std::min( (int) r + 15, 255 ) );
1074  g = wxChar( std::min( (int) g + 15, 255 ) );
1075  b = wxChar( std::min( (int) b + 15, 255 ) );
1076  }
1077  else
1078  {
1079  r = wxChar( std::max( (int) r - 15, 0 ) );
1080  g = wxChar( std::max( (int) g - 15, 0 ) );
1081  b = wxChar( std::max( (int) b - 15, 0 ) );
1082  }
1083 
1084  PCB_LAYER_ID current = m_frame->GetActiveLayer();
1085 
1086  if( !m_layerSettingsMap.count( current ) )
1087  {
1088  wxASSERT( m_layerSettingsMap.count( F_Cu ) );
1089  current = F_Cu;
1090  }
1091 
1092  APPEARANCE_SETTING* newSetting = m_layerSettingsMap[ current ];
1093 
1094  newSetting->ctl_panel->SetBackgroundColour( wxColour( r, g, b ) );
1096 
1097  Refresh();
1098 }
1099 
1100 
1101 void APPEARANCE_CONTROLS::SetLayerVisible( LAYER_NUM aLayer, bool isVisible )
1102 {
1103  LSET visible = getVisibleLayers();
1104  PCB_LAYER_ID layer = ToLAYER_ID( aLayer );
1105 
1106  if( visible.test( layer ) == isVisible )
1107  return;
1108 
1109  visible.set( layer, isVisible );
1110  setVisibleLayers( visible );
1111 
1112  m_frame->GetCanvas()->GetView()->SetLayerVisible( layer, isVisible );
1113 
1115 }
1116 
1117 
1119 {
1120  if( m_objectSettingsMap.count( aLayer ) )
1121  {
1122  APPEARANCE_SETTING* setting = m_objectSettingsMap.at( aLayer );
1123  setting->ctl_visibility->SetValue( isVisible );
1124  }
1125 
1126  m_frame->GetBoard()->SetElementVisibility( aLayer, isVisible );
1127 
1128  m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, isVisible );
1129  m_frame->GetCanvas()->Refresh();
1130 }
1131 
1132 
1134 {
1135  if( m_isFpEditor )
1136  {
1137  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1138 
1139  for( PCB_LAYER_ID layer : LSET::AllLayersMask().Seq() )
1140  view->SetLayerVisible( layer, aLayers.Contains( layer ) );
1141  }
1142  else
1143  {
1144  m_frame->GetBoard()->SetVisibleLayers( aLayers );
1145  }
1146 }
1147 
1148 
1150 {
1151  if( m_isFpEditor )
1152  {
1153  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1154 
1155  for( size_t i = 0; i < GAL_LAYER_INDEX( LAYER_ZONE_START ); i++ )
1156  view->SetLayerVisible( GAL_LAYER_ID_START + GAL_LAYER_ID( i ), aLayers.test( i ) );
1157  }
1158  else
1159  {
1160  // Ratsnest visibility is controlled by the ratsnest option, and not by the preset
1161  if( m_frame->IsType( FRAME_PCB_EDITOR ) )
1162  {
1164  aLayers.set( LAYER_RATSNEST, opt.m_ShowGlobalRatsnest );
1165  }
1166 
1167  m_frame->GetBoard()->SetVisibleElements( aLayers );
1168  }
1169 }
1170 
1171 
1173 {
1174  if( m_isFpEditor )
1175  {
1176  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1177  LSET set;
1178 
1179  for( PCB_LAYER_ID layer : LSET::AllLayersMask().Seq() )
1180  set.set( layer, view->IsLayerVisible( layer ) );
1181 
1182  return set;
1183  }
1184  else
1185  {
1186  return m_frame->GetBoard()->GetVisibleLayers();
1187  }
1188 }
1189 
1190 
1192 {
1193  if( m_isFpEditor )
1194  {
1195  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1196  GAL_SET set;
1197  set.reset();
1198 
1199  for( size_t i = 0; i < set.size(); i++ )
1200  set.set( i, view->IsLayerVisible( GAL_LAYER_ID_START + GAL_LAYER_ID( i ) ) );
1201 
1202  return set;
1203  }
1204  else
1205  {
1206  return m_frame->GetBoard()->GetVisibleElements();
1207  }
1208 }
1209 
1210 
1212 {
1213  // TODO(JE) Is this even needed if the layer alphas are getting directly updated?
1214  // Maybe we just need the "down" arrow to indicate if the alpha is below 1
1215 
1216 #if 0
1217  static constexpr double alphaEpsilon = 0.04;
1218 
1219  PCB_LAYER_ID current = m_frame->GetActiveLayer();
1221  KIGFX::PCB_PAINTER* painter =
1222  static_cast<KIGFX::PCB_PAINTER*>( m_frame->GetCanvas()->GetView()->GetPainter() );
1223  KIGFX::PCB_RENDER_SETTINGS* rs = painter->GetSettings();
1224 
1225  for( APPEARANCE_SETTING& setting : m_layerSettings )
1226  {
1227  if( !setting.ctl_indicator )
1228  continue;
1229 
1230  COLOR4D layerColor = theme->GetColor( setting.id );
1231  COLOR4D screenColor = rs->GetLayerColor( setting.id );
1232 
1233  if( std::abs( screenColor.a - layerColor.a ) > alphaEpsilon )
1234  {
1235  if( screenColor.a < layerColor.a )
1236  setting.ctl_indicator->SetIndicatorState( ROW_ICON_PROVIDER::STATE::DOWN );
1237  else
1238  setting.ctl_indicator->SetIndicatorState( ROW_ICON_PROVIDER::STATE::UP );
1239  }
1240  else
1241  {
1242  setting.ctl_indicator->SetIndicatorState( setting.id == current ?
1244  ROW_ICON_PROVIDER::STATE::OFF );
1245  }
1246  }
1247 #endif
1248 }
1249 
1250 
1252 {
1253  const PCB_DISPLAY_OPTIONS& options = m_frame->GetDisplayOptions();
1254 
1255  switch( options.m_ContrastModeDisplay )
1256  {
1257  case HIGH_CONTRAST_MODE::NORMAL: m_rbHighContrastNormal->SetValue( true ); break;
1258  case HIGH_CONTRAST_MODE::DIMMED: m_rbHighContrastDim->SetValue( true ); break;
1259  case HIGH_CONTRAST_MODE::HIDDEN: m_rbHighContrastOff->SetValue( true ); break;
1260  }
1261 
1262  switch( options.m_NetColorMode )
1263  {
1264  case NET_COLOR_MODE::ALL: m_rbNetColorAll->SetValue( true ); break;
1265  case NET_COLOR_MODE::RATSNEST: m_rbNetColorRatsnest->SetValue( true ); break;
1266  case NET_COLOR_MODE::OFF: m_rbNetColorOff->SetValue( true ); break;
1267  }
1268 
1269  m_cbFlipBoard->SetValue( m_frame->GetCanvas()->GetView()->IsMirroredX() );
1270 
1271  if( !m_isFpEditor )
1272  {
1273  if( options.m_RatsnestMode == RATSNEST_MODE::ALL )
1274  m_rbRatsnestAllLayers->SetValue( true );
1275  else
1276  m_rbRatsnestVisibleLayers->SetValue( true );
1277 
1278  wxASSERT( m_objectSettingsMap.count( LAYER_RATSNEST ) );
1280  ratsnest->ctl_visibility->SetValue( options.m_ShowGlobalRatsnest );
1281  }
1282 }
1283 
1284 
1285 std::vector<LAYER_PRESET> APPEARANCE_CONTROLS::GetUserLayerPresets() const
1286 {
1287  std::vector<LAYER_PRESET> ret;
1288 
1289  for( const auto& pair : m_layerPresets )
1290  if( !pair.second.readOnly )
1291  ret.emplace_back( pair.second );
1292 
1293  return ret;
1294 }
1295 
1296 
1297 void APPEARANCE_CONTROLS::SetUserLayerPresets( std::vector<LAYER_PRESET>& aPresetList )
1298 {
1299  // Reset to defaults
1301 
1302  for( const LAYER_PRESET& preset : aPresetList )
1303  {
1304  if( m_layerPresets.count( preset.name ) )
1305  continue;
1306 
1307  m_layerPresets[preset.name] = preset;
1308 
1309  m_presetMRU.Add( preset.name );
1310  }
1311 
1313 }
1314 
1315 
1317 {
1318  m_layerPresets.clear();
1319  m_presetMRU.clear();
1320 
1321  // Load the read-only defaults
1324  presetBackAssembly } )
1325  {
1326  m_layerPresets[preset.name] = preset;
1327  m_layerPresets[preset.name].readOnly = true;
1328 
1329  m_presetMRU.Add( preset.name );
1330  }
1331 }
1332 
1333 
1334 void APPEARANCE_CONTROLS::ApplyLayerPreset( const wxString& aPresetName )
1335 {
1336  updateLayerPresetSelection( aPresetName );
1337 
1338  wxCommandEvent dummy;
1340 }
1341 
1342 
1344 {
1345  if( m_layerPresets.count( aPreset.name ) )
1346  m_currentPreset = &m_layerPresets[aPreset.name];
1347  else
1348  m_currentPreset = nullptr;
1349 
1351  : nullptr;
1352 
1353  updateLayerPresetSelection( aPreset.name );
1354  doApplyLayerPreset( aPreset );
1355 }
1356 
1357 
1359 {
1360  BOARD* board = m_frame->GetBoard();
1361  LSET enabled = board->GetEnabledLayers();
1362  LSET visible = getVisibleLayers();
1363 
1365  COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
1366  bool firstLayer = true;
1367  bool readOnly = theme->IsReadOnly();
1368 
1369 #ifdef __WXMAC__
1370  wxSizerItem* m_windowLayersSizerItem = m_panelLayersSizer->GetItem( m_windowLayers );
1371  m_windowLayersSizerItem->SetFlag( m_windowLayersSizerItem->GetFlag() & ~wxTOP );
1372 #endif
1373 
1374  m_layerSettings.clear();
1375  m_layerSettingsMap.clear();
1376  m_layersOuterSizer->Clear( true );
1377 
1378  auto appendLayer =
1379  [&]( std::unique_ptr<APPEARANCE_SETTING>& aSetting )
1380  {
1381  int layer = aSetting->id;
1382 
1383  wxPanel* panel = new wxPanel( m_windowLayers, layer );
1384  wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
1385  panel->SetSizer( sizer );
1386 
1387  panel->SetBackgroundColour( m_layerPanelColour );
1388 
1389  aSetting->visible = visible[layer];
1390 
1391  // TODO(JE) consider restyling this indicator
1392  INDICATOR_ICON* indicator = new INDICATOR_ICON( panel, *m_iconProvider,
1393  ROW_ICON_PROVIDER::STATE::OFF,
1394  layer );
1395 
1396  COLOR_SWATCH* swatch = new COLOR_SWATCH( panel, COLOR4D::UNSPECIFIED, layer,
1397  bgColor, theme->GetColor( layer ),
1398  SWATCH_SMALL );
1399  swatch->SetToolTip( _( "Double click or middle click for color change, "
1400  "right click for menu" ) );
1401 
1402  BITMAP_TOGGLE* btn_visible = new BITMAP_TOGGLE( panel, layer,
1405  aSetting->visible );
1406  btn_visible->SetToolTip( _( "Show or hide this layer" ) );
1407 
1408  wxStaticText* label = new wxStaticText( panel, layer, aSetting->label );
1409  label->Wrap( -1 );
1410  label->SetToolTip( aSetting->tooltip );
1411 
1412  int topMargin = firstLayer ? 2 : 1;
1413  firstLayer = false;
1414 
1415  sizer->AddSpacer( 1 );
1416  sizer->Add( indicator, 0, wxALIGN_CENTER_VERTICAL | wxTOP, topMargin );
1417  sizer->AddSpacer( 5 );
1418  sizer->Add( swatch, 0, wxALIGN_CENTER_VERTICAL | wxTOP, topMargin );
1419  sizer->AddSpacer( 6 );
1420  sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL | wxTOP, topMargin );
1421  sizer->AddSpacer( 5 );
1422  sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxTOP, topMargin );
1423 
1424  m_layersOuterSizer->Add( panel, 0, wxEXPAND, 0 );
1425 
1426  aSetting->ctl_panel = panel;
1427  aSetting->ctl_indicator = indicator;
1428  aSetting->ctl_visibility = btn_visible;
1429  aSetting->ctl_color = swatch;
1430  aSetting->ctl_text = label;
1431 
1432  panel->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1433  indicator->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1434  swatch->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1435  label->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1436 
1437  btn_visible->Bind( TOGGLE_CHANGED,
1438  [&]( wxCommandEvent& aEvent )
1439  {
1440  wxObject* btn = aEvent.GetEventObject();
1441  int layId = static_cast<wxWindow*>( btn )->GetId();
1442  bool isVisible = aEvent.GetInt();
1443 
1444  wxASSERT( layId >= 0 && layId < PCB_LAYER_ID_COUNT );
1445 
1447  {
1448  static_cast<BITMAP_TOGGLE*>( btn )->SetValue( !isVisible );
1449  return;
1450  }
1451 
1452  onLayerVisibilityChanged( static_cast<PCB_LAYER_ID>( layId ),
1453  isVisible, true );
1454  } );
1455 
1456  swatch->Bind( COLOR_SWATCH_CHANGED, &APPEARANCE_CONTROLS::OnColorSwatchChanged,
1457  this );
1459  this ) );
1460  swatch->SetReadOnly( readOnly );
1461 
1462  panel->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1463  indicator->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1464  swatch->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1465  btn_visible->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1466  label->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1467  };
1468 
1469  // Add right click handling to show the conterxt menu when clicking to the free area in
1470  // m_windowLayers (below the layer items)
1471  m_windowLayers->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1472 
1473  wxString dsc;
1474 
1475  // show all coppers first, with front on top, back on bottom, then technical layers
1476  for( LSEQ cu_stack = enabled.CuStack(); cu_stack; ++cu_stack )
1477  {
1478  PCB_LAYER_ID layer = *cu_stack;
1479 
1480  switch( layer )
1481  {
1482  case F_Cu: dsc = _( "Front copper layer" ); break;
1483  case B_Cu: dsc = _( "Back copper layer" ); break;
1484  default: dsc = _( "Inner copper layer" ); break;
1485  }
1486 
1487  m_layerSettings.emplace_back(
1488  std::make_unique<APPEARANCE_SETTING>( board->GetLayerName( layer ), layer, dsc ) );
1489 
1490  std::unique_ptr<APPEARANCE_SETTING>& setting = m_layerSettings.back();
1491 
1492  m_layerSettingsMap[layer] = setting.get();
1493 
1494  appendLayer( setting );
1495 
1497  {
1498  setting->ctl_text->Disable();
1499  setting->ctl_color->SetToolTip( wxEmptyString );
1500  }
1501  }
1502 
1503  // technical layers are shown in this order:
1504  // Because they are static, wxGetTranslation must be explicitly
1505  // called for tooltips.
1506  static const struct {
1507  PCB_LAYER_ID layerId;
1508  wxString tooltip;
1509  } non_cu_seq[] = {
1510  { F_Adhes, _( "Adhesive on board's front" ) },
1511  { B_Adhes, _( "Adhesive on board's back" ) },
1512  { F_Paste, _( "Solder paste on board's front" ) },
1513  { B_Paste, _( "Solder paste on board's back" ) },
1514  { F_SilkS, _( "Silkscreen on board's front" ) },
1515  { B_SilkS, _( "Silkscreen on board's back" ) },
1516  { F_Mask, _( "Solder mask on board's front" ) },
1517  { B_Mask, _( "Solder mask on board's back" ) },
1518  { Dwgs_User, _( "Explanatory drawings" ) },
1519  { Cmts_User, _( "Explanatory comments" ) },
1520  { Eco1_User, _( "User defined meaning" ) },
1521  { Eco2_User, _( "User defined meaning" ) },
1522  { Edge_Cuts, _( "Board's perimeter definition" ) },
1523  { Margin, _( "Board's edge setback outline" ) },
1524  { F_CrtYd, _( "Footprint courtyards on board's front" ) },
1525  { B_CrtYd, _( "Footprint courtyards on board's back" ) },
1526  { F_Fab, _( "Footprint assembly on board's front" ) },
1527  { B_Fab, _( "Footprint assembly on board's back" ) },
1528  { User_1, _( "User defined layer 1" ) },
1529  { User_2, _( "User defined layer 2" ) },
1530  { User_3, _( "User defined layer 3" ) },
1531  { User_4, _( "User defined layer 4" ) },
1532  { User_5, _( "User defined layer 5" ) },
1533  { User_6, _( "User defined layer 6" ) },
1534  { User_7, _( "User defined layer 7" ) },
1535  { User_8, _( "User defined layer 8" ) },
1536  { User_9, _( "User defined layer 9" ) },
1537  };
1538 
1539  for( const auto& entry : non_cu_seq )
1540  {
1541  PCB_LAYER_ID layer = entry.layerId;
1542 
1543  if( !enabled[layer] )
1544  continue;
1545 
1546  m_layerSettings.emplace_back( std::make_unique<APPEARANCE_SETTING>(
1547  board->GetLayerName( layer ), layer, wxGetTranslation( entry.tooltip ) ) );
1548 
1549  std::unique_ptr<APPEARANCE_SETTING>& setting = m_layerSettings.back();
1550 
1551  m_layerSettingsMap[layer] = setting.get();
1552 
1553  appendLayer( setting );
1554 
1556  {
1557  setting->ctl_text->Disable();
1558  setting->ctl_color->SetToolTip( wxEmptyString );
1559  }
1560  }
1561 
1562  m_layersOuterSizer->AddSpacer( 10 );
1563  m_windowLayers->SetBackgroundColour( m_layerPanelColour );
1564  m_windowLayers->Layout();
1565 }
1566 
1567 
1569 {
1570  delete m_layerContextMenu;
1571  m_layerContextMenu = new wxMenu;
1572 
1574  _( "Show All Copper Layers" ),
1577  _( "Hide All Copper Layers" ),
1579 
1580  m_layerContextMenu->AppendSeparator();
1581 
1583  _( "Hide All Layers But Active" ),
1585 
1586  m_layerContextMenu->AppendSeparator();
1587 
1588  AddMenuItem( m_layerContextMenu, ID_SHOW_ALL_NON_COPPER, _( "Show All Non Copper Layers" ),
1590 
1591  AddMenuItem( m_layerContextMenu, ID_HIDE_ALL_NON_COPPER, _( "Hide All Non Copper Layers" ),
1593 
1594  m_layerContextMenu->AppendSeparator();
1595 
1596  AddMenuItem( m_layerContextMenu, ID_PRESET_ALL_LAYERS, _( "Show All Layers" ),
1598 
1599  AddMenuItem( m_layerContextMenu, ID_PRESET_NO_LAYERS, _( "Hide All Layers" ),
1601 
1602  m_layerContextMenu->AppendSeparator();
1603 
1605  _( "Show Only Front Assembly Layers" ), KiBitmap( BITMAPS::show_front_assembly_layers ) );
1606 
1607  AddMenuItem( m_layerContextMenu, ID_PRESET_FRONT, _( "Show Only Front Layers" ),
1609 
1610  // Only show the internal layer option if internal layers are enabled
1611  if( m_frame->GetBoard()->GetCopperLayerCount() > 2 )
1612  {
1613  AddMenuItem( m_layerContextMenu, ID_PRESET_INNER_COPPER, _( "Show Only Inner Layers" ),
1615  }
1616 
1617  AddMenuItem( m_layerContextMenu, ID_PRESET_BACK, _( "Show Only Back Layers" ),
1619 
1620  AddMenuItem( m_layerContextMenu, ID_PRESET_BACK_ASSEMBLY, _( "Show Only Back Assembly Layers" ),
1622 }
1623 
1624 
1625 void APPEARANCE_CONTROLS::OnLayerContextMenu( wxCommandEvent& aEvent )
1626 {
1627  BOARD* board = m_frame->GetBoard();
1628  LSET visible = getVisibleLayers();
1629 
1630  PCB_LAYER_ID current = m_frame->GetActiveLayer();
1631 
1632  switch( aEvent.GetId() )
1633  {
1634  case ID_PRESET_NO_LAYERS:
1636  return;
1637 
1638  case ID_PRESET_ALL_LAYERS:
1640  return;
1641 
1643  {
1644  visible |= presetAllCopper.layers;
1645  setVisibleLayers( visible );
1646  break;
1647  }
1648 
1651  SetLayerVisible( current, true );
1652  break;
1653 
1655  {
1656  visible &= ~presetAllCopper.layers;
1657 
1658  if( !visible.test( current ) )
1659  m_frame->SetActiveLayer( *visible.Seq().begin() );
1660 
1661  setVisibleLayers( visible );
1662  break;
1663  }
1664 
1666  {
1667  visible &= presetAllCopper.layers;
1668 
1669  if( !visible.test( current ) )
1670  m_frame->SetActiveLayer( *visible.Seq().begin() );
1671 
1672  setVisibleLayers( visible );
1673  break;
1674  }
1675 
1677  {
1678  visible |= ~presetAllCopper.layers;
1679 
1680  setVisibleLayers( visible );
1681  break;
1682  }
1683 
1686  return;
1687 
1688  case ID_PRESET_FRONT:
1690  return;
1691 
1694  return;
1695 
1696  case ID_PRESET_BACK:
1698  return;
1699 
1702  return;
1703  }
1704 
1707 
1708  if( !m_isFpEditor )
1709  m_frame->GetCanvas()->SyncLayersVisibility( board );
1710 
1711  m_frame->GetCanvas()->Refresh();
1712 }
1713 
1714 
1716 {
1717  return m_notebook->GetSelection();
1718 }
1719 
1720 
1722 {
1723  size_t max = m_notebook->GetPageCount();
1724 
1725  if( aTab >= 0 && static_cast<size_t>( aTab ) < max )
1726  m_notebook->SetSelection( aTab );
1727 }
1728 
1729 
1731 {
1733  bool readOnly = theme->IsReadOnly();
1734  LSET visible = getVisibleLayers();
1735  GAL_SET objects = getVisibleObjects();
1736 
1737  Freeze();
1738 
1739  for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_layerSettings )
1740  {
1741  LAYER_NUM layer = setting->id;
1742 
1743  if( setting->ctl_visibility )
1744  setting->ctl_visibility->SetValue( visible[layer] );
1745 
1746  if( setting->ctl_color )
1747  {
1748  const COLOR4D& color = theme->GetColor( layer );
1749  setting->ctl_color->SetSwatchColor( color, false );
1750  setting->ctl_color->SetReadOnly( readOnly );
1751  }
1752  }
1753 
1754  for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
1755  {
1756  GAL_LAYER_ID layer = static_cast<GAL_LAYER_ID>( setting->id );
1757 
1758  if( setting->ctl_visibility )
1759  setting->ctl_visibility->SetValue( objects.Contains( layer ) );
1760 
1761  if( setting->ctl_color )
1762  {
1763  const COLOR4D& color = theme->GetColor( layer );
1764  setting->ctl_color->SetSwatchColor( color, false );
1765  setting->ctl_color->SetReadOnly( readOnly );
1766  }
1767  }
1768 
1769  // Update indicators and panel background colors
1770  OnLayerChanged();
1771 
1772  Thaw();
1773 
1774  m_windowLayers->Refresh();
1775 }
1776 
1777 
1778 void APPEARANCE_CONTROLS::onLayerLeftClick( wxMouseEvent& aEvent )
1779 {
1780  auto eventSource = static_cast<wxWindow*>( aEvent.GetEventObject() );
1781 
1782  PCB_LAYER_ID layer = ToLAYER_ID( eventSource->GetId() );
1783 
1784  if( m_isFpEditor && LSET::ForbiddenFootprintLayers().test( layer ) )
1785  return;
1786 
1787  m_frame->SetActiveLayer( layer );
1788  passOnFocus();
1789 }
1790 
1791 
1792 void APPEARANCE_CONTROLS::rightClickHandler( wxMouseEvent& aEvent )
1793 {
1794  wxASSERT( m_layerContextMenu );
1795  PopupMenu( m_layerContextMenu );
1796  passOnFocus();
1797 };
1798 
1799 
1801  bool isFinal )
1802 {
1803  LSET visibleLayers = getVisibleLayers();
1804 
1805  if( visibleLayers.test( aLayer ) != isVisible )
1806  {
1807  visibleLayers.set( aLayer, isVisible );
1808 
1809  setVisibleLayers( visibleLayers );
1810 
1811  m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, isVisible );
1812  }
1813 
1815 
1816  if( isFinal )
1817  m_frame->GetCanvas()->Refresh();
1818 }
1819 
1820 
1822  bool isFinal )
1823 {
1824  // Special-case controls
1825  switch( aLayer )
1826  {
1827  case LAYER_RATSNEST:
1828  {
1829  // don't touch the layers. ratsnest is enabled on per-item basis.
1831  m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, true );
1832 
1833  if( m_frame->IsType( FRAME_PCB_EDITOR ) )
1834  {
1836  opt.m_ShowGlobalRatsnest = isVisible;
1837  m_frame->SetDisplayOptions( opt );
1838  m_frame->GetBoard()->SetElementVisibility( aLayer, isVisible );
1840  }
1841 
1842  break;
1843  }
1844 
1845  case LAYER_GRID:
1846  m_frame->SetGridVisibility( isVisible );
1847  m_frame->GetCanvas()->Refresh();
1849  break;
1850 
1851  case LAYER_MOD_TEXT_FR:
1852  // Because Footprint Text is a meta-control that also can disable values/references,
1853  // drag them along here so that the user is less likely to be confused.
1854  onObjectVisibilityChanged( LAYER_MOD_REFERENCES, isVisible, false );
1855  onObjectVisibilityChanged( LAYER_MOD_VALUES, isVisible, false );
1856  m_objectSettingsMap[LAYER_MOD_REFERENCES]->ctl_visibility->SetValue( isVisible );
1857  m_objectSettingsMap[LAYER_MOD_VALUES]->ctl_visibility->SetValue( isVisible );
1858  break;
1859 
1860  default:
1861  break;
1862  }
1863 
1864  GAL_SET visible = getVisibleObjects();
1865 
1866  if( visible.Contains( aLayer ) != isVisible )
1867  {
1868  visible.set( aLayer, isVisible );
1869  setVisibleObjects( visible );
1870  m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, isVisible );
1872  }
1873 
1874  if( isFinal )
1875  {
1876  m_frame->GetCanvas()->Refresh();
1877  passOnFocus();
1878  }
1879 }
1880 
1881 
1883 {
1885  COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
1886  GAL_SET visible = getVisibleObjects();
1887  int swatchWidth = m_windowObjects->ConvertDialogToPixels( wxSize( 8, 0 ) ).x;
1888  int labelWidth = 0;
1889 
1890  m_objectSettings.clear();
1891  m_objectsOuterSizer->Clear( true );
1892  m_objectsOuterSizer->AddSpacer( 5 );
1893 
1894  auto appendObject =
1895  [&]( const std::unique_ptr<APPEARANCE_SETTING>& aSetting )
1896  {
1897  wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
1898  int layer = aSetting->id;
1899 
1900  aSetting->visible = visible.Contains( ToGalLayer( layer ) );
1901  COLOR4D color = theme->GetColor( layer );
1902  COLOR4D defColor = theme->GetDefaultColor( layer );
1903 
1904  if( color != COLOR4D::UNSPECIFIED )
1905  {
1906  COLOR_SWATCH* swatch = new COLOR_SWATCH( m_windowObjects, color, layer,
1907  bgColor, defColor, SWATCH_SMALL );
1908  swatch->SetToolTip( _( "Left double click or middle click for color change, "
1909  "right click for menu" ) );
1910 
1911  sizer->Add( swatch, 0, wxALIGN_CENTER_VERTICAL, 0 );
1912  aSetting->ctl_color = swatch;
1913 
1914  swatch->Bind( COLOR_SWATCH_CHANGED,
1916 
1918  this ) );
1919  }
1920  else
1921  {
1922  sizer->AddSpacer( swatchWidth );
1923  }
1924 
1925  BITMAP_TOGGLE* btn_visible = new BITMAP_TOGGLE( m_windowObjects, layer,
1928  aSetting->visible );
1929 
1930  wxString tip;
1931  tip.Printf( _( "Show or hide %s" ), aSetting->label.Lower() );
1932  btn_visible->SetToolTip( tip );
1933 
1934  aSetting->ctl_visibility = btn_visible;
1935 
1936  sizer->AddSpacer( 5 );
1937 
1938  btn_visible->Bind( TOGGLE_CHANGED,
1939  [&]( wxCommandEvent& aEvent )
1940  {
1941  int id = static_cast<wxWindow*>( aEvent.GetEventObject() )->GetId();
1942  bool isVisible = aEvent.GetInt();
1943  onObjectVisibilityChanged( ToGalLayer( id ), isVisible, true );
1944  } );
1945 
1946  wxStaticText* label = new wxStaticText( m_windowObjects, layer, aSetting->label );
1947  label->Wrap( -1 );
1948  label->SetToolTip( aSetting->tooltip );
1949 
1950  if( aSetting->can_control_opacity )
1951  {
1952  label->SetMinSize( wxSize( labelWidth, -1 ) );
1953 #ifdef __WXMAC__
1954  sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, 10 );
1955  sizer->AddSpacer( 5 );
1956  sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, 10 );
1957 #else
1958  sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL, 0 );
1959  sizer->AddSpacer( 5 );
1960  sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL, 0 );
1961 #endif
1962 
1963  wxSlider* slider = new wxSlider( m_windowObjects, wxID_ANY, 100, 0, 100,
1964  wxDefaultPosition, wxDefaultSize,
1965  wxSL_HORIZONTAL );
1966 #ifdef __WXMAC__
1967  slider->SetMinSize( wxSize( 80, 22 ) );
1968 #else
1969  slider->SetMinSize( wxSize( 80, -1 ) );
1970 #endif
1971 
1972  tip.Printf( _( "Set opacity of %s" ), aSetting->label.Lower() );
1973  slider->SetToolTip( tip );
1974 
1975  sizer->Add( slider, 1, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 5 );
1976  aSetting->ctl_opacity = slider;
1977 
1978  auto opacitySliderHandler =
1979  [=]( wxCommandEvent& aEvent )
1980  {
1981  wxSlider* ctrl = static_cast<wxSlider*>( aEvent.GetEventObject() );
1982  int value = ctrl->GetValue();
1983  onObjectOpacitySlider( layer, value / 100.0f );
1984  };
1985 
1986  slider->Bind( wxEVT_SCROLL_CHANGED, opacitySliderHandler );
1987  slider->Bind( wxEVT_SCROLL_THUMBTRACK, opacitySliderHandler );
1988  slider->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS::OnSetFocus, this );
1989  }
1990  else
1991  {
1992  sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL, 0 );
1993  sizer->AddSpacer( 5 );
1994  sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL, 0 );
1995  }
1996 
1997  aSetting->ctl_text = label;
1998  m_objectsOuterSizer->Add( sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, 5 );
1999  m_objectsOuterSizer->AddSpacer( 1 );
2000  };
2001 
2002  for( const APPEARANCE_SETTING& s_setting : s_objectSettings )
2003  {
2004  if( m_isFpEditor && !s_allowedInFpEditor.count( s_setting.id ) )
2005  continue;
2006 
2007  if( !s_setting.spacer )
2008  {
2009  m_objectSettings.emplace_back( std::make_unique<APPEARANCE_SETTING>( s_setting ) );
2010 
2011  std::unique_ptr<APPEARANCE_SETTING>& setting = m_objectSettings.back();
2012 
2013  // Because s_render_rows is created static, we must explicitly call
2014  // wxGetTranslation for texts which are internationalized (tool tips
2015  // and item names)
2016  setting->tooltip = wxGetTranslation( s_setting.tooltip );
2017  setting->label = wxGetTranslation( s_setting.label );
2018 
2019  if( setting->can_control_opacity )
2020  {
2021  int width = m_windowObjects->GetTextExtent( setting->label ).x;
2022  labelWidth = std::max( labelWidth, width );
2023  }
2024 
2025  m_objectSettingsMap[ToGalLayer( setting->id )] = setting.get();
2026  }
2027  }
2028 
2029  for( const std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
2030  {
2031  if( setting->spacer )
2032  m_objectsOuterSizer->AddSpacer( m_pointSize );
2033  else
2034  appendObject( setting );
2035  }
2036 
2037  m_objectsOuterSizer->Layout();
2038 }
2039 
2040 
2042 {
2043  GAL_SET visible = getVisibleObjects();
2044 
2046 
2047  for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
2048  {
2049  if( setting->spacer )
2050  continue;
2051 
2052  GAL_LAYER_ID layer = ToGalLayer( setting->id );
2053 
2054  if( setting->ctl_visibility )
2055  setting->ctl_visibility->SetValue( visible.Contains( layer ) );
2056 
2057  if( setting->ctl_color )
2058  {
2059  COLOR4D color = m_frame->GetColorSettings()->GetColor( setting->id );
2060  setting->ctl_color->SetSwatchColor( color, false );
2061  }
2062  }
2063 
2064  wxASSERT( m_objectSettingsMap.count( LAYER_TRACKS )
2065  && m_objectSettingsMap.count( LAYER_VIAS )
2066  && m_objectSettingsMap.count( LAYER_PADS )
2067  && m_objectSettingsMap.count( LAYER_ZONES ) );
2068 
2069  m_objectSettingsMap[LAYER_TRACKS]->ctl_opacity->SetValue( opts.m_TrackOpacity * 100 );
2070  m_objectSettingsMap[LAYER_VIAS]->ctl_opacity->SetValue( opts.m_ViaOpacity * 100 );
2071  m_objectSettingsMap[LAYER_PADS]->ctl_opacity->SetValue( opts.m_PadOpacity * 100 );
2072  m_objectSettingsMap[LAYER_ZONES]->ctl_opacity->SetValue( opts.m_ZoneOpacity * 100 );
2073 }
2074 
2075 
2077 {
2078  BOARD* board = m_frame->GetBoard();
2080  COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
2081 
2082  // If the board isn't fully loaded, we can't yet rebuild
2083  if( !board->GetProject() )
2084  return;
2085 
2086  KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>(
2088 
2089  std::map<wxString, KIGFX::COLOR4D>& netclassColors = rs->GetNetclassColorMap();
2090 
2091  m_netclassOuterSizer->Clear( true );
2092 
2093  auto appendNetclass =
2094  [&]( int aId, const NETCLASSPTR& aClass, bool isDefaultClass = false )
2095  {
2096  wxString name = aClass->GetName();
2097 
2098  m_netclassSettings.emplace_back( std::make_unique<APPEARANCE_SETTING>() );
2099  APPEARANCE_SETTING* setting = m_netclassSettings.back().get();
2100  m_netclassSettingsMap[name] = setting;
2101 
2102  setting->ctl_panel = new wxPanel( m_netclassScrolledWindow, aId );
2103  wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
2104  setting->ctl_panel->SetSizer( sizer );
2105  COLOR4D color = netclassColors.count( name ) ? netclassColors.at( name ) :
2106  COLOR4D::UNSPECIFIED;
2107 
2108  setting->ctl_color = new COLOR_SWATCH( setting->ctl_panel, color, aId, bgColor,
2109  COLOR4D::UNSPECIFIED, SWATCH_SMALL );
2110  setting->ctl_color->SetToolTip( _( "Left double click or middle click for color "
2111  "change, right click for menu" ) );
2112 
2113  setting->ctl_color->Bind( COLOR_SWATCH_CHANGED,
2115 
2116  // Default netclass can't have an override color
2117  if( isDefaultClass )
2118  setting->ctl_color->Hide();
2119 
2120  setting->ctl_visibility =
2121  new BITMAP_TOGGLE( setting->ctl_panel, aId, KiBitmap( BITMAPS::visibility ),
2122  KiBitmap( BITMAPS::visibility_off ), true );
2123 
2124  wxString tip;
2125  tip.Printf( _( "Show or hide ratsnest for nets in %s" ), name );
2126  setting->ctl_visibility->SetToolTip( tip );
2127 
2128  setting->ctl_text = new wxStaticText( setting->ctl_panel, aId, name );
2129  setting->ctl_text->Wrap( -1 );
2130 
2131  int flags = wxALIGN_CENTER_VERTICAL;
2132 
2133  sizer->Add( setting->ctl_color, 0, flags | wxRESERVE_SPACE_EVEN_IF_HIDDEN, 5 );
2134  sizer->AddSpacer( 7 );
2135  sizer->Add( setting->ctl_visibility, 0, flags, 5 );
2136  sizer->AddSpacer( 3 );
2137  sizer->Add( setting->ctl_text, 1, flags, 5 );
2138 
2139  m_netclassOuterSizer->Add( setting->ctl_panel, 0, wxEXPAND, 5 );
2140  m_netclassOuterSizer->AddSpacer( 1 );
2141 
2142  setting->ctl_visibility->Bind( TOGGLE_CHANGED,
2144  this );
2145 
2146  auto menuHandler =
2147  [&, name, isDefaultClass]( wxMouseEvent& aEvent )
2148  {
2150 
2151  wxMenu menu;
2152 
2153  if( !isDefaultClass)
2154  {
2155  menu.Append( new wxMenuItem( &menu, ID_SET_NET_COLOR,
2156  _( "Set Netclass Color" ), wxEmptyString,
2157  wxITEM_NORMAL ) );
2158  }
2159 
2160  menu.Append( new wxMenuItem( &menu, ID_HIGHLIGHT_NET,
2161  wxString::Format( _( "Highlight Nets in %s" ), name ),
2162  wxEmptyString, wxITEM_NORMAL ) );
2163  menu.Append( new wxMenuItem( &menu, ID_SELECT_NET,
2164  wxString::Format( _( "Select Tracks and Vias in %s" ),
2165  name ),
2166  wxEmptyString, wxITEM_NORMAL ) );
2167  menu.Append( new wxMenuItem( &menu, ID_DESELECT_NET,
2168  wxString::Format( _( "Unselect Tracks and Vias in %s" ),
2169  name ),
2170  wxEmptyString, wxITEM_NORMAL ) );
2171 
2172  menu.AppendSeparator();
2173 
2174  menu.Append( new wxMenuItem( &menu, ID_SHOW_ALL_NETS,
2175  _( "Show All Netclasses" ), wxEmptyString,
2176  wxITEM_NORMAL ) );
2177  menu.Append( new wxMenuItem( &menu, ID_HIDE_OTHER_NETS,
2178  _( "Hide All Other Netclasses" ), wxEmptyString,
2179  wxITEM_NORMAL ) );
2180 
2181  menu.Bind( wxEVT_COMMAND_MENU_SELECTED,
2183 
2184  PopupMenu( &menu );
2185  };
2186 
2187  setting->ctl_panel->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2188  setting->ctl_visibility->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2189  setting->ctl_color->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2190  setting->ctl_text->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2191  };
2192 
2193  const NETCLASS_MAP& classes = board->GetDesignSettings().GetNetClasses().NetClasses();
2194 
2195  std::vector<wxString> names;
2196 
2197  for( const auto& pair : classes )
2198  names.emplace_back( pair.first );
2199 
2200  std::sort( names.begin(), names.end() );
2201 
2202  m_netclassIdMap.clear();
2203 
2204  int idx = wxID_HIGHEST;
2205 
2206  NETCLASSPTR defaultClass = board->GetDesignSettings().GetNetClasses().GetDefault();
2207 
2208  m_netclassIdMap[idx] = defaultClass->GetName();
2209  appendNetclass( idx++, defaultClass, true );
2210 
2211  for( const wxString& name : names )
2212  {
2213  m_netclassIdMap[idx] = name;
2214  appendNetclass( idx++, classes.at( name ) );
2215  }
2216 
2217  m_netclassOuterSizer->Layout();
2218 
2219  m_netsTable->Rebuild();
2220  m_panelNets->GetSizer()->Layout();
2221 }
2222 
2223 
2225 {
2226  m_cbLayerPresets->Clear();
2227 
2228  for( std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
2229  m_cbLayerPresets->Append( pair.first, static_cast<void*>( &pair.second ) );
2230 
2231  m_cbLayerPresets->Append( wxT( "-----" ) );
2232  m_cbLayerPresets->Append( _( "Save preset..." ) );
2233  m_cbLayerPresets->Append( _( "Delete preset..." ) );
2234 
2235  m_cbLayerPresets->SetSelection( 0 );
2236 
2237  // At least the build in presets should always be present
2238  wxASSERT( !m_layerPresets.empty() );
2239 
2240  // Default preset: all layers
2242 }
2243 
2244 
2246 {
2247  LSET visibleLayers = getVisibleLayers();
2248  GAL_SET visibleObjects = getVisibleObjects();
2249 
2250  auto it = std::find_if( m_layerPresets.begin(), m_layerPresets.end(),
2251  [&]( const std::pair<const wxString, LAYER_PRESET>& aPair )
2252  {
2253  return ( aPair.second.layers == visibleLayers
2254  && aPair.second.renderLayers == visibleObjects );
2255  } );
2256 
2257  if( it != m_layerPresets.end() )
2258  m_cbLayerPresets->SetStringSelection( it->first );
2259  else
2260  m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator
2261 
2262  m_currentPreset = static_cast<LAYER_PRESET*>(
2263  m_cbLayerPresets->GetClientData( m_cbLayerPresets->GetSelection() ) );
2264 }
2265 
2266 
2268 {
2269  int idx = m_cbLayerPresets->FindString( aName );
2270 
2271  if( idx >= 0 && m_cbLayerPresets->GetSelection() != idx )
2272  {
2273  m_cbLayerPresets->SetSelection( idx );
2274  m_currentPreset = static_cast<LAYER_PRESET*>( m_cbLayerPresets->GetClientData( idx ) );
2275  }
2276  else if( idx < 0 )
2277  {
2278  m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator
2279  }
2280 }
2281 
2282 
2283 void APPEARANCE_CONTROLS::onLayerPresetChanged( wxCommandEvent& aEvent )
2284 {
2285  int count = m_cbLayerPresets->GetCount();
2286  int index = m_cbLayerPresets->GetSelection();
2287 
2288  auto resetSelection =
2289  [&]()
2290  {
2291  if( m_currentPreset )
2292  m_cbLayerPresets->SetStringSelection( m_currentPreset->name );
2293  else
2294  m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 );
2295  };
2296 
2297  if( index == count - 3 )
2298  {
2299  // Separator: reject the selection
2300  resetSelection();
2301  return;
2302  }
2303  else if( index == count - 2 )
2304  {
2305  // Save current state to new preset
2306  wxString name;
2307 
2310 
2311  wxTextEntryDialog dlg( this, _( "Layer preset name:" ), _( "Save Layer Preset" ), name );
2312 
2313  if( dlg.ShowModal() != wxID_OK )
2314  {
2315  resetSelection();
2316  return;
2317  }
2318 
2319  name = dlg.GetValue();
2320  bool exists = m_layerPresets.count( name );
2321 
2322  if( !exists )
2325 
2326  LAYER_PRESET* preset = &m_layerPresets[name];
2327  m_currentPreset = preset;
2328 
2329  if( !exists )
2330  {
2331  index = m_cbLayerPresets->Insert( name, index - 1, static_cast<void*>( preset ) );
2332  }
2333  else
2334  {
2335  index = m_cbLayerPresets->FindString( name );
2336  m_presetMRU.Remove( name );
2337  }
2338 
2339  m_cbLayerPresets->SetSelection( index );
2340  m_presetMRU.Insert( name, 0 );
2341 
2342  return;
2343  }
2344  else if( index == count - 1 )
2345  {
2346  // Delete a preset
2347  wxArrayString headers;
2348  std::vector<wxArrayString> items;
2349 
2350  headers.Add( _( "Presets" ) );
2351 
2352  for( std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
2353  {
2354  if( !pair.second.readOnly )
2355  {
2356  wxArrayString item;
2357  item.Add( pair.first );
2358  items.emplace_back( item );
2359  }
2360  }
2361 
2362  EDA_LIST_DIALOG dlg( m_frame, _( "Delete Preset" ), headers, items, wxEmptyString );
2363  dlg.SetListLabel( _( "Select preset:" ) );
2364 
2365  if( dlg.ShowModal() == wxID_OK )
2366  {
2367  wxString presetName = dlg.GetTextSelection();
2368  int idx = m_cbLayerPresets->FindString( presetName );
2369 
2370  if( idx != wxNOT_FOUND )
2371  {
2372  m_layerPresets.erase( presetName );
2373 
2374  m_cbLayerPresets->Delete( idx );
2375  m_currentPreset = nullptr;
2376 
2377  m_presetMRU.Remove( presetName );
2378  }
2379  }
2380 
2381  resetSelection();
2382  return;
2383  }
2384 
2385  LAYER_PRESET* preset = static_cast<LAYER_PRESET*>( m_cbLayerPresets->GetClientData( index ) );
2386  m_currentPreset = preset;
2387 
2388  m_lastSelectedUserPreset = ( !preset || preset->readOnly ) ? nullptr : preset;
2389 
2390  if( preset )
2391  doApplyLayerPreset( *preset );
2392 
2393  if( !m_currentPreset->name.IsEmpty() )
2394  {
2395  m_presetMRU.Remove( m_currentPreset->name );
2396  m_presetMRU.Insert( m_currentPreset->name, 0 );
2397  }
2398 
2399  passOnFocus();
2400 }
2401 
2402 
2404 {
2405  BOARD* board = m_frame->GetBoard();
2406 
2407  setVisibleLayers( aPreset.layers );
2408  setVisibleObjects( aPreset.renderLayers );
2409 
2410  // If the preset doesn't have an explicit active layer to restore, we can at least
2411  // force the active layer to be something in the preset's layer set
2412  PCB_LAYER_ID activeLayer = UNSELECTED_LAYER;
2413 
2414  if( aPreset.activeLayer != UNSELECTED_LAYER )
2415  activeLayer = aPreset.activeLayer;
2416  else if( aPreset.layers.any() && !aPreset.layers.test( m_frame->GetActiveLayer() ) )
2417  activeLayer = *aPreset.layers.Seq().begin();
2418 
2419  LSET boardLayers = board->GetLayerSet();
2420 
2421  if( activeLayer != UNSELECTED_LAYER && boardLayers.Contains( activeLayer ) )
2422  m_frame->SetActiveLayer( activeLayer );
2423 
2424  if( !m_isFpEditor )
2425  m_frame->GetCanvas()->SyncLayersVisibility( board );
2426 
2427  m_frame->GetCanvas()->Refresh();
2428 
2430 }
2431 
2432 
2433 void APPEARANCE_CONTROLS::OnColorSwatchChanged( wxCommandEvent& aEvent )
2434 {
2435  COLOR_SWATCH* swatch = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
2436  COLOR4D newColor = swatch->GetSwatchColor();
2437  LAYER_NUM layer = swatch->GetId();
2438 
2440  cs->SetColor( layer, newColor );
2441 
2443 
2444  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
2445  view->UpdateLayerColor( layer );
2446  view->UpdateLayerColor( GetNetnameLayer( layer ) );
2447 
2448  if( IsCopperLayer( layer ) )
2449  view->UpdateLayerColor( ZONE_LAYER_FOR( layer ) );
2450 
2451  // Update the bitmap of the layer box
2452  if( m_frame->IsType( FRAME_PCB_EDITOR ) )
2453  static_cast<PCB_EDIT_FRAME*>( m_frame )->ReCreateLayerBox( false );
2454 
2455  m_frame->GetCanvas()->Refresh();
2456 
2457  if( layer == LAYER_PCB_BACKGROUND )
2458  m_frame->SetDrawBgColor( newColor );
2459 
2460  passOnFocus();
2461 }
2462 
2463 
2464 void APPEARANCE_CONTROLS::onObjectOpacitySlider( int aLayer, float aOpacity )
2465 {
2467 
2468  switch( aLayer )
2469  {
2470  case static_cast<int>( LAYER_TRACKS ): options.m_TrackOpacity = aOpacity; break;
2471  case static_cast<int>( LAYER_VIAS ): options.m_ViaOpacity = aOpacity; break;
2472  case static_cast<int>( LAYER_PADS ): options.m_PadOpacity = aOpacity; break;
2473  case static_cast<int>( LAYER_ZONES ): options.m_ZoneOpacity = aOpacity; break;
2474  default: return;
2475  }
2476 
2477  m_frame->SetDisplayOptions( options );
2478  passOnFocus();
2479 }
2480 
2481 
2482 void APPEARANCE_CONTROLS::onNetContextMenu( wxCommandEvent& aEvent )
2483 {
2484  wxASSERT( m_netsGrid->GetSelectedRows().size() == 1 );
2485 
2486  int row = m_netsGrid->GetSelectedRows()[0];
2487  NET_GRID_ENTRY& net = m_netsTable->GetEntry( row );
2488 
2489  m_netsGrid->ClearSelection();
2490 
2491  switch( aEvent.GetId() )
2492  {
2493  case ID_SET_NET_COLOR:
2494  {
2495  wxGridCellEditor* editor = m_netsGrid->GetCellEditor( row, NET_GRID_TABLE::COL_COLOR );
2496  editor->BeginEdit( row, NET_GRID_TABLE::COL_COLOR, m_netsGrid );
2497  break;
2498  }
2499 
2500  case ID_HIGHLIGHT_NET:
2501  {
2503  static_cast<intptr_t>( net.code ) );
2504  m_frame->GetCanvas()->Refresh();
2505  break;
2506  }
2507 
2508  case ID_SELECT_NET:
2509  {
2511  static_cast<intptr_t>( net.code ) );
2512  m_frame->GetCanvas()->Refresh();
2513  break;
2514  }
2515 
2516  case ID_DESELECT_NET:
2517  {
2519  static_cast<intptr_t>( net.code ) );
2520  m_frame->GetCanvas()->Refresh();
2521  break;
2522  }
2523 
2524  case ID_SHOW_ALL_NETS:
2526  break;
2527 
2528  case ID_HIDE_OTHER_NETS:
2529  m_netsTable->HideOtherNets( net );
2530  break;
2531 
2532  default:
2533  break;
2534  }
2535 
2536  passOnFocus();
2537 }
2538 
2539 
2541 {
2542  wxString className = netclassNameFromEvent( aEvent );
2543  bool show = aEvent.GetInt();
2544  showNetclass( className, show );
2545  passOnFocus();
2546 }
2547 
2548 
2549 void APPEARANCE_CONTROLS::showNetclass( const wxString& aClassName, bool aShow )
2550 {
2551  BOARD* board = m_frame->GetBoard();
2552  NETINFO_LIST& nets = board->GetNetInfo();
2553  NETCLASSES& classes = board->GetDesignSettings().GetNetClasses();
2554  NETCLASSPTR netclass = classes.Find( aClassName );
2555  TOOL_MANAGER* manager = m_frame->GetToolManager();
2556 
2557  if( !netclass )
2558  return;
2559 
2560  NETCLASS* defaultClass = classes.GetDefaultPtr();
2561 
2562  if( netclass == classes.GetDefault() )
2563  {
2564  const TOOL_ACTION& action = aShow ? PCB_ACTIONS::showNet : PCB_ACTIONS::hideNet;
2565 
2566  for( NETINFO_ITEM* net : nets )
2567  {
2568  if( net->GetNetClass() == defaultClass )
2569  {
2570  manager->RunAction( action, true, static_cast<intptr_t>( net->GetNetCode() ) );
2571 
2572  int row = m_netsTable->GetRowByNetcode( net->GetNetCode() );
2573 
2574  if( row >= 0 )
2576  }
2577  }
2578  }
2579  else
2580  {
2581  const TOOL_ACTION& action = aShow ? PCB_ACTIONS::showNet : PCB_ACTIONS::hideNet;
2582 
2583  for( const wxString& member : *netclass )
2584  {
2585  if( NETINFO_ITEM* net = nets.GetNetItem( member ) )
2586  {
2587  int code = net->GetNetCode();
2588  manager->RunAction( action, true, static_cast<intptr_t>( code ) );
2589 
2590  int row = m_netsTable->GetRowByNetcode( code );
2591 
2592  if( row >= 0 )
2594  }
2595  }
2596  }
2597 
2598  m_netsGrid->ForceRefresh();
2599 }
2600 
2601 
2602 void APPEARANCE_CONTROLS::onNetclassColorChanged( wxCommandEvent& aEvent )
2603 {
2604  KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>(
2606 
2607  std::map<wxString, KIGFX::COLOR4D>& netclassColors = rs->GetNetclassColorMap();
2608 
2609  COLOR_SWATCH* swatch = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
2610  wxString className = netclassNameFromEvent( aEvent );
2611 
2612  netclassColors[className] = swatch->GetSwatchColor();
2613 
2616  m_frame->GetCanvas()->Refresh();
2617 }
2618 
2619 
2621 {
2622  COLOR_SWATCH* s = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
2623  int classId = s->GetId();
2624 
2625  wxASSERT( m_netclassIdMap.count( classId ) );
2626  return m_netclassIdMap.at( classId );
2627 }
2628 
2629 
2630 void APPEARANCE_CONTROLS::onNetColorModeChanged( wxCommandEvent& aEvent )
2631 {
2633 
2634  if( m_rbNetColorAll->GetValue() )
2636  else if( m_rbNetColorRatsnest->GetValue() )
2638  else
2640 
2641  m_frame->SetDisplayOptions( options );
2643  passOnFocus();
2644 }
2645 
2646 
2647 void APPEARANCE_CONTROLS::onRatsnestModeChanged( wxCommandEvent& aEvent )
2648 {
2650 
2651  if( m_rbRatsnestAllLayers->GetValue() )
2653  else
2655 
2656  m_frame->SetDisplayOptions( options );
2658  passOnFocus();
2659 }
2660 
2661 
2662 void APPEARANCE_CONTROLS::onNetclassContextMenu( wxCommandEvent& aEvent )
2663 {
2664  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
2666  static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
2667 
2668  BOARD* board = m_frame->GetBoard();
2669  NETINFO_LIST& nets = board->GetNetInfo();
2670  NETCLASSES& classes = board->GetDesignSettings().GetNetClasses();
2671  NETCLASSPTR netclass = classes.Find( m_contextMenuNetclass );
2672 
2675 
2676  NETCLASSPTR defaultClass = classes.GetDefault();
2677  wxString defaultClassName = defaultClass->GetName();
2678 
2679  auto runOnNetsOfClass =
2680  [&]( NETCLASSPTR aClass, std::function<void( NETINFO_ITEM* )> aFunction )
2681  {
2682  if( aClass == defaultClass )
2683  {
2684  for( NETINFO_ITEM* net : nets )
2685  if( net->GetNetClass() == defaultClass.get() )
2686  aFunction( net );
2687  }
2688  else
2689  {
2690  for( const wxString& netName : *aClass )
2691  aFunction( nets.GetNetItem( netName ) );
2692  }
2693  };
2694 
2695  switch( aEvent.GetId() )
2696  {
2697  case ID_SET_NET_COLOR:
2698  {
2699  if( setting )
2700  {
2701  setting->ctl_color->GetNewSwatchColor();
2702 
2703  COLOR4D color = setting->ctl_color->GetSwatchColor();
2704 
2705  std::map<wxString, KIGFX::COLOR4D>& netclassColors = rs->GetNetclassColorMap();
2706 
2707  if( color != COLOR4D::UNSPECIFIED )
2708  netclassColors[m_contextMenuNetclass] = color;
2709  else
2710  netclassColors.erase( m_contextMenuNetclass );
2711 
2712  view->UpdateAllLayersColor();
2713  }
2714 
2715  break;
2716  }
2717 
2718  case ID_HIGHLIGHT_NET:
2719  {
2720  if( netclass )
2721  {
2722  runOnNetsOfClass( netclass,
2723  [&]( NETINFO_ITEM* aItem )
2724  {
2725  if( !aItem )
2726  return;
2727 
2728  static bool first = true;
2729  int code = aItem->GetNetCode();
2730 
2731  if( first )
2732  {
2733  board->SetHighLightNet( code );
2734  rs->SetHighlight( true, code );
2735  first = false;
2736  }
2737  else
2738  {
2739  board->SetHighLightNet( code, true );
2740  rs->SetHighlight( true, code, true );
2741  }
2742  } );
2743 
2744  view->UpdateAllLayersColor();
2745  board->HighLightON();
2746  }
2747  break;
2748  }
2749 
2750  case ID_SELECT_NET:
2751  case ID_DESELECT_NET:
2752  {
2753  if( netclass )
2754  {
2755  TOOL_ACTION& action = aEvent.GetId() == ID_SELECT_NET ? PCB_ACTIONS::selectNet :
2757  runOnNetsOfClass( netclass,
2758  [&]( NETINFO_ITEM* aItem )
2759  {
2760  if( !aItem )
2761  return;
2762 
2763  intptr_t code = static_cast<intptr_t>( aItem->GetNetCode() );
2764  m_frame->GetToolManager()->RunAction( action, true, code );
2765  } );
2766  }
2767  break;
2768  }
2769 
2770  case ID_SHOW_ALL_NETS:
2771  {
2772  showNetclass( defaultClassName );
2773  wxASSERT( m_netclassSettingsMap.count( defaultClassName ) );
2774  m_netclassSettingsMap.at( defaultClassName )->ctl_visibility->SetValue( true );
2775 
2776  for( const auto& pair : classes.NetClasses() )
2777  {
2778  showNetclass( pair.first );
2779 
2780  if( m_netclassSettingsMap.count( pair.first ) )
2781  m_netclassSettingsMap.at( pair.first )->ctl_visibility->SetValue( true );
2782  }
2783 
2784  break;
2785  }
2786 
2787  case ID_HIDE_OTHER_NETS:
2788  {
2789  bool showDefault = m_contextMenuNetclass == defaultClassName;
2790  showNetclass( defaultClassName, showDefault );
2791  wxASSERT( m_netclassSettingsMap.count( defaultClassName ) );
2792  m_netclassSettingsMap.at( defaultClassName )->ctl_visibility->SetValue( showDefault );
2793 
2794  for( const auto& pair : classes.NetClasses() )
2795  {
2796  bool show = pair.first == m_contextMenuNetclass;
2797 
2798  showNetclass( pair.first, show );
2799 
2800  if( m_netclassSettingsMap.count( pair.first ) )
2801  m_netclassSettingsMap.at( pair.first )->ctl_visibility->SetValue( show );
2802  }
2803 
2804  break;
2805  }
2806 
2807  default:
2808  break;
2809  }
2810 
2812  m_frame->GetCanvas()->Refresh();
2813 
2814  m_contextMenuNetclass.clear();
2815 }
2816 
2817 
2819 {
2820  m_focusOwner->SetFocus();
2821 }
2822 
2823 
2825 {
2826  WX_INFOBAR* infobar = m_frame->GetInfoBar();
2827 
2828  wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY, _( "Open Preferences" ),
2829  wxEmptyString );
2830 
2831  button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
2832  [&]( wxHyperlinkEvent& aEvent )
2833  {
2834  wxCommandEvent dummy;
2836  } ) );
2837 
2838  infobar->RemoveAllButtons();
2839  infobar->AddButton( button );
2840  infobar->AddCloseButton();
2841 
2842  infobar->ShowMessageFor( _( "The current color theme is read-only. Create a new theme in "
2843  "Preferences to enable color editing." ),
2844  10000, wxICON_INFORMATION );
2845 }
2846 
2847 
2849 {
2850  m_paneLayerDisplayOptions->Refresh();
2851 }
static std::set< int > s_allowedInFpEditor
These GAL layers are shown in the Objects tab in the footprint editor.
void OnSize(wxSizeEvent &aEvent) override
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:750
void ShowMessageFor(const wxString &aMessage, int aTime, int aFlags=wxICON_INFORMATION)
Show the infobar with the provided message and icon for a specific period of time.
Definition: infobar.cpp:123
static LAYER_PRESET presetFrontAssembly
void AddListener(BOARD_LISTENER *aListener)
Add a listener to the board to receive calls whenever something on the board has been modified.
Definition: board.cpp:2068
A saved set of layers that are visible.
std::set< int > & GetHiddenNets()
Definition: pcb_painter.h:187
Virtual layers for stacking zones and tracks on a given copper layer.
bool SetBackgroundColour(const wxColour &aColor) override
void SetIndicatorState(ICON_ID aIconId)
Set the row indicator to the given state.
wxSize GetBestSize() const
Update the panel contents from the application and board models.
void onObjectOpacitySlider(int aLayer, float aOpacity)
LSEQ CuStack() const
Return a sequence of copper layers in starting from the front/top and extending to the back/bottom.
Definition: lset.cpp:170
show a marker on pads with no nets
std::map< PCB_LAYER_ID, APPEARANCE_SETTING * > m_layerSettingsMap
void AddButton(wxButton *aButton)
Add an already created button to the infobar.
Definition: infobar.cpp:246
void OnNetGridMouseEvent(wxMouseEvent &aEvent)
#define RR
Icon provider for the "standard" row indicators, for example in layer selection lists.
KIGFX::COLOR4D GetSwatchColor() const
wxString GetTextSelection(int aColumn=0)
Return the selected text from aColumn in the wxListCtrl in the dialog.
static COLOR4D VoidToColor(void *aColor)
void SetElementVisibility(GAL_LAYER_ID aLayer, bool aNewState)
Change the visibility of an element category.
Definition: board.cpp:537
Class APPEARANCE_CONTROLS_BASE.
NETCLASSPTR Find(const wxString &aName) const
Search this container for a NETCLASS given by aName.
Definition: netclass.cpp:132
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:360
void OnBoardItemRemoved(BOARD &aBoard, BOARD_ITEM *aBoardItem) override
void * GetValueAsCustom(int aRow, int aCol, const wxString &aTypeName) override
void HideOtherNets(const NET_GRID_ENTRY &aNet)
void ApplyLayerPreset(const wxString &aPresetName)
Ratsnest lines are drawn to items on visible layers only.
multilayer pads, usually with holes
#define ON
int GetNetnameLayer(int aLayer)
Returns a netname layer corresponding to the given layer.
#define ZONE_LAYER_FOR(copperLayer)
Macro for getting the zone layer for a given copper layer.
WX_COLLAPSIBLE_PANE * m_paneLayerDisplayOptions
void SetValueAsCustom(int aRow, int aCol, const wxString &aTypeName, void *aValue) override
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:80
static LSET ForbiddenFootprintLayers()
Layers which are not allowed within footprint definitions.
Definition: lset.cpp:888
std::vector< std::unique_ptr< APPEARANCE_SETTING > > m_layerSettings
GAL_LAYER_ID ToGalLayer(int aInteger)
static TOOL_ACTION hideNet
Definition: pcb_actions.h:455
wxMenuItem * AddMenuItem(wxMenu *aMenu, int aId, const wxString &aText, const wxBitmap &aImage, wxItemKind aType=wxITEM_NORMAL)
Create and insert a menu item with an icon into aMenu.
Definition: bitmap.cpp:254
double m_TrackOpacity
Opacity override for all tracks.
anchor of items having an anchor point (texts, footprints)
Control for copper zone opacity/visibility (color ignored)
NETCLASS_MAP & NetClasses()
Provide public access to m_NetClasses so it gets swigged.
Definition: netclass.h:290
LAYER_PRESET * m_lastSelectedUserPreset
The last user (non-read-only) preset selected by the user.
std::map< wxString, KIGFX::COLOR4D > & GetNetclassColorMap()
Definition: pcb_painter.h:183
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
void OnBoardItemsChanged(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItems) override
Update the colors on all the widgets from the new chosen color theme.
std::map< int, wxString > m_netclassIdMap
Stores wxIDs for each netclass for control event mapping.
static TOOL_ACTION selectNet
Select all connections belonging to a single net.
Definition: pcb_actions.h:77
bool Contains(PCB_LAYER_ID aLayer)
See if the layer set contains a PCB layer.
void onNetColorModeChanged(wxCommandEvent &aEvent)
int color
Definition: DXF_plotter.cpp:60
wxRadioButton * m_rbNetColorOff
double m_ViaOpacity
Opacity override for all types of via.
wxStaticLine * m_layerDisplaySeparator
void idleFocusHandler(wxIdleEvent &aEvent)
Net/netclass colors are shown on all net copper.
Net/netclass colors are shown on ratsnest lines only.
wxRadioButton * m_rbRatsnestAllLayers
show footprints on back
PROJECT * GetProject() const
Definition: board.h:360
GAL_LAYER_ID
GAL layers are "virtual" layers, i.e.
LSET GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:479
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:143
COLOR4D color
void SetVisibleElements(const GAL_SET &aMask)
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:504
show footprints values (when texts are visible)
static void * ColorToVoid(COLOR4D &aColor)
A dialog which shows:
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:684
NET_GRID_TABLE(PCB_BASE_FRAME *aFrame, wxColor aBackgroundColor)
void SetValue(bool aValue)
Read the checkbox state.
wxRadioButton * m_rbHighContrastOff
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:465
wxGridCellAttr * m_defaultAttr
void SetDrawBgColor(COLOR4D aColor) override
void OnNetGridClick(wxGridEvent &event) override
void SetReadOnly(bool aReadOnly=true)
Definition: color_swatch.h:109
void SetTable(wxGridTableBase *table, bool aTakeOwnership=false)
Hide wxGrid's SetTable() method with one which doesn't mess up the grid column widths when setting th...
Definition: wx_grid.cpp:65
int code
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:411
Contains methods for drawing PCB-specific items.
Definition: pcb_painter.h:241
const PCB_DISPLAY_OPTIONS & GetDisplayOptions() const
Display options control the way tracks, vias, outlines and other things are shown (for instance solid...
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:588
GAL_SET renderLayers
Render layers (e.g. object types) that are visible.
static LSET FrontMask()
Return a mask holding all technical layers and the external CU layer on front side.
Definition: lset.cpp:874
PCB_LAYER_ID activeLayer
Optional layer to set active when this preset is loaded.
void SetReadOnlyCallback(std::function< void()> aCallback)
Registers a handler for when the user tries to interact with a read-only swatch.
Definition: color_swatch.h:115
std::map< GAL_LAYER_ID, APPEARANCE_SETTING * > m_objectSettingsMap
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:207
A checkbox control except with custom bitmaps for the checked and unchecked states.
Definition: bitmap_toggle.h:43
void RedrawRatsnest()
Return the bounding box of the view that should be used if model is not valid.
bool visible
wxScrolledWindow * m_netclassScrolledWindow
Ratsnest lines are drawn to items on all layers (default)
Auxiliary rendering target (noncached)
Definition: definitions.h:49
PCB_BASE_FRAME * m_frame
const NETNAMES_MAP & NetsByName() const
Return the name map, at least for python.
Definition: netinfo.h:358
void OnBoardItemsRemoved(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItems) override
show footprints on front
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:70
virtual COLOR_SETTINGS * GetColorSettings() const override
Helper to retrieve the current color settings.
virtual PCB_LAYER_ID GetActiveLayer() const
wxString name
A name for this layer set.
void onRatsnestModeChanged(wxCommandEvent &aEvent)
PCB specific render settings.
Definition: pcb_painter.h:64
Master controller class:
Definition: tool_manager.h:54
void showNetclass(const wxString &aClassName, bool aShow=true)
RATSNEST_MODE m_RatsnestMode
Ratsnest draw mode (all layers vs only visible layers)
void UpdateDisplayOptions()
Return a list of the layer presets created by the user.
static LSET BackAssembly()
Return a complete set of all bottom assembly layers which is all B_SilkS and B_Mask.
Definition: lset.cpp:696
void SetDisplayOptions(const PCB_DISPLAY_OPTIONS &aOptions, bool aRefresh=true)
Updates the current display options from the given options struct.
Container for display options like enable/disable some optional drawings.
Inactive layers are dimmed (old high-contrast mode)
PCB_LAYER_ID
A quick note on layer IDs:
representing a row indicator icon for use in places like the layer widget
double a
Alpha component.
Definition: color4d.h:366
void OnBoardNetSettingsChanged(BOARD &aBoard) override
LSET is a set of PCB_LAYER_IDs.
static LAYER_PRESET presetNoLayers
A container for NETCLASS instances.
Definition: netclass.h:218
void OnNetGridDoubleClick(wxGridEvent &event) override
GRID_BITMAP_TOGGLE_RENDERER * m_toggleGridRenderer
bool readOnly
True if this is a read-only (built-in) preset.
void onNetclassVisibilityChanged(wxCommandEvent &aEvent)
void OnBoardItemChanged(BOARD &aBoard, BOARD_ITEM *aBoardItem) override
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
virtual PCB_RENDER_SETTINGS * GetSettings() override
Return a pointer to current settings that are going to be used when drawing items.
Definition: pcb_painter.h:247
void MarkTargetDirty(int aTarget)
Set or clear target 'dirty' flag.
Definition: view.h:575
bool IsGridVisible() const
wxGridCellAttr * m_labelAttr
Container for NETINFO_ITEM elements, which are the nets.
Definition: netinfo.h:315
#define GAL_LAYER_INDEX(x)
Use this macro to convert a GAL layer to a 0-indexed offset from LAYER_VIAS.
std::map< wxString, APPEARANCE_SETTING * > m_netclassSettingsMap
void SetVisibleLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings changes the bit-mask of vis...
Definition: board.cpp:497
std::map< wxString, LAYER_PRESET > m_layerPresets
GAL_SET GetVisibleElements() const
Return a set of all the element categories that are visible.
Definition: board.cpp:525
void OnSetFocus(wxFocusEvent &aEvent) override
ROW_ICON_PROVIDER * m_iconProvider
void setVisibleLayers(LSET aLayers)
void doApplyLayerPreset(const LAYER_PRESET &aPreset)
Meta control for all pads opacity/visibility (color ignored)
A collection of nets and the parameters used to route or test these nets.
Definition: netclass.h:46
Inactive layers are shown normally (no high-contrast mode)
HIGH_CONTRAST_MODE
Determine how inactive layers should be displayed.
COLOR4D GetDefaultColor(int aLayer)
Helper for storing and iterating over GAL_LAYER_IDs.
static LSET InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
Definition: lset.cpp:710
LAYER_PRESET * m_currentPreset
Helper dialog and control classes.
wxRadioButton * m_rbHighContrastNormal
static GAL_SET DefaultVisible()
Definition: lset.cpp:933
void SetPadding(int aPadding)
Set the amount of padding present on each side of the bitmap.
wxStaticText * m_txtNetDisplayTitle
void onNetContextMenu(wxCommandEvent &aEvent)
static LSET FrontAssembly()
Return a complete set of all top assembly layers which is all F_SilkS and F_Mask.
Definition: lset.cpp:682
#define _(s)
HIGH_CONTRAST_MODE m_ContrastModeDisplay
How inactive layers are displayed.
wxBoxSizer * m_objectsOuterSizer
NETCLASSES & GetNetClasses() const
static LSET AllLayersMask()
Definition: lset.cpp:787
void SetLayerVisible(int aLayer, bool aVisible=true)
Control the visibility of a particular layer.
Definition: view.h:387
wxGridCellAttr * GetAttr(int aRow, int aCol, wxGridCellAttr::wxAttrKind) override
virtual void SetActiveLayer(PCB_LAYER_ID aLayer)
LSET layers
Board layers that are visible.
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
NETCLASS * GetDefaultPtr() const
Definition: netclass.h:258
void SyncLayersVisibility(const BOARD *aBoard)
Update "visibility" property of each layer of a given BOARD.
void SetUserLayerPresets(std::vector< LAYER_PRESET > &aPresetList)
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:105
int GetTabIndex() const
Set the current notebook tab.
Container for an appearance setting (can control a single board layer, or GAL layer,...
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
APPEARANCE_CONTROLS(PCB_BASE_FRAME *aParent, wxWindow *aFocusOwner, bool aFpEditor=false)
std::vector< LAYER_PRESET > GetUserLayerPresets() const
Update the current layer presets from those saved in the project file.
void OnBoardItemAdded(BOARD &aBoard, BOARD_ITEM *aBoardItem) override
std::vector< std::unique_ptr< APPEARANCE_SETTING > > m_netclassSettings
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
Definition: infobar.cpp:287
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
double m_ZoneOpacity
Opacity override for filled zone areas.
void UpdateColors()
Update the color settings in the painter and GAL.
int LAYER_NUM
This can be replaced with int and removed.
void onLayerPresetChanged(wxCommandEvent &aEvent) override
bool IsMirroredX() const
Return true if view is flipped across the X axis.
Definition: view.h:237
wxRadioButton * m_rbHighContrastDim
layer for drc markers which have been individually excluded
NET_GRID_ENTRY & GetEntry(int aRow)
bool GetValueAsBool(int aRow, int aCol) override
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
layer for drc markers with SEVERITY_WARNING
int GetRowByNetcode(int aCode) const
void UpdateLayerColor(int aLayer)
Apply the new coloring scheme held by RENDER_SETTINGS in case that it has changed.
Definition: view.cpp:753
void SetValueAsBool(int aRow, int aCol, bool aValue) override
void OnNetVisibilityChanged(int aNetCode, bool aVisibility)
Notifies the panel when a net has been hidden or shown via the external tool.
void updateLayerPresetSelection(const wxString &aName)
A modified version of the wxInfoBar class that allows us to:
Definition: infobar.h:73
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
static LAYER_PRESET presetInnerCopper
COLOR4D GetColor(int aLayer) const
Handle the data for a net.
Definition: netinfo.h:64
double m_PadOpacity
Opacity override for SMD pads and PTHs.
static TOOL_ACTION showNet
Definition: pcb_actions.h:456
int GetId() const
Return the unique id of the TOOL_ACTION object.
Definition: tool_action.h:121
Meta control for all vias opacity/visibility.
static TOOL_ACTION highlightNet
Definition: pcb_actions.h:450
bool IsType(FRAME_T aType) const
void SetHighlight(bool aEnabled, int aNetcode=-1, bool aMulti=false)
Turns on/off highlighting.
const char * name
Definition: DXF_plotter.cpp:59
static LAYER_PRESET presetBackAssembly
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
void setVisibleObjects(GAL_SET aObjects)
std::vector< std::unique_ptr< APPEARANCE_SETTING > > m_objectSettings
void SetBitmap(const wxBitmap &aBmp)
Set the bitmap shown when the button is enabled.
Net (and netclass) colors are not shown.
static TOOL_ACTION listNets
Definition: pcb_actions.h:344
A toggle button renderer for a wxGrid, similar to BITMAP_TOGGLE.
class NETINFO_ITEM, a description of a net
Definition: typeinfo.h:107
Represent a single user action.
Definition: tool_action.h:67
NET_GRID_TABLE * m_netsTable
wxString GetTypeName(int aRow, int aCol) override
int GetCopperLayerCount() const
Definition: board.cpp:453
wxString netclassNameFromEvent(wxEvent &aEvent)
wxString GetValue(int aRow, int aCol) override
The main frame for Pcbnew.
Class representing a simple color swatch, of the kind used to set layer colors.
Definition: color_swatch.h:57
void SetValue(int aRow, int aCol, const wxString &aValue) override
void OnNotebookPageChanged(wxNotebookEvent &event) override
void onLayerLeftClick(wxMouseEvent &aEvent)
bool IsReadOnly() const
Definition: json_settings.h:81
void onObjectVisibilityChanged(GAL_LAYER_ID aLayer, bool isVisible, bool isFinal)
void onNetclassColorChanged(wxCommandEvent &aEvent)
void RefreshCollapsiblePanes()
Function to force a redraw of the collapsible panes in this control.
static LSET BackMask()
Return a mask holding all technical layers and the external CU layer on back side.
Definition: lset.cpp:881
static const wxSize SWATCH_SIZE_SMALL_DU(8, 6)
static TOOL_ACTION deselectNet
Remove all connections belonging to a single net from the active selection.
Definition: pcb_actions.h:80
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
void OnPreferences(wxCommandEvent &event)
Displays the preferences and settings of all opened editors paged dialog.
wxString name
void GetNewSwatchColor()
Prompt for a new colour, using the colour picker dialog.
void OnBoardItemsAdded(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItems) override
Color settings are a bit different than most of the settings objects in that there can be more than o...
wxGridCellCoords m_hoveredCell
Grid cell that is being hovered over, for tooltips.
NETCLASSPTR GetDefault() const
Definition: netclass.h:253
WX_INFOBAR * GetInfoBar()
wxBoxSizer * m_layersOuterSizer
std::vector< NET_GRID_ENTRY > m_nets
void SetLayerVisible(LAYER_NUM aLayer, bool isVisible)
wxString m_contextMenuNetclass
The name of the netclass that was right-clicked.
void rightClickHandler(wxMouseEvent &aEvent)
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:54
drawingsheet frame and titleblock
void onNetclassContextMenu(wxCommandEvent &aEvent)
Inactive layers are hidden.
void OnNetGridRightClick(wxGridEvent &event) override
std::map< int, KIGFX::COLOR4D > & GetNetColorMap()
Definition: pcb_painter.h:185
static TOOL_ACTION flipBoard
Definition: pcb_actions.h:294
BOARD * GetBoard() const
PCB_BASE_FRAME * m_frame
void OnColorSwatchChanged(wxCommandEvent &aEvent)
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:67
void onLayerVisibilityChanged(PCB_LAYER_ID aLayer, bool isVisible, bool isFinal)
void OnLayerContextMenu(wxCommandEvent &aEvent)
Return the index of the current tab (0-2).
NETINFO_ITEM * GetNetItem(int aNetCode) const
void UpdateAllLayersColor()
Apply the new coloring scheme to all layers.
Definition: view.cpp:774
void Collapse(bool aCollapse=true)
static LAYER_PRESET presetFront
void OnColorThemeChanged()
Update the widget when the active board layer is changed.
wxStaticText * m_txtRatsnestVisibility
A better wxCollapsiblePane that.
static LAYER_PRESET presetAllCopper
void updateNetColor(const NET_GRID_ENTRY &aNet)
static const APPEARANCE_SETTING s_objectSettings[]
Template for object appearance settings.
Definition of PCB_DISPLAY_OPTIONS class.
bool doesBoardItemNeedRebuild(BOARD_ITEM *aBoardItem)
static LAYER_PRESET presetAllLayers
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:905
virtual void SetGridVisibility(bool aVisible)
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
void updateNetVisibility(const NET_GRID_ENTRY &aNet)
void SetColLabelSize(int aHeight)
Hide wxGrid's SetColLabelSize() method with one which makes sure the size is tall enough for the syst...
Definition: wx_grid.cpp:49
show footprints references (when texts are visible)
wxStaticText * m_staticTextContrastModeTitle
layer for drc markers with SEVERITY_ERROR
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:176
void SetObjectVisible(GAL_LAYER_ID aLayer, bool isVisible=true)
Update the manual layer alpha overrides.
A text renderer that can unescape text for display This is useful where it's desired to keep the unde...
WX_COLLAPSIBLE_PANE * m_paneNetDisplayOptions
NET_COLOR_MODE m_NetColorMode
How to use color overrides on specific nets and netclasses.
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113
wxRadioButton * m_rbRatsnestVisibleLayers
void SetColor(int aLayer, COLOR4D aColor)
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:404
void AddCloseButton(const wxString &aTooltip=_("Hide this message."))
Add the default close button to the infobar on the right side.
Definition: infobar.cpp:277
static LAYER_PRESET presetBack
wxRadioButton * m_rbNetColorRatsnest
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103
wxRadioButton * m_rbNetColorAll
void SetListLabel(const wxString &aLabel)
bool Contains(GAL_LAYER_ID aPos)
int GetNetCode() const
Definition: netinfo.h:113