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-2022 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 ? wxT( "1" ) : wxT( "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 != wxT( "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( wxT( "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( _HKI( "Tracks" ), LAYER_TRACKS, _HKI( "Show tracks" ), true ),
336  RR( _HKI( "Vias" ), LAYER_VIAS, _HKI( "Show all vias" ), true ),
337  RR( _HKI( "Pads" ), LAYER_PADS, _HKI( "Show all pads" ), true ),
338  RR( _HKI( "Zones" ), LAYER_ZONES, _HKI( "Show copper zones" ), true ),
339  RR(),
340  RR( _HKI( "Footprints Front" ), LAYER_MOD_FR, _HKI( "Show footprints that are on board's front" ) ),
341  RR( _HKI( "Footprints Back" ), LAYER_MOD_BK, _HKI( "Show footprints that are on board's back" ) ),
342  RR( _HKI( "Through-hole Pads" ),LAYER_PADS_TH, _HKI( "Show through-hole pads" ) ),
343  RR( _HKI( "Values" ), LAYER_MOD_VALUES, _HKI( "Show footprint values" ) ),
344  RR( _HKI( "References" ), LAYER_MOD_REFERENCES, _HKI( "Show footprint references" ) ),
345  RR( _HKI( "Footprint Text" ), LAYER_MOD_TEXT, _HKI( "Show all footprint text" ) ),
346  RR( _HKI( "Hidden Text" ), LAYER_MOD_TEXT_INVISIBLE, _HKI( "Show footprint text marked as invisible" ) ),
347  RR(),
348  RR(),
349  RR( _HKI( "Ratsnest" ), LAYER_RATSNEST, _HKI( "Show unconnected nets as a ratsnest") ),
350  RR( _HKI( "No-Connects" ), LAYER_NO_CONNECTS, _HKI( "Show a marker on pads which have no net connected" ) ),
351  RR( _HKI( "DRC Warnings" ), LAYER_DRC_WARNING, _HKI( "DRC violations with a Warning severity" ) ),
352  RR( _HKI( "DRC Errors" ), LAYER_DRC_ERROR, _HKI( "DRC violations with an Error severity" ) ),
353  RR( _HKI( "DRC Exclusions" ), LAYER_DRC_EXCLUSION, _HKI( "DRC violations which have been individually excluded" ) ),
354  RR( _HKI( "Anchors" ), LAYER_ANCHOR, _HKI( "Show footprint and text origins as a cross" ) ),
355  RR( _HKI( "Drawing Sheet" ), LAYER_DRAWINGSHEET, _HKI( "Show drawing sheet borders and title block" ) ),
356  RR( _HKI( "Grid" ), LAYER_GRID, _HKI( "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 
381  LSET::AllCuMask().set( Edge_Cuts ) );
382 
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  m_notebook->SetPageText( 0, _( "Layers" ) );
979  m_notebook->SetPageText( 1, _( "Objects" ) );
980  m_notebook->SetPageText( 2, _( "Nets" ) );
981 
982  Freeze();
983  rebuildLayers();
986  rebuildObjects();
987  rebuildNets();
988 
992 
994 
995  Thaw();
996  Refresh();
997 }
998 
999 
1001 {
1002  Freeze();
1003  rebuildLayers();
1007  rebuildNets();
1010 
1012 
1013  m_board = m_frame->GetBoard();
1014 
1015  if( m_board )
1016  m_board->AddListener( this );
1017 
1018  Thaw();
1019  Refresh();
1020 }
1021 
1022 
1024 {
1026 }
1027 
1028 
1029 void APPEARANCE_CONTROLS::OnNetVisibilityChanged( int aNetCode, bool aVisibility )
1030 {
1031  int row = m_netsTable->GetRowByNetcode( aNetCode );
1032 
1033  if( row >= 0 )
1034  {
1036  m_netsGrid->ForceRefresh();
1037  }
1038 }
1039 
1040 
1042 {
1043  return aBoardItem->Type() == PCB_NETINFO_T;
1044 }
1045 
1046 
1047 bool APPEARANCE_CONTROLS::doesBoardItemNeedRebuild( std::vector<BOARD_ITEM*>& aBoardItems )
1048 {
1049  bool rebuild = std::any_of( aBoardItems.begin(), aBoardItems.end(),
1050  []( const BOARD_ITEM* a )
1051  {
1052  return a->Type() == PCB_NETINFO_T;
1053  } );
1054 
1055  return rebuild;
1056 }
1057 
1058 
1060 {
1061  if( doesBoardItemNeedRebuild( aItem ) )
1063 }
1064 
1065 
1066 void APPEARANCE_CONTROLS::OnBoardItemsAdded( BOARD& aBoard, std::vector<BOARD_ITEM*>& aItems )
1067 {
1068  if( doesBoardItemNeedRebuild( aItems ) )
1070 }
1071 
1072 
1074 {
1075  if( doesBoardItemNeedRebuild( aItem ) )
1077 }
1078 
1079 
1080 void APPEARANCE_CONTROLS::OnBoardItemsRemoved( BOARD& aBoard, std::vector<BOARD_ITEM*>& aItems )
1081 {
1082  if( doesBoardItemNeedRebuild( aItems ) )
1084 }
1085 
1086 
1088 {
1089  if( doesBoardItemNeedRebuild( aItem ) )
1091 }
1092 
1093 
1094 void APPEARANCE_CONTROLS::OnBoardItemsChanged( BOARD& aBoard, std::vector<BOARD_ITEM*>& aItems )
1095 {
1096  if( doesBoardItemNeedRebuild( aItems ) )
1098 }
1099 
1100 
1102 {
1103  Freeze();
1104  rebuildNets();
1105  Thaw();
1106 }
1107 
1108 
1110 {
1113 }
1114 
1115 
1117 {
1118  for( const std::unique_ptr<APPEARANCE_SETTING>& setting : m_layerSettings )
1119  {
1120  setting->ctl_panel->SetBackgroundColour( m_layerPanelColour );
1121  setting->ctl_indicator->SetIndicatorState( ROW_ICON_PROVIDER::STATE::OFF );
1122  }
1123 
1124  wxChar r, g, b;
1125 
1126  r = m_layerPanelColour.Red();
1127  g = m_layerPanelColour.Green();
1128  b = m_layerPanelColour.Blue();
1129 
1130  if( r < 240 || g < 240 || b < 240 )
1131  {
1132  r = wxChar( std::min( (int) r + 15, 255 ) );
1133  g = wxChar( std::min( (int) g + 15, 255 ) );
1134  b = wxChar( std::min( (int) b + 15, 255 ) );
1135  }
1136  else
1137  {
1138  r = wxChar( std::max( (int) r - 15, 0 ) );
1139  g = wxChar( std::max( (int) g - 15, 0 ) );
1140  b = wxChar( std::max( (int) b - 15, 0 ) );
1141  }
1142 
1143  PCB_LAYER_ID current = m_frame->GetActiveLayer();
1144 
1145  if( !m_layerSettingsMap.count( current ) )
1146  {
1147  wxASSERT( m_layerSettingsMap.count( F_Cu ) );
1148  current = F_Cu;
1149  }
1150 
1151  APPEARANCE_SETTING* newSetting = m_layerSettingsMap[ current ];
1152 
1153  newSetting->ctl_panel->SetBackgroundColour( wxColour( r, g, b ) );
1155 
1156  Refresh();
1157 }
1158 
1159 
1160 void APPEARANCE_CONTROLS::SetLayerVisible( LAYER_NUM aLayer, bool isVisible )
1161 {
1162  LSET visible = getVisibleLayers();
1163  PCB_LAYER_ID layer = ToLAYER_ID( aLayer );
1164 
1165  if( visible.test( layer ) == isVisible )
1166  return;
1167 
1168  visible.set( layer, isVisible );
1169  setVisibleLayers( visible );
1170 
1171  m_frame->GetCanvas()->GetView()->SetLayerVisible( layer, isVisible );
1172 
1174 }
1175 
1176 
1178 {
1179  if( m_objectSettingsMap.count( aLayer ) )
1180  {
1181  APPEARANCE_SETTING* setting = m_objectSettingsMap.at( aLayer );
1182  setting->ctl_visibility->SetValue( isVisible );
1183  }
1184 
1185  m_frame->GetBoard()->SetElementVisibility( aLayer, isVisible );
1186 
1187  m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, isVisible );
1188  m_frame->GetCanvas()->Refresh();
1189 }
1190 
1191 
1193 {
1194  if( m_isFpEditor )
1195  {
1196  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1197 
1198  for( PCB_LAYER_ID layer : LSET::AllLayersMask().Seq() )
1199  view->SetLayerVisible( layer, aLayers.Contains( layer ) );
1200  }
1201  else
1202  {
1203  m_frame->GetBoard()->SetVisibleLayers( aLayers );
1204  }
1205 }
1206 
1207 
1209 {
1210  if( m_isFpEditor )
1211  {
1212  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1213 
1214  for( size_t i = 0; i < GAL_LAYER_INDEX( LAYER_ZONE_START ); i++ )
1215  view->SetLayerVisible( GAL_LAYER_ID_START + GAL_LAYER_ID( i ), aLayers.test( i ) );
1216  }
1217  else
1218  {
1219  // Ratsnest visibility is controlled by the ratsnest option, and not by the preset
1220  if( m_frame->IsType( FRAME_PCB_EDITOR ) )
1221  {
1223  aLayers.set( LAYER_RATSNEST, opt.m_ShowGlobalRatsnest );
1224  }
1225 
1226  m_frame->GetBoard()->SetVisibleElements( aLayers );
1227  }
1228 }
1229 
1230 
1232 {
1233  if( m_isFpEditor )
1234  {
1235  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1236  LSET set;
1237 
1238  for( PCB_LAYER_ID layer : LSET::AllLayersMask().Seq() )
1239  set.set( layer, view->IsLayerVisible( layer ) );
1240 
1241  return set;
1242  }
1243  else
1244  {
1245  return m_frame->GetBoard()->GetVisibleLayers();
1246  }
1247 }
1248 
1249 
1251 {
1252  if( m_isFpEditor )
1253  {
1254  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
1255  GAL_SET set;
1256  set.reset();
1257 
1258  for( size_t i = 0; i < set.size(); i++ )
1259  set.set( i, view->IsLayerVisible( GAL_LAYER_ID_START + GAL_LAYER_ID( i ) ) );
1260 
1261  return set;
1262  }
1263  else
1264  {
1265  return m_frame->GetBoard()->GetVisibleElements();
1266  }
1267 }
1268 
1269 
1271 {
1272  // TODO(JE) Is this even needed if the layer alphas are getting directly updated?
1273  // Maybe we just need the "down" arrow to indicate if the alpha is below 1
1274 
1275 #if 0
1276  static constexpr double alphaEpsilon = 0.04;
1277 
1278  PCB_LAYER_ID current = m_frame->GetActiveLayer();
1280  KIGFX::PCB_PAINTER* painter =
1281  static_cast<KIGFX::PCB_PAINTER*>( m_frame->GetCanvas()->GetView()->GetPainter() );
1282  KIGFX::PCB_RENDER_SETTINGS* rs = painter->GetSettings();
1283 
1284  for( APPEARANCE_SETTING& setting : m_layerSettings )
1285  {
1286  if( !setting.ctl_indicator )
1287  continue;
1288 
1289  COLOR4D layerColor = theme->GetColor( setting.id );
1290  COLOR4D screenColor = rs->GetLayerColor( setting.id );
1291 
1292  if( std::abs( screenColor.a - layerColor.a ) > alphaEpsilon )
1293  {
1294  if( screenColor.a < layerColor.a )
1295  setting.ctl_indicator->SetIndicatorState( ROW_ICON_PROVIDER::STATE::DOWN );
1296  else
1297  setting.ctl_indicator->SetIndicatorState( ROW_ICON_PROVIDER::STATE::UP );
1298  }
1299  else
1300  {
1301  setting.ctl_indicator->SetIndicatorState( setting.id == current ?
1303  ROW_ICON_PROVIDER::STATE::OFF );
1304  }
1305  }
1306 #endif
1307 }
1308 
1309 
1311 {
1312  const PCB_DISPLAY_OPTIONS& options = m_frame->GetDisplayOptions();
1313 
1314  switch( options.m_ContrastModeDisplay )
1315  {
1316  case HIGH_CONTRAST_MODE::NORMAL: m_rbHighContrastNormal->SetValue( true ); break;
1317  case HIGH_CONTRAST_MODE::DIMMED: m_rbHighContrastDim->SetValue( true ); break;
1318  case HIGH_CONTRAST_MODE::HIDDEN: m_rbHighContrastOff->SetValue( true ); break;
1319  }
1320 
1321  switch( options.m_NetColorMode )
1322  {
1323  case NET_COLOR_MODE::ALL: m_rbNetColorAll->SetValue( true ); break;
1324  case NET_COLOR_MODE::RATSNEST: m_rbNetColorRatsnest->SetValue( true ); break;
1325  case NET_COLOR_MODE::OFF: m_rbNetColorOff->SetValue( true ); break;
1326  }
1327 
1328  m_cbFlipBoard->SetValue( m_frame->GetCanvas()->GetView()->IsMirroredX() );
1329 
1330  if( !m_isFpEditor )
1331  {
1332  if( !options.m_ShowGlobalRatsnest )
1333  m_rbRatsnestNone->SetValue( true );
1334  else if( options.m_RatsnestMode == RATSNEST_MODE::ALL )
1335  m_rbRatsnestAllLayers->SetValue( true );
1336  else
1337  m_rbRatsnestVisLayers->SetValue( true );
1338 
1339  wxASSERT( m_objectSettingsMap.count( LAYER_RATSNEST ) );
1341  ratsnest->ctl_visibility->SetValue( options.m_ShowGlobalRatsnest );
1342  }
1343 }
1344 
1345 
1346 std::vector<LAYER_PRESET> APPEARANCE_CONTROLS::GetUserLayerPresets() const
1347 {
1348  std::vector<LAYER_PRESET> ret;
1349 
1350  for( const std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
1351  {
1352  if( !pair.second.readOnly )
1353  ret.emplace_back( pair.second );
1354  }
1355 
1356  return ret;
1357 }
1358 
1359 
1360 void APPEARANCE_CONTROLS::SetUserLayerPresets( std::vector<LAYER_PRESET>& aPresetList )
1361 {
1362  // Reset to defaults
1364 
1365  for( const LAYER_PRESET& preset : aPresetList )
1366  {
1367  if( m_layerPresets.count( preset.name ) )
1368  continue;
1369 
1370  m_layerPresets[preset.name] = preset;
1371 
1372  m_presetMRU.Add( preset.name );
1373  }
1374 
1376 }
1377 
1378 
1380 {
1381  m_layerPresets.clear();
1382  m_presetMRU.clear();
1383 
1384  // Load the read-only defaults
1387  presetBackAssembly } )
1388  {
1389  m_layerPresets[preset.name] = preset;
1390  m_layerPresets[preset.name].readOnly = true;
1391 
1392  m_presetMRU.Add( preset.name );
1393  }
1394 }
1395 
1396 
1397 void APPEARANCE_CONTROLS::ApplyLayerPreset( const wxString& aPresetName )
1398 {
1399  updateLayerPresetSelection( aPresetName );
1400 
1401  wxCommandEvent dummy;
1403 }
1404 
1405 
1407 {
1408  if( m_layerPresets.count( aPreset.name ) )
1409  m_currentPreset = &m_layerPresets[aPreset.name];
1410  else
1411  m_currentPreset = nullptr;
1412 
1414  : nullptr;
1415 
1416  updateLayerPresetSelection( aPreset.name );
1417  doApplyLayerPreset( aPreset );
1418 }
1419 
1420 
1422 {
1423  BOARD* board = m_frame->GetBoard();
1424  LSET enabled = board->GetEnabledLayers();
1425  LSET visible = getVisibleLayers();
1426 
1428  COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
1429  bool readOnly = theme->IsReadOnly();
1430 
1431 #ifdef __WXMAC__
1432  wxSizerItem* m_windowLayersSizerItem = m_panelLayersSizer->GetItem( m_windowLayers );
1433  m_windowLayersSizerItem->SetFlag( m_windowLayersSizerItem->GetFlag() & ~wxTOP );
1434 #endif
1435 
1436  auto appendLayer =
1437  [&]( std::unique_ptr<APPEARANCE_SETTING>& aSetting )
1438  {
1439  int layer = aSetting->id;
1440 
1441  wxPanel* panel = new wxPanel( m_windowLayers, layer );
1442  wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
1443  panel->SetSizer( sizer );
1444 
1445  panel->SetBackgroundColour( m_layerPanelColour );
1446 
1447  aSetting->visible = visible[layer];
1448 
1449  // TODO(JE) consider restyling this indicator
1450  INDICATOR_ICON* indicator = new INDICATOR_ICON( panel, *m_iconProvider,
1451  ROW_ICON_PROVIDER::STATE::OFF,
1452  layer );
1453 
1454  COLOR_SWATCH* swatch = new COLOR_SWATCH( panel, COLOR4D::UNSPECIFIED, layer,
1455  bgColor, theme->GetColor( layer ),
1456  SWATCH_SMALL );
1457  swatch->SetToolTip( _( "Double click or middle click for color change, "
1458  "right click for menu" ) );
1459 
1460  BITMAP_TOGGLE* btn_visible = new BITMAP_TOGGLE( panel, layer,
1463  aSetting->visible );
1464  btn_visible->SetToolTip( _( "Show or hide this layer" ) );
1465 
1466  wxStaticText* label = new wxStaticText( panel, layer, aSetting->label );
1467  label->Wrap( -1 );
1468  label->SetToolTip( aSetting->tooltip );
1469 
1470  sizer->AddSpacer( 1 );
1471  sizer->Add( indicator, 0, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1472  sizer->AddSpacer( 5 );
1473  sizer->Add( swatch, 0, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1474  sizer->AddSpacer( 6 );
1475  sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1476  sizer->AddSpacer( 5 );
1477  sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxTOP, 2 );
1478 
1479  m_layersOuterSizer->Add( panel, 0, wxEXPAND, 0 );
1480 
1481  aSetting->ctl_panel = panel;
1482  aSetting->ctl_indicator = indicator;
1483  aSetting->ctl_visibility = btn_visible;
1484  aSetting->ctl_color = swatch;
1485  aSetting->ctl_text = label;
1486 
1487  panel->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1488  indicator->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1489  swatch->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1490  label->Bind( wxEVT_LEFT_DOWN, &APPEARANCE_CONTROLS::onLayerLeftClick, this );
1491 
1492  btn_visible->Bind( TOGGLE_CHANGED,
1493  [&]( wxCommandEvent& aEvent )
1494  {
1495  wxObject* btn = aEvent.GetEventObject();
1496  int layerId = static_cast<wxWindow*>( btn )->GetId();
1497 
1498  onLayerVisibilityToggled( static_cast<PCB_LAYER_ID>( layerId ) );
1499  } );
1500 
1501  swatch->Bind( COLOR_SWATCH_CHANGED, &APPEARANCE_CONTROLS::OnColorSwatchChanged,
1502  this );
1504  this ) );
1505  swatch->SetReadOnly( readOnly );
1506 
1507  panel->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1508  indicator->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1509  swatch->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1510  btn_visible->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1511  label->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1512  };
1513 
1514  auto updateLayer =
1515  [&]( std::unique_ptr<APPEARANCE_SETTING>& aSetting )
1516  {
1517  int layer = aSetting->id;
1518  aSetting->visible = visible[layer];
1519  aSetting->ctl_panel->Show();
1520  aSetting->ctl_panel->SetId( layer );
1521  aSetting->ctl_indicator->SetWindowID( layer );
1522  aSetting->ctl_color->SetWindowID( layer );
1523  aSetting->ctl_color->SetSwatchColor( theme->GetColor( layer ), false );
1524  aSetting->ctl_visibility->SetWindowID( layer );
1525  aSetting->ctl_text->SetLabelText( aSetting->label );
1526  aSetting->ctl_text->SetId( layer );
1527  aSetting->ctl_text->SetToolTip( aSetting->tooltip );
1528  };
1529 
1530  // technical layers are shown in this order:
1531  // Because they are static, wxGetTranslation must be explicitly
1532  // called for tooltips.
1533  static const struct {
1534  PCB_LAYER_ID layerId;
1535  wxString tooltip;
1536  } non_cu_seq[] = {
1537  { F_Adhes, _HKI( "Adhesive on board's front" ) },
1538  { B_Adhes, _HKI( "Adhesive on board's back" ) },
1539  { F_Paste, _HKI( "Solder paste on board's front" ) },
1540  { B_Paste, _HKI( "Solder paste on board's back" ) },
1541  { F_SilkS, _HKI( "Silkscreen on board's front" ) },
1542  { B_SilkS, _HKI( "Silkscreen on board's back" ) },
1543  { F_Mask, _HKI( "Solder mask on board's front" ) },
1544  { B_Mask, _HKI( "Solder mask on board's back" ) },
1545  { Dwgs_User, _HKI( "Explanatory drawings" ) },
1546  { Cmts_User, _HKI( "Explanatory comments" ) },
1547  { Eco1_User, _HKI( "User defined meaning" ) },
1548  { Eco2_User, _HKI( "User defined meaning" ) },
1549  { Edge_Cuts, _HKI( "Board's perimeter definition" ) },
1550  { Margin, _HKI( "Board's edge setback outline" ) },
1551  { F_CrtYd, _HKI( "Footprint courtyards on board's front" ) },
1552  { B_CrtYd, _HKI( "Footprint courtyards on board's back" ) },
1553  { F_Fab, _HKI( "Footprint assembly on board's front" ) },
1554  { B_Fab, _HKI( "Footprint assembly on board's back" ) },
1555  { User_1, _HKI( "User defined layer 1" ) },
1556  { User_2, _HKI( "User defined layer 2" ) },
1557  { User_3, _HKI( "User defined layer 3" ) },
1558  { User_4, _HKI( "User defined layer 4" ) },
1559  { User_5, _HKI( "User defined layer 5" ) },
1560  { User_6, _HKI( "User defined layer 6" ) },
1561  { User_7, _HKI( "User defined layer 7" ) },
1562  { User_8, _HKI( "User defined layer 8" ) },
1563  { User_9, _HKI( "User defined layer 9" ) },
1564  };
1565 
1566  // There is a spacer added to the end of the list that we need to remove and re-add
1567  // after possibly adding additional layers
1568  if( m_layersOuterSizer->GetItemCount() > 0 )
1569  {
1570  m_layersOuterSizer->Detach( m_layersOuterSizer->GetItemCount() - 1 );
1571  }
1572  // Otherwise, this is the first time we are updating the control, so we need to attach
1573  // the handler
1574  else
1575  {
1576  // Add right click handling to show the context menu when clicking to the free area in
1577  // m_windowLayers (below the layer items)
1578  m_windowLayers->Bind( wxEVT_RIGHT_DOWN, &APPEARANCE_CONTROLS::rightClickHandler, this );
1579  }
1580 
1581  std::size_t total_layers = enabled.CuStack().size();
1582 
1583  for( const auto& entry : non_cu_seq )
1584  {
1585  if( enabled[entry.layerId] )
1586  total_layers++;
1587  }
1588 
1589  // Adds layers to the panel until we have enough to hold our total count
1590  while( total_layers > m_layerSettings.size() )
1591  m_layerSettings.push_back( std::make_unique<APPEARANCE_SETTING>() );
1592 
1593  // We never delete layers from the panel, only hide them. This saves us
1594  // having to recreate the (possibly) later with minimal overhead
1595  for( std::size_t ii = total_layers; ii < m_layerSettings.size(); ++ii )
1596  {
1597  if( m_layerSettings[ii]->ctl_panel )
1598  m_layerSettings[ii]->ctl_panel->Show( false );
1599  }
1600 
1601  auto layer_it = m_layerSettings.begin();
1602 
1603  // show all coppers first, with front on top, back on bottom, then technical layers
1604  for( LSEQ cu_stack = enabled.CuStack(); cu_stack; ++cu_stack, ++layer_it )
1605  {
1606  PCB_LAYER_ID layer = *cu_stack;
1607  wxString dsc;
1608 
1609  switch( layer )
1610  {
1611  case F_Cu: dsc = _( "Front copper layer" ); break;
1612  case B_Cu: dsc = _( "Back copper layer" ); break;
1613  default: dsc = _( "Inner copper layer" ); break;
1614  }
1615 
1616  std::unique_ptr<APPEARANCE_SETTING>& setting = *layer_it;
1617 
1618  setting->label = board->GetLayerName( layer );
1619  setting->id = layer;
1620  setting->tooltip = dsc;
1621 
1622  if( setting->ctl_panel == nullptr )
1623  appendLayer( setting );
1624  else
1625  updateLayer( setting );
1626 
1627  m_layerSettingsMap[layer] = setting.get();
1628 
1630  {
1631  setting->ctl_text->Disable();
1632  setting->ctl_color->SetToolTip( wxEmptyString );
1633  }
1634  }
1635 
1636  for( const auto& entry : non_cu_seq )
1637  {
1638  PCB_LAYER_ID layer = entry.layerId;
1639 
1640  if( !enabled[layer] )
1641  continue;
1642 
1643  std::unique_ptr<APPEARANCE_SETTING>& setting = *layer_it;
1644 
1645  setting->label = board->GetLayerName( layer );
1646  setting->id = layer;
1647  // Because non_cu_seq is created static, we must explicitly call wxGetTranslation for
1648  // texts which are internationalized
1649  setting->tooltip = wxGetTranslation( entry.tooltip );
1650 
1651  if( setting->ctl_panel == nullptr )
1652  appendLayer( setting );
1653  else
1654  updateLayer( setting );
1655 
1656  m_layerSettingsMap[layer] = setting.get();
1657 
1659  {
1660  setting->ctl_text->Disable();
1661  setting->ctl_color->SetToolTip( wxEmptyString );
1662  }
1663 
1664  ++layer_it;
1665  }
1666 
1667  m_layersOuterSizer->AddSpacer( 10 );
1668  m_windowLayers->SetBackgroundColour( m_layerPanelColour );
1669  m_windowLayers->Layout();
1670 
1671  m_paneLayerDisplayOptions->SetLabel( _( "Layer Display Options" ) );
1672 
1674  wxString msg;
1675 
1676  if( hotkey )
1677  msg = wxString::Format( _( "Inactive layers (%s):" ), KeyNameFromKeyCode( hotkey ) );
1678  else
1679  msg = _( "Inactive layers:" );
1680 
1681  m_inactiveLayersLabel->SetLabel( msg );
1682 
1683  m_rbHighContrastNormal->SetLabel( _( "Normal" ) );
1684  m_rbHighContrastNormal->SetToolTip( _( "Inactive layers will be shown in full color" ) );
1685 
1686  m_rbHighContrastDim->SetLabel( _( "Dim" ) );
1687  m_rbHighContrastDim->SetToolTip( _( "Inactive layers will be dimmed" ) );
1688 
1689  m_rbHighContrastOff->SetLabel( _( "Hide" ) );
1690  m_rbHighContrastOff->SetToolTip( _( "Inactive layers will be hidden" ) );
1691 
1692  m_cbFlipBoard->SetLabel( _( "Flip board view" ) );
1693 }
1694 
1695 
1697 {
1698  delete m_layerContextMenu;
1699  m_layerContextMenu = new wxMenu;
1700 
1702  _( "Show All Copper Layers" ),
1705  _( "Hide All Copper Layers" ),
1707 
1708  m_layerContextMenu->AppendSeparator();
1709 
1711  _( "Hide All Layers But Active" ),
1713 
1714  m_layerContextMenu->AppendSeparator();
1715 
1716  AddMenuItem( m_layerContextMenu, ID_SHOW_ALL_NON_COPPER, _( "Show All Non Copper Layers" ),
1718 
1719  AddMenuItem( m_layerContextMenu, ID_HIDE_ALL_NON_COPPER, _( "Hide All Non Copper Layers" ),
1721 
1722  m_layerContextMenu->AppendSeparator();
1723 
1724  AddMenuItem( m_layerContextMenu, ID_PRESET_ALL_LAYERS, _( "Show All Layers" ),
1726 
1727  AddMenuItem( m_layerContextMenu, ID_PRESET_NO_LAYERS, _( "Hide All Layers" ),
1729 
1730  m_layerContextMenu->AppendSeparator();
1731 
1733  _( "Show Only Front Assembly Layers" ),
1735 
1736  AddMenuItem( m_layerContextMenu, ID_PRESET_FRONT, _( "Show Only Front Layers" ),
1738 
1739  // Only show the internal layer option if internal layers are enabled
1740  if( m_frame->GetBoard()->GetCopperLayerCount() > 2 )
1741  {
1742  AddMenuItem( m_layerContextMenu, ID_PRESET_INNER_COPPER, _( "Show Only Inner Layers" ),
1744  }
1745 
1746  AddMenuItem( m_layerContextMenu, ID_PRESET_BACK, _( "Show Only Back Layers" ),
1748 
1749  AddMenuItem( m_layerContextMenu, ID_PRESET_BACK_ASSEMBLY, _( "Show Only Back Assembly Layers" ),
1751 }
1752 
1753 
1754 void APPEARANCE_CONTROLS::OnLayerContextMenu( wxCommandEvent& aEvent )
1755 {
1756  BOARD* board = m_frame->GetBoard();
1757  LSET visible = getVisibleLayers();
1758 
1759  PCB_LAYER_ID current = m_frame->GetActiveLayer();
1760 
1761  switch( aEvent.GetId() )
1762  {
1763  case ID_PRESET_NO_LAYERS:
1765  return;
1766 
1767  case ID_PRESET_ALL_LAYERS:
1769  return;
1770 
1772  {
1773  visible |= presetAllCopper.layers;
1774  setVisibleLayers( visible );
1775  break;
1776  }
1777 
1780  SetLayerVisible( current, true );
1781  break;
1782 
1784  {
1785  visible &= ~presetAllCopper.layers;
1786 
1787  if( !visible.test( current ) && visible.count() > 0 )
1788  m_frame->SetActiveLayer( *visible.Seq().begin() );
1789 
1790  setVisibleLayers( visible );
1791  break;
1792  }
1793 
1795  {
1796  visible &= presetAllCopper.layers;
1797 
1798  if( !visible.test( current ) && visible.count() > 0 )
1799  m_frame->SetActiveLayer( *visible.Seq().begin() );
1800 
1801  setVisibleLayers( visible );
1802  break;
1803  }
1804 
1806  {
1807  visible |= ~presetAllCopper.layers;
1808 
1809  setVisibleLayers( visible );
1810  break;
1811  }
1812 
1815  return;
1816 
1817  case ID_PRESET_FRONT:
1819  return;
1820 
1823  return;
1824 
1825  case ID_PRESET_BACK:
1827  return;
1828 
1831  return;
1832  }
1833 
1836 
1837  if( !m_isFpEditor )
1838  m_frame->GetCanvas()->SyncLayersVisibility( board );
1839 
1840  m_frame->GetCanvas()->Refresh();
1841 }
1842 
1843 
1845 {
1846  return m_notebook->GetSelection();
1847 }
1848 
1849 
1851 {
1852  size_t max = m_notebook->GetPageCount();
1853 
1854  if( aTab >= 0 && static_cast<size_t>( aTab ) < max )
1855  m_notebook->SetSelection( aTab );
1856 }
1857 
1858 
1860 {
1862  bool readOnly = theme->IsReadOnly();
1863  LSET visible = getVisibleLayers();
1864  GAL_SET objects = getVisibleObjects();
1865 
1866  Freeze();
1867 
1868  for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_layerSettings )
1869  {
1870  LAYER_NUM layer = setting->id;
1871 
1872  if( setting->ctl_visibility )
1873  setting->ctl_visibility->SetValue( visible[layer] );
1874 
1875  if( setting->ctl_color )
1876  {
1877  const COLOR4D& color = theme->GetColor( layer );
1878  setting->ctl_color->SetSwatchColor( color, false );
1879  setting->ctl_color->SetReadOnly( readOnly );
1880  }
1881  }
1882 
1883  for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
1884  {
1885  GAL_LAYER_ID layer = static_cast<GAL_LAYER_ID>( setting->id );
1886 
1887  if( setting->ctl_visibility )
1888  setting->ctl_visibility->SetValue( objects.Contains( layer ) );
1889 
1890  if( setting->ctl_color )
1891  {
1892  const COLOR4D& color = theme->GetColor( layer );
1893  setting->ctl_color->SetSwatchColor( color, false );
1894  setting->ctl_color->SetReadOnly( readOnly );
1895  }
1896  }
1897 
1898  // Update indicators and panel background colors
1899  OnLayerChanged();
1900 
1901  Thaw();
1902 
1903  m_windowLayers->Refresh();
1904 }
1905 
1906 
1907 void APPEARANCE_CONTROLS::onLayerLeftClick( wxMouseEvent& aEvent )
1908 {
1909  auto eventSource = static_cast<wxWindow*>( aEvent.GetEventObject() );
1910 
1911  PCB_LAYER_ID layer = ToLAYER_ID( eventSource->GetId() );
1912 
1913  if( m_isFpEditor && LSET::ForbiddenFootprintLayers().test( layer ) )
1914  return;
1915 
1916  m_frame->SetActiveLayer( layer );
1917  passOnFocus();
1918 }
1919 
1920 
1921 void APPEARANCE_CONTROLS::rightClickHandler( wxMouseEvent& aEvent )
1922 {
1923  wxASSERT( m_layerContextMenu );
1924  PopupMenu( m_layerContextMenu );
1925  passOnFocus();
1926 };
1927 
1928 
1930 {
1931  LSET visibleLayers = getVisibleLayers();
1932 
1933  visibleLayers.set( aLayer, !visibleLayers.test( aLayer ) );
1934  setVisibleLayers( visibleLayers );
1935  m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, visibleLayers.test( aLayer ) );
1936 
1938  m_frame->GetCanvas()->Refresh();
1939 }
1940 
1941 
1943  bool isFinal )
1944 {
1945  // Special-case controls
1946  switch( aLayer )
1947  {
1948  case LAYER_RATSNEST:
1949  {
1950  // don't touch the layers. ratsnest is enabled on per-item basis.
1952  m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, true );
1953 
1954  if( m_frame->IsType( FRAME_PCB_EDITOR ) )
1955  {
1957  opt.m_ShowGlobalRatsnest = isVisible;
1958  m_frame->SetDisplayOptions( opt );
1959  m_frame->GetBoard()->SetElementVisibility( aLayer, isVisible );
1961  }
1962 
1963  break;
1964  }
1965 
1966  case LAYER_GRID:
1967  m_frame->SetGridVisibility( isVisible );
1968  m_frame->GetCanvas()->Refresh();
1970  break;
1971 
1972  case LAYER_MOD_TEXT:
1973  // Because Footprint Text is a meta-control that also can disable values/references,
1974  // drag them along here so that the user is less likely to be confused.
1975  if( isFinal )
1976  {
1977  // Should only trigger when you actually click the Footprint Text button
1978  // Otherwise it goes into infinite recursive loop with the following case section
1979  onObjectVisibilityChanged( LAYER_MOD_REFERENCES, isVisible, false );
1980  onObjectVisibilityChanged( LAYER_MOD_VALUES, isVisible, false );
1981  m_objectSettingsMap[LAYER_MOD_REFERENCES]->ctl_visibility->SetValue( isVisible );
1982  m_objectSettingsMap[LAYER_MOD_VALUES]->ctl_visibility->SetValue( isVisible );
1983  }
1984  break;
1985 
1986  case LAYER_MOD_REFERENCES:
1987  case LAYER_MOD_VALUES:
1988  // In case that user changes Footprint Value/References when the Footprint Text
1989  // meta-control is disabled, we should put it back on.
1990  if( isVisible )
1991  {
1992  onObjectVisibilityChanged( LAYER_MOD_TEXT, isVisible, false );
1993  m_objectSettingsMap[LAYER_MOD_TEXT]->ctl_visibility->SetValue( isVisible );
1994  }
1995  break;
1996 
1997  default:
1998  break;
1999  }
2000 
2001  GAL_SET visible = getVisibleObjects();
2002 
2003  if( visible.Contains( aLayer ) != isVisible )
2004  {
2005  visible.set( aLayer, isVisible );
2006  setVisibleObjects( visible );
2007  m_frame->GetCanvas()->GetView()->SetLayerVisible( aLayer, isVisible );
2009  }
2010 
2011  if( isFinal )
2012  {
2013  m_frame->GetCanvas()->Refresh();
2014  passOnFocus();
2015  }
2016 }
2017 
2018 
2020 {
2022  COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
2023  GAL_SET visible = getVisibleObjects();
2024  int swatchWidth = m_windowObjects->ConvertDialogToPixels( wxSize( 8, 0 ) ).x;
2025  int labelWidth = 0;
2026 
2027  m_objectSettings.clear();
2028  m_objectsOuterSizer->Clear( true );
2029  m_objectsOuterSizer->AddSpacer( 5 );
2030 
2031  auto appendObject =
2032  [&]( const std::unique_ptr<APPEARANCE_SETTING>& aSetting )
2033  {
2034  wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
2035  int layer = aSetting->id;
2036 
2037  aSetting->visible = visible.Contains( ToGalLayer( layer ) );
2038  COLOR4D color = theme->GetColor( layer );
2039  COLOR4D defColor = theme->GetDefaultColor( layer );
2040 
2041  if( color != COLOR4D::UNSPECIFIED )
2042  {
2043  COLOR_SWATCH* swatch = new COLOR_SWATCH( m_windowObjects, color, layer,
2044  bgColor, defColor, SWATCH_SMALL );
2045  swatch->SetToolTip( _( "Left double click or middle click for color change, "
2046  "right click for menu" ) );
2047 
2048  sizer->Add( swatch, 0, wxALIGN_CENTER_VERTICAL, 0 );
2049  aSetting->ctl_color = swatch;
2050 
2051  swatch->Bind( COLOR_SWATCH_CHANGED,
2053 
2055  this ) );
2056  }
2057  else
2058  {
2059  sizer->AddSpacer( swatchWidth );
2060  }
2061 
2062  BITMAP_TOGGLE* btn_visible = new BITMAP_TOGGLE( m_windowObjects, layer,
2065  aSetting->visible );
2066 
2067  wxString tip;
2068  tip.Printf( _( "Show or hide %s" ), aSetting->label.Lower() );
2069  btn_visible->SetToolTip( tip );
2070 
2071  aSetting->ctl_visibility = btn_visible;
2072 
2073  sizer->AddSpacer( 5 );
2074 
2075  btn_visible->Bind( TOGGLE_CHANGED,
2076  [&]( wxCommandEvent& aEvent )
2077  {
2078  int id = static_cast<wxWindow*>( aEvent.GetEventObject() )->GetId();
2079  bool isVisible = aEvent.GetInt();
2080  onObjectVisibilityChanged( ToGalLayer( id ), isVisible, true );
2081  } );
2082 
2083  wxStaticText* label = new wxStaticText( m_windowObjects, layer, aSetting->label );
2084  label->Wrap( -1 );
2085  label->SetToolTip( aSetting->tooltip );
2086 
2087  if( aSetting->can_control_opacity )
2088  {
2089  label->SetMinSize( wxSize( labelWidth, -1 ) );
2090 #ifdef __WXMAC__
2091  sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, 10 );
2092  sizer->AddSpacer( 5 );
2093  sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, 10 );
2094 #else
2095  sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL, 0 );
2096  sizer->AddSpacer( 5 );
2097  sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL, 0 );
2098 #endif
2099 
2100  wxSlider* slider = new wxSlider( m_windowObjects, wxID_ANY, 100, 0, 100,
2101  wxDefaultPosition, wxDefaultSize,
2102  wxSL_HORIZONTAL );
2103 #ifdef __WXMAC__
2104  slider->SetMinSize( wxSize( 80, 16 ) );
2105 #else
2106  slider->SetMinSize( wxSize( 80, -1 ) );
2107 #endif
2108 
2109  tip.Printf( _( "Set opacity of %s" ), aSetting->label.Lower() );
2110  slider->SetToolTip( tip );
2111 
2112  sizer->Add( slider, 1, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 5 );
2113  aSetting->ctl_opacity = slider;
2114 
2115  auto opacitySliderHandler =
2116  [=]( wxCommandEvent& aEvent )
2117  {
2118  wxSlider* ctrl = static_cast<wxSlider*>( aEvent.GetEventObject() );
2119  int value = ctrl->GetValue();
2120  onObjectOpacitySlider( layer, value / 100.0f );
2121  };
2122 
2123  slider->Bind( wxEVT_SCROLL_CHANGED, opacitySliderHandler );
2124  slider->Bind( wxEVT_SCROLL_THUMBTRACK, opacitySliderHandler );
2125  slider->Bind( wxEVT_SET_FOCUS, &APPEARANCE_CONTROLS::OnSetFocus, this );
2126  }
2127  else
2128  {
2129  sizer->Add( btn_visible, 0, wxALIGN_CENTER_VERTICAL, 0 );
2130  sizer->AddSpacer( 5 );
2131  sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL, 0 );
2132  }
2133 
2134  aSetting->ctl_text = label;
2135  m_objectsOuterSizer->Add( sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, 5 );
2136 
2137  if( !aSetting->can_control_opacity )
2138  m_objectsOuterSizer->AddSpacer( 2 );
2139  };
2140 
2141  for( const APPEARANCE_SETTING& s_setting : s_objectSettings )
2142  {
2143  if( m_isFpEditor && !s_allowedInFpEditor.count( s_setting.id ) )
2144  continue;
2145 
2146  if( !s_setting.spacer )
2147  {
2148  m_objectSettings.emplace_back( std::make_unique<APPEARANCE_SETTING>( s_setting ) );
2149 
2150  std::unique_ptr<APPEARANCE_SETTING>& setting = m_objectSettings.back();
2151 
2152  // Because s_render_rows is created static, we must explicitly call wxGetTranslation
2153  // for texts which are internationalized (tool tips and item names)
2154  setting->tooltip = wxGetTranslation( s_setting.tooltip );
2155  setting->label = wxGetTranslation( s_setting.label );
2156 
2157  if( setting->can_control_opacity )
2158  {
2159  int width = m_windowObjects->GetTextExtent( setting->label ).x + 5;
2160  labelWidth = std::max( labelWidth, width );
2161  }
2162 
2163  m_objectSettingsMap[ToGalLayer( setting->id )] = setting.get();
2164  }
2165  }
2166 
2167  for( const std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
2168  {
2169  if( setting->spacer )
2170  m_objectsOuterSizer->AddSpacer( m_pointSize );
2171  else
2172  appendObject( setting );
2173  }
2174 
2175  m_objectsOuterSizer->Layout();
2176 }
2177 
2178 
2180 {
2181  GAL_SET visible = getVisibleObjects();
2182 
2184 
2185  for( std::unique_ptr<APPEARANCE_SETTING>& setting : m_objectSettings )
2186  {
2187  if( setting->spacer )
2188  continue;
2189 
2190  GAL_LAYER_ID layer = ToGalLayer( setting->id );
2191 
2192  if( setting->ctl_visibility )
2193  setting->ctl_visibility->SetValue( visible.Contains( layer ) );
2194 
2195  if( setting->ctl_color )
2196  {
2197  COLOR4D color = m_frame->GetColorSettings()->GetColor( setting->id );
2198  setting->ctl_color->SetSwatchColor( color, false );
2199  }
2200  }
2201 
2202  wxASSERT( m_objectSettingsMap.count( LAYER_TRACKS )
2203  && m_objectSettingsMap.count( LAYER_VIAS )
2204  && m_objectSettingsMap.count( LAYER_PADS )
2205  && m_objectSettingsMap.count( LAYER_ZONES ) );
2206 
2207  m_objectSettingsMap[LAYER_TRACKS]->ctl_opacity->SetValue( opts.m_TrackOpacity * 100 );
2208  m_objectSettingsMap[LAYER_VIAS]->ctl_opacity->SetValue( opts.m_ViaOpacity * 100 );
2209  m_objectSettingsMap[LAYER_PADS]->ctl_opacity->SetValue( opts.m_PadOpacity * 100 );
2210  m_objectSettingsMap[LAYER_ZONES]->ctl_opacity->SetValue( opts.m_ZoneOpacity * 100 );
2211 }
2212 
2213 
2215 {
2216  BOARD* board = m_frame->GetBoard();
2218  COLOR4D bgColor = theme->GetColor( LAYER_PCB_BACKGROUND );
2219 
2220  // If the board isn't fully loaded, we can't yet rebuild
2221  if( !board->GetProject() )
2222  return;
2223 
2224  m_staticTextNets->SetLabel( _( "Nets" ) );
2225  m_staticTextNetClasses->SetLabel( _( "Net Classes" ) );
2226 
2227  KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>(
2229 
2230  std::map<wxString, KIGFX::COLOR4D>& netclassColors = rs->GetNetclassColorMap();
2231 
2232  m_netclassOuterSizer->Clear( true );
2233 
2234  auto appendNetclass =
2235  [&]( int aId, const NETCLASSPTR& aClass, bool isDefaultClass = false )
2236  {
2237  wxString name = aClass->GetName();
2238 
2239  m_netclassSettings.emplace_back( std::make_unique<APPEARANCE_SETTING>() );
2240  APPEARANCE_SETTING* setting = m_netclassSettings.back().get();
2241  m_netclassSettingsMap[name] = setting;
2242 
2243  setting->ctl_panel = new wxPanel( m_netclassScrolledWindow, aId );
2244  wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
2245  setting->ctl_panel->SetSizer( sizer );
2246  COLOR4D color = netclassColors.count( name ) ? netclassColors.at( name ) :
2247  COLOR4D::UNSPECIFIED;
2248 
2249  setting->ctl_color = new COLOR_SWATCH( setting->ctl_panel, color, aId, bgColor,
2250  COLOR4D::UNSPECIFIED, SWATCH_SMALL );
2251  setting->ctl_color->SetToolTip( _( "Left double click or middle click for color "
2252  "change, right click for menu" ) );
2253 
2254  setting->ctl_color->Bind( COLOR_SWATCH_CHANGED,
2256 
2257  // Default netclass can't have an override color
2258  if( isDefaultClass )
2259  setting->ctl_color->Hide();
2260 
2261  setting->ctl_visibility = new BITMAP_TOGGLE( setting->ctl_panel, aId,
2264  true );
2265 
2266  wxString tip;
2267  tip.Printf( _( "Show or hide ratsnest for nets in %s" ), name );
2268  setting->ctl_visibility->SetToolTip( tip );
2269 
2270  setting->ctl_text = new wxStaticText( setting->ctl_panel, aId, name );
2271  setting->ctl_text->Wrap( -1 );
2272 
2273  int flags = wxALIGN_CENTER_VERTICAL;
2274 
2275  sizer->Add( setting->ctl_color, 0, flags | wxRESERVE_SPACE_EVEN_IF_HIDDEN, 5 );
2276  sizer->AddSpacer( 7 );
2277  sizer->Add( setting->ctl_visibility, 0, flags, 5 );
2278  sizer->AddSpacer( 3 );
2279  sizer->Add( setting->ctl_text, 1, flags, 5 );
2280 
2281  m_netclassOuterSizer->Add( setting->ctl_panel, 0, wxEXPAND, 5 );
2282  m_netclassOuterSizer->AddSpacer( 2 );
2283 
2284  setting->ctl_visibility->Bind( TOGGLE_CHANGED,
2286  this );
2287 
2288  auto menuHandler =
2289  [&, name, isDefaultClass]( wxMouseEvent& aEvent )
2290  {
2292 
2293  wxMenu menu;
2294 
2295  if( !isDefaultClass)
2296  {
2297  menu.Append( new wxMenuItem( &menu, ID_SET_NET_COLOR,
2298  _( "Set Netclass Color" ), wxEmptyString,
2299  wxITEM_NORMAL ) );
2300  }
2301 
2302  menu.Append( new wxMenuItem( &menu, ID_HIGHLIGHT_NET,
2303  wxString::Format( _( "Highlight Nets in %s" ), name ),
2304  wxEmptyString, wxITEM_NORMAL ) );
2305  menu.Append( new wxMenuItem( &menu, ID_SELECT_NET,
2306  wxString::Format( _( "Select Tracks and Vias in %s" ),
2307  name ),
2308  wxEmptyString, wxITEM_NORMAL ) );
2309  menu.Append( new wxMenuItem( &menu, ID_DESELECT_NET,
2310  wxString::Format( _( "Unselect Tracks and Vias in %s" ),
2311  name ),
2312  wxEmptyString, wxITEM_NORMAL ) );
2313 
2314  menu.AppendSeparator();
2315 
2316  menu.Append( new wxMenuItem( &menu, ID_SHOW_ALL_NETS,
2317  _( "Show All Netclasses" ), wxEmptyString,
2318  wxITEM_NORMAL ) );
2319  menu.Append( new wxMenuItem( &menu, ID_HIDE_OTHER_NETS,
2320  _( "Hide All Other Netclasses" ), wxEmptyString,
2321  wxITEM_NORMAL ) );
2322 
2323  menu.Bind( wxEVT_COMMAND_MENU_SELECTED,
2325 
2326  PopupMenu( &menu );
2327  };
2328 
2329  setting->ctl_panel->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2330  setting->ctl_visibility->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2331  setting->ctl_color->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2332  setting->ctl_text->Bind( wxEVT_RIGHT_DOWN, menuHandler );
2333  };
2334 
2335  const NETCLASS_MAP& classes = board->GetDesignSettings().GetNetClasses().NetClasses();
2336 
2337  std::vector<wxString> names;
2338 
2339  for( const auto& pair : classes )
2340  names.emplace_back( pair.first );
2341 
2342  std::sort( names.begin(), names.end() );
2343 
2344  m_netclassIdMap.clear();
2345 
2346  int idx = wxID_HIGHEST;
2347 
2348  NETCLASSPTR defaultClass = board->GetDesignSettings().GetNetClasses().GetDefault();
2349 
2350  m_netclassIdMap[idx] = defaultClass->GetName();
2351  appendNetclass( idx++, defaultClass, true );
2352 
2353  for( const wxString& name : names )
2354  {
2355  m_netclassIdMap[idx] = name;
2356  appendNetclass( idx++, classes.at( name ) );
2357  }
2358 
2359  int hotkey;
2360  wxString msg;
2361 
2362  m_paneNetDisplayOptions->SetLabel( _( "Net Display Options" ) );
2363 
2365 
2366  if( hotkey )
2367  msg = wxString::Format( _( "Net colors (%s):" ), KeyNameFromKeyCode( hotkey ) );
2368  else
2369  msg = _( "Net colors:" );
2370 
2371  m_txtNetDisplayTitle->SetLabel( msg );
2372  m_txtNetDisplayTitle->SetToolTip( _( "Choose when to show net and netclass colors" ) );
2373 
2374  m_rbNetColorAll->SetLabel( _( "All" ) );
2375  m_rbNetColorAll->SetToolTip( _( "Net and netclass colors are shown on all copper items" ) );
2376 
2377  m_rbNetColorRatsnest->SetLabel( _( "Ratsnest" ) );
2378  m_rbNetColorRatsnest->SetToolTip( _( "Net and netclass colors are shown on the ratsnest only" ) );
2379 
2380  m_rbNetColorOff->SetLabel( _( "None" ) );
2381  m_rbNetColorOff->SetToolTip( _( "Net and netclass colors are not shown" ) );
2382 
2384 
2385  if( hotkey )
2386  msg = wxString::Format( _( "Ratsnest display (%s):" ), KeyNameFromKeyCode( hotkey ) );
2387  else
2388  msg = _( "Ratsnest display:" );
2389 
2390  m_txtRatsnestVisibility->SetLabel( msg );
2391  m_txtRatsnestVisibility->SetToolTip( _( "Choose which ratsnest lines to display" ) );
2392 
2393  m_rbRatsnestAllLayers->SetLabel( _( "All" ) );
2394  m_rbRatsnestAllLayers->SetToolTip( _( "Show ratsnest lines to items on all layers" ) );
2395 
2396  m_rbRatsnestVisLayers->SetLabel( _( "Visible layers" ) );
2397  m_rbRatsnestVisLayers->SetToolTip( _( "Show ratsnest lines to items on visible layers" ) );
2398 
2399  m_rbRatsnestNone->SetLabel( _( "None" ) );
2400  m_rbRatsnestNone->SetToolTip( _( "Hide all ratsnest lines" ) );
2401 
2402  m_netclassOuterSizer->Layout();
2403 
2404  m_netsTable->Rebuild();
2405  m_panelNets->GetSizer()->Layout();
2406 }
2407 
2408 
2410 {
2411  m_presetsLabel->SetLabel( _( "Presets (Ctrl+Tab):" ) );
2412 
2413  m_cbLayerPresets->Clear();
2414 
2415  for( std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
2416  {
2417  m_cbLayerPresets->Append( wxGetTranslation( pair.first ),
2418  static_cast<void*>( &pair.second ) );
2419  }
2420 
2421  m_cbLayerPresets->Append( wxT( "-----" ) );
2422  m_cbLayerPresets->Append( _( "Save preset..." ) );
2423  m_cbLayerPresets->Append( _( "Delete preset..." ) );
2424 
2425  m_cbLayerPresets->SetSelection( 0 );
2426 
2427  // At least the build in presets should always be present
2428  wxASSERT( !m_layerPresets.empty() );
2429 
2430  // Default preset: all layers
2432 }
2433 
2434 
2436 {
2437  LSET visibleLayers = getVisibleLayers();
2438  GAL_SET visibleObjects = getVisibleObjects();
2439 
2440  auto it = std::find_if( m_layerPresets.begin(), m_layerPresets.end(),
2441  [&]( const std::pair<const wxString, LAYER_PRESET>& aPair )
2442  {
2443  return ( aPair.second.layers == visibleLayers
2444  && aPair.second.renderLayers == visibleObjects );
2445  } );
2446 
2447  if( it != m_layerPresets.end() )
2448  m_cbLayerPresets->SetStringSelection( it->first );
2449  else
2450  m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator
2451 
2452  m_currentPreset = static_cast<LAYER_PRESET*>(
2453  m_cbLayerPresets->GetClientData( m_cbLayerPresets->GetSelection() ) );
2454 }
2455 
2456 
2458 {
2459  int idx = m_cbLayerPresets->FindString( aName );
2460 
2461  if( idx >= 0 && m_cbLayerPresets->GetSelection() != idx )
2462  {
2463  m_cbLayerPresets->SetSelection( idx );
2464  m_currentPreset = static_cast<LAYER_PRESET*>( m_cbLayerPresets->GetClientData( idx ) );
2465  }
2466  else if( idx < 0 )
2467  {
2468  m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 ); // separator
2469  }
2470 }
2471 
2472 
2473 void APPEARANCE_CONTROLS::onLayerPresetChanged( wxCommandEvent& aEvent )
2474 {
2475  int count = m_cbLayerPresets->GetCount();
2476  int index = m_cbLayerPresets->GetSelection();
2477 
2478  auto resetSelection =
2479  [&]()
2480  {
2481  if( m_currentPreset )
2482  m_cbLayerPresets->SetStringSelection( m_currentPreset->name );
2483  else
2484  m_cbLayerPresets->SetSelection( m_cbLayerPresets->GetCount() - 3 );
2485  };
2486 
2487  if( index == count - 3 )
2488  {
2489  // Separator: reject the selection
2490  resetSelection();
2491  return;
2492  }
2493  else if( index == count - 2 )
2494  {
2495  // Save current state to new preset
2496  wxString name;
2497 
2500 
2501  wxTextEntryDialog dlg( this, _( "Layer preset name:" ), _( "Save Layer Preset" ), name );
2502 
2503  if( dlg.ShowModal() != wxID_OK )
2504  {
2505  resetSelection();
2506  return;
2507  }
2508 
2509  name = dlg.GetValue();
2510  bool exists = m_layerPresets.count( name );
2511 
2512  if( !exists )
2513  {
2516  }
2517 
2518  LAYER_PRESET* preset = &m_layerPresets[name];
2519  m_currentPreset = preset;
2520 
2521  if( !exists )
2522  {
2523  index = m_cbLayerPresets->Insert( name, index - 1, static_cast<void*>( preset ) );
2524  }
2525  else
2526  {
2527  preset->layers = getVisibleLayers();
2528  preset->renderLayers = getVisibleObjects();
2529 
2530  index = m_cbLayerPresets->FindString( name );
2531  m_presetMRU.Remove( name );
2532  }
2533 
2534  m_cbLayerPresets->SetSelection( index );
2535  m_presetMRU.Insert( name, 0 );
2536 
2537  return;
2538  }
2539  else if( index == count - 1 )
2540  {
2541  // Delete a preset
2542  wxArrayString headers;
2543  std::vector<wxArrayString> items;
2544 
2545  headers.Add( _( "Presets" ) );
2546 
2547  for( std::pair<const wxString, LAYER_PRESET>& pair : m_layerPresets )
2548  {
2549  if( !pair.second.readOnly )
2550  {
2551  wxArrayString item;
2552  item.Add( pair.first );
2553  items.emplace_back( item );
2554  }
2555  }
2556 
2557  EDA_LIST_DIALOG dlg( m_frame, _( "Delete Preset" ), headers, items );
2558  dlg.SetListLabel( _( "Select preset:" ) );
2559 
2560  if( dlg.ShowModal() == wxID_OK )
2561  {
2562  wxString presetName = dlg.GetTextSelection();
2563  int idx = m_cbLayerPresets->FindString( presetName );
2564 
2565  if( idx != wxNOT_FOUND )
2566  {
2567  m_layerPresets.erase( presetName );
2568 
2569  m_cbLayerPresets->Delete( idx );
2570  m_currentPreset = nullptr;
2571 
2572  m_presetMRU.Remove( presetName );
2573  }
2574  }
2575 
2576  resetSelection();
2577  return;
2578  }
2579 
2580  LAYER_PRESET* preset = static_cast<LAYER_PRESET*>( m_cbLayerPresets->GetClientData( index ) );
2581  m_currentPreset = preset;
2582 
2583  m_lastSelectedUserPreset = ( !preset || preset->readOnly ) ? nullptr : preset;
2584 
2585  if( preset )
2586  doApplyLayerPreset( *preset );
2587 
2588  if( !m_currentPreset->name.IsEmpty() )
2589  {
2590  m_presetMRU.Remove( m_currentPreset->name );
2591  m_presetMRU.Insert( m_currentPreset->name, 0 );
2592  }
2593 
2594  passOnFocus();
2595 }
2596 
2597 
2599 {
2600  BOARD* board = m_frame->GetBoard();
2601 
2602  setVisibleLayers( aPreset.layers );
2603  setVisibleObjects( aPreset.renderLayers );
2604 
2605  // If the preset doesn't have an explicit active layer to restore, we can at least
2606  // force the active layer to be something in the preset's layer set
2607  PCB_LAYER_ID activeLayer = UNSELECTED_LAYER;
2608 
2609  if( aPreset.activeLayer != UNSELECTED_LAYER )
2610  activeLayer = aPreset.activeLayer;
2611  else if( aPreset.layers.any() && !aPreset.layers.test( m_frame->GetActiveLayer() ) )
2612  activeLayer = *aPreset.layers.Seq().begin();
2613 
2614  LSET boardLayers = board->GetLayerSet();
2615 
2616  if( activeLayer != UNSELECTED_LAYER && boardLayers.Contains( activeLayer ) )
2617  m_frame->SetActiveLayer( activeLayer );
2618 
2619  if( !m_isFpEditor )
2620  m_frame->GetCanvas()->SyncLayersVisibility( board );
2621 
2622  m_frame->GetCanvas()->Refresh();
2623 
2625 }
2626 
2627 
2628 void APPEARANCE_CONTROLS::OnColorSwatchChanged( wxCommandEvent& aEvent )
2629 {
2630  COLOR_SWATCH* swatch = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
2631  COLOR4D newColor = swatch->GetSwatchColor();
2632  LAYER_NUM layer = swatch->GetId();
2633 
2635  cs->SetColor( layer, newColor );
2636 
2638 
2639  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
2640  view->UpdateLayerColor( layer );
2641  view->UpdateLayerColor( GetNetnameLayer( layer ) );
2642 
2643  if( IsCopperLayer( layer ) )
2644  view->UpdateLayerColor( ZONE_LAYER_FOR( layer ) );
2645 
2646  // Update the bitmap of the layer box
2647  if( m_frame->IsType( FRAME_PCB_EDITOR ) )
2648  static_cast<PCB_EDIT_FRAME*>( m_frame )->ReCreateLayerBox( false );
2649 
2650  m_frame->GetCanvas()->Refresh();
2651 
2652  if( layer == LAYER_PCB_BACKGROUND )
2653  m_frame->SetDrawBgColor( newColor );
2654 
2655  passOnFocus();
2656 }
2657 
2658 
2659 void APPEARANCE_CONTROLS::onObjectOpacitySlider( int aLayer, float aOpacity )
2660 {
2662 
2663  switch( aLayer )
2664  {
2665  case static_cast<int>( LAYER_TRACKS ): options.m_TrackOpacity = aOpacity; break;
2666  case static_cast<int>( LAYER_VIAS ): options.m_ViaOpacity = aOpacity; break;
2667  case static_cast<int>( LAYER_PADS ): options.m_PadOpacity = aOpacity; break;
2668  case static_cast<int>( LAYER_ZONES ): options.m_ZoneOpacity = aOpacity; break;
2669  default: return;
2670  }
2671 
2672  m_frame->SetDisplayOptions( options );
2673  passOnFocus();
2674 }
2675 
2676 
2677 void APPEARANCE_CONTROLS::onNetContextMenu( wxCommandEvent& aEvent )
2678 {
2679  wxASSERT( m_netsGrid->GetSelectedRows().size() == 1 );
2680 
2681  int row = m_netsGrid->GetSelectedRows()[0];
2682  NET_GRID_ENTRY& net = m_netsTable->GetEntry( row );
2683 
2684  m_netsGrid->ClearSelection();
2685 
2686  switch( aEvent.GetId() )
2687  {
2688  case ID_SET_NET_COLOR:
2689  {
2690  wxGridCellEditor* editor = m_netsGrid->GetCellEditor( row, NET_GRID_TABLE::COL_COLOR );
2691  editor->BeginEdit( row, NET_GRID_TABLE::COL_COLOR, m_netsGrid );
2692  break;
2693  }
2694 
2695  case ID_HIGHLIGHT_NET:
2696  {
2698  static_cast<intptr_t>( net.code ) );
2699  m_frame->GetCanvas()->Refresh();
2700  break;
2701  }
2702 
2703  case ID_SELECT_NET:
2704  {
2706  static_cast<intptr_t>( net.code ) );
2707  m_frame->GetCanvas()->Refresh();
2708  break;
2709  }
2710 
2711  case ID_DESELECT_NET:
2712  {
2714  static_cast<intptr_t>( net.code ) );
2715  m_frame->GetCanvas()->Refresh();
2716  break;
2717  }
2718 
2719  case ID_SHOW_ALL_NETS:
2721  break;
2722 
2723  case ID_HIDE_OTHER_NETS:
2724  m_netsTable->HideOtherNets( net );
2725  break;
2726 
2727  default:
2728  break;
2729  }
2730 
2731  passOnFocus();
2732 }
2733 
2734 
2736 {
2737  wxString className = netclassNameFromEvent( aEvent );
2738  bool show = aEvent.GetInt();
2739  showNetclass( className, show );
2740  passOnFocus();
2741 }
2742 
2743 
2744 void APPEARANCE_CONTROLS::showNetclass( const wxString& aClassName, bool aShow )
2745 {
2746  BOARD* board = m_frame->GetBoard();
2747  NETINFO_LIST& nets = board->GetNetInfo();
2748  NETCLASSES& classes = board->GetDesignSettings().GetNetClasses();
2749  NETCLASSPTR netclass = classes.Find( aClassName );
2750  TOOL_MANAGER* manager = m_frame->GetToolManager();
2751 
2752  if( !netclass )
2753  return;
2754 
2755  NETCLASS* defaultClass = classes.GetDefaultPtr();
2756 
2757  if( netclass == classes.GetDefault() )
2758  {
2759  const TOOL_ACTION& action = aShow ? PCB_ACTIONS::showNet : PCB_ACTIONS::hideNet;
2760 
2761  for( NETINFO_ITEM* net : nets )
2762  {
2763  if( net->GetNetClass() == defaultClass )
2764  {
2765  manager->RunAction( action, true, static_cast<intptr_t>( net->GetNetCode() ) );
2766 
2767  int row = m_netsTable->GetRowByNetcode( net->GetNetCode() );
2768 
2769  if( row >= 0 )
2771  }
2772  }
2773  }
2774  else
2775  {
2776  const TOOL_ACTION& action = aShow ? PCB_ACTIONS::showNet : PCB_ACTIONS::hideNet;
2777 
2778  for( const wxString& member : *netclass )
2779  {
2780  if( NETINFO_ITEM* net = nets.GetNetItem( member ) )
2781  {
2782  int code = net->GetNetCode();
2783  manager->RunAction( action, true, static_cast<intptr_t>( code ) );
2784 
2785  int row = m_netsTable->GetRowByNetcode( code );
2786 
2787  if( row >= 0 )
2789  }
2790  }
2791  }
2792 
2793  m_netsGrid->ForceRefresh();
2794 }
2795 
2796 
2797 void APPEARANCE_CONTROLS::onNetclassColorChanged( wxCommandEvent& aEvent )
2798 {
2799  KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>(
2801 
2802  std::map<wxString, KIGFX::COLOR4D>& netclassColors = rs->GetNetclassColorMap();
2803 
2804  COLOR_SWATCH* swatch = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
2805  wxString className = netclassNameFromEvent( aEvent );
2806 
2807  netclassColors[className] = swatch->GetSwatchColor();
2808 
2811  m_frame->GetCanvas()->Refresh();
2812 }
2813 
2814 
2816 {
2817  COLOR_SWATCH* s = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
2818  int classId = s->GetId();
2819 
2820  wxASSERT( m_netclassIdMap.count( classId ) );
2821  return m_netclassIdMap.at( classId );
2822 }
2823 
2824 
2825 void APPEARANCE_CONTROLS::onNetColorMode( wxCommandEvent& aEvent )
2826 {
2828 
2829  if( m_rbNetColorAll->GetValue() )
2831  else if( m_rbNetColorRatsnest->GetValue() )
2833  else
2835 
2836  m_frame->SetDisplayOptions( options );
2838  passOnFocus();
2839 }
2840 
2841 
2842 void APPEARANCE_CONTROLS::onRatsnestMode( wxCommandEvent& aEvent )
2843 {
2845 
2846  if( m_rbRatsnestAllLayers->GetValue() )
2847  {
2848  options.m_ShowGlobalRatsnest = true;
2850  }
2851  else if( m_rbRatsnestVisLayers->GetValue() )
2852  {
2853  options.m_ShowGlobalRatsnest = true;
2855  }
2856  else
2857  {
2858  options.m_ShowGlobalRatsnest = false;
2859  }
2860 
2861  m_frame->SetDisplayOptions( options );
2863  passOnFocus();
2864 }
2865 
2866 
2867 void APPEARANCE_CONTROLS::onNetclassContextMenu( wxCommandEvent& aEvent )
2868 {
2869  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
2871  static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
2872 
2873  BOARD* board = m_frame->GetBoard();
2874  NETINFO_LIST& nets = board->GetNetInfo();
2875  NETCLASSES& classes = board->GetDesignSettings().GetNetClasses();
2876  NETCLASSPTR netclass = classes.Find( m_contextMenuNetclass );
2877 
2880 
2881  NETCLASSPTR defaultClass = classes.GetDefault();
2882  wxString defaultClassName = defaultClass->GetName();
2883 
2884  auto runOnNetsOfClass =
2885  [&]( NETCLASSPTR aClass, std::function<void( NETINFO_ITEM* )> aFunction )
2886  {
2887  if( aClass == defaultClass )
2888  {
2889  for( NETINFO_ITEM* net : nets )
2890  if( net->GetNetClass() == defaultClass.get() )
2891  aFunction( net );
2892  }
2893  else
2894  {
2895  for( const wxString& netName : *aClass )
2896  aFunction( nets.GetNetItem( netName ) );
2897  }
2898  };
2899 
2900  switch( aEvent.GetId() )
2901  {
2902  case ID_SET_NET_COLOR:
2903  {
2904  if( setting )
2905  {
2906  setting->ctl_color->GetNewSwatchColor();
2907 
2908  COLOR4D color = setting->ctl_color->GetSwatchColor();
2909 
2910  std::map<wxString, KIGFX::COLOR4D>& netclassColors = rs->GetNetclassColorMap();
2911 
2912  if( color != COLOR4D::UNSPECIFIED )
2913  netclassColors[m_contextMenuNetclass] = color;
2914  else
2915  netclassColors.erase( m_contextMenuNetclass );
2916 
2917  view->UpdateAllLayersColor();
2918  }
2919 
2920  break;
2921  }
2922 
2923  case ID_HIGHLIGHT_NET:
2924  {
2925  if( netclass )
2926  {
2927  runOnNetsOfClass( netclass,
2928  [&]( NETINFO_ITEM* aItem )
2929  {
2930  if( !aItem )
2931  return;
2932 
2933  static bool first = true;
2934  int code = aItem->GetNetCode();
2935 
2936  if( first )
2937  {
2938  board->SetHighLightNet( code );
2939  rs->SetHighlight( true, code );
2940  first = false;
2941  }
2942  else
2943  {
2944  board->SetHighLightNet( code, true );
2945  rs->SetHighlight( true, code, true );
2946  }
2947  } );
2948 
2949  view->UpdateAllLayersColor();
2950  board->HighLightON();
2951  }
2952  break;
2953  }
2954 
2955  case ID_SELECT_NET:
2956  case ID_DESELECT_NET:
2957  {
2958  if( netclass )
2959  {
2960  TOOL_ACTION& action = aEvent.GetId() == ID_SELECT_NET ? PCB_ACTIONS::selectNet :
2962  runOnNetsOfClass( netclass,
2963  [&]( NETINFO_ITEM* aItem )
2964  {
2965  if( !aItem )
2966  return;
2967 
2968  intptr_t code = static_cast<intptr_t>( aItem->GetNetCode() );
2969  m_frame->GetToolManager()->RunAction( action, true, code );
2970  } );
2971  }
2972  break;
2973  }
2974 
2975  case ID_SHOW_ALL_NETS:
2976  {
2977  showNetclass( defaultClassName );
2978  wxASSERT( m_netclassSettingsMap.count( defaultClassName ) );
2979  m_netclassSettingsMap.at( defaultClassName )->ctl_visibility->SetValue( true );
2980 
2981  for( const auto& pair : classes.NetClasses() )
2982  {
2983  showNetclass( pair.first );
2984 
2985  if( m_netclassSettingsMap.count( pair.first ) )
2986  m_netclassSettingsMap.at( pair.first )->ctl_visibility->SetValue( true );
2987  }
2988 
2989  break;
2990  }
2991 
2992  case ID_HIDE_OTHER_NETS:
2993  {
2994  bool showDefault = m_contextMenuNetclass == defaultClassName;
2995  showNetclass( defaultClassName, showDefault );
2996  wxASSERT( m_netclassSettingsMap.count( defaultClassName ) );
2997  m_netclassSettingsMap.at( defaultClassName )->ctl_visibility->SetValue( showDefault );
2998 
2999  for( const auto& pair : classes.NetClasses() )
3000  {
3001  bool show = pair.first == m_contextMenuNetclass;
3002 
3003  showNetclass( pair.first, show );
3004 
3005  if( m_netclassSettingsMap.count( pair.first ) )
3006  m_netclassSettingsMap.at( pair.first )->ctl_visibility->SetValue( show );
3007  }
3008 
3009  break;
3010  }
3011 
3012  default:
3013  break;
3014  }
3015 
3017  m_frame->GetCanvas()->Refresh();
3018 
3019  m_contextMenuNetclass.clear();
3020 }
3021 
3022 
3024 {
3025  m_focusOwner->SetFocus();
3026 }
3027 
3028 
3030 {
3031  WX_INFOBAR* infobar = m_frame->GetInfoBar();
3032 
3033  wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY, _( "Open Preferences" ),
3034  wxEmptyString );
3035 
3036  button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
3037  [&]( wxHyperlinkEvent& aEvent )
3038  {
3039  wxCommandEvent dummy;
3041  } ) );
3042 
3043  infobar->RemoveAllButtons();
3044  infobar->AddButton( button );
3045  infobar->AddCloseButton();
3046 
3047  infobar->ShowMessageFor( _( "The current color theme is read-only. Create a new theme in "
3048  "Preferences to enable color editing." ),
3049  10000, wxICON_INFORMATION );
3050 }
3051 
3052 
3054 {
3055  m_paneLayerDisplayOptions->Refresh();
3056 }
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:1915
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.
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:223
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
void onLayerVisibilityToggled(PCB_LAYER_ID aLayer)
static TOOL_ACTION hideNet
Definition: pcb_actions.h:456
Meta control for all pads opacity/visibility (color ignored)
Definition: layer_ids.h:237
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:217
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.
void OnLanguageChanged()
Update the panel contents from the application and board models.
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:196
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:587
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:273
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:208
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:216
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:263
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:93
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:238
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:953
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:516
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:260
Meta control for all vias opacity/visibility.
Definition: layer_ids.h:200
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:207
COLOR4D GetDefaultColor(int aLayer)
show footprints on front
Definition: layer_ids.h:215
Helper for storing and iterating over GAL_LAYER_IDs.
Definition: layer_ids.h:290
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:253
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:224
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:477
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:808
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:214
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:218
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:220
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:243
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:242
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:227
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:306
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
void SetLabel(const wxString &aLabel) override
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 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
#define _HKI(x)
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:74
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:148
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:324
int GetNetCode() const
Definition: netinfo.h:120
wxRadioButton * m_rbRatsnestVisLayers