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