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 <[email protected]>
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, _( "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  SetBorders( true, false, false, false );
417 
418  m_layersOuterSizer = new wxBoxSizer( wxVERTICAL );
419  m_windowLayers->SetSizer( m_layersOuterSizer );
420  m_windowLayers->SetScrollRate( 0, 5 );
421  m_windowLayers->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS::OnSetFocus, this );
422 
423  m_objectsOuterSizer = new wxBoxSizer( wxVERTICAL );
425  m_windowObjects->SetScrollRate( 0, 5 );
426  m_windowObjects->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS::OnSetFocus, this );
427 
428  wxFont infoFont = KIUI::GetInfoFont( this );
429  m_staticTextNets->SetFont( infoFont );
430  m_staticTextNetClasses->SetFont( infoFont );
431  m_panelLayers->SetFont( infoFont );
432  m_windowLayers->SetFont( infoFont );
433  m_windowObjects->SetFont( infoFont );
434  m_presetsLabel->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, &APPEARANCE_CONTROLS::OnNetGridMouseEvent,
546  this );
547 
548  // To handle middle click on color swatches
549  m_netsGrid->GetGridWindow()->Bind( wxEVT_MIDDLE_UP, &APPEARANCE_CONTROLS::OnNetGridMouseEvent,
550  this );
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  int hotkey;
579  wxString msg;
580  wxFont infoFont = KIUI::GetInfoFont( this );
581 
582  // Create layer display options
584  _( "Layer Display Options" ) );
586  m_paneLayerDisplayOptions->SetBackgroundColour( m_notebook->GetThemeBackgroundColour() );
587 
588  wxWindow* layerDisplayPane = m_paneLayerDisplayOptions->GetPane();
589 
590  wxBoxSizer* layerDisplayOptionsSizer;
591  layerDisplayOptionsSizer = new wxBoxSizer( wxVERTICAL );
592 
594 
595  if( hotkey )
596  msg = wxString::Format( _( "Inactive layers (%s):" ), KeyNameFromKeyCode( hotkey ) );
597  else
598  msg = _( "Inactive layers:" );
599 
600  m_inactiveLayersLabel = new wxStaticText( layerDisplayPane, wxID_ANY, msg );
601  m_inactiveLayersLabel->SetFont( infoFont );
602  m_inactiveLayersLabel->Wrap( -1 );
603  layerDisplayOptionsSizer->Add( m_inactiveLayersLabel, 0, wxEXPAND | wxBOTTOM | wxLEFT, 2 );
604 
605  wxBoxSizer* contrastModeSizer;
606  contrastModeSizer = new wxBoxSizer( wxHORIZONTAL );
607 
608  m_rbHighContrastNormal = new wxRadioButton( layerDisplayPane, wxID_ANY, _( "Normal" ),
609  wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
610  m_rbHighContrastNormal->SetFont( infoFont );
611  m_rbHighContrastNormal->SetValue( true );
612  m_rbHighContrastNormal->SetToolTip( _( "Inactive layers will be shown in full color" ) );
613 
614  contrastModeSizer->Add( m_rbHighContrastNormal, 0, wxRIGHT, 5 );
615  contrastModeSizer->AddStretchSpacer();
616 
617  m_rbHighContrastDim = new wxRadioButton( layerDisplayPane, wxID_ANY, _( "Dim" ) );
618  m_rbHighContrastDim->SetFont( infoFont );
619  m_rbHighContrastDim->SetToolTip( _( "Inactive layers will be dimmed" ) );
620 
621  contrastModeSizer->Add( m_rbHighContrastDim, 0, wxRIGHT, 5 );
622  contrastModeSizer->AddStretchSpacer();
623 
624  m_rbHighContrastOff = new wxRadioButton( layerDisplayPane, wxID_ANY, _( "Hide" ) );
625  m_rbHighContrastOff->SetFont( infoFont );
626  m_rbHighContrastOff->SetToolTip( _( "Inactive layers will be hidden" ) );
627 
628  contrastModeSizer->Add( m_rbHighContrastOff, 0, 0, 5 );
629  contrastModeSizer->AddStretchSpacer();
630 
631  layerDisplayOptionsSizer->Add( contrastModeSizer, 0, wxEXPAND, 5 );
632 
633  m_layerDisplaySeparator = new wxStaticLine( layerDisplayPane, wxID_ANY, wxDefaultPosition,
634  wxDefaultSize, wxLI_HORIZONTAL );
635  layerDisplayOptionsSizer->Add( m_layerDisplaySeparator, 0, wxEXPAND | wxTOP | wxBOTTOM, 5 );
636 
637  m_cbFlipBoard = new wxCheckBox( layerDisplayPane, wxID_ANY, _( "Flip board view" ) );
638  m_cbFlipBoard->SetFont( infoFont );
639  layerDisplayOptionsSizer->Add( m_cbFlipBoard, 0, 0, 5 );
640 
641  layerDisplayPane->SetSizer( layerDisplayOptionsSizer );
642  layerDisplayPane->Layout();
643  layerDisplayOptionsSizer->Fit( layerDisplayPane );
644 
645  m_panelLayersSizer->Add( m_paneLayerDisplayOptions, 0, wxEXPAND | wxTOP, 5 );
646 
647  m_paneLayerDisplayOptions->Bind( WX_COLLAPSIBLE_PANE_CHANGED,
648  [&]( wxCommandEvent& aEvent )
649  {
650  Freeze();
651  m_panelLayers->Fit();
652  m_sizerOuter->Layout();
653  Thaw();
654  } );
655 
656  // Create net display options
657 
659  _( "Net Display Options" ) );
661  m_paneNetDisplayOptions->SetBackgroundColour( m_notebook->GetThemeBackgroundColour() );
662 
663  wxWindow* netDisplayPane = m_paneNetDisplayOptions->GetPane();
664  wxBoxSizer* netDisplayOptionsSizer = new wxBoxSizer( wxVERTICAL );
665 
667 
669 
670  if( hotkey )
671  msg = wxString::Format( _( "Net colors (%s):" ), KeyNameFromKeyCode( hotkey ) );
672  else
673  msg = _( "Net colors:" );
674 
675  m_txtNetDisplayTitle = new wxStaticText( netDisplayPane, wxID_ANY, msg );
676  m_txtNetDisplayTitle->SetFont( infoFont );
677  m_txtNetDisplayTitle->Wrap( -1 );
678  m_txtNetDisplayTitle->SetToolTip( _( "Choose when to show net and netclass colors" ) );
679 
680  netDisplayOptionsSizer->Add( m_txtNetDisplayTitle, 0, wxEXPAND | wxBOTTOM | wxLEFT, 2 );
681 
682  wxBoxSizer* netColorSizer = new wxBoxSizer( wxHORIZONTAL );
683 
684  m_rbNetColorAll = new wxRadioButton( netDisplayPane, wxID_ANY, _( "All" ), wxDefaultPosition,
685  wxDefaultSize, wxRB_GROUP );
686  m_rbNetColorAll->SetFont( infoFont );
687  m_rbNetColorAll->SetToolTip( _( "Net and netclass colors are shown on all copper items" ) );
688 
689  netColorSizer->Add( m_rbNetColorAll, 0, wxRIGHT, 5 );
690  netColorSizer->AddStretchSpacer();
691 
692  m_rbNetColorRatsnest = new wxRadioButton( netDisplayPane, wxID_ANY, _( "Ratsnest" ) );
693  m_rbNetColorRatsnest->SetFont( infoFont );
694  m_rbNetColorRatsnest->SetValue( true );
695  m_rbNetColorRatsnest->SetToolTip( _( "Net and netclass colors are shown on the ratsnest only" ) );
696 
697  netColorSizer->Add( m_rbNetColorRatsnest, 0, wxRIGHT, 5 );
698  netColorSizer->AddStretchSpacer();
699 
700  m_rbNetColorOff = new wxRadioButton( netDisplayPane, wxID_ANY, _( "None" ) );
701  m_rbNetColorOff->SetFont( infoFont );
702  m_rbNetColorOff->SetToolTip( _( "Net and netclass colors are not shown" ) );
703 
704  netColorSizer->Add( m_rbNetColorOff, 0, 0, 5 );
705 
706  netDisplayOptionsSizer->Add( netColorSizer, 0, wxEXPAND | wxBOTTOM, 5 );
707 
709 
711 
712  if( hotkey )
713  msg = wxString::Format( _( "Ratsnest display (%s):" ), KeyNameFromKeyCode( hotkey ) );
714  else
715  msg = _( "Ratsnest display:" );
716 
717  m_txtRatsnestVisibility = new wxStaticText( netDisplayPane, wxID_ANY, msg );
718  m_txtRatsnestVisibility->SetFont( infoFont );
719  m_txtRatsnestVisibility->Wrap( -1 );
720  m_txtRatsnestVisibility->SetToolTip( _( "Choose which ratsnest lines to display" ) );
721 
722  netDisplayOptionsSizer->Add( m_txtRatsnestVisibility, 0, wxEXPAND | wxBOTTOM | wxLEFT, 2 );
723 
724  wxBoxSizer* ratsnestDisplayModeSizer = new wxBoxSizer( wxHORIZONTAL );
725 
726  m_rbRatsnestAllLayers = new wxRadioButton( netDisplayPane, wxID_ANY, _( "All" ),
727  wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
728  m_rbRatsnestAllLayers->SetFont( infoFont );
729  m_rbRatsnestAllLayers->SetValue( true );
730  m_rbRatsnestAllLayers->SetToolTip( _( "Show ratsnest lines to items on all layers" ) );
731 
732  ratsnestDisplayModeSizer->Add( m_rbRatsnestAllLayers, 0, wxRIGHT, 5 );
733  ratsnestDisplayModeSizer->AddStretchSpacer();
734 
735  m_rbRatsnestVisLayers = new wxRadioButton( netDisplayPane, wxID_ANY, _( "Visible layers" ) );
736  m_rbRatsnestVisLayers->SetFont( infoFont );
737  m_rbRatsnestVisLayers->SetToolTip( _( "Show ratsnest lines to items on visible layers" ) );
738 
739  ratsnestDisplayModeSizer->Add( m_rbRatsnestVisLayers, 0, wxRIGHT, 5 );
740  ratsnestDisplayModeSizer->AddStretchSpacer();
741 
742  m_rbRatsnestNone = new wxRadioButton( netDisplayPane, wxID_ANY, _( "None" ) );
743  m_rbRatsnestNone->SetFont( infoFont );
744  m_rbRatsnestNone->SetToolTip( _( "Hide all ratsnest lines" ) );
745 
746  ratsnestDisplayModeSizer->Add( m_rbRatsnestNone, 0, 0, 5 );
747 
748  netDisplayOptionsSizer->Add( ratsnestDisplayModeSizer, 0, wxEXPAND | wxBOTTOM, 5 );
749 
751 
752  netDisplayPane->SetSizer( netDisplayOptionsSizer );
753  netDisplayPane->Layout();
754  netDisplayOptionsSizer->Fit( netDisplayPane );
755 
756  m_netsTabOuterSizer->Add( m_paneNetDisplayOptions, 0, wxEXPAND | wxTOP, 5 );
757 
758  m_paneNetDisplayOptions->Bind( WX_COLLAPSIBLE_PANE_CHANGED,
759  [&]( wxCommandEvent& aEvent )
760  {
761  Freeze();
762  m_panelNetsAndClasses->Fit();
763  m_sizerOuter->Layout();
764  passOnFocus();
765  Thaw();
766  } );
767 
768  m_rbNetColorAll->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onNetColorMode, this );
769  m_rbNetColorOff->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onNetColorMode, this );
770  m_rbNetColorRatsnest->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onNetColorMode, this );
771 
772  m_rbRatsnestAllLayers->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onRatsnestMode, this );
773  m_rbRatsnestVisLayers->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onRatsnestMode, this );
774  m_rbRatsnestNone->Bind( wxEVT_RADIOBUTTON, &APPEARANCE_CONTROLS::onRatsnestMode, this );
775 }
776 
777 
779 {
780  wxSize size( 220, 480 );
781  // TODO(JE) appropriate logic
782  return size;
783 }
784 
785 
786 void APPEARANCE_CONTROLS::OnNotebookPageChanged( wxNotebookEvent& aEvent )
787 {
788  // Work around wxMac issue where the notebook pages are blank
789 #ifdef __WXMAC__
790  int page = aEvent.GetSelection();
791 
792  if( page >= 0 )
793  m_notebook->ChangeSelection( static_cast<unsigned>( page ) );
794 #endif
795 
796 #ifndef __WXMSW__
797  // Because wxWidgets is broken and will send click events to children of the collapsible
798  // panes even if they are collapsed without this
799  Freeze();
800  m_panelLayers->Fit();
801  m_panelNetsAndClasses->Fit();
802  m_sizerOuter->Layout();
803  Thaw();
804 #endif
805 
806  Bind( wxEVT_IDLE, &APPEARANCE_CONTROLS::idleFocusHandler, this );
807 }
808 
809 
810 void APPEARANCE_CONTROLS::idleFocusHandler( wxIdleEvent& aEvent )
811 {
812  passOnFocus();
813  Unbind( wxEVT_IDLE, &APPEARANCE_CONTROLS::idleFocusHandler, this );
814 }
815 
816 
817 void APPEARANCE_CONTROLS::OnSetFocus( wxFocusEvent& aEvent )
818 {
819 #ifdef __WXMSW__
820  // In wxMSW, buttons won't process events unless they have focus, so we'll let it take the
821  // focus and give it back to the parent in the button event handler.
822  if( wxBitmapButton* btn = dynamic_cast<wxBitmapButton*>( aEvent.GetEventObject() ) )
823  {
824  wxCommandEvent evt( wxEVT_BUTTON );
825  wxPostEvent( btn, evt );
826  }
827 #endif
828 
829  passOnFocus();
830  aEvent.Skip();
831 }
832 
833 
834 void APPEARANCE_CONTROLS::OnSize( wxSizeEvent& aEvent )
835 {
836  aEvent.Skip();
837 }
838 
839 
840 void APPEARANCE_CONTROLS::OnNetGridClick( wxGridEvent& event )
841 {
842  int row = event.GetRow();
843  int col = event.GetCol();
844 
845  switch( col )
846  {
848  m_netsTable->SetValueAsBool( row, col, !m_netsTable->GetValueAsBool( row, col ) );
849  m_netsGrid->ForceRefresh();
850  break;
851 
852  default:
853  break;
854  }
855 }
856 
857 
859 {
860  int row = event.GetRow();
861  int col = event.GetCol();
862 
863  switch( col )
864  {
866  m_netsGrid->GetCellEditor( row, col )->BeginEdit( row, col, m_netsGrid );
867  break;
868 
869  default:
870  break;
871  }
872 }
873 
874 
876 {
877  m_netsGrid->SelectRow( event.GetRow() );
878 
879  wxString netName = m_netsGrid->GetCellValue( event.GetRow(), NET_GRID_TABLE::COL_LABEL );
880  wxMenu menu;
881 
882  menu.Append( new wxMenuItem( &menu, ID_SET_NET_COLOR, _( "Set Net Color" ), wxEmptyString,
883  wxITEM_NORMAL ) );
884  menu.Append( new wxMenuItem( &menu, ID_HIGHLIGHT_NET,
885  wxString::Format( _( "Highlight %s" ), netName ), wxEmptyString,
886  wxITEM_NORMAL ) );
887  menu.Append( new wxMenuItem( &menu, ID_SELECT_NET,
888  wxString::Format( _( "Select Tracks and Vias in %s" ), netName ),
889  wxEmptyString, wxITEM_NORMAL ) );
890  menu.Append( new wxMenuItem( &menu, ID_DESELECT_NET,
891  wxString::Format( _( "Unselect Tracks and Vias in %s" ), netName ),
892  wxEmptyString, wxITEM_NORMAL ) );
893 
894  menu.AppendSeparator();
895 
896  menu.Append( new wxMenuItem( &menu, ID_SHOW_ALL_NETS, _( "Show All Nets" ), wxEmptyString,
897  wxITEM_NORMAL ) );
898  menu.Append( new wxMenuItem( &menu, ID_HIDE_OTHER_NETS, _( "Hide All Other Nets" ),
899  wxEmptyString, wxITEM_NORMAL ) );
900 
901  menu.Bind( wxEVT_COMMAND_MENU_SELECTED, &APPEARANCE_CONTROLS::onNetContextMenu, this );
902 
903  PopupMenu( &menu );
904 }
905 
906 
907 void APPEARANCE_CONTROLS::OnNetGridMouseEvent( wxMouseEvent& aEvent )
908 {
909  wxPoint pos = m_netsGrid->CalcUnscrolledPosition( aEvent.GetPosition() );
910  wxGridCellCoords cell = m_netsGrid->XYToCell( pos );
911 
912  if( aEvent.Moving() || aEvent.Entering() )
913  {
914  aEvent.Skip();
915 
916  if( !cell )
917  {
918  m_netsGrid->GetGridWindow()->UnsetToolTip();
919  return;
920  }
921 
922  if( cell == m_hoveredCell )
923  return;
924 
925  m_hoveredCell = cell;
926 
927  NET_GRID_ENTRY& net = m_netsTable->GetEntry( cell.GetRow() );
928 
929  wxString name = net.name;
930  wxString showOrHide = net.visible ? _( "Click to hide ratsnest for %s" )
931  : _( "Click to show ratsnest for %s" );
932  wxString tip;
933 
934  if( cell.GetCol() == NET_GRID_TABLE::COL_VISIBILITY )
935  {
936  tip.Printf( showOrHide, name );
937  }
938  else if( cell.GetCol() == NET_GRID_TABLE::COL_COLOR )
939  {
940  tip = _( "Double click (or middle click) to change color; "
941  "right click for more actions" );
942  }
943 
944  m_netsGrid->GetGridWindow()->SetToolTip( tip );
945  }
946  else if( aEvent.Leaving() )
947  {
948  m_netsGrid->UnsetToolTip();
949  aEvent.Skip();
950  }
951  else if( aEvent.Dragging() )
952  {
953  // not allowed
954  CallAfter( [&]()
955  {
956  m_netsGrid->ClearSelection();
957  } );
958  }
959  else if( aEvent.ButtonUp( wxMOUSE_BTN_MIDDLE ) && !!cell )
960  {
961  int row = cell.GetRow();
962  int col = cell.GetCol();
963 
964  if(col == NET_GRID_TABLE::COL_COLOR )
965  m_netsGrid->GetCellEditor( row, col )->BeginEdit( row, col, m_netsGrid );
966 
967  aEvent.Skip();
968  }
969  else
970  {
971  aEvent.Skip();
972  }
973 }
974 
975 
977 {
978  Freeze();
979  rebuildLayers();
983  rebuildNets();
986 
988 
989  m_board = m_frame->GetBoard();
990 
991  if( m_board )
992  m_board->AddListener( this );
993 
994  Thaw();
995  Refresh();
996 }
997 
998 
1000 {
1002 }
1003 
1004 
1005 void APPEARANCE_CONTROLS::OnNetVisibilityChanged( int aNetCode, bool aVisibility )
1006 {
1007  int row = m_netsTable->GetRowByNetcode( aNetCode );
1008 
1009  if( row >= 0 )
1010  {
1012  m_netsGrid->ForceRefresh();
1013  }
1014 }
1015 
1016 
1018 {
1019  return aBoardItem->Type() == PCB_NETINFO_T;
1020 }
1021 
1022 
1023 bool APPEARANCE_CONTROLS::doesBoardItemNeedRebuild( std::vector<BOARD_ITEM*>& aBoardItems )
1024 {
1025  bool rebuild = std::any_of( aBoardItems.begin(), aBoardItems.end(),
1026  []( const BOARD_ITEM* a )
1027  {
1028  return a->Type() == PCB_NETINFO_T;
1029  } );
1030 
1031  return rebuild;
1032 }
1033 
1034 
1036 {
1037  if( doesBoardItemNeedRebuild( aItem ) )
1039 }
1040 
1041 
1042 void APPEARANCE_CONTROLS::OnBoardItemsAdded( BOARD& aBoard, std::vector<BOARD_ITEM*>& aItems )
1043 {
1044  if( doesBoardItemNeedRebuild( aItems ) )
1046 }
1047 
1048 
1050 {
1051  if( doesBoardItemNeedRebuild( aItem ) )
1053 }
1054 
1055 
1056 void APPEARANCE_CONTROLS::OnBoardItemsRemoved( BOARD& aBoard, std::vector<BOARD_ITEM*>& aItems )
1057 {
1058  if( doesBoardItemNeedRebuild( aItems ) )
1060 }
1061 
1062 
1064 {
1065  if( doesBoardItemNeedRebuild( aItem ) )
1067 }
1068 
1069 
1070 void APPEARANCE_CONTROLS::OnBoardItemsChanged( BOARD& aBoard, std::vector<BOARD_ITEM*>& aItems )
1071 {
1072  if( doesBoardItemNeedRebuild( aItems ) )
1074 }
1075 
1076 
1078 {
1079  Freeze();
1080  rebuildNets();
1081  Thaw();
1082 }
1083 
1084 
1086 {
1089 }
1090 
1091 
1093 {
1094  for( const std::unique_ptr<APPEARANCE_SETTING>& setting : m_layerSettings )
1095  {
1096  setting->ctl_panel->SetBackgroundColour( m_layerPanelColour );
1097  setting->ctl_indicator->SetIndicatorState( ROW_ICON_PROVIDER::STATE::OFF );
1098  }
1099 
1100  wxChar r, g, b;
1101 
1102  r = m_layerPanelColour.Red();
1103  g = m_layerPanelColour.Green();
1104  b = m_layerPanelColour.Blue();
1105 
1106  if( r < 240 || g < 240 || b < 240 )
1107  {
1108  r = wxChar( std::min( (int) r + 15, 255 ) );
1109  g = wxChar( std::min( (int) g + 15, 255 ) );
1110  b = wxChar( std::min( (int) b + 15, 255 ) );
1111  }
1112  else
1113  {
1114  r = wxChar( std::max( (int) r - 15, 0 ) );
1115  g = wxChar( std::max( (int) g - 15, 0 ) );
1116  b = wxChar( std::max( (int) b - 15, 0 ) );
1117  }
1118 
1119  PCB_LAYER_ID current = m_frame->GetActiveLayer();
1120 
1121  if( !m_layerSettingsMap.count( current ) )
1122  {
1123  wxASSERT( m_layerSettingsMap.count( F_Cu ) );
1124  current = F_Cu;
1125  }
1126 
1127  APPEARANCE_SETTING* newSetting = m_layerSettingsMap[ current ];
1128 
1129  newSetting->ctl_panel->SetBackgroundColour( wxColour( r, g, b ) );
1131 
1132  Refresh();
1133 }
1134 
1135 
1136 void APPEARANCE_CONTROLS::SetLayerVisible( LAYER_NUM aLayer, bool isVisible )
1137 {
1138  LSET visible = getVisibleLayers();
1139  PCB_LAYER_ID layer = ToLAYER_ID( aLayer );
1140 
1141  if( visible.test( layer ) == isVisible )
1142  return;
1143 
1144  visible.set( layer, isVisible );
1145  setVisibleLayers( visible );
1146 
1147  m_frame->GetCanvas()->GetView()->SetLayerVisible( layer, isVisible );
1148 
1150 }
1151 
1152 
1154 {
1155  if( m_objectSettingsMap.count( aLayer ) )
1156  {
1157  APPEARANCE_SETTING* setting = m_objectSettingsMap.at( aLayer );
1158  setting->ctl_visibility->SetValue( isVisible );
1159  }
1160 
1161  m_frame->GetBoard()->SetElementVisibility( aLayer, isVisible );
1162 
1163  m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, isVisible );
1164  m_frame->GetCanvas()->Refresh();
1165 }
1166 
1167 
1169 {
1170  if( m_isFpEditor )
1171  {
1172  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1173 
1174  for( PCB_LAYER_ID layer : LSET::AllLayersMask().Seq() )
1175  view->SetLayerVisible( layer, aLayers.Contains( layer ) );
1176  }
1177  else
1178  {
1179  m_frame->GetBoard()->SetVisibleLayers( aLayers );
1180  }
1181 }
1182 
1183 
1185 {
1186  if( m_isFpEditor )
1187  {
1188  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1189 
1190  for( size_t i = 0; i < GAL_LAYER_INDEX( LAYER_ZONE_START ); i++ )
1191  view->SetLayerVisible( GAL_LAYER_ID_START + GAL_LAYER_ID( i ), aLayers.test( i ) );
1192  }
1193  else
1194  {
1195  // Ratsnest visibility is controlled by the ratsnest option, and not by the preset
1196  if( m_frame->IsType( FRAME_PCB_EDITOR ) )
1197  {
1199  aLayers.set( LAYER_RATSNEST, opt.m_ShowGlobalRatsnest );
1200  }
1201 
1202  m_frame->GetBoard()->SetVisibleElements( aLayers );
1203  }
1204 }
1205 
1206 
1208 {
1209  if( m_isFpEditor )
1210  {
1211  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1212  LSET set;
1213 
1214  for( PCB_LAYER_ID layer : LSET::AllLayersMask().Seq() )
1215  set.set( layer, view->IsLayerVisible( layer ) );
1216 
1217  return set;
1218  }
1219  else
1220  {
1221  return m_frame->GetBoard()->GetVisibleLayers();
1222  }
1223 }
1224 
1225 
1227 {
1228  if( m_isFpEditor )
1229  {
1230  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1231  GAL_SET set;
1232  set.reset();
1233 
1234  for( size_t i = 0; i < set.size(); i++ )
1235  set.set( i, view->IsLayerVisible( GAL_LAYER_ID_START + GAL_LAYER_ID( i ) ) );
1236 
1237  return set;
1238  }
1239  else
1240  {
1241  return m_frame->GetBoard()->GetVisibleElements();
1242  }
1243 }
1244 
1245 
1247 {
1248  // TODO(JE) Is this even needed if the layer alphas are getting directly updated?
1249  // Maybe we just need the "down" arrow to indicate if the alpha is below 1
1250 
1251 #if 0
1252  static constexpr double alphaEpsilon = 0.04;
1253 
1254  PCB_LAYER_ID current = m_frame->GetActiveLayer();
1256  KIGFX::PCB_PAINTER* painter =
1257  static_cast<KIGFX::PCB_PAINTER*>( m_frame->GetCanvas()->GetView()->GetPainter() );
1258  KIGFX::PCB_RENDER_SETTINGS* rs = painter->GetSettings();
1259 
1260  for( APPEARANCE_SETTING& setting : m_layerSettings )
1261  {
1262  if( !setting.ctl_indicator )
1263  continue;
1264 
1265  COLOR4D layerColor = theme->GetColor( setting.id );
1266  COLOR4D screenColor = rs->GetLayerColor( setting.id );
1267 
1268  if( std::abs( screenColor.a - layerColor.a ) > alphaEpsilon )
1269  {
1270  if( screenColor.a < layerColor.a )
1271  setting.ctl_indicator->SetIndicatorState( ROW_ICON_PROVIDER::STATE::DOWN );
1272  else
1273  setting.ctl_indicator->SetIndicatorState( ROW_ICON_PROVIDER::STATE::UP );
1274  }
1275  else
1276  {
1277  setting.ctl_indicator->SetIndicatorState( setting.id == current ?
1279  ROW_ICON_PROVIDER::STATE::OFF );
1280  }
1281  }
1282 #endif
1283 }
1284 
1285 
1287 {
1288  const PCB_DISPLAY_OPTIONS& options = m_frame->GetDisplayOptions();
1289 
1290  switch( options.m_ContrastModeDisplay )
1291  {
1292  case HIGH_CONTRAST_MODE::NORMAL: m_rbHighContrastNormal->SetValue( true ); break;
1293  case HIGH_CONTRAST_MODE::DIMMED: m_rbHighContrastDim->SetValue( true ); break;
1294  case HIGH_CONTRAST_MODE::HIDDEN: m_rbHighContrastOff->SetValue( true ); break;
1295  }
1296 
1297  switch( options.m_NetColorMode )
1298  {
1299  case NET_COLOR_MODE::ALL: m_rbNetColorAll->SetValue( true ); break;
1300  case NET_COLOR_MODE::RATSNEST: m_rbNetColorRatsnest->SetValue( true ); break;
1301  case NET_COLOR_MODE::OFF: m_rbNetColorOff->SetValue( true ); break;
1302  }
1303 
1304  m_cbFlipBoard->SetValue( m_frame->GetCanvas()->GetView()->IsMirroredX() );
1305 
1306  if( !m_isFpEditor )
1307  {
1308  if( !options.m_ShowGlobalRatsnest )
1309  m_rbRatsnestNone->SetValue( true );
1310  else if( options.m_RatsnestMode == RATSNEST_MODE::ALL )
1311  m_rbRatsnestAllLayers->SetValue( true );
1312  else
1313  m_rbRatsnestVisLayers->SetValue( true );
1314 
1315  wxASSERT( m_objectSettingsMap.count( LAYER_RATSNEST ) );
1317  ratsnest->ctl_visibility->SetValue( options.m_ShowGlobalRatsnest );
1318  }
1319 }
1320 
1321 
1322 std::vector<LAYER_PRESET> APPEARANCE_CONTROLS::GetUserLayerPresets() const
1323 {
1324  std::vector<LAYER_PRESET> ret;
1325 
1326  for( const std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
1327  {
1328  if( !pair.second.readOnly )
1329  ret.emplace_back( pair.second );
1330  }
1331 
1332  return ret;
1333 }
1334 
1335 
1336 void APPEARANCE_CONTROLS::SetUserLayerPresets( std::vector<LAYER_PRESET>& aPresetList )
1337 {
1338  // Reset to defaults
1340 
1341  for( const LAYER_PRESET& preset : aPresetList )
1342  {
1343  if( m_layerPresets.count( preset.name ) )
1344  continue;
1345 
1346  m_layerPresets[preset.name] = preset;
1347 
1348  m_presetMRU.Add( preset.name );
1349  }
1350 
1352 }
1353 
1354 
1356 {
1357  m_layerPresets.clear();
1358  m_presetMRU.clear();
1359 
1360  // Load the read-only defaults
1363  presetBackAssembly } )
1364  {
1365  m_layerPresets[preset.name] = preset;
1366  m_layerPresets[preset.name].readOnly = true;
1367 
1368  m_presetMRU.Add( preset.name );
1369  }
1370 }
1371 
1372 
1373 void APPEARANCE_CONTROLS::ApplyLayerPreset( const wxString& aPresetName )
1374 {
1375  updateLayerPresetSelection( aPresetName );
1376 
1377  wxCommandEvent dummy;
1379 }
1380 
1381 
1383 {
1384  if( m_layerPresets.count( aPreset.name ) )
1385  m_currentPreset = &m_layerPresets[aPreset.name];
1386  else
1387  m_currentPreset = nullptr;
1388 
1390  : nullptr;
1391 
1392  updateLayerPresetSelection( aPreset.name );
1393  doApplyLayerPreset( aPreset );
1394 }
1395 
1396 
1398 {
1399  BOARD* board = m_frame->GetBoard();
1400  LSET enabled = board->GetEnabledLayers();
1401  LSET visible = getVisibleLayers();
1402 
1404  COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
1405  bool readOnly = theme->IsReadOnly();
1406 
1407 #ifdef __WXMAC__
1408  wxSizerItem* m_windowLayersSizerItem = m_panelLayersSizer->GetItem( m_windowLayers );
1409  m_windowLayersSizerItem->SetFlag( m_windowLayersSizerItem->GetFlag() & ~wxTOP );
1410 #endif
1411 
1412  auto appendLayer =
1413  [&]( std::unique_ptr<APPEARANCE_SETTING>& aSetting )
1414  {
1415  int layer = aSetting->id;
1416 
1417  wxPanel* panel = new wxPanel( m_windowLayers, layer );
1418  wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
1419  panel->SetSizer( sizer );
1420 
1421  panel->SetBackgroundColour( m_layerPanelColour );
1422 
1423  aSetting->visible = visible[layer];
1424 
1425  // TODO(JE) consider restyling this indicator
1426  INDICATOR_ICON* indicator = new INDICATOR_ICON( panel, *m_iconProvider,
1427  ROW_ICON_PROVIDER::STATE::OFF,
1428  layer );
1429 
1430  COLOR_SWATCH* swatch = new COLOR_SWATCH( panel, COLOR4D::UNSPECIFIED, layer,
1431  bgColor, theme->GetColor( layer ),
1432  SWATCH_SMALL );
1433  swatch->SetToolTip( _( "Double click or middle click for color change, "
1434  "right click for menu" ) );
1435 
1436  BITMAP_TOGGLE* btn_visible = new BITMAP_TOGGLE( panel, layer,
1439  aSetting->visible );
1440  btn_visible->SetToolTip( _( "Show or hide this layer" ) );
1441 
1442  wxStaticText* label = new wxStaticText( panel, layer, aSetting->label );
1443  label->Wrap( -1 );
1444  label->SetToolTip( aSetting->tooltip );
1445 
1446  sizer->AddSpacer( 1 );
1447  sizer->Add( indicator, 0, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1448  sizer->AddSpacer( 5 );
1449  sizer->Add( swatch, 0, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1450  sizer->AddSpacer( 6 );
1451  sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1452  sizer->AddSpacer( 5 );
1453  sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1454 
1455  m_layersOuterSizer->Add( panel, 0, wxEXPAND, 0 );
1456 
1457  aSetting->ctl_panel = panel;
1458  aSetting->ctl_indicator = indicator;
1459  aSetting->ctl_visibility = btn_visible;
1460  aSetting->ctl_color = swatch;
1461  aSetting->ctl_text = label;
1462 
1463  panel->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1464  indicator->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1465  swatch->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1466  label->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1467 
1468  btn_visible->Bind( TOGGLE_CHANGED,
1469  [&]( wxCommandEvent& aEvent )
1470  {
1471  wxObject* btn = aEvent.GetEventObject();
1472  int layId = static_cast<wxWindow*>( btn )->GetId();
1473  bool isVisible = aEvent.GetInt();
1474 
1475  wxASSERT( layId >= 0 && layId < PCB_LAYER_ID_COUNT );
1476 
1478  {
1479  static_cast<BITMAP_TOGGLE*>( btn )->SetValue( !isVisible );
1480  return;
1481  }
1482 
1483  onLayerVisibilityChanged( static_cast<PCB_LAYER_ID>( layId ),
1484  isVisible, true );
1485  } );
1486 
1487  swatch->Bind( COLOR_SWATCH_CHANGED, &APPEARANCE_CONTROLS::OnColorSwatchChanged,
1488  this );
1490  this ) );
1491  swatch->SetReadOnly( readOnly );
1492 
1493  panel->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1494  indicator->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1495  swatch->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1496  btn_visible->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1497  label->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1498  };
1499 
1500  auto updateLayer =
1501  [&]( std::unique_ptr<APPEARANCE_SETTING>& aSetting )
1502  {
1503  int layer = aSetting->id;
1504  aSetting->visible = visible[layer];
1505  aSetting->ctl_panel->Show();
1506  aSetting->ctl_panel->SetId( layer );
1507  aSetting->ctl_indicator->SetWindowID( layer );
1508  aSetting->ctl_color->SetWindowID( layer );
1509  aSetting->ctl_color->SetSwatchColor( theme->GetColor( layer ), false );
1510  aSetting->ctl_visibility->SetWindowID( layer );
1511  aSetting->ctl_text->SetLabelText( aSetting->label );
1512  aSetting->ctl_text->SetId( layer );
1513  aSetting->ctl_text->SetToolTip( aSetting->tooltip );
1514  };
1515 
1516  // technical layers are shown in this order:
1517  // Because they are static, wxGetTranslation must be explicitly
1518  // called for tooltips.
1519  static const struct {
1520  PCB_LAYER_ID layerId;
1521  wxString tooltip;
1522  } non_cu_seq[] = {
1523  { F_Adhes, _( "Adhesive on board's front" ) },
1524  { B_Adhes, _( "Adhesive on board's back" ) },
1525  { F_Paste, _( "Solder paste on board's front" ) },
1526  { B_Paste, _( "Solder paste on board's back" ) },
1527  { F_SilkS, _( "Silkscreen on board's front" ) },
1528  { B_SilkS, _( "Silkscreen on board's back" ) },
1529  { F_Mask, _( "Solder mask on board's front" ) },
1530  { B_Mask, _( "Solder mask on board's back" ) },
1531  { Dwgs_User, _( "Explanatory drawings" ) },
1532  { Cmts_User, _( "Explanatory comments" ) },
1533  { Eco1_User, _( "User defined meaning" ) },
1534  { Eco2_User, _( "User defined meaning" ) },
1535  { Edge_Cuts, _( "Board's perimeter definition" ) },
1536  { Margin, _( "Board's edge setback outline" ) },
1537  { F_CrtYd, _( "Footprint courtyards on board's front" ) },
1538  { B_CrtYd, _( "Footprint courtyards on board's back" ) },
1539  { F_Fab, _( "Footprint assembly on board's front" ) },
1540  { B_Fab, _( "Footprint assembly on board's back" ) },
1541  { User_1, _( "User defined layer 1" ) },
1542  { User_2, _( "User defined layer 2" ) },
1543  { User_3, _( "User defined layer 3" ) },
1544  { User_4, _( "User defined layer 4" ) },
1545  { User_5, _( "User defined layer 5" ) },
1546  { User_6, _( "User defined layer 6" ) },
1547  { User_7, _( "User defined layer 7" ) },
1548  { User_8, _( "User defined layer 8" ) },
1549  { User_9, _( "User defined layer 9" ) },
1550  };
1551 
1552  // There is a spacer added to the end of the list that we need to remove and re-add
1553  // after possibly adding additional layers
1554  if( m_layersOuterSizer->GetItemCount() > 0 )
1555  {
1556  m_layersOuterSizer->Detach( m_layersOuterSizer->GetItemCount() - 1 );
1557  }
1558  // Otherwise, this is the first time we are updating the control, so we need to attach
1559  // the handler
1560  else
1561  {
1562  // Add right click handling to show the context menu when clicking to the free area in
1563  // m_windowLayers (below the layer items)
1564  m_windowLayers->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1565  }
1566 
1567  std::size_t total_layers = enabled.CuStack().size();
1568 
1569  for( const auto& entry : non_cu_seq )
1570  {
1571  if( enabled[entry.layerId] )
1572  total_layers++;
1573  }
1574 
1575  // Adds layers to the panel until we have enough to hold our total count
1576  while( total_layers > m_layerSettings.size() )
1577  m_layerSettings.push_back( std::make_unique<APPEARANCE_SETTING>() );
1578 
1579  // We never delete layers from the panel, only hide them. This saves us
1580  // having to recreate the (possibly) later with minimal overhead
1581  for( std::size_t ii = total_layers; ii < m_layerSettings.size(); ++ii )
1582  {
1583  if( m_layerSettings[ii]->ctl_panel )
1584  m_layerSettings[ii]->ctl_panel->Show( false );
1585  }
1586 
1587  auto layer_it = m_layerSettings.begin();
1588 
1589  // show all coppers first, with front on top, back on bottom, then technical layers
1590  for( LSEQ cu_stack = enabled.CuStack(); cu_stack; ++cu_stack, ++layer_it )
1591  {
1592  PCB_LAYER_ID layer = *cu_stack;
1593  wxString dsc;
1594 
1595  switch( layer )
1596  {
1597  case F_Cu: dsc = _( "Front copper layer" ); break;
1598  case B_Cu: dsc = _( "Back copper layer" ); break;
1599  default: dsc = _( "Inner copper layer" ); break;
1600  }
1601 
1602  std::unique_ptr<APPEARANCE_SETTING>& setting = *layer_it;
1603 
1604  setting->label = board->GetLayerName( layer );
1605  setting->id = layer;
1606  setting->tooltip = dsc;
1607 
1608  if( setting->ctl_panel == nullptr )
1609  appendLayer( setting );
1610  else
1611  updateLayer( setting );
1612 
1613  m_layerSettingsMap[layer] = setting.get();
1614 
1616  {
1617  setting->ctl_text->Disable();
1618  setting->ctl_color->SetToolTip( wxEmptyString );
1619  }
1620  }
1621 
1622  for( const auto& entry : non_cu_seq )
1623  {
1624  PCB_LAYER_ID layer = entry.layerId;
1625 
1626  if( !enabled[layer] )
1627  continue;
1628 
1629  std::unique_ptr<APPEARANCE_SETTING>& setting = *layer_it;
1630 
1631  setting->label = board->GetLayerName( layer );
1632  setting->id = layer;
1633  setting->tooltip = entry.tooltip;
1634 
1635  if( setting->ctl_panel == nullptr )
1636  appendLayer( setting );
1637  else
1638  updateLayer( setting );
1639 
1640  m_layerSettingsMap[layer] = setting.get();
1641 
1643  {
1644  setting->ctl_text->Disable();
1645  setting->ctl_color->SetToolTip( wxEmptyString );
1646  }
1647 
1648  ++layer_it;
1649  }
1650 
1651  m_layersOuterSizer->AddSpacer( 10 );
1652  m_windowLayers->SetBackgroundColour( m_layerPanelColour );
1653  m_windowLayers->Layout();
1654 }
1655 
1656 
1658 {
1659  delete m_layerContextMenu;
1660  m_layerContextMenu = new wxMenu;
1661 
1663  _( "Show All Copper Layers" ),
1666  _( "Hide All Copper Layers" ),
1668 
1669  m_layerContextMenu->AppendSeparator();
1670 
1672  _( "Hide All Layers But Active" ),
1674 
1675  m_layerContextMenu->AppendSeparator();
1676 
1677  AddMenuItem( m_layerContextMenu, ID_SHOW_ALL_NON_COPPER, _( "Show All Non Copper Layers" ),
1679 
1680  AddMenuItem( m_layerContextMenu, ID_HIDE_ALL_NON_COPPER, _( "Hide All Non Copper Layers" ),
1682 
1683  m_layerContextMenu->AppendSeparator();
1684 
1685  AddMenuItem( m_layerContextMenu, ID_PRESET_ALL_LAYERS, _( "Show All Layers" ),
1687 
1688  AddMenuItem( m_layerContextMenu, ID_PRESET_NO_LAYERS, _( "Hide All Layers" ),
1690 
1691  m_layerContextMenu->AppendSeparator();
1692 
1694  _( "Show Only Front Assembly Layers" ),
1696 
1697  AddMenuItem( m_layerContextMenu, ID_PRESET_FRONT, _( "Show Only Front Layers" ),
1699 
1700  // Only show the internal layer option if internal layers are enabled
1701  if( m_frame->GetBoard()->GetCopperLayerCount() > 2 )
1702  {
1703  AddMenuItem( m_layerContextMenu, ID_PRESET_INNER_COPPER, _( "Show Only Inner Layers" ),
1705  }
1706 
1707  AddMenuItem( m_layerContextMenu, ID_PRESET_BACK, _( "Show Only Back Layers" ),
1709 
1710  AddMenuItem( m_layerContextMenu, ID_PRESET_BACK_ASSEMBLY, _( "Show Only Back Assembly Layers" ),
1712 }
1713 
1714 
1715 void APPEARANCE_CONTROLS::OnLayerContextMenu( wxCommandEvent& aEvent )
1716 {
1717  BOARD* board = m_frame->GetBoard();
1718  LSET visible = getVisibleLayers();
1719 
1720  PCB_LAYER_ID current = m_frame->GetActiveLayer();
1721 
1722  switch( aEvent.GetId() )
1723  {
1724  case ID_PRESET_NO_LAYERS:
1726  return;
1727 
1728  case ID_PRESET_ALL_LAYERS:
1730  return;
1731 
1733  {
1734  visible |= presetAllCopper.layers;
1735  setVisibleLayers( visible );
1736  break;
1737  }
1738 
1741  SetLayerVisible( current, true );
1742  break;
1743 
1745  {
1746  visible &= ~presetAllCopper.layers;
1747 
1748  if( !visible.test( current ) )
1749  m_frame->SetActiveLayer( *visible.Seq().begin() );
1750 
1751  setVisibleLayers( visible );
1752  break;
1753  }
1754 
1756  {
1757  visible &= presetAllCopper.layers;
1758 
1759  if( !visible.test( current ) )
1760  m_frame->SetActiveLayer( *visible.Seq().begin() );
1761 
1762  setVisibleLayers( visible );
1763  break;
1764  }
1765 
1767  {
1768  visible |= ~presetAllCopper.layers;
1769 
1770  setVisibleLayers( visible );
1771  break;
1772  }
1773 
1776  return;
1777 
1778  case ID_PRESET_FRONT:
1780  return;
1781 
1784  return;
1785 
1786  case ID_PRESET_BACK:
1788  return;
1789 
1792  return;
1793  }
1794 
1797 
1798  if( !m_isFpEditor )
1799  m_frame->GetCanvas()->SyncLayersVisibility( board );
1800 
1801  m_frame->GetCanvas()->Refresh();
1802 }
1803 
1804 
1806 {
1807  return m_notebook->GetSelection();
1808 }
1809 
1810 
1812 {
1813  size_t max = m_notebook->GetPageCount();
1814 
1815  if( aTab >= 0 && static_cast<size_t>( aTab ) < max )
1816  m_notebook->SetSelection( aTab );
1817 }
1818 
1819 
1821 {
1823  bool readOnly = theme->IsReadOnly();
1824  LSET visible = getVisibleLayers();
1825  GAL_SET objects = getVisibleObjects();
1826 
1827  Freeze();
1828 
1829  for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_layerSettings )
1830  {
1831  LAYER_NUM layer = setting->id;
1832 
1833  if( setting->ctl_visibility )
1834  setting->ctl_visibility->SetValue( visible[layer] );
1835 
1836  if( setting->ctl_color )
1837  {
1838  const COLOR4D& color = theme->GetColor( layer );
1839  setting->ctl_color->SetSwatchColor( color, false );
1840  setting->ctl_color->SetReadOnly( readOnly );
1841  }
1842  }
1843 
1844  for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
1845  {
1846  GAL_LAYER_ID layer = static_cast<GAL_LAYER_ID>( setting->id );
1847 
1848  if( setting->ctl_visibility )
1849  setting->ctl_visibility->SetValue( objects.Contains( layer ) );
1850 
1851  if( setting->ctl_color )
1852  {
1853  const COLOR4D& color = theme->GetColor( layer );
1854  setting->ctl_color->SetSwatchColor( color, false );
1855  setting->ctl_color->SetReadOnly( readOnly );
1856  }
1857  }
1858 
1859  // Update indicators and panel background colors
1860  OnLayerChanged();
1861 
1862  Thaw();
1863 
1864  m_windowLayers->Refresh();
1865 }
1866 
1867 
1868 void APPEARANCE_CONTROLS::onLayerLeftClick( wxMouseEvent& aEvent )
1869 {
1870  auto eventSource = static_cast<wxWindow*>( aEvent.GetEventObject() );
1871 
1872  PCB_LAYER_ID layer = ToLAYER_ID( eventSource->GetId() );
1873 
1874  if( m_isFpEditor && LSET::ForbiddenFootprintLayers().test( layer ) )
1875  return;
1876 
1877  m_frame->SetActiveLayer( layer );
1878  passOnFocus();
1879 }
1880 
1881 
1882 void APPEARANCE_CONTROLS::rightClickHandler( wxMouseEvent& aEvent )
1883 {
1884  wxASSERT( m_layerContextMenu );
1885  PopupMenu( m_layerContextMenu );
1886  passOnFocus();
1887 };
1888 
1889 
1891  bool isFinal )
1892 {
1893  LSET visibleLayers = getVisibleLayers();
1894 
1895  if( visibleLayers.test( aLayer ) != isVisible )
1896  {
1897  visibleLayers.set( aLayer, isVisible );
1898 
1899  setVisibleLayers( visibleLayers );
1900 
1901  m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, isVisible );
1902  }
1903 
1905 
1906  if( isFinal )
1907  m_frame->GetCanvas()->Refresh();
1908 }
1909 
1910 
1912  bool isFinal )
1913 {
1914  // Special-case controls
1915  switch( aLayer )
1916  {
1917  case LAYER_RATSNEST:
1918  {
1919  // don't touch the layers. ratsnest is enabled on per-item basis.
1921  m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, true );
1922 
1923  if( m_frame->IsType( FRAME_PCB_EDITOR ) )
1924  {
1926  opt.m_ShowGlobalRatsnest = isVisible;
1927  m_frame->SetDisplayOptions( opt );
1928  m_frame->GetBoard()->SetElementVisibility( aLayer, isVisible );
1930  }
1931 
1932  break;
1933  }
1934 
1935  case LAYER_GRID:
1936  m_frame->SetGridVisibility( isVisible );
1937  m_frame->GetCanvas()->Refresh();
1939  break;
1940 
1941  case LAYER_MOD_TEXT:
1942  // Because Footprint Text is a meta-control that also can disable values/references,
1943  // drag them along here so that the user is less likely to be confused.
1944  if( isFinal )
1945  {
1946  // Should only trigger when you actually click the Footprint Text button
1947  // Otherwise it goes into infinite recursive loop with the following case section
1948  onObjectVisibilityChanged( LAYER_MOD_REFERENCES, isVisible, false );
1949  onObjectVisibilityChanged( LAYER_MOD_VALUES, isVisible, false );
1950  m_objectSettingsMap[LAYER_MOD_REFERENCES]->ctl_visibility->SetValue( isVisible );
1951  m_objectSettingsMap[LAYER_MOD_VALUES]->ctl_visibility->SetValue( isVisible );
1952  }
1953  break;
1954 
1955  case LAYER_MOD_REFERENCES:
1956  case LAYER_MOD_VALUES:
1957  // In case that user changes Footprint Value/References when the Footprint Text
1958  // meta-control is disabled, we should put it back on.
1959  if( isVisible )
1960  {
1961  onObjectVisibilityChanged( LAYER_MOD_TEXT, isVisible, false );
1962  m_objectSettingsMap[LAYER_MOD_TEXT]->ctl_visibility->SetValue( isVisible );
1963  }
1964  break;
1965 
1966  default:
1967  break;
1968  }
1969 
1970  GAL_SET visible = getVisibleObjects();
1971 
1972  if( visible.Contains( aLayer ) != isVisible )
1973  {
1974  visible.set( aLayer, isVisible );
1975  setVisibleObjects( visible );
1976  m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, isVisible );
1978  }
1979 
1980  if( isFinal )
1981  {
1982  m_frame->GetCanvas()->Refresh();
1983  passOnFocus();
1984  }
1985 }
1986 
1987 
1989 {
1991  COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
1992  GAL_SET visible = getVisibleObjects();
1993  int swatchWidth = m_windowObjects->ConvertDialogToPixels( wxSize( 8, 0 ) ).x;
1994  int labelWidth = 0;
1995 
1996  m_objectSettings.clear();
1997  m_objectsOuterSizer->Clear( true );
1998  m_objectsOuterSizer->AddSpacer( 5 );
1999 
2000  auto appendObject =
2001  [&]( const std::unique_ptr<APPEARANCE_SETTING>& aSetting )
2002  {
2003  wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
2004  int layer = aSetting->id;
2005 
2006  aSetting->visible = visible.Contains( ToGalLayer( layer ) );
2007  COLOR4D color = theme->GetColor( layer );
2008  COLOR4D defColor = theme->GetDefaultColor( layer );
2009 
2010  if( color != COLOR4D::UNSPECIFIED )
2011  {
2012  COLOR_SWATCH* swatch = new COLOR_SWATCH( m_windowObjects, color, layer,
2013  bgColor, defColor, SWATCH_SMALL );
2014  swatch->SetToolTip( _( "Left double click or middle click for color change, "
2015  "right click for menu" ) );
2016 
2017  sizer->Add( swatch, 0, wxALIGN_CENTER_VERTICAL, 0 );
2018  aSetting->ctl_color = swatch;
2019 
2020  swatch->Bind( COLOR_SWATCH_CHANGED,
2022 
2024  this ) );
2025  }
2026  else
2027  {
2028  sizer->AddSpacer( swatchWidth );
2029  }
2030 
2031  BITMAP_TOGGLE* btn_visible = new BITMAP_TOGGLE( m_windowObjects, layer,
2034  aSetting->visible );
2035 
2036  wxString tip;
2037  tip.Printf( _( "Show or hide %s" ), aSetting->label.Lower() );
2038  btn_visible->SetToolTip( tip );
2039 
2040  aSetting->ctl_visibility = btn_visible;
2041 
2042  sizer->AddSpacer( 5 );
2043 
2044  btn_visible->Bind( TOGGLE_CHANGED,
2045  [&]( wxCommandEvent& aEvent )
2046  {
2047  int id = static_cast<wxWindow*>( aEvent.GetEventObject() )->GetId();
2048  bool isVisible = aEvent.GetInt();
2049  onObjectVisibilityChanged( ToGalLayer( id ), isVisible, true );
2050  } );
2051 
2052  wxStaticText* label = new wxStaticText( m_windowObjects, layer, aSetting->label );
2053  label->Wrap( -1 );
2054  label->SetToolTip( aSetting->tooltip );
2055 
2056  if( aSetting->can_control_opacity )
2057  {
2058  label->SetMinSize( wxSize( labelWidth, -1 ) );
2059 #ifdef __WXMAC__
2060  sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, 10 );
2061  sizer->AddSpacer( 5 );
2062  sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, 10 );
2063 #else
2064  sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL, 0 );
2065  sizer->AddSpacer( 5 );
2066  sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL, 0 );
2067 #endif
2068 
2069  wxSlider* slider = new wxSlider( m_windowObjects, wxID_ANY, 100, 0, 100,
2070  wxDefaultPosition, wxDefaultSize,
2071  wxSL_HORIZONTAL );
2072 #ifdef __WXMAC__
2073  slider->SetMinSize( wxSize( 80, 16 ) );
2074 #else
2075  slider->SetMinSize( wxSize( 80, -1 ) );
2076 #endif
2077 
2078  tip.Printf( _( "Set opacity of %s" ), aSetting->label.Lower() );
2079  slider->SetToolTip( tip );
2080 
2081  sizer->Add( slider, 1, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 5 );
2082  aSetting->ctl_opacity = slider;
2083 
2084  auto opacitySliderHandler =
2085  [=]( wxCommandEvent& aEvent )
2086  {
2087  wxSlider* ctrl = static_cast<wxSlider*>( aEvent.GetEventObject() );
2088  int value = ctrl->GetValue();
2089  onObjectOpacitySlider( layer, value / 100.0f );
2090  };
2091 
2092  slider->Bind( wxEVT_SCROLL_CHANGED, opacitySliderHandler );
2093  slider->Bind( wxEVT_SCROLL_THUMBTRACK, opacitySliderHandler );
2094  slider->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS::OnSetFocus, this );
2095  }
2096  else
2097  {
2098  sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL, 0 );
2099  sizer->AddSpacer( 5 );
2100  sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL, 0 );
2101  }
2102 
2103  aSetting->ctl_text = label;
2104  m_objectsOuterSizer->Add( sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, 5 );
2105 
2106  if( !aSetting->can_control_opacity )
2107  m_objectsOuterSizer->AddSpacer( 2 );
2108  };
2109 
2110  for( const APPEARANCE_SETTING& s_setting : s_objectSettings )
2111  {
2112  if( m_isFpEditor && !s_allowedInFpEditor.count( s_setting.id ) )
2113  continue;
2114 
2115  if( !s_setting.spacer )
2116  {
2117  m_objectSettings.emplace_back( std::make_unique<APPEARANCE_SETTING>( s_setting ) );
2118 
2119  std::unique_ptr<APPEARANCE_SETTING>& setting = m_objectSettings.back();
2120 
2121  // Because s_render_rows is created static, we must explicitly call
2122  // wxGetTranslation for texts which are internationalized (tool tips
2123  // and item names)
2124  setting->tooltip = wxGetTranslation( s_setting.tooltip );
2125  setting->label = wxGetTranslation( s_setting.label );
2126 
2127  if( setting->can_control_opacity )
2128  {
2129  int width = m_windowObjects->GetTextExtent( setting->label ).x + 5;
2130  labelWidth = std::max( labelWidth, width );
2131  }
2132 
2133  m_objectSettingsMap[ToGalLayer( setting->id )] = setting.get();
2134  }
2135  }
2136 
2137  for( const std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
2138  {
2139  if( setting->spacer )
2140  m_objectsOuterSizer->AddSpacer( m_pointSize );
2141  else
2142  appendObject( setting );
2143  }
2144 
2145  m_objectsOuterSizer->Layout();
2146 }
2147 
2148 
2150 {
2151  GAL_SET visible = getVisibleObjects();
2152 
2154 
2155  for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
2156  {
2157  if( setting->spacer )
2158  continue;
2159 
2160  GAL_LAYER_ID layer = ToGalLayer( setting->id );
2161 
2162  if( setting->ctl_visibility )
2163  setting->ctl_visibility->SetValue( visible.Contains( layer ) );
2164 
2165  if( setting->ctl_color )
2166  {
2167  COLOR4D color = m_frame->GetColorSettings()->GetColor( setting->id );
2168  setting->ctl_color->SetSwatchColor( color, false );
2169  }
2170  }
2171 
2172  wxASSERT( m_objectSettingsMap.count( LAYER_TRACKS )
2173  && m_objectSettingsMap.count( LAYER_VIAS )
2174  && m_objectSettingsMap.count( LAYER_PADS )
2175  && m_objectSettingsMap.count( LAYER_ZONES ) );
2176 
2177  m_objectSettingsMap[LAYER_TRACKS]->ctl_opacity->SetValue( opts.m_TrackOpacity * 100 );
2178  m_objectSettingsMap[LAYER_VIAS]->ctl_opacity->SetValue( opts.m_ViaOpacity * 100 );
2179  m_objectSettingsMap[LAYER_PADS]->ctl_opacity->SetValue( opts.m_PadOpacity * 100 );
2180  m_objectSettingsMap[LAYER_ZONES]->ctl_opacity->SetValue( opts.m_ZoneOpacity * 100 );
2181 }
2182 
2183 
2185 {
2186  BOARD* board = m_frame->GetBoard();
2188  COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
2189 
2190  // If the board isn't fully loaded, we can't yet rebuild
2191  if( !board->GetProject() )
2192  return;
2193 
2194  KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>(
2196 
2197  std::map<wxString, KIGFX::COLOR4D>& netclassColors = rs->GetNetclassColorMap();
2198 
2199  m_netclassOuterSizer->Clear( true );
2200 
2201  auto appendNetclass =
2202  [&]( int aId, const NETCLASSPTR& aClass, bool isDefaultClass = false )
2203  {
2204  wxString name = aClass->GetName();
2205 
2206  m_netclassSettings.emplace_back( std::make_unique<APPEARANCE_SETTING>() );
2207  APPEARANCE_SETTING* setting = m_netclassSettings.back().get();
2208  m_netclassSettingsMap[name] = setting;
2209 
2210  setting->ctl_panel = new wxPanel( m_netclassScrolledWindow, aId );
2211  wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
2212  setting->ctl_panel->SetSizer( sizer );
2213  COLOR4D color = netclassColors.count( name ) ? netclassColors.at( name ) :
2214  COLOR4D::UNSPECIFIED;
2215 
2216  setting->ctl_color = new COLOR_SWATCH( setting->ctl_panel, color, aId, bgColor,
2217  COLOR4D::UNSPECIFIED, SWATCH_SMALL );
2218  setting->ctl_color->SetToolTip( _( "Left double click or middle click for color "
2219  "change, right click for menu" ) );
2220 
2221  setting->ctl_color->Bind( COLOR_SWATCH_CHANGED,
2223 
2224  // Default netclass can't have an override color
2225  if( isDefaultClass )
2226  setting->ctl_color->Hide();
2227 
2228  setting->ctl_visibility = new BITMAP_TOGGLE( setting->ctl_panel, aId,
2231  true );
2232 
2233  wxString tip;
2234  tip.Printf( _( "Show or hide ratsnest for nets in %s" ), name );
2235  setting->ctl_visibility->SetToolTip( tip );
2236 
2237  setting->ctl_text = new wxStaticText( setting->ctl_panel, aId, name );
2238  setting->ctl_text->Wrap( -1 );
2239 
2240  int flags = wxALIGN_CENTER_VERTICAL;
2241 
2242  sizer->Add( setting->ctl_color, 0, flags | wxRESERVE_SPACE_EVEN_IF_HIDDEN, 5 );
2243  sizer->AddSpacer( 7 );
2244  sizer->Add( setting->ctl_visibility, 0, flags, 5 );
2245  sizer->AddSpacer( 3 );
2246  sizer->Add( setting->ctl_text, 1, flags, 5 );
2247 
2248  m_netclassOuterSizer->Add( setting->ctl_panel, 0, wxEXPAND, 5 );
2249  m_netclassOuterSizer->AddSpacer( 2 );
2250 
2251  setting->ctl_visibility->Bind( TOGGLE_CHANGED,
2253  this );
2254 
2255  auto menuHandler =
2256  [&, name, isDefaultClass]( wxMouseEvent& aEvent )
2257  {
2259 
2260  wxMenu menu;
2261 
2262  if( !isDefaultClass)
2263  {
2264  menu.Append( new wxMenuItem( &menu, ID_SET_NET_COLOR,
2265  _( "Set Netclass Color" ), wxEmptyString,
2266  wxITEM_NORMAL ) );
2267  }
2268 
2269  menu.Append( new wxMenuItem( &menu, ID_HIGHLIGHT_NET,
2270  wxString::Format( _( "Highlight Nets in %s" ), name ),
2271  wxEmptyString, wxITEM_NORMAL ) );
2272  menu.Append( new wxMenuItem( &menu, ID_SELECT_NET,
2273  wxString::Format( _( "Select Tracks and Vias in %s" ),
2274  name ),
2275  wxEmptyString, wxITEM_NORMAL ) );
2276  menu.Append( new wxMenuItem( &menu, ID_DESELECT_NET,
2277  wxString::Format( _( "Unselect Tracks and Vias in %s" ),
2278  name ),
2279  wxEmptyString, wxITEM_NORMAL ) );
2280 
2281  menu.AppendSeparator();
2282 
2283  menu.Append( new wxMenuItem( &menu, ID_SHOW_ALL_NETS,
2284  _( "Show All Netclasses" ), wxEmptyString,
2285  wxITEM_NORMAL ) );
2286  menu.Append( new wxMenuItem( &menu, ID_HIDE_OTHER_NETS,
2287  _( "Hide All Other Netclasses" ), wxEmptyString,
2288  wxITEM_NORMAL ) );
2289 
2290  menu.Bind( wxEVT_COMMAND_MENU_SELECTED,
2292 
2293  PopupMenu( &menu );
2294  };
2295 
2296  setting->ctl_panel->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2297  setting->ctl_visibility->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2298  setting->ctl_color->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2299  setting->ctl_text->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2300  };
2301 
2302  const NETCLASS_MAP& classes = board->GetDesignSettings().GetNetClasses().NetClasses();
2303 
2304  std::vector<wxString> names;
2305 
2306  for( const auto& pair : classes )
2307  names.emplace_back( pair.first );
2308 
2309  std::sort( names.begin(), names.end() );
2310 
2311  m_netclassIdMap.clear();
2312 
2313  int idx = wxID_HIGHEST;
2314 
2315  NETCLASSPTR defaultClass = board->GetDesignSettings().GetNetClasses().GetDefault();
2316 
2317  m_netclassIdMap[idx] = defaultClass->GetName();
2318  appendNetclass( idx++, defaultClass, true );
2319 
2320  for( const wxString& name : names )
2321  {
2322  m_netclassIdMap[idx] = name;
2323  appendNetclass( idx++, classes.at( name ) );
2324  }
2325 
2326  m_netclassOuterSizer->Layout();
2327 
2328  m_netsTable->Rebuild();
2329  m_panelNets->GetSizer()->Layout();
2330 }
2331 
2332 
2334 {
2335  m_cbLayerPresets->Clear();
2336 
2337  for( std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
2338  m_cbLayerPresets->Append( pair.first, static_cast<void*>( &pair.second ) );
2339 
2340  m_cbLayerPresets->Append( wxT( "-----" ) );
2341  m_cbLayerPresets->Append( _( "Save preset..." ) );
2342  m_cbLayerPresets->Append( _( "Delete preset..." ) );
2343 
2344  m_cbLayerPresets->SetSelection( 0 );
2345 
2346  // At least the build in presets should always be present
2347  wxASSERT( !m_layerPresets.empty() );
2348 
2349  // Default preset: all layers
2351 }
2352 
2353 
2355 {
2356  LSET visibleLayers = getVisibleLayers();
2357  GAL_SET visibleObjects = getVisibleObjects();
2358 
2359  auto it = std::find_if( m_layerPresets.begin(), m_layerPresets.end(),
2360  [&]( const std::pair<const wxString, LAYER_PRESET>& aPair )
2361  {
2362  return ( aPair.second.layers == visibleLayers
2363  && aPair.second.renderLayers == visibleObjects );
2364  } );
2365 
2366  if( it != m_layerPresets.end() )
2367  m_cbLayerPresets->SetStringSelection( it->first );
2368  else
2369  m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator
2370 
2371  m_currentPreset = static_cast<LAYER_PRESET*>(
2372  m_cbLayerPresets->GetClientData( m_cbLayerPresets->GetSelection() ) );
2373 }
2374 
2375 
2377 {
2378  int idx = m_cbLayerPresets->FindString( aName );
2379 
2380  if( idx >= 0 && m_cbLayerPresets->GetSelection() != idx )
2381  {
2382  m_cbLayerPresets->SetSelection( idx );
2383  m_currentPreset = static_cast<LAYER_PRESET*>( m_cbLayerPresets->GetClientData( idx ) );
2384  }
2385  else if( idx < 0 )
2386  {
2387  m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator
2388  }
2389 }
2390 
2391 
2392 void APPEARANCE_CONTROLS::onLayerPresetChanged( wxCommandEvent& aEvent )
2393 {
2394  int count = m_cbLayerPresets->GetCount();
2395  int index = m_cbLayerPresets->GetSelection();
2396 
2397  auto resetSelection =
2398  [&]()
2399  {
2400  if( m_currentPreset )
2401  m_cbLayerPresets->SetStringSelection( m_currentPreset->name );
2402  else
2403  m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 );
2404  };
2405 
2406  if( index == count - 3 )
2407  {
2408  // Separator: reject the selection
2409  resetSelection();
2410  return;
2411  }
2412  else if( index == count - 2 )
2413  {
2414  // Save current state to new preset
2415  wxString name;
2416 
2419 
2420  wxTextEntryDialog dlg( this, _( "Layer preset name:" ), _( "Save Layer Preset" ), name );
2421 
2422  if( dlg.ShowModal() != wxID_OK )
2423  {
2424  resetSelection();
2425  return;
2426  }
2427 
2428  name = dlg.GetValue();
2429  bool exists = m_layerPresets.count( name );
2430 
2431  if( !exists )
2432  {
2435  }
2436 
2437  LAYER_PRESET* preset = &m_layerPresets[name];
2438  m_currentPreset = preset;
2439 
2440  if( !exists )
2441  {
2442  index = m_cbLayerPresets->Insert( name, index - 1, static_cast<void*>( preset ) );
2443  }
2444  else
2445  {
2446  preset->layers = getVisibleLayers();
2447  preset->renderLayers = getVisibleObjects();
2448 
2449  index = m_cbLayerPresets->FindString( name );
2450  m_presetMRU.Remove( name );
2451  }
2452 
2453  m_cbLayerPresets->SetSelection( index );
2454  m_presetMRU.Insert( name, 0 );
2455 
2456  return;
2457  }
2458  else if( index == count - 1 )
2459  {
2460  // Delete a preset
2461  wxArrayString headers;
2462  std::vector<wxArrayString> items;
2463 
2464  headers.Add( _( "Presets" ) );
2465 
2466  for( std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
2467  {
2468  if( !pair.second.readOnly )
2469  {
2470  wxArrayString item;
2471  item.Add( pair.first );
2472  items.emplace_back( item );
2473  }
2474  }
2475 
2476  EDA_LIST_DIALOG dlg( m_frame, _( "Delete Preset" ), headers, items );
2477  dlg.SetListLabel( _( "Select preset:" ) );
2478 
2479  if( dlg.ShowModal() == wxID_OK )
2480  {
2481  wxString presetName = dlg.GetTextSelection();
2482  int idx = m_cbLayerPresets->FindString( presetName );
2483 
2484  if( idx != wxNOT_FOUND )
2485  {
2486  m_layerPresets.erase( presetName );
2487 
2488  m_cbLayerPresets->Delete( idx );
2489  m_currentPreset = nullptr;
2490 
2491  m_presetMRU.Remove( presetName );
2492  }
2493  }
2494 
2495  resetSelection();
2496  return;
2497  }
2498 
2499  LAYER_PRESET* preset = static_cast<LAYER_PRESET*>( m_cbLayerPresets->GetClientData( index ) );
2500  m_currentPreset = preset;
2501 
2502  m_lastSelectedUserPreset = ( !preset || preset->readOnly ) ? nullptr : preset;
2503 
2504  if( preset )
2505  doApplyLayerPreset( *preset );
2506 
2507  if( !m_currentPreset->name.IsEmpty() )
2508  {
2509  m_presetMRU.Remove( m_currentPreset->name );
2510  m_presetMRU.Insert( m_currentPreset->name, 0 );
2511  }
2512 
2513  passOnFocus();
2514 }
2515 
2516 
2518 {
2519  BOARD* board = m_frame->GetBoard();
2520 
2521  setVisibleLayers( aPreset.layers );
2522  setVisibleObjects( aPreset.renderLayers );
2523 
2524  // If the preset doesn't have an explicit active layer to restore, we can at least
2525  // force the active layer to be something in the preset's layer set
2526  PCB_LAYER_ID activeLayer = UNSELECTED_LAYER;
2527 
2528  if( aPreset.activeLayer != UNSELECTED_LAYER )
2529  activeLayer = aPreset.activeLayer;
2530  else if( aPreset.layers.any() && !aPreset.layers.test( m_frame->GetActiveLayer() ) )
2531  activeLayer = *aPreset.layers.Seq().begin();
2532 
2533  LSET boardLayers = board->GetLayerSet();
2534 
2535  if( activeLayer != UNSELECTED_LAYER && boardLayers.Contains( activeLayer ) )
2536  m_frame->SetActiveLayer( activeLayer );
2537 
2538  if( !m_isFpEditor )
2539  m_frame->GetCanvas()->SyncLayersVisibility( board );
2540 
2541  m_frame->GetCanvas()->Refresh();
2542 
2544 }
2545 
2546 
2547 void APPEARANCE_CONTROLS::OnColorSwatchChanged( wxCommandEvent& aEvent )
2548 {
2549  COLOR_SWATCH* swatch = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
2550  COLOR4D newColor = swatch->GetSwatchColor();
2551  LAYER_NUM layer = swatch->GetId();
2552 
2554  cs->SetColor( layer, newColor );
2555 
2557 
2558  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
2559  view->UpdateLayerColor( layer );
2560  view->UpdateLayerColor( GetNetnameLayer( layer ) );
2561 
2562  if( IsCopperLayer( layer ) )
2563  view->UpdateLayerColor( ZONE_LAYER_FOR( layer ) );
2564 
2565  // Update the bitmap of the layer box
2566  if( m_frame->IsType( FRAME_PCB_EDITOR ) )
2567  static_cast<PCB_EDIT_FRAME*>( m_frame )->ReCreateLayerBox( false );
2568 
2569  m_frame->GetCanvas()->Refresh();
2570 
2571  if( layer == LAYER_PCB_BACKGROUND )
2572  m_frame->SetDrawBgColor( newColor );
2573 
2574  passOnFocus();
2575 }
2576 
2577 
2578 void APPEARANCE_CONTROLS::onObjectOpacitySlider( int aLayer, float aOpacity )
2579 {
2581 
2582  switch( aLayer )
2583  {
2584  case static_cast<int>( LAYER_TRACKS ): options.m_TrackOpacity = aOpacity; break;
2585  case static_cast<int>( LAYER_VIAS ): options.m_ViaOpacity = aOpacity; break;
2586  case static_cast<int>( LAYER_PADS ): options.m_PadOpacity = aOpacity; break;
2587  case static_cast<int>( LAYER_ZONES ): options.m_ZoneOpacity = aOpacity; break;
2588  default: return;
2589  }
2590 
2591  m_frame->SetDisplayOptions( options );
2592  passOnFocus();
2593 }
2594 
2595 
2596 void APPEARANCE_CONTROLS::onNetContextMenu( wxCommandEvent& aEvent )
2597 {
2598  wxASSERT( m_netsGrid->GetSelectedRows().size() == 1 );
2599 
2600  int row = m_netsGrid->GetSelectedRows()[0];
2601  NET_GRID_ENTRY& net = m_netsTable->GetEntry( row );
2602 
2603  m_netsGrid->ClearSelection();
2604 
2605  switch( aEvent.GetId() )
2606  {
2607  case ID_SET_NET_COLOR:
2608  {
2609  wxGridCellEditor* editor = m_netsGrid->GetCellEditor( row, NET_GRID_TABLE::COL_COLOR );
2610  editor->BeginEdit( row, NET_GRID_TABLE::COL_COLOR, m_netsGrid );
2611  break;
2612  }
2613 
2614  case ID_HIGHLIGHT_NET:
2615  {
2617  static_cast<intptr_t>( net.code ) );
2618  m_frame->GetCanvas()->Refresh();
2619  break;
2620  }
2621 
2622  case ID_SELECT_NET:
2623  {
2625  static_cast<intptr_t>( net.code ) );
2626  m_frame->GetCanvas()->Refresh();
2627  break;
2628  }
2629 
2630  case ID_DESELECT_NET:
2631  {
2633  static_cast<intptr_t>( net.code ) );
2634  m_frame->GetCanvas()->Refresh();
2635  break;
2636  }
2637 
2638  case ID_SHOW_ALL_NETS:
2640  break;
2641 
2642  case ID_HIDE_OTHER_NETS:
2643  m_netsTable->HideOtherNets( net );
2644  break;
2645 
2646  default:
2647  break;
2648  }
2649 
2650  passOnFocus();
2651 }
2652 
2653 
2655 {
2656  wxString className = netclassNameFromEvent( aEvent );
2657  bool show = aEvent.GetInt();
2658  showNetclass( className, show );
2659  passOnFocus();
2660 }
2661 
2662 
2663 void APPEARANCE_CONTROLS::showNetclass( const wxString& aClassName, bool aShow )
2664 {
2665  BOARD* board = m_frame->GetBoard();
2666  NETINFO_LIST& nets = board->GetNetInfo();
2667  NETCLASSES& classes = board->GetDesignSettings().GetNetClasses();
2668  NETCLASSPTR netclass = classes.Find( aClassName );
2669  TOOL_MANAGER* manager = m_frame->GetToolManager();
2670 
2671  if( !netclass )
2672  return;
2673 
2674  NETCLASS* defaultClass = classes.GetDefaultPtr();
2675 
2676  if( netclass == classes.GetDefault() )
2677  {
2678  const TOOL_ACTION& action = aShow ? PCB_ACTIONS::showNet : PCB_ACTIONS::hideNet;
2679 
2680  for( NETINFO_ITEM* net : nets )
2681  {
2682  if( net->GetNetClass() == defaultClass )
2683  {
2684  manager->RunAction( action, true, static_cast<intptr_t>( net->GetNetCode() ) );
2685 
2686  int row = m_netsTable->GetRowByNetcode( net->GetNetCode() );
2687 
2688  if( row >= 0 )
2690  }
2691  }
2692  }
2693  else
2694  {
2695  const TOOL_ACTION& action = aShow ? PCB_ACTIONS::showNet : PCB_ACTIONS::hideNet;
2696 
2697  for( const wxString& member : *netclass )
2698  {
2699  if( NETINFO_ITEM* net = nets.GetNetItem( member ) )
2700  {
2701  int code = net->GetNetCode();
2702  manager->RunAction( action, true, static_cast<intptr_t>( code ) );
2703 
2704  int row = m_netsTable->GetRowByNetcode( code );
2705 
2706  if( row >= 0 )
2708  }
2709  }
2710  }
2711 
2712  m_netsGrid->ForceRefresh();
2713 }
2714 
2715 
2716 void APPEARANCE_CONTROLS::onNetclassColorChanged( wxCommandEvent& aEvent )
2717 {
2718  KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>(
2720 
2721  std::map<wxString, KIGFX::COLOR4D>& netclassColors = rs->GetNetclassColorMap();
2722 
2723  COLOR_SWATCH* swatch = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
2724  wxString className = netclassNameFromEvent( aEvent );
2725 
2726  netclassColors[className] = swatch->GetSwatchColor();
2727 
2730  m_frame->GetCanvas()->Refresh();
2731 }
2732 
2733 
2735 {
2736  COLOR_SWATCH* s = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
2737  int classId = s->GetId();
2738 
2739  wxASSERT( m_netclassIdMap.count( classId ) );
2740  return m_netclassIdMap.at( classId );
2741 }
2742 
2743 
2744 void APPEARANCE_CONTROLS::onNetColorMode( wxCommandEvent& aEvent )
2745 {
2747 
2748  if( m_rbNetColorAll->GetValue() )
2750  else if( m_rbNetColorRatsnest->GetValue() )
2752  else
2754 
2755  m_frame->SetDisplayOptions( options );
2757  passOnFocus();
2758 }
2759 
2760 
2761 void APPEARANCE_CONTROLS::onRatsnestMode( wxCommandEvent& aEvent )
2762 {
2764 
2765  if( m_rbRatsnestAllLayers->GetValue() )
2766  {
2767  options.m_ShowGlobalRatsnest = true;
2769  }
2770  else if( m_rbRatsnestVisLayers->GetValue() )
2771  {
2772  options.m_ShowGlobalRatsnest = true;
2774  }
2775  else
2776  {
2777  options.m_ShowGlobalRatsnest = false;
2778  }
2779 
2780  m_frame->SetDisplayOptions( options );
2782  passOnFocus();
2783 }
2784 
2785 
2786 void APPEARANCE_CONTROLS::onNetclassContextMenu( wxCommandEvent& aEvent )
2787 {
2788  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
2790  static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
2791 
2792  BOARD* board = m_frame->GetBoard();
2793  NETINFO_LIST& nets = board->GetNetInfo();
2794  NETCLASSES& classes = board->GetDesignSettings().GetNetClasses();
2795  NETCLASSPTR netclass = classes.Find( m_contextMenuNetclass );
2796 
2799 
2800  NETCLASSPTR defaultClass = classes.GetDefault();
2801  wxString defaultClassName = defaultClass->GetName();
2802 
2803  auto runOnNetsOfClass =
2804  [&]( NETCLASSPTR aClass, std::function<void( NETINFO_ITEM* )> aFunction )
2805  {
2806  if( aClass == defaultClass )
2807  {
2808  for( NETINFO_ITEM* net : nets )
2809  if( net->GetNetClass() == defaultClass.get() )
2810  aFunction( net );
2811  }
2812  else
2813  {
2814  for( const wxString& netName : *aClass )
2815  aFunction( nets.GetNetItem( netName ) );
2816  }
2817  };
2818 
2819  switch( aEvent.GetId() )
2820  {
2821  case ID_SET_NET_COLOR:
2822  {
2823  if( setting )
2824  {
2825  setting->ctl_color->GetNewSwatchColor();
2826 
2827  COLOR4D color = setting->ctl_color->GetSwatchColor();
2828 
2829  std::map<wxString, KIGFX::COLOR4D>& netclassColors = rs->GetNetclassColorMap();
2830 
2831  if( color != COLOR4D::UNSPECIFIED )
2832  netclassColors[m_contextMenuNetclass] = color;
2833  else
2834  netclassColors.erase( m_contextMenuNetclass );
2835 
2836  view->UpdateAllLayersColor();
2837  }
2838 
2839  break;
2840  }
2841 
2842  case ID_HIGHLIGHT_NET:
2843  {
2844  if( netclass )
2845  {
2846  runOnNetsOfClass( netclass,
2847  [&]( NETINFO_ITEM* aItem )
2848  {
2849  if( !aItem )
2850  return;
2851 
2852  static bool first = true;
2853  int code = aItem->GetNetCode();
2854 
2855  if( first )
2856  {
2857  board->SetHighLightNet( code );
2858  rs->SetHighlight( true, code );
2859  first = false;
2860  }
2861  else
2862  {
2863  board->SetHighLightNet( code, true );
2864  rs->SetHighlight( true, code, true );
2865  }
2866  } );
2867 
2868  view->UpdateAllLayersColor();
2869  board->HighLightON();
2870  }
2871  break;
2872  }
2873 
2874  case ID_SELECT_NET:
2875  case ID_DESELECT_NET:
2876  {
2877  if( netclass )
2878  {
2879  TOOL_ACTION& action = aEvent.GetId() == ID_SELECT_NET ? PCB_ACTIONS::selectNet :
2881  runOnNetsOfClass( netclass,
2882  [&]( NETINFO_ITEM* aItem )
2883  {
2884  if( !aItem )
2885  return;
2886 
2887  intptr_t code = static_cast<intptr_t>( aItem->GetNetCode() );
2888  m_frame->GetToolManager()->RunAction( action, true, code );
2889  } );
2890  }
2891  break;
2892  }
2893 
2894  case ID_SHOW_ALL_NETS:
2895  {
2896  showNetclass( defaultClassName );
2897  wxASSERT( m_netclassSettingsMap.count( defaultClassName ) );
2898  m_netclassSettingsMap.at( defaultClassName )->ctl_visibility->SetValue( true );
2899 
2900  for( const auto& pair : classes.NetClasses() )
2901  {
2902  showNetclass( pair.first );
2903 
2904  if( m_netclassSettingsMap.count( pair.first ) )
2905  m_netclassSettingsMap.at( pair.first )->ctl_visibility->SetValue( true );
2906  }
2907 
2908  break;
2909  }
2910 
2911  case ID_HIDE_OTHER_NETS:
2912  {
2913  bool showDefault = m_contextMenuNetclass == defaultClassName;
2914  showNetclass( defaultClassName, showDefault );
2915  wxASSERT( m_netclassSettingsMap.count( defaultClassName ) );
2916  m_netclassSettingsMap.at( defaultClassName )->ctl_visibility->SetValue( showDefault );
2917 
2918  for( const auto& pair : classes.NetClasses() )
2919  {
2920  bool show = pair.first == m_contextMenuNetclass;
2921 
2922  showNetclass( pair.first, show );
2923 
2924  if( m_netclassSettingsMap.count( pair.first ) )
2925  m_netclassSettingsMap.at( pair.first )->ctl_visibility->SetValue( show );
2926  }
2927 
2928  break;
2929  }
2930 
2931  default:
2932  break;
2933  }
2934 
2936  m_frame->GetCanvas()->Refresh();
2937 
2938  m_contextMenuNetclass.clear();
2939 }
2940 
2941 
2943 {
2944  m_focusOwner->SetFocus();
2945 }
2946 
2947 
2949 {
2950  WX_INFOBAR* infobar = m_frame->GetInfoBar();
2951 
2952  wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY, _( "Open Preferences" ),
2953  wxEmptyString );
2954 
2955  button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
2956  [&]( wxHyperlinkEvent& aEvent )
2957  {
2958  wxCommandEvent dummy;
2960  } ) );
2961 
2962  infobar->RemoveAllButtons();
2963  infobar->AddButton( button );
2964  infobar->AddCloseButton();
2965 
2966  infobar->ShowMessageFor( _( "The current color theme is read-only. Create a new theme in "
2967  "Preferences to enable color editing." ),
2968  10000, wxICON_INFORMATION );
2969 }
2970 
2971 
2973 {
2974  m_paneLayerDisplayOptions->Refresh();
2975 }
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:759
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:1960
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:539
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:362
void * GetValueAsCustom(int aRow, int aCol, const wxString &aTypeName) override
layer for drc markers with SEVERITY_ERROR
Definition: layer_ids.h:212
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:49
static LSET ForbiddenFootprintLayers()
Layers which are not allowed within footprint definitions.
Definition: lset.cpp:897
std::vector< std::unique_ptr< APPEARANCE_SETTING > > m_layerSettings
static TOOL_ACTION hideNet
Definition: pcb_actions.h:456
Meta control for all pads opacity/visibility (color ignored)
Definition: layer_ids.h:226
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:206
void onNetColorMode(wxCommandEvent &aEvent)
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
void onRatsnestMode(wxCommandEvent &aEvent)
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:185
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:576
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:262
wxFont GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:144
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:361
anchor of items having an anchor point (texts, footprints)
Definition: layer_ids.h:197
LSET GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:481
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:506
int LAYER_NUM
This can be replaced with int and removed.
Definition: layer_ids.h:41
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:680
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:205
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:467
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:119
#define ZONE_LAYER_FOR(copperLayer)
Macro for getting the zone layer for a given copper layer.
Definition: layer_ids.h:252
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:590
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:883
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:125
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:227
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:365
int GetNetnameLayer(int aLayer)
Returns a netname layer corresponding to the given layer.
Definition: layer_ids.h:942
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.
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:705
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:387
void OnBoardNetSettingsChanged(BOARD &aBoard) override
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:505
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 SetBorders(bool aLeft, bool aRight, bool aTop, bool aBottom)
Definition: wx_panel.h:38
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:249
Meta control for all vias opacity/visibility.
Definition: layer_ids.h:189
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:322
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:499
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:527
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:196
COLOR4D GetDefaultColor(int aLayer)
show footprints on front
Definition: layer_ids.h:204
Helper for storing and iterating over GAL_LAYER_IDs.
Definition: layer_ids.h:279
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:719
LAYER_PRESET * m_currentPreset
wxRadioButton * m_rbHighContrastNormal
static GAL_SET DefaultVisible()
Definition: lset.cpp:942
Virtual layers for stacking zones and tracks on a given copper layer.
Definition: layer_ids.h:242
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:691
#define _(s)
HIGH_CONTRAST_MODE m_ContrastModeDisplay
How inactive layers are displayed.
wxBoxSizer * m_objectsOuterSizer
NETCLASSES & GetNetClasses() const
static LSET AllLayersMask()
Definition: lset.cpp:796
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:213
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
E_SERIE r
Definition: eserie.cpp:41
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:466
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:797
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:203
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
wxStaticText * m_inactiveLayersLabel
void UpdateLayerColor(int aLayer)
Apply the new coloring scheme held by RENDER_SETTINGS in case that it has changed.
Definition: view.cpp:741
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:207
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:66
double m_PadOpacity
Opacity override for SMD pads and PTHs.
static TOOL_ACTION showNet
Definition: pcb_actions.h:457
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:451
multilayer pads, usually with holes
Definition: layer_ids.h:209
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:232
static LAYER_PRESET presetBackAssembly
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:191
void setVisibleObjects(GAL_SET aObjects)
std::vector< std::unique_ptr< APPEARANCE_SETTING > > m_objectSettings
wxRadioButton * m_rbRatsnestNone
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:65
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:71
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:455
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:231
bool IsReadOnly() const
Definition: json_settings.h:83
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:890
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:216
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:295
wxBoxSizer * m_layersOuterSizer
wxString KeyNameFromKeyCode(int aKeycode, bool *aIsFound)
Return the key name from the key code.
std::vector< NET_GRID_ENTRY > m_nets
static TOOL_ACTION highContrastModeCycle
Definition: actions.h:104
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
static TOOL_ACTION ratsnestModeCycle
Definition: pcb_actions.h:239
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:762
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
int GetHotKey() const
Return the hotkey keycode which initiates the action.
Definition: tool_action.h:111
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:914
virtual void SetGridVisibility(bool aVisible)
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
static TOOL_ACTION netColorModeCycle
Definition: pcb_actions.h:238
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
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:147
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:112
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:313
int GetNetCode() const
Definition: netinfo.h:120
wxRadioButton * m_rbRatsnestVisLayers