KiCad PCB EDA Suite
color_settings.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
5  * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software: you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the
9  * Free Software Foundation, either version 3 of the License, or (at your
10  * option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include <layer_ids.h>
22 #include <pgm_base.h>
25 #include <settings/parameters.h>
27 #include <wx/log.h>
28 
29 #include "builtin_color_themes.h"
30 
31 
33 const int colorsSchemaVersion = 3;
34 
35 
36 COLOR_SETTINGS::COLOR_SETTINGS( const wxString& aFilename ) :
38  m_overrideSchItemColors( false ),
39  m_useBoardStackupColors( true )
40 {
41 
42  m_params.emplace_back( new PARAM<wxString>( "meta.name", &m_displayName, "KiCad Default" ) );
43 
44  std::vector<COLOR4D> default_palette = {
45  CSS_COLOR( 200, 52, 52, 1 ),
46  CSS_COLOR( 127, 200, 127, 1 ),
47  CSS_COLOR( 206, 125, 44, 1 ),
48  CSS_COLOR( 79, 203, 203, 1 ),
49  CSS_COLOR( 219, 98, 139, 1 ),
50  CSS_COLOR( 167, 165, 198, 1 ),
51  CSS_COLOR( 40, 204, 217, 1 ),
52  CSS_COLOR( 232, 178, 167, 1 ),
53  CSS_COLOR( 242, 237, 161, 1 ),
54  CSS_COLOR( 141, 203, 129, 1 ),
55  CSS_COLOR( 237, 124, 51, 1 ),
56  CSS_COLOR( 91, 195, 235, 1 ),
57  CSS_COLOR( 247, 111, 142, 1 ),
58  CSS_COLOR( 77, 127, 196, 1 )
59  };
60 
61  // TODO(JE) in actual usage, how long does the default palette need to be?
62  m_params.emplace_back( new PARAM_LIST<COLOR4D>( "palette", &m_Palette, default_palette ) );
63 
64  m_params.emplace_back( new PARAM<bool>( "schematic.override_item_colors",
65  &m_overrideSchItemColors, false ) );
66 
67  m_params.emplace_back( new PARAM<bool>( "3d_viewer.use_board_stackup_colors",
68  &m_useBoardStackupColors, true ) );
69 
70 #define CLR( x, y ) \
71  wxASSERT( s_defaultTheme.count( y ) ); \
72  m_params.emplace_back( new COLOR_MAP_PARAM( x, y, s_defaultTheme.at( y ), &m_colors ) );
73 
74  CLR( "schematic.aux_items", LAYER_SCHEMATIC_AUX_ITEMS );
75  CLR( "schematic.background", LAYER_SCHEMATIC_BACKGROUND );
76  CLR( "schematic.brightened", LAYER_BRIGHTENED );
77  CLR( "schematic.bus", LAYER_BUS );
78  CLR( "schematic.bus_junction", LAYER_BUS_JUNCTION );
79  CLR( "schematic.component_body", LAYER_DEVICE_BACKGROUND );
80  CLR( "schematic.component_outline", LAYER_DEVICE );
81  CLR( "schematic.cursor", LAYER_SCHEMATIC_CURSOR );
82  CLR( "schematic.erc_error", LAYER_ERC_ERR );
83  CLR( "schematic.erc_warning", LAYER_ERC_WARN );
84  CLR( "schematic.fields", LAYER_FIELDS );
85  CLR( "schematic.grid", LAYER_SCHEMATIC_GRID );
86  CLR( "schematic.grid_axes", LAYER_SCHEMATIC_GRID_AXES );
87  CLR( "schematic.hidden", LAYER_HIDDEN );
88  CLR( "schematic.junction", LAYER_JUNCTION );
89  CLR( "schematic.label_global", LAYER_GLOBLABEL );
90  CLR( "schematic.label_hier", LAYER_HIERLABEL );
91  CLR( "schematic.label_local", LAYER_LOCLABEL );
92  CLR( "schematic.no_connect", LAYER_NOCONNECT );
93  CLR( "schematic.note", LAYER_NOTES );
94  CLR( "schematic.pin", LAYER_PIN );
95  CLR( "schematic.pin_name", LAYER_PINNAM );
96  CLR( "schematic.pin_number", LAYER_PINNUM );
97  CLR( "schematic.reference", LAYER_REFERENCEPART );
98  // Macs look better with a lighter shadow
99 #ifdef __WXMAC__
100  CLR( "schematic.shadow", LAYER_SELECTION_SHADOWS );
101 #else
102  CLR( "schematic.shadow", LAYER_SELECTION_SHADOWS );
103 #endif
104  CLR( "schematic.sheet", LAYER_SHEET );
105  CLR( "schematic.sheet_background", LAYER_SHEET_BACKGROUND );
106  CLR( "schematic.sheet_filename", LAYER_SHEETFILENAME );
107  CLR( "schematic.sheet_fields", LAYER_SHEETFIELDS );
108  CLR( "schematic.sheet_label", LAYER_SHEETLABEL );
109  CLR( "schematic.sheet_name", LAYER_SHEETNAME );
110  CLR( "schematic.value", LAYER_VALUEPART );
111  CLR( "schematic.wire", LAYER_WIRE );
112  CLR( "schematic.worksheet", LAYER_SCHEMATIC_DRAWINGSHEET );
113 
114  CLR( "gerbview.axes", LAYER_GERBVIEW_AXES );
115  CLR( "gerbview.background", LAYER_GERBVIEW_BACKGROUND );
116  CLR( "gerbview.dcodes", LAYER_DCODES );
117  CLR( "gerbview.grid", LAYER_GERBVIEW_GRID );
118  CLR( "gerbview.negative_objects", LAYER_NEGATIVE_OBJECTS );
119  CLR( "gerbview.worksheet", LAYER_GERBVIEW_DRAWINGSHEET );
120 
121  for( int i = 0, id = GERBVIEW_LAYER_ID_START;
123  {
124  m_params.emplace_back( new COLOR_MAP_PARAM( "gerbview.layers." + std::to_string( i ), id,
125  default_palette[ i % default_palette.size() ],
126  &m_colors ) );
127  }
128 
129  CLR( "board.anchor", LAYER_ANCHOR );
130  CLR( "board.aux_items", LAYER_AUX_ITEMS );
131  CLR( "board.background", LAYER_PCB_BACKGROUND );
132  CLR( "board.cursor", LAYER_CURSOR );
133  CLR( "board.drc_error", LAYER_DRC_ERROR );
134  CLR( "board.drc_warning", LAYER_DRC_WARNING );
135  CLR( "board.drc_exclusion", LAYER_DRC_EXCLUSION );
136  CLR( "board.footprint_text_invisible", LAYER_MOD_TEXT_INVISIBLE );
137  CLR( "board.grid", LAYER_GRID );
138  CLR( "board.grid_axes", LAYER_GRID_AXES );
139  CLR( "board.no_connect", LAYER_NO_CONNECTS );
140  CLR( "board.pad_plated_hole", LAYER_PAD_PLATEDHOLES );
141  CLR( "board.pad_through_hole", LAYER_PADS_TH );
142  CLR( "board.plated_hole", LAYER_NON_PLATEDHOLES );
143  CLR( "board.ratsnest", LAYER_RATSNEST );
144  CLR( "board.via_blind_buried", LAYER_VIA_BBLIND );
145  CLR( "board.via_hole", LAYER_VIA_HOLES );
146  CLR( "board.via_micro", LAYER_VIA_MICROVIA );
147  CLR( "board.via_through", LAYER_VIA_THROUGH );
148  CLR( "board.worksheet", LAYER_DRAWINGSHEET );
149 
150  CLR( "board.copper.f", F_Cu );
151  CLR( "board.copper.in1", In1_Cu );
152  CLR( "board.copper.in2", In2_Cu );
153  CLR( "board.copper.in3", In3_Cu );
154  CLR( "board.copper.in4", In4_Cu );
155  CLR( "board.copper.in5", In5_Cu );
156  CLR( "board.copper.in6", In6_Cu );
157  CLR( "board.copper.in7", In7_Cu );
158  CLR( "board.copper.in8", In8_Cu );
159  CLR( "board.copper.in9", In9_Cu );
160  CLR( "board.copper.in10", In10_Cu );
161  CLR( "board.copper.in11", In11_Cu );
162  CLR( "board.copper.in12", In12_Cu );
163  CLR( "board.copper.in13", In13_Cu );
164  CLR( "board.copper.in14", In14_Cu );
165  CLR( "board.copper.in15", In15_Cu );
166  CLR( "board.copper.in16", In16_Cu );
167  CLR( "board.copper.in17", In17_Cu );
168  CLR( "board.copper.in18", In18_Cu );
169  CLR( "board.copper.in19", In19_Cu );
170  CLR( "board.copper.in20", In20_Cu );
171  CLR( "board.copper.in21", In21_Cu );
172  CLR( "board.copper.in22", In22_Cu );
173  CLR( "board.copper.in23", In23_Cu );
174  CLR( "board.copper.in24", In24_Cu );
175  CLR( "board.copper.in25", In25_Cu );
176  CLR( "board.copper.in26", In26_Cu );
177  CLR( "board.copper.in27", In27_Cu );
178  CLR( "board.copper.in28", In28_Cu );
179  CLR( "board.copper.in29", In29_Cu );
180  CLR( "board.copper.in30", In30_Cu );
181  CLR( "board.copper.b", B_Cu );
182 
183  CLR( "board.b_adhes", B_Adhes );
184  CLR( "board.f_adhes", F_Adhes );
185  CLR( "board.b_paste", B_Paste );
186  CLR( "board.f_paste", F_Paste );
187  CLR( "board.b_silks", B_SilkS );
188  CLR( "board.f_silks", F_SilkS );
189  CLR( "board.b_mask", B_Mask );
190  CLR( "board.f_mask", F_Mask );
191  CLR( "board.dwgs_user", Dwgs_User );
192  CLR( "board.cmts_user", Cmts_User );
193  CLR( "board.eco1_user", Eco1_User );
194  CLR( "board.eco2_user", Eco2_User );
195  CLR( "board.edge_cuts", Edge_Cuts );
196  CLR( "board.margin", Margin );
197  CLR( "board.b_crtyd", B_CrtYd );
198  CLR( "board.f_crtyd", F_CrtYd );
199  CLR( "board.b_fab", B_Fab );
200  CLR( "board.f_fab", F_Fab );
201  CLR( "board.user_1", User_1 );
202  CLR( "board.user_2", User_2 );
203  CLR( "board.user_3", User_3 );
204  CLR( "board.user_4", User_4 );
205  CLR( "board.user_5", User_5 );
206  CLR( "board.user_6", User_6 );
207  CLR( "board.user_7", User_7 );
208  CLR( "board.user_8", User_8 );
209  CLR( "board.user_9", User_9 );
210 
211  // Colors for 3D viewer, which are used as defaults unless overridden by the board
212  CLR( "3d_viewer.background_bottom", LAYER_3D_BACKGROUND_BOTTOM );
213  CLR( "3d_viewer.background_top", LAYER_3D_BACKGROUND_TOP );
214  CLR( "3d_viewer.board", LAYER_3D_BOARD );
215  CLR( "3d_viewer.copper", LAYER_3D_COPPER );
216  CLR( "3d_viewer.silkscreen_bottom", LAYER_3D_SILKSCREEN_BOTTOM );
217  CLR( "3d_viewer.silkscreen_top", LAYER_3D_SILKSCREEN_TOP );
218  CLR( "3d_viewer.soldermask_bottom", LAYER_3D_SOLDERMASK_BOTTOM );
219  CLR( "3d_viewer.soldermask_top", LAYER_3D_SOLDERMASK_TOP );
220  CLR( "3d_viewer.solderpaste", LAYER_3D_SOLDERPASTE );
221 
222  registerMigration( 0, 1, std::bind( &COLOR_SETTINGS::migrateSchema0to1, this ) );
223 
224  registerMigration( 1, 2,
225  [&]()
226  {
227  // Fix LAYER_VIA_HOLES color - before version 2, this setting had no effect
228  nlohmann::json::json_pointer ptr( "/board/via_hole");
229 
230  ( *m_internals )[ptr] = COLOR4D( 0.5, 0.4, 0, 0.8 ).ToWxString( wxC2S_CSS_SYNTAX );
231 
232  return true;
233  } );
234 
235  registerMigration( 2, 3,
236  [&]()
237  {
238  // We don't support opacity in some 3D colors but some versions of 5.99 let
239  // you set it.
240 
241  for( std::string path : { "3d_viewer.background_top",
242  "3d_viewer.background_bottom",
243  "3d_viewer.copper",
244  "3d_viewer.silkscreen_top",
245  "3d_viewer.silkscreen_bottom",
246  "3d_viewer.solderpaste" } )
247  {
248  if( OPT<COLOR4D> optval = Get<COLOR4D>( path ) )
249  Set( path, optval->WithAlpha( 1.0 ) );
250  }
251 
252  return true;
253  } );
254 }
255 
256 
258  JSON_SETTINGS( aOther.m_filename, SETTINGS_LOC::COLORS, colorsSchemaVersion )
259 {
260  initFromOther( aOther );
261 }
262 
263 
265 {
266  m_filename = aOther.m_filename;
267 
268  initFromOther( aOther );
269 
270  return *this;
271 }
272 
273 
275 {
276  m_displayName = aOther.m_displayName;
279  m_colors = aOther.m_colors;
281  m_writeFile = aOther.m_writeFile;
282 
283  // Ensure default colors are present
284  for( PARAM_BASE* param : aOther.m_params )
285  {
286  if( COLOR_MAP_PARAM* cmp = dynamic_cast<COLOR_MAP_PARAM*>( param ) )
287  m_defaultColors[cmp->GetKey()] = cmp->GetDefault();
288  }
289 }
290 
291 
292 bool COLOR_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
293 {
294  return false;
295 }
296 
297 
299 {
307  if( !m_manager )
308  {
309  wxLogTrace( traceSettings, "Error: COLOR_SETTINGS migration cannot run unmanaged!" );
310  return false;
311  }
312 
313  if( !Contains( "fpedit" ) )
314  {
315  wxLogTrace( traceSettings, "migrateSchema0to1: %s doesn't have fpedit settings; skipping.",
316  m_filename );
317  return true;
318  }
319 
320  wxString filename = m_filename + wxT( "_footprints" );
321 
322  COLOR_SETTINGS* fpsettings = m_manager->AddNewColorSettings( filename );
323 
324  // Start out with a clone
325  fpsettings->m_internals->CloneFrom( *m_internals );
326 
327  // Footprint editor now just looks at the "board" namespace
328  fpsettings->Set( "board", fpsettings->At( "fpedit" ) );
329 
330  fpsettings->Internals()->erase( "fpedit" );
331  fpsettings->Load();
332  fpsettings->SetName( fpsettings->GetName() + wxS( " " ) + _( "(Footprints)" ) );
333  m_manager->Save( fpsettings );
334 
335  // Now we can get rid of our own copy
336  m_internals->erase( "fpedit" );
337 
338  return true;
339 }
340 
341 
343 {
344  if( m_colors.count( aLayer ) )
345  return m_colors.at( aLayer );
346 
347  return COLOR4D::UNSPECIFIED;
348 }
349 
350 
352 {
353  if( !m_defaultColors.count( aLayer ) )
354  {
355  COLOR_MAP_PARAM* p = nullptr;
356 
357  for( PARAM_BASE* param : m_params )
358  {
359  COLOR_MAP_PARAM* cmp = dynamic_cast<COLOR_MAP_PARAM*>( param );
360 
361  if( cmp && cmp->GetKey() == aLayer )
362  p = cmp;
363  }
364 
365  if( p )
366  m_defaultColors[aLayer] = p->GetDefault();
367  else
368  m_defaultColors[aLayer] = COLOR4D::UNSPECIFIED;
369  }
370 
371  return m_defaultColors.at( aLayer );
372 }
373 
374 
375 void COLOR_SETTINGS::SetColor( int aLayer, const COLOR4D& aColor )
376 {
377  m_colors[ aLayer ] = aColor;
378 }
379 
380 
381 std::vector<COLOR_SETTINGS*> COLOR_SETTINGS::CreateBuiltinColorSettings()
382 {
383  COLOR_SETTINGS* defaultTheme = new COLOR_SETTINGS( wxT( "_builtin_default" ) );
384  defaultTheme->SetName( _( "KiCad Default" ) );
385  defaultTheme->m_writeFile = false;
386  defaultTheme->Load(); // We can just get the colors out of the param defaults for this one
387 
388  COLOR_SETTINGS* classicTheme = new COLOR_SETTINGS( wxT( "_builtin_classic" ) );
389  classicTheme->SetName( _( "KiCad Classic" ) );
390  classicTheme->m_writeFile = false;
391 
392  for( PARAM_BASE* param : classicTheme->m_params )
393  delete param;
394 
395  classicTheme->m_params.clear(); // Disable load/store
396 
397  for( const std::pair<int, COLOR4D> entry : s_classicTheme )
398  classicTheme->m_colors[entry.first] = entry.second;
399 
400  std::vector<COLOR_SETTINGS*> ret;
401 
402  ret.push_back( defaultTheme );
403  ret.push_back( classicTheme );
404 
405  return ret;
406 }
to draw micro vias
Definition: layer_ids.h:189
Auxiliary items (guides, rule, etc)
Definition: layer_ids.h:217
void Set(const std::string &aPath, ValueType aVal)
Stores a value into the JSON document Will throw an exception if ValueType isn't something that the l...
JSON_SETTINGS_INTERNALS * Internals()
std::vector< PARAM_BASE * > m_params
The list of parameters (owned by this object)
layer for drc markers with SEVERITY_ERROR
Definition: layer_ids.h:211
PCB cursor.
Definition: layer_ids.h:216
bool m_overrideSchItemColors
SETTINGS_LOC
Definition: json_settings.h:46
anchor of items having an anchor point (texts, footprints)
Definition: layer_ids.h:196
COLOR_SETTINGS(const wxString &aFilename=wxT("user"))
void SetColor(int aLayer, const COLOR4D &aColor)
Definition: bitmap.cpp:64
static const std::map< int, COLOR4D > s_classicTheme
const int colorsSchemaVersion
! Update the schema version whenever a migration is required
wxString m_displayName
const wxString & GetName() const
COLOR_SETTINGS * AddNewColorSettings(const wxString &aFilename)
Registers a new color settings object with the given filename.
nlohmann::json & At(const std::string &aPath)
Wrappers for the underlying JSON API so that most consumers don't need json.hpp All of these function...
COLOR4D GetDefault() const
to draw via holes (pad holes do not use this layer)
Definition: layer_ids.h:210
The color scheme directory (e.g. ~/.config/kicad/colors/)
to draw usual through hole vias
Definition: layer_ids.h:191
int GetKey() const
wxString m_filename
The filename (not including path) of this settings file (inicode)
handle color for not plated holes (holes, not pads)
Definition: layer_ids.h:192
#define CSS_COLOR(r, g, b, a)
std::unique_ptr< JSON_SETTINGS_INTERNALS > m_internals
#define GERBER_DRAWLAYERS_COUNT
Definition: layer_ids.h:376
#define CLR(x, y)
text marked as invisible
Definition: layer_ids.h:195
COLOR4D GetDefaultColor(int aLayer)
static std::vector< COLOR_SETTINGS * > CreateBuiltinColorSettings()
Constructs and returns a list of color settings objects based on the built-in color themes.
#define _(s)
void SetName(const wxString &aName)
std::unordered_map< int, COLOR4D > m_defaultColors
drawingsheet frame and titleblock
Definition: layer_ids.h:212
show a marker on pads with no nets
Definition: layer_ids.h:202
std::vector< COLOR4D > m_Palette
m_Pallete stores a list of colors that are used, in order, when a list of colors needs to be generate...
COLOR4D GetColor(int aLayer) const
std::unordered_map< int, COLOR4D > m_colors
Map of all layer colors.
see class PGM_BASE
multilayer pads, usually with holes
Definition: layer_ids.h:208
to draw blind/buried vias
Definition: layer_ids.h:190
layer for drc markers which have been individually excluded
Definition: layer_ids.h:231
void registerMigration(int aOldSchemaVersion, int aNewSchemaVersion, std::function< bool(void)> aMigrator)
Registers a migration from one schema version to another.
void initFromOther(const COLOR_SETTINGS &aOther)
Definition: layer_ids.h:70
COLOR_SETTINGS & operator=(const COLOR_SETTINGS &aOther)
layer for drc markers with SEVERITY_WARNING
Definition: layer_ids.h:230
bool MigrateFromLegacy(wxConfigBase *aCfg) override
Migrates from wxConfig to JSON-based configuration.
bool m_useBoardStackupColors
boost::optional< T > OPT
Definition: optional.h:7
PCB background color.
Definition: layer_ids.h:215
Color settings are a bit different than most of the settings objects in that there can be more than o...
to draw pad holes (plated)
Definition: layer_ids.h:209
bool Contains(const std::string &aPath) const
const wxChar *const traceSettings
Flag to enable debug output of settings operations and management.
SETTINGS_MANAGER * m_manager
A pointer to the settings manager managing this file (may be null)
virtual void Load()
Updates the parameters of this object based on the current JSON document contents.
bool m_writeFile
Whether or not the backing store file should be written.
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103