KiCad PCB EDA Suite
footprint_editor_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) 2020 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 <common.h>
24 #include <pgm_base.h>
26 #include <settings/parameters.h>
28 #include <wx/config.h>
29 
30 
31 extern const char* traceSettings;
32 
33 
35 const int fpEditSchemaVersion = 1;
36 
37 
40  m_DesignSettings(),
41  m_MagneticItems(),
42  m_Display(),
43  m_UserGrid(),
44  m_PolarCoords( false ),
45  m_Use45DegreeGraphicSegments( true ),
46  m_LibWidth( 250 ),
47  m_LastImportExportPath(),
48  m_FootprintTextShownColumns()
49 {
52  m_MagneticItems.graphics = false;
53 
54  m_params.emplace_back( new PARAM<int>( "window.lib_width",
55  &m_LibWidth, 250 ) );
56 
57  m_params.emplace_back( new PARAM<wxString>( "system.last_import_export_path",
58  &m_LastImportExportPath, "" ) );
59 
60  m_params.emplace_back( new PARAM<wxString>( "window.footprint_text_shown_columns",
61  &m_FootprintTextShownColumns, "0 1 2 3 4 5 6" ) );
62 
63  m_params.emplace_back( new PARAM<int>( "editing.magnetic_pads",
64  reinterpret_cast<int*>( &m_MagneticItems.pads ),
65  static_cast<int>( MAGNETIC_OPTIONS::CAPTURE_CURSOR_IN_TRACK_TOOL ) ) );
66 
67  m_params.emplace_back( new PARAM<bool>( "editing.polar_coords", &m_PolarCoords, false ) );
68 
69  m_params.emplace_back( new PARAM<bool>( "editing.use_45_degree_graphic_segments",
70  &m_Use45DegreeGraphicSegments, false ) );
71 
72  m_params.emplace_back( new PARAM<bool>( "pcb_display.text_fill",
73  &m_Display.m_DisplayTextFill, true ) );
74 
75  m_params.emplace_back( new PARAM<bool>( "pcb_display.graphic_items_fill",
77 
78  m_params.emplace_back( new PARAM<bool>( "pcb_display.pad_fill",
79  &m_Display.m_DisplayPadFill, true ) );
80 
81  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>(
82  "design_settings.default_footprint_text_items",
83  [&] () -> nlohmann::json
84  {
85  nlohmann::json js = nlohmann::json::array();
86 
88  {
89  js.push_back( nlohmann::json( { item.m_Text.ToUTF8(),
90  item.m_Visible,
91  item.m_Layer } ) );
92  }
93 
94  return js;
95  },
96  [&] ( const nlohmann::json& aObj )
97  {
99 
100  if( !aObj.is_array() )
101  return;
102 
103  for( const nlohmann::json& entry : aObj )
104  {
105  if( entry.empty() || !entry.is_array() )
106  continue;
107 
108  TEXT_ITEM_INFO textInfo( wxT( "" ), true, F_SilkS );
109 
110  textInfo.m_Text = entry.at(0).get<wxString>();
111  textInfo.m_Visible = entry.at(1).get<bool>();
112  textInfo.m_Layer = entry.at(2).get<int>();
113 
114  m_DesignSettings.m_DefaultFPTextItems.push_back( std::move( textInfo ) );
115  }
116  },
117  nlohmann::json::array( {
118  { "REF**", true, F_SilkS },
119  { "", true, F_Fab },
120  { "${REFERENCE}", true, F_Fab }
121  } ) ) );
122 
123  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_line_width",
125  Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 100.0 ),
126  MM_PER_IU ) );
127 
128  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_text_size_h",
130  Millimeter2iu( DEFAULT_SILK_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
131 
132  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_text_size_v",
134  Millimeter2iu( DEFAULT_SILK_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
135 
136  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_text_thickness",
138  Millimeter2iu( DEFAULT_SILK_TEXT_WIDTH ), 1, TEXTS_MAX_WIDTH, MM_PER_IU ) );
139 
140  m_params.emplace_back( new PARAM<bool>( "design_settings.silk_text_italic",
142 
143  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_line_width",
145  Millimeter2iu( DEFAULT_COPPER_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
146  MM_PER_IU ) );
147 
148  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_text_size_h",
151  MM_PER_IU ) );
152 
153  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_text_size_v",
156  MM_PER_IU ) );
157 
158  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_text_thickness",
160  Millimeter2iu( DEFAULT_COPPER_TEXT_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
161  MM_PER_IU ) );
162 
163  m_params.emplace_back( new PARAM<bool>( "design_settings.copper_text_italic",
165 
166  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.edge_line_width",
168  Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
169  MM_PER_IU ) );
170 
171  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.courtyard_line_width",
173  Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
174  MM_PER_IU ) );
175 
176  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_line_width",
178  Millimeter2iu( DEFAULT_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
179  MM_PER_IU ) );
180 
181  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_text_size_h",
183  Millimeter2iu( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
184 
185  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_text_size_v",
187  Millimeter2iu( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
188 
189  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_text_thickness",
191  Millimeter2iu( DEFAULT_TEXT_WIDTH ), 1, TEXTS_MAX_WIDTH, MM_PER_IU ) );
192 
193  m_params.emplace_back( new PARAM<bool>( "design_settings.fab_text_italic",
195 
196  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_line_width",
198  Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
199  MM_PER_IU ) );
200 
201  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_text_size_h",
203  Millimeter2iu( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
204 
205  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_text_size_v",
207  Millimeter2iu( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
208 
209  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_text_thickness",
211  Millimeter2iu( DEFAULT_TEXT_WIDTH ), 1, TEXTS_MAX_WIDTH, MM_PER_IU ) );
212 
213  m_params.emplace_back( new PARAM<bool>( "design_settings.others_text_italic",
215 }
216 
217 
219 {
220  bool ret = APP_SETTINGS_BASE::MigrateFromLegacy( aCfg );
221 
222  //
223  // NOTE: there's no value in line-wrapping these; it just makes the table unreadable.
224  //
225  ret &= fromLegacy<int>( aCfg, "ModeditLibWidth", "window.lib_width" );
226  ret &= fromLegacyString( aCfg, "import_last_path", "system.last_import_export_path" );
227  ret &= fromLegacyString( aCfg, "LibFootprintTextShownColumns", "window.footprint_text_shown_columns" );
228 
229  ret &= fromLegacy<int>( aCfg, "FpEditorMagneticPads", "editing.magnetic_pads" );
230  ret &= fromLegacy<bool>( aCfg, "FpEditorDisplayPolarCoords", "editing.polar_coords" );
231  ret &= fromLegacy<int>( aCfg, "FpEditorUse45DegreeGraphicSegments", "editing.use_45_degree_graphic_segments" );
232 
233  ret &= fromLegacy<bool>( aCfg, "FpEditorGraphicLinesDisplayMode", "pcb_display.graphic_items_fill" );
234  ret &= fromLegacy<bool>( aCfg, "FpEditorPadDisplayMode", "pcb_display.pad_fill" );
235  ret &= fromLegacy<bool>( aCfg, "FpEditorTextsDisplayMode", "pcb_display.footprint_text" );
236 
237  ret &= fromLegacy<double>( aCfg, "FpEditorSilkLineWidth", "design_settings.silk_line_width" );
238  ret &= fromLegacy<double>( aCfg, "FpEditorSilkTextSizeH", "design_settings.silk_text_size_h" );
239  ret &= fromLegacy<double>( aCfg, "FpEditorSilkTextSizeV", "design_settings.silk_text_size_v" );
240  ret &= fromLegacy<double>( aCfg, "FpEditorSilkTextThickness", "design_settings.silk_text_thickness" );
241  ret &= fromLegacy<bool>( aCfg, "FpEditorSilkTextItalic", "design_settings.silk_text_italic" );
242  ret &= fromLegacy<double>( aCfg, "FpEditorCopperLineWidth", "design_settings.copper_line_width" );
243  ret &= fromLegacy<double>( aCfg, "FpEditorCopperTextSizeH", "design_settings.copper_text_size_h" );
244  ret &= fromLegacy<double>( aCfg, "FpEditorCopperTextSizeV", "design_settings.copper_text_size_v" );
245  ret &= fromLegacy<double>( aCfg, "FpEditorCopperTextThickness", "design_settings.copper_text_thickness" );
246  ret &= fromLegacy<bool>( aCfg, "FpEditorCopperTextItalic", "design_settings.copper_text_italic" );
247  ret &= fromLegacy<double>( aCfg, "FpEditorEdgeCutLineWidth", "design_settings.edge_line_width" );
248  ret &= fromLegacy<double>( aCfg, "FpEditorCourtyardLineWidth", "design_settings.courtyard_line_width" );
249  ret &= fromLegacy<double>( aCfg, "FpEditorOthersLineWidth", "design_settings.others_line_width" );
250  ret &= fromLegacy<double>( aCfg, "FpEditorOthersTextSizeH", "design_settings.others_text_size_h" );
251  ret &= fromLegacy<double>( aCfg, "FpEditorOthersTextSizeV", "design_settings.others_text_size_v" );
252  ret &= fromLegacy<double>( aCfg, "FpEditorOthersTextThickness", "design_settings.others_text_thickness" );
253  ret &= fromLegacy<bool>( aCfg, "FpEditorOthersTextItalic", "design_settings.others_text_italic" );
254 
255  nlohmann::json textItems = nlohmann::json::array( {
256  { "REF**", true, F_SilkS },
257  { "", true, F_Fab }
258  } );
259 
260  ( *this )[PointerFromString( "design_settings.default_footprint_text_items" )] = textItems;
261 
262  ret &= fromLegacyString( aCfg, "FpEditorRefDefaultText", "design_settings.default_footprint_text_items.0.0" );
263  ret &= fromLegacy<bool>( aCfg, "FpEditorRefDefaultVisibility", "design_settings.default_footprint_text_items.0.1" );
264  ret &= fromLegacy<int>( aCfg, "FpEditorRefDefaultLayer", "design_settings.default_footprint_text_items.0.2" );
265  ret &= fromLegacyString( aCfg, "FpEditorValueDefaultText", "design_settings.default_footprint_text_items.1.0" );
266  ret &= fromLegacy<bool>( aCfg, "FpEditorValueDefaultVisibility", "design_settings.default_footprint_text_items.1.1" );
267  ret &= fromLegacy<int>( aCfg, "FpEditorValueDefaultLayer", "design_settings.default_footprint_text_items.1.2" );
268 
269 
270  const std::string f = "ModEdit";
271 
272  // Migrate color settings that were stored in the pcbnew config file
273  // We create a copy of the user scheme for the footprint editor context
274 
275  SETTINGS_MANAGER& manager = Pgm().GetSettingsManager();
276  COLOR_SETTINGS* cs = manager.AddNewColorSettings( "user_footprints" );
277 
278  cs->SetName( wxT( "KiCad Default (Footprints)" ) );
279  manager.Save( cs );
280 
281  auto migrateLegacyColor = [&] ( const std::string& aKey, int aLayerId )
282  {
283  wxString str;
284 
285  if( aCfg->Read( aKey, &str ) )
286  cs->SetColor( aLayerId, COLOR4D( str ) );
287  };
288 
289  for( int i = 0; i < PCB_LAYER_ID_COUNT; ++i )
290  {
291  wxString layer = LSET::Name( PCB_LAYER_ID( i ) );
292  migrateLegacyColor( f + "Color4DPCBLayer_" + layer.ToStdString(), PCB_LAYER_ID( i ) );
293  }
294 
295  migrateLegacyColor( f + "Color4DAnchorEx", LAYER_ANCHOR );
296  migrateLegacyColor( f + "Color4DAuxItems", LAYER_AUX_ITEMS );
297  migrateLegacyColor( f + "Color4DGrid", LAYER_GRID );
298  migrateLegacyColor( f + "Color4DNoNetPadMarker", LAYER_NO_CONNECTS );
299  migrateLegacyColor( f + "Color4DNonPlatedEx", LAYER_NON_PLATEDHOLES );
300  migrateLegacyColor( f + "Color4DPadBackEx", LAYER_PAD_BK );
301  migrateLegacyColor( f + "Color4DPadFrontEx", LAYER_PAD_FR );
302  migrateLegacyColor( f + "Color4DPadThruHoleEx", LAYER_PADS_TH );
303  migrateLegacyColor( f + "Color4DPCBBackground", LAYER_PCB_BACKGROUND );
304  migrateLegacyColor( f + "Color4DPCBCursor", LAYER_CURSOR );
305  migrateLegacyColor( f + "Color4DRatsEx", LAYER_RATSNEST );
306  migrateLegacyColor( f + "Color4DTxtBackEx", LAYER_MOD_TEXT_BK );
307  migrateLegacyColor( f + "Color4DTxtFrontEx", LAYER_MOD_TEXT_FR );
308  migrateLegacyColor( f + "Color4DTxtInvisEx", LAYER_MOD_TEXT_INVISIBLE );
309  migrateLegacyColor( f + "Color4DViaBBlindEx", LAYER_VIA_BBLIND );
310  migrateLegacyColor( f + "Color4DViaMicroEx", LAYER_VIA_MICROVIA );
311  migrateLegacyColor( f + "Color4DViaThruEx", LAYER_VIA_THROUGH );
312  migrateLegacyColor( f + "Color4DWorksheet", LAYER_WORKSHEET );
313 
314  manager.SaveColorSettings( cs, "board" );
315 
316  ( *this )[PointerFromString( "appearance.color_theme" )] = "user_footprints";
317 
318  return ret;
319 }
320 
321 
323 {
324  bool ret = true;
325  int filever = at( PointerFromString( "meta.version" ) ).get<int>();
326 
327  if( filever == 0 )
328  {
329  ret &= migrateSchema0to1();
330 
331  if( ret )
332  {
333  ( *this )[PointerFromString( "meta.version" )] = 1;
334  }
335  }
336 
337  return ret;
338 }
339 
340 
342 {
350  if( !m_manager )
351  {
352  wxLogTrace(
353  traceSettings, "Error: FOOTPRINT_EDITOR_SETTINGS migration cannot run unmanaged!" );
354  return false;
355  }
356 
357  nlohmann::json::json_pointer theme_ptr( "/appearance/color_theme" );
358 
359  wxString selected = at( theme_ptr ).get<wxString>();
360  wxString search = selected + wxT( "_footprints" );
361 
362  for( COLOR_SETTINGS* settings : Pgm().GetSettingsManager().GetColorSettingsList() )
363  {
364  if( settings->GetFilename() == search )
365  {
366  wxLogTrace( traceSettings, "Updating footprint editor theme from %s to %s",
367  selected, search );
368  ( *this )[theme_ptr] = search;
369  return true;
370  }
371  }
372 
373  return true;
374 }
#define DEFAULT_SILK_TEXT_WIDTH
to draw blind/buried vias
show a marker on pads with no nets
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:104
std::vector< TEXT_ITEM_INFO > m_DefaultFPTextItems
std::vector< PARAM_BASE * > m_params
The list of parameters (owned by this object)
Like a normal param, but with custom getter and setter functions.
Definition: parameters.h:173
multilayer pads, usually with holes
#define TEXTS_MAX_WIDTH
Maximum text width in internal units (10 inches)
Definition: pcbnew.h:40
virtual bool MigrateFromLegacy(wxConfigBase *aCfg) override
Migrates from wxConfig to JSON-based configuration.
handle color for not plated holes (holes, not pads)
anchor of items having an anchor point (texts, footprints)
#define DEFAULT_LINE_WIDTH
#define DEFAULT_COPPER_LINE_WIDTH
COLOR_SETTINGS * AddNewColorSettings(const wxString &aFilename)
Registers a new color settings object with the given filename.
nlohmann::json json
Definition: gerbview.cpp:40
#define DEFAULT_TEXT_WIDTH
wxSize m_TextSize[LAYER_CLASS_COUNT]
const int fpEditSchemaVersion
! Update the schema version whenever a migration is required
PCB_LAYER_ID
A quick note on layer IDs:
#define DEFAULT_SILK_TEXT_SIZE
int m_TextThickness[LAYER_CLASS_COUNT]
#define DEFAULT_SILK_LINE_WIDTH
Auxiliary items (guides, rule, etc)
bool Migrate() override
Migrates the schema of this settings from the version in the file to the latest version.
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
Definition: app_settings.h:73
static const wxChar * Name(PCB_LAYER_ID aLayerId)
Function Name returns the fixed name association with aLayerId.
Definition: lset.cpp:78
to draw usual through hole vias
bool m_TextItalic[LAYER_CLASS_COUNT]
Represents a parameter that has a scaling factor between the value in the file and the value used int...
Definition: parameters.h:265
void SetName(const wxString &aName)
#define TEXTS_MAX_SIZE
Maximum text size in internal units (10 inches)
Definition: pcbnew.h:39
int m_LineThickness[LAYER_CLASS_COUNT]
#define TEXTS_MIN_SIZE
Minimum text size in internal units (1 mil)
Definition: pcbnew.h:38
bool fromLegacyString(wxConfigBase *aConfig, const std::string &aKey, const std::string &aDest)
Translates a legacy wxConfig string value to a given JSON pointer value.
smd pads, front layer
see class PGM_BASE
Board layer functions and definitions.
MAGNETIC_OPTIONS pads
void SaveColorSettings(COLOR_SETTINGS *aSettings, const std::string &aNamespace="")
Safely saves a COLOR_SETTINGS to disk, preserving any changes outside the given namespace.
The common library.
#define DEFAULT_COPPER_TEXT_WIDTH
virtual bool MigrateFromLegacy(wxConfigBase *aLegacyConfig) override
Migrates from wxConfig to JSON-based configuration.
Color settings are a bit different than most of the settings objects in that there can be more than o...
#define DEFAULT_TEXT_SIZE
#define DEFAULT_COPPER_TEXT_SIZE
BOARD_DESIGN_SETTINGS m_DesignSettings
SETTINGS_MANAGER * m_manager
A pointer to the settings manager managing this file (may be null)
const char * traceSettings
Flag to enable settings tracing.
static nlohmann::json::json_pointer PointerFromString(std::string aPath)
Builds a JSON pointer based on a given string.
MAGNETIC_OPTIONS tracks
void SetColor(int aLayer, COLOR4D aColor)
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:40