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 <eda_list_dialog.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: return wxT( "COLOR4D" );
153  case COL_VISIBILITY: return wxGRID_VALUE_BOOL;
154  case COL_LABEL: return wxGRID_VALUE_STRING;
155  default: return wxGRID_VALUE_STRING;
156  }
157 }
158 
159 
160 bool NET_GRID_TABLE::GetValueAsBool( int aRow, int aCol )
161 {
162  wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
163  wxASSERT( aCol == COL_VISIBILITY );
164 
165  return m_nets[aRow].visible;
166 }
167 
168 
169 void NET_GRID_TABLE::SetValueAsBool( int aRow, int aCol, bool aValue )
170 {
171  wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
172  wxASSERT( aCol == COL_VISIBILITY );
173 
174  m_nets[aRow].visible = aValue;
175  updateNetVisibility( m_nets[aRow] );
176 }
177 
178 
179 void* NET_GRID_TABLE::GetValueAsCustom( int aRow, int aCol, const wxString& aTypeName )
180 {
181  wxASSERT( aCol == COL_COLOR );
182  wxASSERT( aTypeName == wxT( "COLOR4D" ) );
183  wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
184 
185  return ColorToVoid( m_nets[aRow].color );
186 }
187 
188 
189 void NET_GRID_TABLE::SetValueAsCustom( int aRow, int aCol, const wxString& aTypeName, void* aValue )
190 {
191  wxASSERT( aCol == COL_COLOR );
192  wxASSERT( aTypeName == wxT( "COLOR4D" ) );
193  wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
194 
195  m_nets[aRow].color = VoidToColor( aValue );
196  updateNetColor( m_nets[aRow] );
197 
198  if( GetView() )
199  {
200  wxGridTableMessage msg( this, wxGRIDTABLE_REQUEST_VIEW_GET_VALUES );
201  GetView()->ProcessTableMessage( msg );
202  }
203 }
204 
205 
207 {
208  wxASSERT( static_cast<size_t>( aRow ) < m_nets.size() );
209  return m_nets[aRow];
210 }
211 
212 
213 int NET_GRID_TABLE::GetRowByNetcode( int aCode ) const
214 {
215  auto it = std::find_if( m_nets.cbegin(), m_nets.cend(),
216  [aCode]( const NET_GRID_ENTRY& aEntry )
217  {
218  return aEntry.code == aCode;
219  } );
220 
221  if( it == m_nets.cend() )
222  return -1;
223 
224  return std::distance( m_nets.cbegin(), it );
225 }
226 
227 
229 {
230  BOARD* board = m_frame->GetBoard();
231  const NETNAMES_MAP& nets = board->GetNetInfo().NetsByName();
232 
233  KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>(
235 
236  std::set<int>& hiddenNets = rs->GetHiddenNets();
237  std::map<int, KIGFX::COLOR4D>& netColors = rs->GetNetColorMap();
238 
239  int deleted = m_nets.size();
240  m_nets.clear();
241 
242  if( GetView() )
243  {
244  wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, 0, deleted );
245  GetView()->ProcessTableMessage( msg );
246  }
247 
248  for( const std::pair<const wxString, NETINFO_ITEM*>& pair : nets )
249  {
250  int netCode = pair.second->GetNetCode();
251 
252  if( netCode > 0 && !pair.first.StartsWith( "unconnected-(" ) )
253  {
254  COLOR4D color = netColors.count( netCode ) ? netColors.at( netCode ) :
255  COLOR4D::UNSPECIFIED;
256 
257  bool visible = hiddenNets.count( netCode ) == 0;
258 
259  m_nets.emplace_back( NET_GRID_ENTRY( netCode, pair.first, color, visible ) );
260  }
261  }
262 
263  // TODO(JE) move to ::Compare so we can re-sort easily
264  std::sort( m_nets.begin(), m_nets.end(),
265  []( const NET_GRID_ENTRY& a, const NET_GRID_ENTRY& b )
266  {
267  return a.name < b.name;
268  } );
269 
270  if( GetView() )
271  {
272  wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_nets.size() );
273  GetView()->ProcessTableMessage( msg );
274  }
275 }
276 
277 
279 {
280  for( NET_GRID_ENTRY& net : m_nets )
281  {
282  net.visible = true;
283  updateNetVisibility( net );
284  }
285 
286  if( GetView() )
287  GetView()->ForceRefresh();
288 }
289 
290 
292 {
293  for( NET_GRID_ENTRY& net : m_nets )
294  {
295  net.visible = ( net.code == aNet.code );
296  updateNetVisibility( net );
297  }
298 
299  if( GetView() )
300  GetView()->ForceRefresh();
301 }
302 
303 
305 {
307  m_frame->GetToolManager()->RunAction( action, true, static_cast<intptr_t>( aNet.code ) );
308 }
309 
310 
312 {
313  KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>(
315 
316  std::map<int, KIGFX::COLOR4D>& netColors = rs->GetNetColorMap();
317 
318  if( aNet.color != COLOR4D::UNSPECIFIED )
319  netColors[aNet.code] = aNet.color;
320  else
321  netColors.erase( aNet.code );
322 
325  m_frame->GetCanvas()->Refresh();
326 }
327 
328 
331 
332 #define RR APPEARANCE_CONTROLS::APPEARANCE_SETTING // Render Row abbreviation to reduce source width
333 
334  // text id tooltip opacity slider
335  RR( _( "Tracks" ), LAYER_TRACKS, _( "Show tracks" ), true ),
336  RR( _( "Vias" ), LAYER_VIAS, _( "Show all vias" ), true ),
337  RR( _( "Pads" ), LAYER_PADS, _( "Show all pads" ), true ),
338  RR( _( "Zones" ), LAYER_ZONES, _( "Show copper zones" ), true ),
339  RR(),
340  RR( _( "Footprints Front" ), LAYER_MOD_FR, _( "Show footprints that are on board's front" ) ),
341  RR( _( "Footprints Back" ), LAYER_MOD_BK, _( "Show footprints that are on board's back" ) ),
342  RR( _( "Through-hole Pads" ),LAYER_PADS_TH, _( "Show through-hole pads" ) ),
343  RR( _( "Values" ), LAYER_MOD_VALUES, _( "Show footprint values" ) ),
344  RR( _( "References" ), LAYER_MOD_REFERENCES, _( "Show footprint references" ) ),
345  RR( _( "Footprint Text" ), LAYER_MOD_TEXT_FR, _( "Show all footprint text" ) ),
346  RR( _( "Hidden Text" ), LAYER_MOD_TEXT_INVISIBLE, _( "Show footprint text marked as invisible" ) ),
347  RR(),
348  RR(),
349  RR( _( "Ratsnest" ), LAYER_RATSNEST, _( "Show unconnected nets as a ratsnest") ),
350  RR( _( "No-Connects" ), LAYER_NO_CONNECTS, _( "Show a marker on pads which have no net connected" ) ),
351  RR( _( "DRC Warnings" ), LAYER_DRC_WARNING, _( "DRC violations with a Warning severity" ) ),
352  RR( _( "DRC Errors" ), LAYER_DRC_ERROR, _( "DRC violations with an Error severity" ) ),
353  RR( _( "DRC Exclusions" ), LAYER_DRC_EXCLUSION, _( "DRC violations which have been individually excluded" ) ),
354  RR( _( "Anchors" ), LAYER_ANCHOR, _( "Show footprint and text origins as a cross" ) ),
355  RR( _( "Drawing Sheet" ), LAYER_DRAWINGSHEET, _( "Show drawing sheet borders and title block" ) ),
356  RR( _( "Grid" ), LAYER_GRID, _( "Show the (x,y) grid dots" ) )
357 };
358 
360 static std::set<int> s_allowedInFpEditor =
361  {
362  LAYER_TRACKS,
363  LAYER_VIAS,
364  LAYER_PADS,
365  LAYER_ZONES,
371  LAYER_GRID
372  };
373 
374 // These are the built-in layer presets that cannot be deleted
375 
377 
379 
380 LAYER_PRESET APPEARANCE_CONTROLS::presetAllCopper( _( "All Copper Layers" ),
381  LSET::AllCuMask().set( Edge_Cuts ) );
382 
383 LAYER_PRESET APPEARANCE_CONTROLS::presetInnerCopper( _( "Inner Copper Layers" ),
384  LSET::InternalCuMask().set( Edge_Cuts ) );
385 
387  LSET::FrontMask().set( Edge_Cuts ) );
388 
391 
393  LSET::BackMask().set( Edge_Cuts ) );
394 
397 
398 
400  bool aFpEditorMode ) :
401  APPEARANCE_CONTROLS_BASE( aParent ),
402  m_frame( aParent ),
403  m_focusOwner( aFocusOwner ),
404  m_board( nullptr ),
405  m_isFpEditor( aFpEditorMode ),
406  m_currentPreset( nullptr ),
407  m_lastSelectedUserPreset( nullptr ),
408  m_layerContextMenu( nullptr )
409 {
410  int indicatorSize = ConvertDialogToPixels( wxSize( 6, 6 ) ).x;
411  m_iconProvider = new ROW_ICON_PROVIDER( indicatorSize );
412  int pointSize = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ).GetPointSize();
413  int screenHeight = wxSystemSettings::GetMetric( wxSYS_SCREEN_Y );
414 
415  m_layerPanelColour = m_panelLayers->GetBackgroundColour().ChangeLightness( 110 );
416 
417  m_layersOuterSizer = new wxBoxSizer( wxVERTICAL );
418  m_windowLayers->SetSizer( m_layersOuterSizer );
419  m_windowLayers->SetScrollRate( 0, 5 );
420  m_windowLayers->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS::OnSetFocus, this );
421 
422  m_objectsOuterSizer = new wxBoxSizer( wxVERTICAL );
424  m_windowObjects->SetScrollRate( 0, 5 );
425  m_windowObjects->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS::OnSetFocus, this );
426 
427  wxFont infoFont = KIUI::GetInfoFont( this );
428  m_staticTextNets->SetFont( infoFont );
429  m_staticTextNetClasses->SetFont( infoFont );
430  m_panelLayers->SetFont( infoFont );
431  m_windowLayers->SetFont( infoFont );
432  m_windowObjects->SetFont( infoFont );
433  m_presetsLabel->SetFont( infoFont );
434  m_presetsHotkey->SetFont( infoFont );
435 
436  createControls();
437 
440 
443 
444  m_txtNetFilter->SetHint( _( "Filter nets" ) );
445 
446  if( screenHeight <= 900 && pointSize >= indicatorSize )
447  pointSize = pointSize * 8 / 10;
448 
449  m_pointSize = pointSize;
450  wxFont font = m_notebook->GetFont();
451 
452 #ifdef __WXMAC__
453  font.SetPointSize( m_pointSize );
454  m_notebook->SetFont( font );
455 #endif
456 
457  auto setHighContrastMode =
458  [&]( HIGH_CONTRAST_MODE aMode )
459  {
461  opts.m_ContrastModeDisplay = aMode;
462 
463  m_frame->SetDisplayOptions( opts );
464  passOnFocus();
465  };
466 
467  m_rbHighContrastNormal->Bind( wxEVT_RADIOBUTTON,
468  [=]( wxCommandEvent& aEvent )
469  {
470  setHighContrastMode( HIGH_CONTRAST_MODE::NORMAL );
471  } );
472 
473  m_rbHighContrastDim->Bind( wxEVT_RADIOBUTTON,
474  [=]( wxCommandEvent& aEvent )
475  {
476  setHighContrastMode( HIGH_CONTRAST_MODE::DIMMED );
477  } );
478 
479  m_rbHighContrastOff->Bind( wxEVT_RADIOBUTTON,
480  [=]( wxCommandEvent& aEvent )
481  {
482  setHighContrastMode( HIGH_CONTRAST_MODE::HIDDEN );
483  } );
484 
485  m_cbLayerPresets->Bind( wxEVT_CHOICE, &APPEARANCE_CONTROLS::onLayerPresetChanged, this );
486 
487  m_btnNetInspector->Bind( wxEVT_BUTTON,
488  [&]( wxCommandEvent& aEvent )
489  {
491  passOnFocus();
492  } );
493 
494  m_btnConfigureNetClasses->Bind( wxEVT_BUTTON,
495  [&]( wxCommandEvent& aEvent )
496  {
497  // This panel should only be visible in the PCB_EDIT_FRAME anyway
498  if( PCB_EDIT_FRAME* editframe = dynamic_cast<PCB_EDIT_FRAME*>( m_frame ) )
499  editframe->ShowBoardSetupDialog( _( "Net Classes" ) );
500 
501  passOnFocus();
502  } );
503 
504  m_cbFlipBoard->SetValue( m_frame->GetCanvas()->GetView()->IsMirroredX() );
505  m_cbFlipBoard->Bind( wxEVT_CHECKBOX,
506  [&]( wxCommandEvent& aEvent )
507  {
509  } );
510 
513 
514  m_netsGrid->RegisterDataType( wxT( "bool" ), m_toggleGridRenderer, new wxGridCellBoolEditor );
515 
516  // TODO(JE) Update background color of swatch renderer when theme changes
517  m_netsGrid->RegisterDataType( wxT( "COLOR4D" ),
520 
521  m_netsTable = new NET_GRID_TABLE( m_frame, m_panelNets->GetBackgroundColour() );
522  m_netsGrid->SetTable( m_netsTable, true );
524 
525  m_netsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
526  m_netsGrid->SetSelectionForeground( m_netsGrid->GetDefaultCellTextColour() );
527  m_netsGrid->SetSelectionBackground( m_panelNets->GetBackgroundColour() );
528 
529  const int cellPadding = 6;
530 #ifdef __WXMAC__
531  const int rowHeightPadding = 5;
532 #else
533  const int rowHeightPadding = 3;
534 #endif
535 
536  wxSize size = ConvertDialogToPixels( SWATCH_SIZE_SMALL_DU );
537  m_netsGrid->SetColSize( NET_GRID_TABLE::COL_COLOR, size.x + cellPadding );
538 
539  size = KiBitmap( BITMAPS::visibility ).GetSize();
540  m_netsGrid->SetColSize( NET_GRID_TABLE::COL_VISIBILITY, size.x + cellPadding );
541 
542  m_netsGrid->SetDefaultCellFont( font );
543  m_netsGrid->SetDefaultRowSize( font.GetPixelSize().y + rowHeightPadding );
544 
545  m_netsGrid->GetGridWindow()->Bind( wxEVT_MOTION,
547 
548  // To handle middle click on color swatches
549  m_netsGrid->GetGridWindow()->Bind( wxEVT_MIDDLE_UP,
551 
552  m_netsGrid->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_DEFAULT );
553  m_netclassScrolledWindow->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_DEFAULT );
554 
555  if( m_isFpEditor )
556  m_notebook->RemovePage( 2 );
557 
559  rebuildObjects();
560  OnBoardChanged();
561 
562  // Grid visibility is loaded and set to the GAL before we are constructed
564 
565  Bind( wxEVT_COMMAND_MENU_SELECTED, &APPEARANCE_CONTROLS::OnLayerContextMenu, this,
567 }
568 
569 
571 {
572  delete m_iconProvider;
573 }
574 
575 
577 {
578  // Create layer display options
580  _( "Layer Display Options" ) );
582  m_paneLayerDisplayOptions->SetBackgroundColour( m_notebook->GetThemeBackgroundColour() );
583 
584  wxWindow* layerDisplayPane = m_paneLayerDisplayOptions->GetPane();
585 
586  wxBoxSizer* layerDisplayOptionsSizer;
587  layerDisplayOptionsSizer = new wxBoxSizer( wxVERTICAL );
588 
589  m_staticTextContrastModeTitle = new wxStaticText( layerDisplayPane, wxID_ANY,
590  _( "Inactive layers:" ), wxDefaultPosition,
591  wxDefaultSize, 0 );
592  m_staticTextContrastModeTitle->Wrap( -1 );
593  layerDisplayOptionsSizer->Add( m_staticTextContrastModeTitle, 0,
594  wxEXPAND | wxBOTTOM | wxLEFT, 2 );
595 
596  wxBoxSizer* contrastModeSizer;
597  contrastModeSizer = new wxBoxSizer( wxHORIZONTAL );
598 
599  m_rbHighContrastNormal = new wxRadioButton( layerDisplayPane, wxID_ANY, _( "Normal" ),
600  wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
601  m_rbHighContrastNormal->SetValue( true );
602  m_rbHighContrastNormal->SetToolTip( _( "Inactive layers will be shown in full color" ) );
603 
604  contrastModeSizer->Add( m_rbHighContrastNormal, 0, wxRIGHT, 4 );
605 
606  m_rbHighContrastDim = new wxRadioButton( layerDisplayPane, wxID_ANY, _( "Dim" ),
607  wxDefaultPosition, wxDefaultSize, 0 );
608  m_rbHighContrastDim->SetToolTip( _( "Inactive layers will be dimmed" ) );
609 
610  contrastModeSizer->Add( m_rbHighContrastDim, 0, wxRIGHT | wxLEFT, 10 );
611 
612  m_rbHighContrastOff = new wxRadioButton( layerDisplayPane, wxID_ANY, _( "Hide" ),
613  wxDefaultPosition, wxDefaultSize, 0 );
614  m_rbHighContrastOff->SetToolTip( _( "Inactive layers will be hidden" ) );
615 
616  contrastModeSizer->Add( m_rbHighContrastOff, 0, 0, 5 );
617 
618  layerDisplayOptionsSizer->Add( contrastModeSizer, 0, wxEXPAND, 5 );
619 
620  m_layerDisplaySeparator = new wxStaticLine( layerDisplayPane, wxID_ANY, wxDefaultPosition,
621  wxDefaultSize, wxLI_HORIZONTAL );
622  layerDisplayOptionsSizer->Add( m_layerDisplaySeparator, 0, wxEXPAND | wxTOP | wxBOTTOM, 5 );
623 
624  m_cbFlipBoard = new wxCheckBox( layerDisplayPane, wxID_ANY, _( "Flip board view" ),
625  wxDefaultPosition, wxDefaultSize, 0 );
626  layerDisplayOptionsSizer->Add( m_cbFlipBoard, 0, 0, 5 );
627 
628  layerDisplayPane->SetSizer( layerDisplayOptionsSizer );
629  layerDisplayPane->Layout();
630  layerDisplayOptionsSizer->Fit( layerDisplayPane );
631 
632  m_panelLayersSizer->Add( m_paneLayerDisplayOptions, 0, wxEXPAND | wxTOP, 5 );
633 
634  m_paneLayerDisplayOptions->Bind( WX_COLLAPSIBLE_PANE_CHANGED,
635  [&]( wxCommandEvent& aEvent )
636  {
637  Freeze();
638  m_panelLayers->Fit();
639  m_sizerOuter->Layout();
640  Thaw();
641  } );
642 
643  // Create net display options
644 
646  _( "Net Display Options" ) );
648  m_paneNetDisplayOptions->SetBackgroundColour( m_notebook->GetThemeBackgroundColour() );
649 
650  wxWindow* netDisplayPane = m_paneNetDisplayOptions->GetPane();
651  wxBoxSizer* netDisplayOptionsSizer = new wxBoxSizer( wxVERTICAL );
652 
654 
655  m_txtNetDisplayTitle = new wxStaticText( netDisplayPane, wxID_ANY, _( "Net colors:" ),
656  wxDefaultPosition, wxDefaultSize, 0 );
657  m_txtNetDisplayTitle->Wrap( -1 );
658  m_txtNetDisplayTitle->SetToolTip( _( "Choose when to show net and netclass colors" ) );
659 
660  netDisplayOptionsSizer->Add( m_txtNetDisplayTitle, 0, wxEXPAND | wxBOTTOM | wxLEFT, 2 );
661 
662  wxBoxSizer* netColorSizer = new wxBoxSizer( wxHORIZONTAL );
663 
664  m_rbNetColorAll = new wxRadioButton( netDisplayPane, wxID_ANY, _( "All" ), wxDefaultPosition,
665  wxDefaultSize, wxRB_GROUP );
666  m_rbNetColorAll->SetToolTip( _( "Net and netclass colors are shown on all copper items" ) );
667 
668  netColorSizer->Add( m_rbNetColorAll, 0, wxRIGHT, 10 );
669 
670  m_rbNetColorRatsnest = new wxRadioButton( netDisplayPane, wxID_ANY, _( "Ratsnest" ),
671  wxDefaultPosition, wxDefaultSize, 0 );
672  m_rbNetColorRatsnest->SetValue( true );
673  m_rbNetColorRatsnest->SetToolTip( _( "Net and netclass colors are shown on the ratsnest only" ) );
674 
675  netColorSizer->Add( m_rbNetColorRatsnest, 0, wxRIGHT, 4 );
676 
677  m_rbNetColorOff = new wxRadioButton( netDisplayPane, wxID_ANY, _( "None" ), wxDefaultPosition,
678  wxDefaultSize, 0 );
679  m_rbNetColorOff->SetToolTip( _( "Net and netclass colors are not shown" ) );
680 
681  netColorSizer->Add( m_rbNetColorOff, 0, 0, 5 );
682 
683  netDisplayOptionsSizer->Add( netColorSizer, 0, wxEXPAND | wxBOTTOM, 5 );
684 
686 
687  m_txtRatsnestVisibility = new wxStaticText( netDisplayPane, wxID_ANY, _( "Ratsnest display:" ),
688  wxDefaultPosition, wxDefaultSize, 0 );
689  m_txtRatsnestVisibility->Wrap( -1 );
690  m_txtRatsnestVisibility->SetToolTip( _( "Choose what ratsnest lines to display" ) );
691 
692  netDisplayOptionsSizer->Add( m_txtRatsnestVisibility, 0, wxEXPAND | wxBOTTOM | wxLEFT, 2 );
693 
694  wxBoxSizer* ratsnestDisplayModeSizer = new wxBoxSizer( wxHORIZONTAL );
695 
696  m_rbRatsnestAllLayers = new wxRadioButton( netDisplayPane, wxID_ANY, _( "All layers" ),
697  wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
698  m_rbRatsnestAllLayers->SetToolTip( _( "Ratsnest lines are shown to items on all layers" ) );
699  m_rbRatsnestAllLayers->SetValue( true );
700 
701  ratsnestDisplayModeSizer->Add( m_rbRatsnestAllLayers, 0, wxRIGHT, 10 );
702 
703  m_rbRatsnestVisibleLayers = new wxRadioButton( netDisplayPane, wxID_ANY, _( "Visible layers" ),
704  wxDefaultPosition, wxDefaultSize, 0 );
705  m_rbRatsnestVisibleLayers->SetToolTip( _( "Ratsnest lines are shown to items on visible layers" ) );
706 
707  ratsnestDisplayModeSizer->Add( m_rbRatsnestVisibleLayers, 0, wxRIGHT, 4 );
708 
709  netDisplayOptionsSizer->Add( ratsnestDisplayModeSizer, 0, wxEXPAND | wxBOTTOM, 5 );
710 
712 
713  netDisplayPane->SetSizer( netDisplayOptionsSizer );
714  netDisplayPane->Layout();
715  netDisplayOptionsSizer->Fit( netDisplayPane );
716 
717  m_netsTabOuterSizer->Add( m_paneNetDisplayOptions, 0, wxEXPAND | wxTOP, 5 );
718 
719  m_paneNetDisplayOptions->Bind( WX_COLLAPSIBLE_PANE_CHANGED,
720  [&]( wxCommandEvent& aEvent )
721  {
722  Freeze();
723  m_panelNetsAndClasses->Fit();
724  m_sizerOuter->Layout();
725  passOnFocus();
726  Thaw();
727  } );
728 
729  m_rbNetColorAll->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onNetColorModeChanged, this );
730  m_rbNetColorOff->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onNetColorModeChanged, this );
731  m_rbNetColorRatsnest->Bind( wxEVT_RADIOBUTTON,
733 
734  m_rbRatsnestAllLayers->Bind( wxEVT_RADIOBUTTON,
736  m_rbRatsnestVisibleLayers->Bind( wxEVT_RADIOBUTTON,
738 }
739 
740 
742 {
743  wxSize size( 220, 480 );
744  // TODO(JE) appropriate logic
745  return size;
746 }
747 
748 
749 void APPEARANCE_CONTROLS::OnNotebookPageChanged( wxNotebookEvent& aEvent )
750 {
751  // Work around wxMac issue where the notebook pages are blank
752 #ifdef __WXMAC__
753  int page = aEvent.GetSelection();
754 
755  if( page >= 0 )
756  m_notebook->ChangeSelection( static_cast<unsigned>( page ) );
757 #endif
758 
759 #ifndef __WXMSW__
760  // Because wxWidgets is broken and will send click events to children of the collapsible
761  // panes even if they are collapsed without this
762  Freeze();
763  m_panelLayers->Fit();
764  m_panelNetsAndClasses->Fit();
765  m_sizerOuter->Layout();
766  Thaw();
767 #endif
768 
769  Bind( wxEVT_IDLE, &APPEARANCE_CONTROLS::idleFocusHandler, this );
770 }
771 
772 
773 void APPEARANCE_CONTROLS::idleFocusHandler( wxIdleEvent& aEvent )
774 {
775  passOnFocus();
776  Unbind( wxEVT_IDLE, &APPEARANCE_CONTROLS::idleFocusHandler, this );
777 }
778 
779 
780 void APPEARANCE_CONTROLS::OnSetFocus( wxFocusEvent& aEvent )
781 {
782 #ifdef __WXMSW__
783  // In wxMSW, buttons won't process events unless they have focus, so we'll let it take the
784  // focus and give it back to the parent in the button event handler.
785  if( wxBitmapButton* btn = dynamic_cast<wxBitmapButton*>( aEvent.GetEventObject() ) )
786  {
787  wxCommandEvent evt( wxEVT_BUTTON );
788  wxPostEvent( btn, evt );
789  }
790 #endif
791 
792  passOnFocus();
793  aEvent.Skip();
794 }
795 
796 
797 void APPEARANCE_CONTROLS::OnSize( wxSizeEvent& aEvent )
798 {
799  aEvent.Skip();
800 }
801 
802 
803 void APPEARANCE_CONTROLS::OnNetGridClick( wxGridEvent& event )
804 {
805  int row = event.GetRow();
806  int col = event.GetCol();
807 
808  switch( col )
809  {
811  m_netsTable->SetValueAsBool( row, col, !m_netsTable->GetValueAsBool( row, col ) );
812  m_netsGrid->ForceRefresh();
813  break;
814 
815  default:
816  break;
817  }
818 }
819 
820 
822 {
823  int row = event.GetRow();
824  int col = event.GetCol();
825 
826  switch( col )
827  {
829  m_netsGrid->GetCellEditor( row, col )->BeginEdit( row, col, m_netsGrid );
830  break;
831 
832  default:
833  break;
834  }
835 }
836 
837 
839 {
840  m_netsGrid->SelectRow( event.GetRow() );
841 
842  wxString netName = m_netsGrid->GetCellValue( event.GetRow(), NET_GRID_TABLE::COL_LABEL );
843  wxMenu menu;
844 
845  menu.Append( new wxMenuItem( &menu, ID_SET_NET_COLOR,
846  _( "Set Net Color" ), wxEmptyString, wxITEM_NORMAL ) );
847  menu.Append( new wxMenuItem( &menu, ID_HIGHLIGHT_NET,
848  wxString::Format( _( "Highlight %s" ), netName ),
849  wxEmptyString, wxITEM_NORMAL ) );
850  menu.Append( new wxMenuItem( &menu, ID_SELECT_NET,
851  wxString::Format( _( "Select Tracks and Vias in %s" ), netName ),
852  wxEmptyString, wxITEM_NORMAL ) );
853  menu.Append( new wxMenuItem( &menu, ID_DESELECT_NET,
854  wxString::Format( _( "Unselect Tracks and Vias in %s" ), netName ),
855  wxEmptyString, wxITEM_NORMAL ) );
856 
857  menu.AppendSeparator();
858 
859  menu.Append( new wxMenuItem( &menu, ID_SHOW_ALL_NETS,
860  _( "Show All Nets" ), wxEmptyString, wxITEM_NORMAL ) );
861  menu.Append( new wxMenuItem( &menu, ID_HIDE_OTHER_NETS,
862  _( "Hide All Other Nets" ), wxEmptyString, wxITEM_NORMAL ) );
863 
864  menu.Bind( wxEVT_COMMAND_MENU_SELECTED, &APPEARANCE_CONTROLS::onNetContextMenu, this );
865 
866  PopupMenu( &menu );
867 }
868 
869 
870 void APPEARANCE_CONTROLS::OnNetGridMouseEvent( wxMouseEvent& aEvent )
871 {
872  wxPoint pos = m_netsGrid->CalcUnscrolledPosition( aEvent.GetPosition() );
873  wxGridCellCoords cell = m_netsGrid->XYToCell( pos );
874 
875  if( aEvent.Moving() || aEvent.Entering() )
876  {
877  aEvent.Skip();
878 
879  if( !cell )
880  {
881  m_netsGrid->GetGridWindow()->UnsetToolTip();
882  return;
883  }
884 
885  if( cell == m_hoveredCell )
886  return;
887 
888  m_hoveredCell = cell;
889 
890  NET_GRID_ENTRY& net = m_netsTable->GetEntry( cell.GetRow() );
891 
892  wxString name = net.name;
893  wxString showOrHide = net.visible ? _( "Click to hide ratsnest for %s" )
894  : _( "Click to show ratsnest for %s" );
895  wxString tip;
896 
897  if( cell.GetCol() == NET_GRID_TABLE::COL_VISIBILITY )
898  {
899  tip.Printf( showOrHide, name );
900  }
901  else if( cell.GetCol() == NET_GRID_TABLE::COL_COLOR )
902  {
903  tip = _( "Double click (or middle click) to change color; "
904  "right click for more actions" );
905  }
906 
907  m_netsGrid->GetGridWindow()->SetToolTip( tip );
908  }
909  else if( aEvent.Leaving() )
910  {
911  m_netsGrid->UnsetToolTip();
912  aEvent.Skip();
913  }
914  else if( aEvent.Dragging() )
915  {
916  // not allowed
917  CallAfter( [&]()
918  {
919  m_netsGrid->ClearSelection();
920  } );
921  }
922  else if( aEvent.ButtonUp( wxMOUSE_BTN_MIDDLE ) && !!cell )
923  {
924  int row = cell.GetRow();
925  int col = cell.GetCol();
926 
927  if(col == NET_GRID_TABLE::COL_COLOR )
928  m_netsGrid->GetCellEditor( row, col )->BeginEdit( row, col, m_netsGrid );
929 
930  aEvent.Skip();
931  }
932  else
933  {
934  aEvent.Skip();
935  }
936 }
937 
938 
940 {
941  Freeze();
942  rebuildLayers();
946  rebuildNets();
949 
951 
952  m_board = m_frame->GetBoard();
953 
954  if( m_board )
955  m_board->AddListener( this );
956 
957  Thaw();
958  Refresh();
959 }
960 
961 
963 {
965 }
966 
967 
968 void APPEARANCE_CONTROLS::OnNetVisibilityChanged( int aNetCode, bool aVisibility )
969 {
970  int row = m_netsTable->GetRowByNetcode( aNetCode );
971 
972  if( row >= 0 )
973  {
975  m_netsGrid->ForceRefresh();
976  }
977 }
978 
979 
981 {
982  return aBoardItem->Type() == PCB_NETINFO_T;
983 }
984 
985 
986 bool APPEARANCE_CONTROLS::doesBoardItemNeedRebuild( std::vector<BOARD_ITEM*>& aBoardItems )
987 {
988  bool rebuild = std::any_of( aBoardItems.begin(), aBoardItems.end(),
989  []( const BOARD_ITEM* a )
990  {
991  return a->Type() == PCB_NETINFO_T;
992  } );
993 
994  return rebuild;
995 }
996 
997 
999 {
1000  if( doesBoardItemNeedRebuild( aItem ) )
1002 }
1003 
1004 
1005 void APPEARANCE_CONTROLS::OnBoardItemsAdded( BOARD& aBoard, std::vector<BOARD_ITEM*>& aItems )
1006 {
1007  if( doesBoardItemNeedRebuild( aItems ) )
1009 }
1010 
1011 
1013 {
1014  if( doesBoardItemNeedRebuild( aItem ) )
1016 }
1017 
1018 
1019 void APPEARANCE_CONTROLS::OnBoardItemsRemoved( BOARD& aBoard, std::vector<BOARD_ITEM*>& aItems )
1020 {
1021  if( doesBoardItemNeedRebuild( aItems ) )
1023 }
1024 
1025 
1027 {
1028  if( doesBoardItemNeedRebuild( aItem ) )
1030 }
1031 
1032 
1033 void APPEARANCE_CONTROLS::OnBoardItemsChanged( BOARD& aBoard, std::vector<BOARD_ITEM*>& aItems )
1034 {
1035  if( doesBoardItemNeedRebuild( aItems ) )
1037 }
1038 
1039 
1041 {
1042  Freeze();
1043  rebuildNets();
1044  Thaw();
1045 }
1046 
1047 
1049 {
1052 }
1053 
1054 
1056 {
1057  for( const std::unique_ptr<APPEARANCE_SETTING>& setting : m_layerSettings )
1058  {
1059  setting->ctl_panel->SetBackgroundColour( m_layerPanelColour );
1060  setting->ctl_indicator->SetIndicatorState( ROW_ICON_PROVIDER::STATE::OFF );
1061  }
1062 
1063  wxChar r, g, b;
1064 
1065  r = m_layerPanelColour.Red();
1066  g = m_layerPanelColour.Green();
1067  b = m_layerPanelColour.Blue();
1068 
1069  if( r < 240 || g < 240 || b < 240 )
1070  {
1071  r = wxChar( std::min( (int) r + 15, 255 ) );
1072  g = wxChar( std::min( (int) g + 15, 255 ) );
1073  b = wxChar( std::min( (int) b + 15, 255 ) );
1074  }
1075  else
1076  {
1077  r = wxChar( std::max( (int) r - 15, 0 ) );
1078  g = wxChar( std::max( (int) g - 15, 0 ) );
1079  b = wxChar( std::max( (int) b - 15, 0 ) );
1080  }
1081 
1082  PCB_LAYER_ID current = m_frame->GetActiveLayer();
1083 
1084  if( !m_layerSettingsMap.count( current ) )
1085  {
1086  wxASSERT( m_layerSettingsMap.count( F_Cu ) );
1087  current = F_Cu;
1088  }
1089 
1090  APPEARANCE_SETTING* newSetting = m_layerSettingsMap[ current ];
1091 
1092  newSetting->ctl_panel->SetBackgroundColour( wxColour( r, g, b ) );
1094 
1095  Refresh();
1096 }
1097 
1098 
1099 void APPEARANCE_CONTROLS::SetLayerVisible( LAYER_NUM aLayer, bool isVisible )
1100 {
1101  LSET visible = getVisibleLayers();
1102  PCB_LAYER_ID layer = ToLAYER_ID( aLayer );
1103 
1104  if( visible.test( layer ) == isVisible )
1105  return;
1106 
1107  visible.set( layer, isVisible );
1108  setVisibleLayers( visible );
1109 
1110  m_frame->GetCanvas()->GetView()->SetLayerVisible( layer, isVisible );
1111 
1113 }
1114 
1115 
1117 {
1118  if( m_objectSettingsMap.count( aLayer ) )
1119  {
1120  APPEARANCE_SETTING* setting = m_objectSettingsMap.at( aLayer );
1121  setting->ctl_visibility->SetValue( isVisible );
1122  }
1123 
1124  m_frame->GetBoard()->SetElementVisibility( aLayer, isVisible );
1125 
1126  m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, isVisible );
1127  m_frame->GetCanvas()->Refresh();
1128 }
1129 
1130 
1132 {
1133  if( m_isFpEditor )
1134  {
1135  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1136 
1137  for( PCB_LAYER_ID layer : LSET::AllLayersMask().Seq() )
1138  view->SetLayerVisible( layer, aLayers.Contains( layer ) );
1139  }
1140  else
1141  {
1142  m_frame->GetBoard()->SetVisibleLayers( aLayers );
1143  }
1144 }
1145 
1146 
1148 {
1149  if( m_isFpEditor )
1150  {
1151  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1152 
1153  for( size_t i = 0; i < GAL_LAYER_INDEX( LAYER_ZONE_START ); i++ )
1154  view->SetLayerVisible( GAL_LAYER_ID_START + GAL_LAYER_ID( i ), aLayers.test( i ) );
1155  }
1156  else
1157  {
1158  // Ratsnest visibility is controlled by the ratsnest option, and not by the preset
1159  if( m_frame->IsType( FRAME_PCB_EDITOR ) )
1160  {
1162  aLayers.set( LAYER_RATSNEST, opt.m_ShowGlobalRatsnest );
1163  }
1164 
1165  m_frame->GetBoard()->SetVisibleElements( aLayers );
1166  }
1167 }
1168 
1169 
1171 {
1172  if( m_isFpEditor )
1173  {
1174  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1175  LSET set;
1176 
1177  for( PCB_LAYER_ID layer : LSET::AllLayersMask().Seq() )
1178  set.set( layer, view->IsLayerVisible( layer ) );
1179 
1180  return set;
1181  }
1182  else
1183  {
1184  return m_frame->GetBoard()->GetVisibleLayers();
1185  }
1186 }
1187 
1188 
1190 {
1191  if( m_isFpEditor )
1192  {
1193  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1194  GAL_SET set;
1195  set.reset();
1196 
1197  for( size_t i = 0; i < set.size(); i++ )
1198  set.set( i, view->IsLayerVisible( GAL_LAYER_ID_START + GAL_LAYER_ID( i ) ) );
1199 
1200  return set;
1201  }
1202  else
1203  {
1204  return m_frame->GetBoard()->GetVisibleElements();
1205  }
1206 }
1207 
1208 
1210 {
1211  // TODO(JE) Is this even needed if the layer alphas are getting directly updated?
1212  // Maybe we just need the "down" arrow to indicate if the alpha is below 1
1213 
1214 #if 0
1215  static constexpr double alphaEpsilon = 0.04;
1216 
1217  PCB_LAYER_ID current = m_frame->GetActiveLayer();
1219  KIGFX::PCB_PAINTER* painter =
1220  static_cast<KIGFX::PCB_PAINTER*>( m_frame->GetCanvas()->GetView()->GetPainter() );
1221  KIGFX::PCB_RENDER_SETTINGS* rs = painter->GetSettings();
1222 
1223  for( APPEARANCE_SETTING& setting : m_layerSettings )
1224  {
1225  if( !setting.ctl_indicator )
1226  continue;
1227 
1228  COLOR4D layerColor = theme->GetColor( setting.id );
1229  COLOR4D screenColor = rs->GetLayerColor( setting.id );
1230 
1231  if( std::abs( screenColor.a - layerColor.a ) > alphaEpsilon )
1232  {
1233  if( screenColor.a < layerColor.a )
1234  setting.ctl_indicator->SetIndicatorState( ROW_ICON_PROVIDER::STATE::DOWN );
1235  else
1236  setting.ctl_indicator->SetIndicatorState( ROW_ICON_PROVIDER::STATE::UP );
1237  }
1238  else
1239  {
1240  setting.ctl_indicator->SetIndicatorState( setting.id == current ?
1242  ROW_ICON_PROVIDER::STATE::OFF );
1243  }
1244  }
1245 #endif
1246 }
1247 
1248 
1250 {
1251  const PCB_DISPLAY_OPTIONS& options = m_frame->GetDisplayOptions();
1252 
1253  switch( options.m_ContrastModeDisplay )
1254  {
1255  case HIGH_CONTRAST_MODE::NORMAL: m_rbHighContrastNormal->SetValue( true ); break;
1256  case HIGH_CONTRAST_MODE::DIMMED: m_rbHighContrastDim->SetValue( true ); break;
1257  case HIGH_CONTRAST_MODE::HIDDEN: m_rbHighContrastOff->SetValue( true ); break;
1258  }
1259 
1260  switch( options.m_NetColorMode )
1261  {
1262  case NET_COLOR_MODE::ALL: m_rbNetColorAll->SetValue( true ); break;
1263  case NET_COLOR_MODE::RATSNEST: m_rbNetColorRatsnest->SetValue( true ); break;
1264  case NET_COLOR_MODE::OFF: m_rbNetColorOff->SetValue( true ); break;
1265  }
1266 
1267  m_cbFlipBoard->SetValue( m_frame->GetCanvas()->GetView()->IsMirroredX() );
1268 
1269  if( !m_isFpEditor )
1270  {
1271  if( options.m_RatsnestMode == RATSNEST_MODE::ALL )
1272  m_rbRatsnestAllLayers->SetValue( true );
1273  else
1274  m_rbRatsnestVisibleLayers->SetValue( true );
1275 
1276  wxASSERT( m_objectSettingsMap.count( LAYER_RATSNEST ) );
1278  ratsnest->ctl_visibility->SetValue( options.m_ShowGlobalRatsnest );
1279  }
1280 }
1281 
1282 
1283 std::vector<LAYER_PRESET> APPEARANCE_CONTROLS::GetUserLayerPresets() const
1284 {
1285  std::vector<LAYER_PRESET> ret;
1286 
1287  for( const std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
1288  {
1289  if( !pair.second.readOnly )
1290  ret.emplace_back( pair.second );
1291  }
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 readOnly = theme->IsReadOnly();
1367 
1368 #ifdef __WXMAC__
1369  wxSizerItem* m_windowLayersSizerItem = m_panelLayersSizer->GetItem( m_windowLayers );
1370  m_windowLayersSizerItem->SetFlag( m_windowLayersSizerItem->GetFlag() & ~wxTOP );
1371 #endif
1372 
1373  m_layerSettings.clear();
1374  m_layerSettingsMap.clear();
1375  m_layersOuterSizer->Clear( true );
1376 
1377  auto appendLayer =
1378  [&]( std::unique_ptr<APPEARANCE_SETTING>& aSetting )
1379  {
1380  int layer = aSetting->id;
1381 
1382  wxPanel* panel = new wxPanel( m_windowLayers, layer );
1383  wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
1384  panel->SetSizer( sizer );
1385 
1386  panel->SetBackgroundColour( m_layerPanelColour );
1387 
1388  aSetting->visible = visible[layer];
1389 
1390  // TODO(JE) consider restyling this indicator
1391  INDICATOR_ICON* indicator = new INDICATOR_ICON( panel, *m_iconProvider,
1392  ROW_ICON_PROVIDER::STATE::OFF,
1393  layer );
1394 
1395  COLOR_SWATCH* swatch = new COLOR_SWATCH( panel, COLOR4D::UNSPECIFIED, layer,
1396  bgColor, theme->GetColor( layer ),
1397  SWATCH_SMALL );
1398  swatch->SetToolTip( _( "Double click or middle click for color change, "
1399  "right click for menu" ) );
1400 
1401  BITMAP_TOGGLE* btn_visible = new BITMAP_TOGGLE( panel, layer,
1404  aSetting->visible );
1405  btn_visible->SetToolTip( _( "Show or hide this layer" ) );
1406 
1407  wxStaticText* label = new wxStaticText( panel, layer, aSetting->label );
1408  label->Wrap( -1 );
1409  label->SetToolTip( aSetting->tooltip );
1410 
1411  sizer->AddSpacer( 1 );
1412  sizer->Add( indicator, 0, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1413  sizer->AddSpacer( 5 );
1414  sizer->Add( swatch, 0, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1415  sizer->AddSpacer( 6 );
1416  sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1417  sizer->AddSpacer( 5 );
1418  sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1419 
1420  m_layersOuterSizer->Add( panel, 0, wxEXPAND, 0 );
1421 
1422  aSetting->ctl_panel = panel;
1423  aSetting->ctl_indicator = indicator;
1424  aSetting->ctl_visibility = btn_visible;
1425  aSetting->ctl_color = swatch;
1426  aSetting->ctl_text = label;
1427 
1428  panel->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1429  indicator->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1430  swatch->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1431  label->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1432 
1433  btn_visible->Bind( TOGGLE_CHANGED,
1434  [&]( wxCommandEvent& aEvent )
1435  {
1436  wxObject* btn = aEvent.GetEventObject();
1437  int layId = static_cast<wxWindow*>( btn )->GetId();
1438  bool isVisible = aEvent.GetInt();
1439 
1440  wxASSERT( layId >= 0 && layId < PCB_LAYER_ID_COUNT );
1441 
1443  {
1444  static_cast<BITMAP_TOGGLE*>( btn )->SetValue( !isVisible );
1445  return;
1446  }
1447 
1448  onLayerVisibilityChanged( static_cast<PCB_LAYER_ID>( layId ),
1449  isVisible, true );
1450  } );
1451 
1452  swatch->Bind( COLOR_SWATCH_CHANGED, &APPEARANCE_CONTROLS::OnColorSwatchChanged,
1453  this );
1455  this ) );
1456  swatch->SetReadOnly( readOnly );
1457 
1458  panel->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1459  indicator->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1460  swatch->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1461  btn_visible->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1462  label->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1463  };
1464 
1465  // Add right click handling to show the conterxt menu when clicking to the free area in
1466  // m_windowLayers (below the layer items)
1467  m_windowLayers->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1468 
1469  wxString dsc;
1470 
1471  // show all coppers first, with front on top, back on bottom, then technical layers
1472  for( LSEQ cu_stack = enabled.CuStack(); cu_stack; ++cu_stack )
1473  {
1474  PCB_LAYER_ID layer = *cu_stack;
1475 
1476  switch( layer )
1477  {
1478  case F_Cu: dsc = _( "Front copper layer" ); break;
1479  case B_Cu: dsc = _( "Back copper layer" ); break;
1480  default: dsc = _( "Inner copper layer" ); break;
1481  }
1482 
1483  m_layerSettings.emplace_back(
1484  std::make_unique<APPEARANCE_SETTING>( board->GetLayerName( layer ), layer, dsc ) );
1485 
1486  std::unique_ptr<APPEARANCE_SETTING>& setting = m_layerSettings.back();
1487 
1488  m_layerSettingsMap[layer] = setting.get();
1489 
1490  appendLayer( setting );
1491 
1493  {
1494  setting->ctl_text->Disable();
1495  setting->ctl_color->SetToolTip( wxEmptyString );
1496  }
1497  }
1498 
1499  // technical layers are shown in this order:
1500  // Because they are static, wxGetTranslation must be explicitly
1501  // called for tooltips.
1502  static const struct {
1503  PCB_LAYER_ID layerId;
1504  wxString tooltip;
1505  } non_cu_seq[] = {
1506  { F_Adhes, _( "Adhesive on board's front" ) },
1507  { B_Adhes, _( "Adhesive on board's back" ) },
1508  { F_Paste, _( "Solder paste on board's front" ) },
1509  { B_Paste, _( "Solder paste on board's back" ) },
1510  { F_SilkS, _( "Silkscreen on board's front" ) },
1511  { B_SilkS, _( "Silkscreen on board's back" ) },
1512  { F_Mask, _( "Solder mask on board's front" ) },
1513  { B_Mask, _( "Solder mask on board's back" ) },
1514  { Dwgs_User, _( "Explanatory drawings" ) },
1515  { Cmts_User, _( "Explanatory comments" ) },
1516  { Eco1_User, _( "User defined meaning" ) },
1517  { Eco2_User, _( "User defined meaning" ) },
1518  { Edge_Cuts, _( "Board's perimeter definition" ) },
1519  { Margin, _( "Board's edge setback outline" ) },
1520  { F_CrtYd, _( "Footprint courtyards on board's front" ) },
1521  { B_CrtYd, _( "Footprint courtyards on board's back" ) },
1522  { F_Fab, _( "Footprint assembly on board's front" ) },
1523  { B_Fab, _( "Footprint assembly on board's back" ) },
1524  { User_1, _( "User defined layer 1" ) },
1525  { User_2, _( "User defined layer 2" ) },
1526  { User_3, _( "User defined layer 3" ) },
1527  { User_4, _( "User defined layer 4" ) },
1528  { User_5, _( "User defined layer 5" ) },
1529  { User_6, _( "User defined layer 6" ) },
1530  { User_7, _( "User defined layer 7" ) },
1531  { User_8, _( "User defined layer 8" ) },
1532  { User_9, _( "User defined layer 9" ) },
1533  };
1534 
1535  for( const auto& entry : non_cu_seq )
1536  {
1537  PCB_LAYER_ID layer = entry.layerId;
1538 
1539  if( !enabled[layer] )
1540  continue;
1541 
1542  m_layerSettings.emplace_back( std::make_unique<APPEARANCE_SETTING>(
1543  board->GetLayerName( layer ), layer, wxGetTranslation( entry.tooltip ) ) );
1544 
1545  std::unique_ptr<APPEARANCE_SETTING>& setting = m_layerSettings.back();
1546 
1547  m_layerSettingsMap[layer] = setting.get();
1548 
1549  appendLayer( setting );
1550 
1552  {
1553  setting->ctl_text->Disable();
1554  setting->ctl_color->SetToolTip( wxEmptyString );
1555  }
1556  }
1557 
1558  m_layersOuterSizer->AddSpacer( 10 );
1559  m_windowLayers->SetBackgroundColour( m_layerPanelColour );
1560  m_windowLayers->Layout();
1561 }
1562 
1563 
1565 {
1566  delete m_layerContextMenu;
1567  m_layerContextMenu = new wxMenu;
1568 
1570  _( "Show All Copper Layers" ),
1573  _( "Hide All Copper Layers" ),
1575 
1576  m_layerContextMenu->AppendSeparator();
1577 
1579  _( "Hide All Layers But Active" ),
1581 
1582  m_layerContextMenu->AppendSeparator();
1583 
1584  AddMenuItem( m_layerContextMenu, ID_SHOW_ALL_NON_COPPER, _( "Show All Non Copper Layers" ),
1586 
1587  AddMenuItem( m_layerContextMenu, ID_HIDE_ALL_NON_COPPER, _( "Hide All Non Copper Layers" ),
1589 
1590  m_layerContextMenu->AppendSeparator();
1591 
1592  AddMenuItem( m_layerContextMenu, ID_PRESET_ALL_LAYERS, _( "Show All Layers" ),
1594 
1595  AddMenuItem( m_layerContextMenu, ID_PRESET_NO_LAYERS, _( "Hide All Layers" ),
1597 
1598  m_layerContextMenu->AppendSeparator();
1599 
1601  _( "Show Only Front Assembly Layers" ), KiBitmap( BITMAPS::show_front_assembly_layers ) );
1602 
1603  AddMenuItem( m_layerContextMenu, ID_PRESET_FRONT, _( "Show Only Front Layers" ),
1605 
1606  // Only show the internal layer option if internal layers are enabled
1607  if( m_frame->GetBoard()->GetCopperLayerCount() > 2 )
1608  {
1609  AddMenuItem( m_layerContextMenu, ID_PRESET_INNER_COPPER, _( "Show Only Inner Layers" ),
1611  }
1612 
1613  AddMenuItem( m_layerContextMenu, ID_PRESET_BACK, _( "Show Only Back Layers" ),
1615 
1616  AddMenuItem( m_layerContextMenu, ID_PRESET_BACK_ASSEMBLY, _( "Show Only Back Assembly Layers" ),
1618 }
1619 
1620 
1621 void APPEARANCE_CONTROLS::OnLayerContextMenu( wxCommandEvent& aEvent )
1622 {
1623  BOARD* board = m_frame->GetBoard();
1624  LSET visible = getVisibleLayers();
1625 
1626  PCB_LAYER_ID current = m_frame->GetActiveLayer();
1627 
1628  switch( aEvent.GetId() )
1629  {
1630  case ID_PRESET_NO_LAYERS:
1632  return;
1633 
1634  case ID_PRESET_ALL_LAYERS:
1636  return;
1637 
1639  {
1640  visible |= presetAllCopper.layers;
1641  setVisibleLayers( visible );
1642  break;
1643  }
1644 
1647  SetLayerVisible( current, true );
1648  break;
1649 
1651  {
1652  visible &= ~presetAllCopper.layers;
1653 
1654  if( !visible.test( current ) )
1655  m_frame->SetActiveLayer( *visible.Seq().begin() );
1656 
1657  setVisibleLayers( visible );
1658  break;
1659  }
1660 
1662  {
1663  visible &= presetAllCopper.layers;
1664 
1665  if( !visible.test( current ) )
1666  m_frame->SetActiveLayer( *visible.Seq().begin() );
1667 
1668  setVisibleLayers( visible );
1669  break;
1670  }
1671 
1673  {
1674  visible |= ~presetAllCopper.layers;
1675 
1676  setVisibleLayers( visible );
1677  break;
1678  }
1679 
1682  return;
1683 
1684  case ID_PRESET_FRONT:
1686  return;
1687 
1690  return;
1691 
1692  case ID_PRESET_BACK:
1694  return;
1695 
1698  return;
1699  }
1700 
1703 
1704  if( !m_isFpEditor )
1705  m_frame->GetCanvas()->SyncLayersVisibility( board );
1706 
1707  m_frame->GetCanvas()->Refresh();
1708 }
1709 
1710 
1712 {
1713  return m_notebook->GetSelection();
1714 }
1715 
1716 
1718 {
1719  size_t max = m_notebook->GetPageCount();
1720 
1721  if( aTab >= 0 && static_cast<size_t>( aTab ) < max )
1722  m_notebook->SetSelection( aTab );
1723 }
1724 
1725 
1727 {
1729  bool readOnly = theme->IsReadOnly();
1730  LSET visible = getVisibleLayers();
1731  GAL_SET objects = getVisibleObjects();
1732 
1733  Freeze();
1734 
1735  for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_layerSettings )
1736  {
1737  LAYER_NUM layer = setting->id;
1738 
1739  if( setting->ctl_visibility )
1740  setting->ctl_visibility->SetValue( visible[layer] );
1741 
1742  if( setting->ctl_color )
1743  {
1744  const COLOR4D& color = theme->GetColor( layer );
1745  setting->ctl_color->SetSwatchColor( color, false );
1746  setting->ctl_color->SetReadOnly( readOnly );
1747  }
1748  }
1749 
1750  for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
1751  {
1752  GAL_LAYER_ID layer = static_cast<GAL_LAYER_ID>( setting->id );
1753 
1754  if( setting->ctl_visibility )
1755  setting->ctl_visibility->SetValue( objects.Contains( layer ) );
1756 
1757  if( setting->ctl_color )
1758  {
1759  const COLOR4D& color = theme->GetColor( layer );
1760  setting->ctl_color->SetSwatchColor( color, false );
1761  setting->ctl_color->SetReadOnly( readOnly );
1762  }
1763  }
1764 
1765  // Update indicators and panel background colors
1766  OnLayerChanged();
1767 
1768  Thaw();
1769 
1770  m_windowLayers->Refresh();
1771 }
1772 
1773 
1774 void APPEARANCE_CONTROLS::onLayerLeftClick( wxMouseEvent& aEvent )
1775 {
1776  auto eventSource = static_cast<wxWindow*>( aEvent.GetEventObject() );
1777 
1778  PCB_LAYER_ID layer = ToLAYER_ID( eventSource->GetId() );
1779 
1780  if( m_isFpEditor && LSET::ForbiddenFootprintLayers().test( layer ) )
1781  return;
1782 
1783  m_frame->SetActiveLayer( layer );
1784  passOnFocus();
1785 }
1786 
1787 
1788 void APPEARANCE_CONTROLS::rightClickHandler( wxMouseEvent& aEvent )
1789 {
1790  wxASSERT( m_layerContextMenu );
1791  PopupMenu( m_layerContextMenu );
1792  passOnFocus();
1793 };
1794 
1795 
1797  bool isFinal )
1798 {
1799  LSET visibleLayers = getVisibleLayers();
1800 
1801  if( visibleLayers.test( aLayer ) != isVisible )
1802  {
1803  visibleLayers.set( aLayer, isVisible );
1804 
1805  setVisibleLayers( visibleLayers );
1806 
1807  m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, isVisible );
1808  }
1809 
1811 
1812  if( isFinal )
1813  m_frame->GetCanvas()->Refresh();
1814 }
1815 
1816 
1818  bool isFinal )
1819 {
1820  // Special-case controls
1821  switch( aLayer )
1822  {
1823  case LAYER_RATSNEST:
1824  {
1825  // don't touch the layers. ratsnest is enabled on per-item basis.
1827  m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, true );
1828 
1829  if( m_frame->IsType( FRAME_PCB_EDITOR ) )
1830  {
1832  opt.m_ShowGlobalRatsnest = isVisible;
1833  m_frame->SetDisplayOptions( opt );
1834  m_frame->GetBoard()->SetElementVisibility( aLayer, isVisible );
1836  }
1837 
1838  break;
1839  }
1840 
1841  case LAYER_GRID:
1842  m_frame->SetGridVisibility( isVisible );
1843  m_frame->GetCanvas()->Refresh();
1845  break;
1846 
1847  case LAYER_MOD_TEXT_FR:
1848  // Because Footprint Text is a meta-control that also can disable values/references,
1849  // drag them along here so that the user is less likely to be confused.
1850  if( isFinal )
1851  {
1852  // Should only trigger when you actually click the Footprint Text button
1853  // Otherwise it goes into infinite recursive loop with the following case section
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  }
1859  break;
1860 
1861  case LAYER_MOD_REFERENCES:
1862  case LAYER_MOD_VALUES:
1863  // In case that user changes Footprint Value/References when the Footprint Text
1864  // meta-control is disabled, we should put it back on.
1865  if( isVisible )
1866  {
1867  onObjectVisibilityChanged( LAYER_MOD_TEXT_FR, isVisible, false );
1868  m_objectSettingsMap[LAYER_MOD_TEXT_FR]->ctl_visibility->SetValue( isVisible );
1869  }
1870  break;
1871 
1872  default:
1873  break;
1874  }
1875 
1876  GAL_SET visible = getVisibleObjects();
1877 
1878  if( visible.Contains( aLayer ) != isVisible )
1879  {
1880  visible.set( aLayer, isVisible );
1881  setVisibleObjects( visible );
1882  m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, isVisible );
1884  }
1885 
1886  if( isFinal )
1887  {
1888  m_frame->GetCanvas()->Refresh();
1889  passOnFocus();
1890  }
1891 }
1892 
1893 
1895 {
1897  COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
1898  GAL_SET visible = getVisibleObjects();
1899  int swatchWidth = m_windowObjects->ConvertDialogToPixels( wxSize( 8, 0 ) ).x;
1900  int labelWidth = 0;
1901 
1902  m_objectSettings.clear();
1903  m_objectsOuterSizer->Clear( true );
1904  m_objectsOuterSizer->AddSpacer( 5 );
1905 
1906  auto appendObject =
1907  [&]( const std::unique_ptr<APPEARANCE_SETTING>& aSetting )
1908  {
1909  wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
1910  int layer = aSetting->id;
1911 
1912  aSetting->visible = visible.Contains( ToGalLayer( layer ) );
1913  COLOR4D color = theme->GetColor( layer );
1914  COLOR4D defColor = theme->GetDefaultColor( layer );
1915 
1916  if( color != COLOR4D::UNSPECIFIED )
1917  {
1918  COLOR_SWATCH* swatch = new COLOR_SWATCH( m_windowObjects, color, layer,
1919  bgColor, defColor, SWATCH_SMALL );
1920  swatch->SetToolTip( _( "Left double click or middle click for color change, "
1921  "right click for menu" ) );
1922 
1923  sizer->Add( swatch, 0, wxALIGN_CENTER_VERTICAL, 0 );
1924  aSetting->ctl_color = swatch;
1925 
1926  swatch->Bind( COLOR_SWATCH_CHANGED,
1928 
1930  this ) );
1931  }
1932  else
1933  {
1934  sizer->AddSpacer( swatchWidth );
1935  }
1936 
1937  BITMAP_TOGGLE* btn_visible = new BITMAP_TOGGLE( m_windowObjects, layer,
1940  aSetting->visible );
1941 
1942  wxString tip;
1943  tip.Printf( _( "Show or hide %s" ), aSetting->label.Lower() );
1944  btn_visible->SetToolTip( tip );
1945 
1946  aSetting->ctl_visibility = btn_visible;
1947 
1948  sizer->AddSpacer( 5 );
1949 
1950  btn_visible->Bind( TOGGLE_CHANGED,
1951  [&]( wxCommandEvent& aEvent )
1952  {
1953  int id = static_cast<wxWindow*>( aEvent.GetEventObject() )->GetId();
1954  bool isVisible = aEvent.GetInt();
1955  onObjectVisibilityChanged( ToGalLayer( id ), isVisible, true );
1956  } );
1957 
1958  wxStaticText* label = new wxStaticText( m_windowObjects, layer, aSetting->label );
1959  label->Wrap( -1 );
1960  label->SetToolTip( aSetting->tooltip );
1961 
1962  if( aSetting->can_control_opacity )
1963  {
1964  label->SetMinSize( wxSize( labelWidth, -1 ) );
1965 #ifdef __WXMAC__
1966  sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, 10 );
1967  sizer->AddSpacer( 5 );
1968  sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, 10 );
1969 #else
1970  sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL, 0 );
1971  sizer->AddSpacer( 5 );
1972  sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL, 0 );
1973 #endif
1974 
1975  wxSlider* slider = new wxSlider( m_windowObjects, wxID_ANY, 100, 0, 100,
1976  wxDefaultPosition, wxDefaultSize,
1977  wxSL_HORIZONTAL );
1978 #ifdef __WXMAC__
1979  slider->SetMinSize( wxSize( 80, 16 ) );
1980 #else
1981  slider->SetMinSize( wxSize( 80, -1 ) );
1982 #endif
1983 
1984  tip.Printf( _( "Set opacity of %s" ), aSetting->label.Lower() );
1985  slider->SetToolTip( tip );
1986 
1987  sizer->Add( slider, 1, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 5 );
1988  aSetting->ctl_opacity = slider;
1989 
1990  auto opacitySliderHandler =
1991  [=]( wxCommandEvent& aEvent )
1992  {
1993  wxSlider* ctrl = static_cast<wxSlider*>( aEvent.GetEventObject() );
1994  int value = ctrl->GetValue();
1995  onObjectOpacitySlider( layer, value / 100.0f );
1996  };
1997 
1998  slider->Bind( wxEVT_SCROLL_CHANGED, opacitySliderHandler );
1999  slider->Bind( wxEVT_SCROLL_THUMBTRACK, opacitySliderHandler );
2000  slider->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS::OnSetFocus, this );
2001  }
2002  else
2003  {
2004  sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL, 0 );
2005  sizer->AddSpacer( 5 );
2006  sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL, 0 );
2007  }
2008 
2009  aSetting->ctl_text = label;
2010  m_objectsOuterSizer->Add( sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, 5 );
2011 
2012  if( !aSetting->can_control_opacity )
2013  m_objectsOuterSizer->AddSpacer( 2 );
2014  };
2015 
2016  for( const APPEARANCE_SETTING& s_setting : s_objectSettings )
2017  {
2018  if( m_isFpEditor && !s_allowedInFpEditor.count( s_setting.id ) )
2019  continue;
2020 
2021  if( !s_setting.spacer )
2022  {
2023  m_objectSettings.emplace_back( std::make_unique<APPEARANCE_SETTING>( s_setting ) );
2024 
2025  std::unique_ptr<APPEARANCE_SETTING>& setting = m_objectSettings.back();
2026 
2027  // Because s_render_rows is created static, we must explicitly call
2028  // wxGetTranslation for texts which are internationalized (tool tips
2029  // and item names)
2030  setting->tooltip = wxGetTranslation( s_setting.tooltip );
2031  setting->label = wxGetTranslation( s_setting.label );
2032 
2033  if( setting->can_control_opacity )
2034  {
2035  int width = m_windowObjects->GetTextExtent( setting->label ).x + 5;
2036  labelWidth = std::max( labelWidth, width );
2037  }
2038 
2039  m_objectSettingsMap[ToGalLayer( setting->id )] = setting.get();
2040  }
2041  }
2042 
2043  for( const std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
2044  {
2045  if( setting->spacer )
2046  m_objectsOuterSizer->AddSpacer( m_pointSize );
2047  else
2048  appendObject( setting );
2049  }
2050 
2051  m_objectsOuterSizer->Layout();
2052 }
2053 
2054 
2056 {
2057  GAL_SET visible = getVisibleObjects();
2058 
2060 
2061  for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
2062  {
2063  if( setting->spacer )
2064  continue;
2065 
2066  GAL_LAYER_ID layer = ToGalLayer( setting->id );
2067 
2068  if( setting->ctl_visibility )
2069  setting->ctl_visibility->SetValue( visible.Contains( layer ) );
2070 
2071  if( setting->ctl_color )
2072  {
2073  COLOR4D color = m_frame->GetColorSettings()->GetColor( setting->id );
2074  setting->ctl_color->SetSwatchColor( color, false );
2075  }
2076  }
2077 
2078  wxASSERT( m_objectSettingsMap.count( LAYER_TRACKS )
2079  && m_objectSettingsMap.count( LAYER_VIAS )
2080  && m_objectSettingsMap.count( LAYER_PADS )
2081  && m_objectSettingsMap.count( LAYER_ZONES ) );
2082 
2083  m_objectSettingsMap[LAYER_TRACKS]->ctl_opacity->SetValue( opts.m_TrackOpacity * 100 );
2084  m_objectSettingsMap[LAYER_VIAS]->ctl_opacity->SetValue( opts.m_ViaOpacity * 100 );
2085  m_objectSettingsMap[LAYER_PADS]->ctl_opacity->SetValue( opts.m_PadOpacity * 100 );
2086  m_objectSettingsMap[LAYER_ZONES]->ctl_opacity->SetValue( opts.m_ZoneOpacity * 100 );
2087 }
2088 
2089 
2091 {
2092  BOARD* board = m_frame->GetBoard();
2094  COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
2095 
2096  // If the board isn't fully loaded, we can't yet rebuild
2097  if( !board->GetProject() )
2098  return;
2099 
2100  KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>(
2102 
2103  std::map<wxString, KIGFX::COLOR4D>& netclassColors = rs->GetNetclassColorMap();
2104 
2105  m_netclassOuterSizer->Clear( true );
2106 
2107  auto appendNetclass =
2108  [&]( int aId, const NETCLASSPTR& aClass, bool isDefaultClass = false )
2109  {
2110  wxString name = aClass->GetName();
2111 
2112  m_netclassSettings.emplace_back( std::make_unique<APPEARANCE_SETTING>() );
2113  APPEARANCE_SETTING* setting = m_netclassSettings.back().get();
2114  m_netclassSettingsMap[name] = setting;
2115 
2116  setting->ctl_panel = new wxPanel( m_netclassScrolledWindow, aId );
2117  wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
2118  setting->ctl_panel->SetSizer( sizer );
2119  COLOR4D color = netclassColors.count( name ) ? netclassColors.at( name ) :
2120  COLOR4D::UNSPECIFIED;
2121 
2122  setting->ctl_color = new COLOR_SWATCH( setting->ctl_panel, color, aId, bgColor,
2123  COLOR4D::UNSPECIFIED, SWATCH_SMALL );
2124  setting->ctl_color->SetToolTip( _( "Left double click or middle click for color "
2125  "change, right click for menu" ) );
2126 
2127  setting->ctl_color->Bind( COLOR_SWATCH_CHANGED,
2129 
2130  // Default netclass can't have an override color
2131  if( isDefaultClass )
2132  setting->ctl_color->Hide();
2133 
2134  setting->ctl_visibility = new BITMAP_TOGGLE( setting->ctl_panel, aId,
2137  true );
2138 
2139  wxString tip;
2140  tip.Printf( _( "Show or hide ratsnest for nets in %s" ), name );
2141  setting->ctl_visibility->SetToolTip( tip );
2142 
2143  setting->ctl_text = new wxStaticText( setting->ctl_panel, aId, name );
2144  setting->ctl_text->Wrap( -1 );
2145 
2146  int flags = wxALIGN_CENTER_VERTICAL;
2147 
2148  sizer->Add( setting->ctl_color, 0, flags | wxRESERVE_SPACE_EVEN_IF_HIDDEN, 5 );
2149  sizer->AddSpacer( 7 );
2150  sizer->Add( setting->ctl_visibility, 0, flags, 5 );
2151  sizer->AddSpacer( 3 );
2152  sizer->Add( setting->ctl_text, 1, flags, 5 );
2153 
2154  m_netclassOuterSizer->Add( setting->ctl_panel, 0, wxEXPAND, 5 );
2155  m_netclassOuterSizer->AddSpacer( 2 );
2156 
2157  setting->ctl_visibility->Bind( TOGGLE_CHANGED,
2159  this );
2160 
2161  auto menuHandler =
2162  [&, name, isDefaultClass]( wxMouseEvent& aEvent )
2163  {
2165 
2166  wxMenu menu;
2167 
2168  if( !isDefaultClass)
2169  {
2170  menu.Append( new wxMenuItem( &menu, ID_SET_NET_COLOR,
2171  _( "Set Netclass Color" ), wxEmptyString,
2172  wxITEM_NORMAL ) );
2173  }
2174 
2175  menu.Append( new wxMenuItem( &menu, ID_HIGHLIGHT_NET,
2176  wxString::Format( _( "Highlight Nets in %s" ), name ),
2177  wxEmptyString, wxITEM_NORMAL ) );
2178  menu.Append( new wxMenuItem( &menu, ID_SELECT_NET,
2179  wxString::Format( _( "Select Tracks and Vias in %s" ),
2180  name ),
2181  wxEmptyString, wxITEM_NORMAL ) );
2182  menu.Append( new wxMenuItem( &menu, ID_DESELECT_NET,
2183  wxString::Format( _( "Unselect Tracks and Vias in %s" ),
2184  name ),
2185  wxEmptyString, wxITEM_NORMAL ) );
2186 
2187  menu.AppendSeparator();
2188 
2189  menu.Append( new wxMenuItem( &menu, ID_SHOW_ALL_NETS,
2190  _( "Show All Netclasses" ), wxEmptyString,
2191  wxITEM_NORMAL ) );
2192  menu.Append( new wxMenuItem( &menu, ID_HIDE_OTHER_NETS,
2193  _( "Hide All Other Netclasses" ), wxEmptyString,
2194  wxITEM_NORMAL ) );
2195 
2196  menu.Bind( wxEVT_COMMAND_MENU_SELECTED,
2198 
2199  PopupMenu( &menu );
2200  };
2201 
2202  setting->ctl_panel->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2203  setting->ctl_visibility->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2204  setting->ctl_color->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2205  setting->ctl_text->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2206  };
2207 
2208  const NETCLASS_MAP& classes = board->GetDesignSettings().GetNetClasses().NetClasses();
2209 
2210  std::vector<wxString> names;
2211 
2212  for( const auto& pair : classes )
2213  names.emplace_back( pair.first );
2214 
2215  std::sort( names.begin(), names.end() );
2216 
2217  m_netclassIdMap.clear();
2218 
2219  int idx = wxID_HIGHEST;
2220 
2221  NETCLASSPTR defaultClass = board->GetDesignSettings().GetNetClasses().GetDefault();
2222 
2223  m_netclassIdMap[idx] = defaultClass->GetName();
2224  appendNetclass( idx++, defaultClass, true );
2225 
2226  for( const wxString& name : names )
2227  {
2228  m_netclassIdMap[idx] = name;
2229  appendNetclass( idx++, classes.at( name ) );
2230  }
2231 
2232  m_netclassOuterSizer->Layout();
2233 
2234  m_netsTable->Rebuild();
2235  m_panelNets->GetSizer()->Layout();
2236 }
2237 
2238 
2240 {
2241  m_cbLayerPresets->Clear();
2242 
2243  for( std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
2244  m_cbLayerPresets->Append( pair.first, static_cast<void*>( &pair.second ) );
2245 
2246  m_cbLayerPresets->Append( wxT( "-----" ) );
2247  m_cbLayerPresets->Append( _( "Save preset..." ) );
2248  m_cbLayerPresets->Append( _( "Delete preset..." ) );
2249 
2250  m_cbLayerPresets->SetSelection( 0 );
2251 
2252  // At least the build in presets should always be present
2253  wxASSERT( !m_layerPresets.empty() );
2254 
2255  // Default preset: all layers
2257 }
2258 
2259 
2261 {
2262  LSET visibleLayers = getVisibleLayers();
2263  GAL_SET visibleObjects = getVisibleObjects();
2264 
2265  auto it = std::find_if( m_layerPresets.begin(), m_layerPresets.end(),
2266  [&]( const std::pair<const wxString, LAYER_PRESET>& aPair )
2267  {
2268  return ( aPair.second.layers == visibleLayers
2269  && aPair.second.renderLayers == visibleObjects );
2270  } );
2271 
2272  if( it != m_layerPresets.end() )
2273  m_cbLayerPresets->SetStringSelection( it->first );
2274  else
2275  m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator
2276 
2277  m_currentPreset = static_cast<LAYER_PRESET*>(
2278  m_cbLayerPresets->GetClientData( m_cbLayerPresets->GetSelection() ) );
2279 }
2280 
2281 
2283 {
2284  int idx = m_cbLayerPresets->FindString( aName );
2285 
2286  if( idx >= 0 && m_cbLayerPresets->GetSelection() != idx )
2287  {
2288  m_cbLayerPresets->SetSelection( idx );
2289  m_currentPreset = static_cast<LAYER_PRESET*>( m_cbLayerPresets->GetClientData( idx ) );
2290  }
2291  else if( idx < 0 )
2292  {
2293  m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator
2294  }
2295 }
2296 
2297 
2298 void APPEARANCE_CONTROLS::onLayerPresetChanged( wxCommandEvent& aEvent )
2299 {
2300  int count = m_cbLayerPresets->GetCount();
2301  int index = m_cbLayerPresets->GetSelection();
2302 
2303  auto resetSelection =
2304  [&]()
2305  {
2306  if( m_currentPreset )
2307  m_cbLayerPresets->SetStringSelection( m_currentPreset->name );
2308  else
2309  m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 );
2310  };
2311 
2312  if( index == count - 3 )
2313  {
2314  // Separator: reject the selection
2315  resetSelection();
2316  return;
2317  }
2318  else if( index == count - 2 )
2319  {
2320  // Save current state to new preset
2321  wxString name;
2322 
2325 
2326  wxTextEntryDialog dlg( this, _( "Layer preset name:" ), _( "Save Layer Preset" ), name );
2327 
2328  if( dlg.ShowModal() != wxID_OK )
2329  {
2330  resetSelection();
2331  return;
2332  }
2333 
2334  name = dlg.GetValue();
2335  bool exists = m_layerPresets.count( name );
2336 
2337  if( !exists )
2338  {
2341  }
2342 
2343  LAYER_PRESET* preset = &m_layerPresets[name];
2344  m_currentPreset = preset;
2345 
2346  if( !exists )
2347  {
2348  index = m_cbLayerPresets->Insert( name, index - 1, static_cast<void*>( preset ) );
2349  }
2350  else
2351  {
2352  index = m_cbLayerPresets->FindString( name );
2353  m_presetMRU.Remove( name );
2354  }
2355 
2356  m_cbLayerPresets->SetSelection( index );
2357  m_presetMRU.Insert( name, 0 );
2358 
2359  return;
2360  }
2361  else if( index == count - 1 )
2362  {
2363  // Delete a preset
2364  wxArrayString headers;
2365  std::vector<wxArrayString> items;
2366 
2367  headers.Add( _( "Presets" ) );
2368 
2369  for( std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
2370  {
2371  if( !pair.second.readOnly )
2372  {
2373  wxArrayString item;
2374  item.Add( pair.first );
2375  items.emplace_back( item );
2376  }
2377  }
2378 
2379  EDA_LIST_DIALOG dlg( m_frame, _( "Delete Preset" ), headers, items );
2380  dlg.SetListLabel( _( "Select preset:" ) );
2381 
2382  if( dlg.ShowModal() == wxID_OK )
2383  {
2384  wxString presetName = dlg.GetTextSelection();
2385  int idx = m_cbLayerPresets->FindString( presetName );
2386 
2387  if( idx != wxNOT_FOUND )
2388  {
2389  m_layerPresets.erase( presetName );
2390 
2391  m_cbLayerPresets->Delete( idx );
2392  m_currentPreset = nullptr;
2393 
2394  m_presetMRU.Remove( presetName );
2395  }
2396  }
2397 
2398  resetSelection();
2399  return;
2400  }
2401 
2402  LAYER_PRESET* preset = static_cast<LAYER_PRESET*>( m_cbLayerPresets->GetClientData( index ) );
2403  m_currentPreset = preset;
2404 
2405  m_lastSelectedUserPreset = ( !preset || preset->readOnly ) ? nullptr : preset;
2406 
2407  if( preset )
2408  doApplyLayerPreset( *preset );
2409 
2410  if( !m_currentPreset->name.IsEmpty() )
2411  {
2412  m_presetMRU.Remove( m_currentPreset->name );
2413  m_presetMRU.Insert( m_currentPreset->name, 0 );
2414  }
2415 
2416  passOnFocus();
2417 }
2418 
2419 
2421 {
2422  BOARD* board = m_frame->GetBoard();
2423 
2424  setVisibleLayers( aPreset.layers );
2425  setVisibleObjects( aPreset.renderLayers );
2426 
2427  // If the preset doesn't have an explicit active layer to restore, we can at least
2428  // force the active layer to be something in the preset's layer set
2429  PCB_LAYER_ID activeLayer = UNSELECTED_LAYER;
2430 
2431  if( aPreset.activeLayer != UNSELECTED_LAYER )
2432  activeLayer = aPreset.activeLayer;
2433  else if( aPreset.layers.any() && !aPreset.layers.test( m_frame->GetActiveLayer() ) )
2434  activeLayer = *aPreset.layers.Seq().begin();
2435 
2436  LSET boardLayers = board->GetLayerSet();
2437 
2438  if( activeLayer != UNSELECTED_LAYER && boardLayers.Contains( activeLayer ) )
2439  m_frame->SetActiveLayer( activeLayer );
2440 
2441  if( !m_isFpEditor )
2442  m_frame->GetCanvas()->SyncLayersVisibility( board );
2443 
2444  m_frame->GetCanvas()->Refresh();
2445 
2447 }
2448 
2449 
2450 void APPEARANCE_CONTROLS::OnColorSwatchChanged( wxCommandEvent& aEvent )
2451 {
2452  COLOR_SWATCH* swatch = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
2453  COLOR4D newColor = swatch->GetSwatchColor();
2454  LAYER_NUM layer = swatch->GetId();
2455 
2457  cs->SetColor( layer, newColor );
2458 
2460 
2461  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
2462  view->UpdateLayerColor( layer );
2463  view->UpdateLayerColor( GetNetnameLayer( layer ) );
2464 
2465  if( IsCopperLayer( layer ) )
2466  view->UpdateLayerColor( ZONE_LAYER_FOR( layer ) );
2467 
2468  // Update the bitmap of the layer box
2469  if( m_frame->IsType( FRAME_PCB_EDITOR ) )
2470  static_cast<PCB_EDIT_FRAME*>( m_frame )->ReCreateLayerBox( false );
2471 
2472  m_frame->GetCanvas()->Refresh();
2473 
2474  if( layer == LAYER_PCB_BACKGROUND )
2475  m_frame->SetDrawBgColor( newColor );
2476 
2477  passOnFocus();
2478 }
2479 
2480 
2481 void APPEARANCE_CONTROLS::onObjectOpacitySlider( int aLayer, float aOpacity )
2482 {
2484 
2485  switch( aLayer )
2486  {
2487  case static_cast<int>( LAYER_TRACKS ): options.m_TrackOpacity = aOpacity; break;
2488  case static_cast<int>( LAYER_VIAS ): options.m_ViaOpacity = aOpacity; break;
2489  case static_cast<int>( LAYER_PADS ): options.m_PadOpacity = aOpacity; break;
2490  case static_cast<int>( LAYER_ZONES ): options.m_ZoneOpacity = aOpacity; break;
2491  default: return;
2492  }
2493 
2494  m_frame->SetDisplayOptions( options );
2495  passOnFocus();
2496 }
2497 
2498 
2499 void APPEARANCE_CONTROLS::onNetContextMenu( wxCommandEvent& aEvent )
2500 {
2501  wxASSERT( m_netsGrid->GetSelectedRows().size() == 1 );
2502 
2503  int row = m_netsGrid->GetSelectedRows()[0];
2504  NET_GRID_ENTRY& net = m_netsTable->GetEntry( row );
2505 
2506  m_netsGrid->ClearSelection();
2507 
2508  switch( aEvent.GetId() )
2509  {
2510  case ID_SET_NET_COLOR:
2511  {
2512  wxGridCellEditor* editor = m_netsGrid->GetCellEditor( row, NET_GRID_TABLE::COL_COLOR );
2513  editor->BeginEdit( row, NET_GRID_TABLE::COL_COLOR, m_netsGrid );
2514  break;
2515  }
2516 
2517  case ID_HIGHLIGHT_NET:
2518  {
2520  static_cast<intptr_t>( net.code ) );
2521  m_frame->GetCanvas()->Refresh();
2522  break;
2523  }
2524 
2525  case ID_SELECT_NET:
2526  {
2528  static_cast<intptr_t>( net.code ) );
2529  m_frame->GetCanvas()->Refresh();
2530  break;
2531  }
2532 
2533  case ID_DESELECT_NET:
2534  {
2536  static_cast<intptr_t>( net.code ) );
2537  m_frame->GetCanvas()->Refresh();
2538  break;
2539  }
2540 
2541  case ID_SHOW_ALL_NETS:
2543  break;
2544 
2545  case ID_HIDE_OTHER_NETS:
2546  m_netsTable->HideOtherNets( net );
2547  break;
2548 
2549  default:
2550  break;
2551  }
2552 
2553  passOnFocus();
2554 }
2555 
2556 
2558 {
2559  wxString className = netclassNameFromEvent( aEvent );
2560  bool show = aEvent.GetInt();
2561  showNetclass( className, show );
2562  passOnFocus();
2563 }
2564 
2565 
2566 void APPEARANCE_CONTROLS::showNetclass( const wxString& aClassName, bool aShow )
2567 {
2568  BOARD* board = m_frame->GetBoard();
2569  NETINFO_LIST& nets = board->GetNetInfo();
2570  NETCLASSES& classes = board->GetDesignSettings().GetNetClasses();
2571  NETCLASSPTR netclass = classes.Find( aClassName );
2572  TOOL_MANAGER* manager = m_frame->GetToolManager();
2573 
2574  if( !netclass )
2575  return;
2576 
2577  NETCLASS* defaultClass = classes.GetDefaultPtr();
2578 
2579  if( netclass == classes.GetDefault() )
2580  {
2581  const TOOL_ACTION& action = aShow ? PCB_ACTIONS::showNet : PCB_ACTIONS::hideNet;
2582 
2583  for( NETINFO_ITEM* net : nets )
2584  {
2585  if( net->GetNetClass() == defaultClass )
2586  {
2587  manager->RunAction( action, true, static_cast<intptr_t>( net->GetNetCode() ) );
2588 
2589  int row = m_netsTable->GetRowByNetcode( net->GetNetCode() );
2590 
2591  if( row >= 0 )
2593  }
2594  }
2595  }
2596  else
2597  {
2598  const TOOL_ACTION& action = aShow ? PCB_ACTIONS::showNet : PCB_ACTIONS::hideNet;
2599 
2600  for( const wxString& member : *netclass )
2601  {
2602  if( NETINFO_ITEM* net = nets.GetNetItem( member ) )
2603  {
2604  int code = net->GetNetCode();
2605  manager->RunAction( action, true, static_cast<intptr_t>( code ) );
2606 
2607  int row = m_netsTable->GetRowByNetcode( code );
2608 
2609  if( row >= 0 )
2611  }
2612  }
2613  }
2614 
2615  m_netsGrid->ForceRefresh();
2616 }
2617 
2618 
2619 void APPEARANCE_CONTROLS::onNetclassColorChanged( wxCommandEvent& aEvent )
2620 {
2621  KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>(
2623 
2624  std::map<wxString, KIGFX::COLOR4D>& netclassColors = rs->GetNetclassColorMap();
2625 
2626  COLOR_SWATCH* swatch = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
2627  wxString className = netclassNameFromEvent( aEvent );
2628 
2629  netclassColors[className] = swatch->GetSwatchColor();
2630 
2633  m_frame->GetCanvas()->Refresh();
2634 }
2635 
2636 
2638 {
2639  COLOR_SWATCH* s = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
2640  int classId = s->GetId();
2641 
2642  wxASSERT( m_netclassIdMap.count( classId ) );
2643  return m_netclassIdMap.at( classId );
2644 }
2645 
2646 
2647 void APPEARANCE_CONTROLS::onNetColorModeChanged( wxCommandEvent& aEvent )
2648 {
2650 
2651  if( m_rbNetColorAll->GetValue() )
2653  else if( m_rbNetColorRatsnest->GetValue() )
2655  else
2657 
2658  m_frame->SetDisplayOptions( options );
2660  passOnFocus();
2661 }
2662 
2663 
2664 void APPEARANCE_CONTROLS::onRatsnestModeChanged( wxCommandEvent& aEvent )
2665 {
2667 
2668  if( m_rbRatsnestAllLayers->GetValue() )
2670  else
2672 
2673  m_frame->SetDisplayOptions( options );
2675  passOnFocus();
2676 }
2677 
2678 
2679 void APPEARANCE_CONTROLS::onNetclassContextMenu( wxCommandEvent& aEvent )
2680 {
2681  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
2683  static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
2684 
2685  BOARD* board = m_frame->GetBoard();
2686  NETINFO_LIST& nets = board->GetNetInfo();
2687  NETCLASSES& classes = board->GetDesignSettings().GetNetClasses();
2688  NETCLASSPTR netclass = classes.Find( m_contextMenuNetclass );
2689 
2692 
2693  NETCLASSPTR defaultClass = classes.GetDefault();
2694  wxString defaultClassName = defaultClass->GetName();
2695 
2696  auto runOnNetsOfClass =
2697  [&]( NETCLASSPTR aClass, std::function<void( NETINFO_ITEM* )> aFunction )
2698  {
2699  if( aClass == defaultClass )
2700  {
2701  for( NETINFO_ITEM* net : nets )
2702  if( net->GetNetClass() == defaultClass.get() )
2703  aFunction( net );
2704  }
2705  else
2706  {
2707  for( const wxString& netName : *aClass )
2708  aFunction( nets.GetNetItem( netName ) );
2709  }
2710  };
2711 
2712  switch( aEvent.GetId() )
2713  {
2714  case ID_SET_NET_COLOR:
2715  {
2716  if( setting )
2717  {
2718  setting->ctl_color->GetNewSwatchColor();
2719 
2720  COLOR4D color = setting->ctl_color->GetSwatchColor();
2721 
2722  std::map<wxString, KIGFX::COLOR4D>& netclassColors = rs->GetNetclassColorMap();
2723 
2724  if( color != COLOR4D::UNSPECIFIED )
2725  netclassColors[m_contextMenuNetclass] = color;
2726  else
2727  netclassColors.erase( m_contextMenuNetclass );
2728 
2729  view->UpdateAllLayersColor();
2730  }
2731 
2732  break;
2733  }
2734 
2735  case ID_HIGHLIGHT_NET:
2736  {
2737  if( netclass )
2738  {
2739  runOnNetsOfClass( netclass,
2740  [&]( NETINFO_ITEM* aItem )
2741  {
2742  if( !aItem )
2743  return;
2744 
2745  static bool first = true;
2746  int code = aItem->GetNetCode();
2747 
2748  if( first )
2749  {
2750  board->SetHighLightNet( code );
2751  rs->SetHighlight( true, code );
2752  first = false;
2753  }
2754  else
2755  {
2756  board->SetHighLightNet( code, true );
2757  rs->SetHighlight( true, code, true );
2758  }
2759  } );
2760 
2761  view->UpdateAllLayersColor();
2762  board->HighLightON();
2763  }
2764  break;
2765  }
2766 
2767  case ID_SELECT_NET:
2768  case ID_DESELECT_NET:
2769  {
2770  if( netclass )
2771  {
2772  TOOL_ACTION& action = aEvent.GetId() == ID_SELECT_NET ? PCB_ACTIONS::selectNet :
2774  runOnNetsOfClass( netclass,
2775  [&]( NETINFO_ITEM* aItem )
2776  {
2777  if( !aItem )
2778  return;
2779 
2780  intptr_t code = static_cast<intptr_t>( aItem->GetNetCode() );
2781  m_frame->GetToolManager()->RunAction( action, true, code );
2782  } );
2783  }
2784  break;
2785  }
2786 
2787  case ID_SHOW_ALL_NETS:
2788  {
2789  showNetclass( defaultClassName );
2790  wxASSERT( m_netclassSettingsMap.count( defaultClassName ) );
2791  m_netclassSettingsMap.at( defaultClassName )->ctl_visibility->SetValue( true );
2792 
2793  for( const auto& pair : classes.NetClasses() )
2794  {
2795  showNetclass( pair.first );
2796 
2797  if( m_netclassSettingsMap.count( pair.first ) )
2798  m_netclassSettingsMap.at( pair.first )->ctl_visibility->SetValue( true );
2799  }
2800 
2801  break;
2802  }
2803 
2804  case ID_HIDE_OTHER_NETS:
2805  {
2806  bool showDefault = m_contextMenuNetclass == defaultClassName;
2807  showNetclass( defaultClassName, showDefault );
2808  wxASSERT( m_netclassSettingsMap.count( defaultClassName ) );
2809  m_netclassSettingsMap.at( defaultClassName )->ctl_visibility->SetValue( showDefault );
2810 
2811  for( const auto& pair : classes.NetClasses() )
2812  {
2813  bool show = pair.first == m_contextMenuNetclass;
2814 
2815  showNetclass( pair.first, show );
2816 
2817  if( m_netclassSettingsMap.count( pair.first ) )
2818  m_netclassSettingsMap.at( pair.first )->ctl_visibility->SetValue( show );
2819  }
2820 
2821  break;
2822  }
2823 
2824  default:
2825  break;
2826  }
2827 
2829  m_frame->GetCanvas()->Refresh();
2830 
2831  m_contextMenuNetclass.clear();
2832 }
2833 
2834 
2836 {
2837  m_focusOwner->SetFocus();
2838 }
2839 
2840 
2842 {
2843  WX_INFOBAR* infobar = m_frame->GetInfoBar();
2844 
2845  wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY, _( "Open Preferences" ),
2846  wxEmptyString );
2847 
2848  button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
2849  [&]( wxHyperlinkEvent& aEvent )
2850  {
2851  wxCommandEvent dummy;
2853  } ) );
2854 
2855  infobar->RemoveAllButtons();
2856  infobar->AddButton( button );
2857  infobar->AddCloseButton();
2858 
2859  infobar->ShowMessageFor( _( "The current color theme is read-only. Create a new theme in "
2860  "Preferences to enable color editing." ),
2861  10000, wxICON_INFORMATION );
2862 }
2863 
2864 
2866 {
2867  m_paneLayerDisplayOptions->Refresh();
2868 }
static std::set< int > s_allowedInFpEditor
These GAL layers are shown in the Objects tab in the footprint editor.
void OnSize(wxSizeEvent &aEvent) override
void OnBoardItemChanged(BOARD &aBoard, BOARD_ITEM *aItem) 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
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:1990
A saved set of layers that are visible.
std::set< int > & GetHiddenNets()
Definition: pcb_painter.h:187
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
std::map< PCB_LAYER_ID, APPEARANCE_SETTING * > m_layerSettingsMap
void AddButton(wxButton *aButton)
Add an already created button to the infobar.
Definition: infobar.cpp:245
void OnNetGridMouseEvent(wxMouseEvent &aEvent)
#define RR
Icon provider for the "standard" row indicators, for example in layer selection lists.
void SetDrawBgColor(const COLOR4D &aColor) override
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:538
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:361
void * GetValueAsCustom(int aRow, int aCol, const wxString &aTypeName) override
layer for drc markers with SEVERITY_ERROR
Definition: layer_ids.h:211
void HideOtherNets(const NET_GRID_ENTRY &aNet)
void ApplyLayerPreset(const wxString &aPresetName)
Ratsnest lines are drawn to items on visible layers only.
#define ON
void OnBoardItemsChanged(BOARD &aBoard, std::vector< BOARD_ITEM * > &aItems) override
Update the colors on all the widgets from the new chosen color theme.
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
static TOOL_ACTION hideNet
Definition: pcb_actions.h:454
Meta control for all pads opacity/visibility (color ignored)
Definition: layer_ids.h:225
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:257
double m_TrackOpacity
Opacity override for all tracks.
show footprints values (when texts are visible)
Definition: layer_ids.h:205
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.
GAL_LAYER_ID
GAL layers are "virtual" layers, i.e.
Definition: layer_ids.h:184
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.
Definition: layer_ids.h:573
void onNetColorModeChanged(wxCommandEvent &aEvent)
int color
Definition: DXF_plotter.cpp:57
wxRadioButton * m_rbNetColorOff
double m_ViaOpacity
Opacity override for all types of via.
wxStaticLine * m_layerDisplaySeparator
void idleFocusHandler(wxIdleEvent &aEvent)
GAL_LAYER_ID ToGalLayer(int aInteger)
Definition: layer_ids.h:261
wxFont GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:141
Net/netclass colors are shown on all net copper.
Net/netclass colors are shown on ratsnest lines only.
wxRadioButton * m_rbRatsnestAllLayers
PROJECT * GetProject() const
Definition: board.h:360
anchor of items having an anchor point (texts, footprints)
Definition: layer_ids.h:196
LSET GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:480
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:505
int LAYER_NUM
This can be replaced with int and removed.
Definition: layer_ids.h:40
void SetColor(int aLayer, const COLOR4D &aColor)
static void * ColorToVoid(COLOR4D &aColor)
void OnBoardItemAdded(BOARD &aBoard, BOARD_ITEM *aItem) override
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
show footprints on back
Definition: layer_ids.h:204
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:466
wxGridCellAttr * m_defaultAttr
void OnNetGridClick(wxGridEvent &event) override
void ShowMessageFor(const wxString &aMessage, int aTime, int aFlags=wxICON_INFORMATION, MESSAGE_TYPE aType=WX_INFOBAR::MESSAGE_TYPE::GENERIC)
Show the infobar with the provided message and icon for a specific period of time.
Definition: infobar.cpp:128
void SetReadOnly(bool aReadOnly=true)
Definition: color_swatch.h:109
#define ZONE_LAYER_FOR(copperLayer)
Macro for getting the zone layer for a given copper layer.
Definition: layer_ids.h:251
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:72
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:589
GAL_SET renderLayers
Render layers (e.g. object types) that are visible.
void OnBoardItemsRemoved(BOARD &aBoard, std::vector< BOARD_ITEM * > &aItems) override
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:208
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
Control for copper zone opacity/visibility (color ignored)
Definition: layer_ids.h:226
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
int GetNetnameLayer(int aLayer)
Returns a netname layer corresponding to the given layer.
Definition: layer_ids.h:932
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:72
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)
void OnBoardItemRemoved(BOARD &aBoard, BOARD_ITEM *aItem) override
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)
representing a row indicator icon for use in places like the layer widget
double a
Alpha component.
Definition: color4d.h:374
void OnBoardNetSettingsChanged(BOARD &aBoard) override
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:502
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)
#define GAL_LAYER_INDEX(x)
Use this macro to convert a GAL layer to a 0-indexed offset from LAYER_VIAS.
Definition: layer_ids.h:248
Meta control for all vias opacity/visibility.
Definition: layer_ids.h:188
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:609
bool IsGridVisible() const
wxGridCellAttr * m_labelAttr
Container for NETINFO_ITEM elements, which are the nets.
Definition: netinfo.h:315
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:498
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:526
void OnSetFocus(wxFocusEvent &aEvent) override
ROW_ICON_PROVIDER * m_iconProvider
void setVisibleLayers(LSET aLayers)
void doApplyLayerPreset(const LAYER_PRESET &aPreset)
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.
text marked as invisible
Definition: layer_ids.h:195
COLOR4D GetDefaultColor(int aLayer)
show footprints on front
Definition: layer_ids.h:203
Helper for storing and iterating over GAL_LAYER_IDs.
Definition: layer_ids.h:278
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
wxRadioButton * m_rbHighContrastNormal
static GAL_SET DefaultVisible()
Definition: lset.cpp:933
Virtual layers for stacking zones and tracks on a given copper layer.
Definition: layer_ids.h:241
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:388
wxGridCellAttr * GetAttr(int aRow, int aCol, wxGridCellAttr::wxAttrKind) override
drawingsheet frame and titleblock
Definition: layer_ids.h:212
virtual void SetActiveLayer(PCB_LAYER_ID aLayer)
LSET layers
Board layers that are visible.
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
void OnBoardItemsAdded(BOARD &aBoard, std::vector< BOARD_ITEM * > &aItems) override
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.
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:286
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: layer_ids.h:463
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:787
double m_ZoneOpacity
Opacity override for filled zone areas.
void UpdateColors()
Update the color settings in the painter and GAL.
void onLayerPresetChanged(wxCommandEvent &aEvent) override
bool IsMirroredX() const
Return true if view is flipped across the X axis.
Definition: view.h:238
wxRadioButton * m_rbHighContrastDim
NET_GRID_ENTRY & GetEntry(int aRow)
bool GetValueAsBool(int aRow, int aCol) override
show a marker on pads with no nets
Definition: layer_ids.h:202
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
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:754
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.
show footprints references (when texts are visible)
Definition: layer_ids.h:206
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:455
int GetId() const
Return the unique id of the TOOL_ACTION object.
Definition: tool_action.h:121
static TOOL_ACTION highlightNet
Definition: pcb_actions.h:449
multilayer pads, usually with holes
Definition: layer_ids.h:208
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:56
layer for drc markers which have been individually excluded
Definition: layer_ids.h:231
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.
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:64
Net (and netclass) colors are not shown.
static TOOL_ACTION listNets
Definition: pcb_actions.h:341
A toggle button renderer for a wxGrid, similar to BITMAP_TOGGLE.
Definition: layer_ids.h:70
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:454
wxString netclassNameFromEvent(wxEvent &aEvent)
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
wxString GetValue(int aRow, int aCol) override
The main frame for Pcbnew.
A simple color swatch of the kind used to set layer colors.
Definition: color_swatch.h:56
void SetValue(int aRow, int aCol, const wxString &aValue) override
void OnNotebookPageChanged(wxNotebookEvent &event) override
void onLayerLeftClick(wxMouseEvent &aEvent)
layer for drc markers with SEVERITY_WARNING
Definition: layer_ids.h:230
bool IsReadOnly() const
Definition: json_settings.h:82
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
PCB background color.
Definition: layer_ids.h:215
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.
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()
GAL_SET & set()
Definition: layer_ids.h:294
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
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:291
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:68
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:775
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:53
wxStaticText * m_staticTextContrastModeTitle
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
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:405
void AddCloseButton(const wxString &aTooltip=_("Hide this message."))
Add the default close button to the infobar on the right side.
Definition: infobar.cpp:276
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)
Definition: layer_ids.h:312
int GetNetCode() const
Definition: netinfo.h:113