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 #include <base_units.h>
30 #include <drc/drc.h>
31 #include <widgets/ui_common.h>
32 
33 extern const char* traceSettings;
34 
35 
37 const int fpEditSchemaVersion = 1;
38 
39 
42  m_DesignSettings( nullptr, "fpedit.settings" ),
43  m_MagneticItems(),
44  m_Display(),
45  m_UserGrid(),
46  m_PolarCoords( false ),
47  m_Use45DegreeGraphicSegments( true ),
48  m_LibWidth( 250 ),
49  m_LastImportExportPath(),
50  m_FootprintTextShownColumns()
51 {
54  m_MagneticItems.graphics = false;
55 
56  m_params.emplace_back( new PARAM<int>( "window.lib_width",
57  &m_LibWidth, 250 ) );
58 
59  m_params.emplace_back( new PARAM<wxString>( "system.last_import_export_path",
60  &m_LastImportExportPath, "" ) );
61 
62  m_params.emplace_back( new PARAM<wxString>( "window.footprint_text_shown_columns",
63  &m_FootprintTextShownColumns, "0 1 2 3 4 5 6" ) );
64 
65  m_params.emplace_back( new PARAM<int>( "editing.magnetic_pads",
66  reinterpret_cast<int*>( &m_MagneticItems.pads ),
67  static_cast<int>( MAGNETIC_OPTIONS::CAPTURE_CURSOR_IN_TRACK_TOOL ) ) );
68 
69  m_params.emplace_back( new PARAM<bool>( "editing.polar_coords", &m_PolarCoords, false ) );
70 
71  m_params.emplace_back( new PARAM<bool>( "editing.use_45_degree_graphic_segments",
72  &m_Use45DegreeGraphicSegments, false ) );
73 
74  m_params.emplace_back( new PARAM<bool>( "pcb_display.text_fill",
75  &m_Display.m_DisplayTextFill, true ) );
76 
77  m_params.emplace_back( new PARAM<bool>( "pcb_display.graphic_items_fill",
79 
80  m_params.emplace_back( new PARAM<bool>( "pcb_display.pad_fill",
81  &m_Display.m_DisplayPadFill, true ) );
82 
83  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>(
84  "design_settings.default_footprint_text_items",
85  [&] () -> nlohmann::json
86  {
87  nlohmann::json js = nlohmann::json::array();
88 
90  {
91  js.push_back( nlohmann::json( { item.m_Text.ToUTF8(),
92  item.m_Visible,
93  item.m_Layer } ) );
94  }
95 
96  return js;
97  },
98  [&] ( const nlohmann::json& aObj )
99  {
101 
102  if( !aObj.is_array() )
103  return;
104 
105  for( const nlohmann::json& entry : aObj )
106  {
107  if( entry.empty() || !entry.is_array() )
108  continue;
109 
110  TEXT_ITEM_INFO textInfo( wxT( "" ), true, F_SilkS );
111 
112  textInfo.m_Text = entry.at(0).get<wxString>();
113  textInfo.m_Visible = entry.at(1).get<bool>();
114  textInfo.m_Layer = entry.at(2).get<int>();
115 
116  m_DesignSettings.m_DefaultFPTextItems.push_back( std::move( textInfo ) );
117  }
118  },
119  nlohmann::json::array( {
120  { "REF**", true, F_SilkS },
121  { "", true, F_Fab },
122  { "${REFERENCE}", true, F_Fab }
123  } ) ) );
124 
125  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_line_width",
128  MM_PER_IU ) );
129 
130  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_text_size_h",
133 
134  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_text_size_v",
137 
138  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_text_thickness",
141 
142  m_params.emplace_back( new PARAM<bool>( "design_settings.silk_text_italic",
144 
145  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_line_width",
148  MM_PER_IU ) );
149 
150  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_text_size_h",
153  MM_PER_IU ) );
154 
155  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_text_size_v",
158  MM_PER_IU ) );
159 
160  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_text_thickness",
163  MM_PER_IU ) );
164 
165  m_params.emplace_back( new PARAM<bool>( "design_settings.copper_text_italic",
167 
168  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.edge_line_width",
171  MM_PER_IU ) );
172 
173  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.courtyard_line_width",
176  MM_PER_IU ) );
177 
178  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_line_width",
181  MM_PER_IU ) );
182 
183  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_text_size_h",
186 
187  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_text_size_v",
190 
191  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_text_thickness",
193  Millimeter2iu( DEFAULT_TEXT_WIDTH ), 1, TEXTS_MAX_WIDTH, MM_PER_IU ) );
194 
195  m_params.emplace_back( new PARAM<bool>( "design_settings.fab_text_italic",
197 
198  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_line_width",
201  MM_PER_IU ) );
202 
203  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_text_size_h",
206 
207  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_text_size_v",
210 
211  m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_text_thickness",
213  Millimeter2iu( DEFAULT_TEXT_WIDTH ), 1, TEXTS_MAX_WIDTH, MM_PER_IU ) );
214 
215  m_params.emplace_back( new PARAM<bool>( "design_settings.others_text_italic",
217 }
218 
219 
221 {
222  bool ret = APP_SETTINGS_BASE::MigrateFromLegacy( aCfg );
223 
224  //
225  // NOTE: there's no value in line-wrapping these; it just makes the table unreadable.
226  //
227  ret &= fromLegacy<int>( aCfg, "ModeditLibWidth", "window.lib_width" );
228  ret &= fromLegacyString( aCfg, "import_last_path", "system.last_import_export_path" );
229  ret &= fromLegacyString( aCfg, "LibFootprintTextShownColumns", "window.footprint_text_shown_columns" );
230 
231  ret &= fromLegacy<int>( aCfg, "FpEditorMagneticPads", "editing.magnetic_pads" );
232  ret &= fromLegacy<bool>( aCfg, "FpEditorDisplayPolarCoords", "editing.polar_coords" );
233  ret &= fromLegacy<int>( aCfg, "FpEditorUse45DegreeGraphicSegments", "editing.use_45_degree_graphic_segments" );
234 
235  ret &= fromLegacy<bool>( aCfg, "FpEditorGraphicLinesDisplayMode", "pcb_display.graphic_items_fill" );
236  ret &= fromLegacy<bool>( aCfg, "FpEditorPadDisplayMode", "pcb_display.pad_fill" );
237  ret &= fromLegacy<bool>( aCfg, "FpEditorTextsDisplayMode", "pcb_display.footprint_text" );
238 
239  ret &= fromLegacy<double>( aCfg, "FpEditorSilkLineWidth", "design_settings.silk_line_width" );
240  ret &= fromLegacy<double>( aCfg, "FpEditorSilkTextSizeH", "design_settings.silk_text_size_h" );
241  ret &= fromLegacy<double>( aCfg, "FpEditorSilkTextSizeV", "design_settings.silk_text_size_v" );
242  ret &= fromLegacy<double>( aCfg, "FpEditorSilkTextThickness", "design_settings.silk_text_thickness" );
243  ret &= fromLegacy<bool>( aCfg, "FpEditorSilkTextItalic", "design_settings.silk_text_italic" );
244  ret &= fromLegacy<double>( aCfg, "FpEditorCopperLineWidth", "design_settings.copper_line_width" );
245  ret &= fromLegacy<double>( aCfg, "FpEditorCopperTextSizeH", "design_settings.copper_text_size_h" );
246  ret &= fromLegacy<double>( aCfg, "FpEditorCopperTextSizeV", "design_settings.copper_text_size_v" );
247  ret &= fromLegacy<double>( aCfg, "FpEditorCopperTextThickness", "design_settings.copper_text_thickness" );
248  ret &= fromLegacy<bool>( aCfg, "FpEditorCopperTextItalic", "design_settings.copper_text_italic" );
249  ret &= fromLegacy<double>( aCfg, "FpEditorEdgeCutLineWidth", "design_settings.edge_line_width" );
250  ret &= fromLegacy<double>( aCfg, "FpEditorCourtyardLineWidth", "design_settings.courtyard_line_width" );
251  ret &= fromLegacy<double>( aCfg, "FpEditorOthersLineWidth", "design_settings.others_line_width" );
252  ret &= fromLegacy<double>( aCfg, "FpEditorOthersTextSizeH", "design_settings.others_text_size_h" );
253  ret &= fromLegacy<double>( aCfg, "FpEditorOthersTextSizeV", "design_settings.others_text_size_v" );
254  ret &= fromLegacy<double>( aCfg, "FpEditorOthersTextThickness", "design_settings.others_text_thickness" );
255  ret &= fromLegacy<bool>( aCfg, "FpEditorOthersTextItalic", "design_settings.others_text_italic" );
256 
257  nlohmann::json textItems = nlohmann::json::array( {
258  { "REF**", true, F_SilkS },
259  { "", true, F_Fab }
260  } );
261 
262  ( *this )[PointerFromString( "design_settings.default_footprint_text_items" )] = textItems;
263 
264  ret &= fromLegacyString( aCfg, "FpEditorRefDefaultText", "design_settings.default_footprint_text_items.0.0" );
265  ret &= fromLegacy<bool>( aCfg, "FpEditorRefDefaultVisibility", "design_settings.default_footprint_text_items.0.1" );
266  ret &= fromLegacy<int>( aCfg, "FpEditorRefDefaultLayer", "design_settings.default_footprint_text_items.0.2" );
267  ret &= fromLegacyString( aCfg, "FpEditorValueDefaultText", "design_settings.default_footprint_text_items.1.0" );
268  ret &= fromLegacy<bool>( aCfg, "FpEditorValueDefaultVisibility", "design_settings.default_footprint_text_items.1.1" );
269  ret &= fromLegacy<int>( aCfg, "FpEditorValueDefaultLayer", "design_settings.default_footprint_text_items.1.2" );
270 
271 
272  std::string f = "ModEdit";
273 
274  // Migrate color settings that were stored in the pcbnew config file
275  // We create a copy of the user scheme for the footprint editor context
276 
277  SETTINGS_MANAGER& manager = Pgm().GetSettingsManager();
278  COLOR_SETTINGS* cs = manager.AddNewColorSettings( "user_footprints" );
279 
280  cs->SetName( wxT( "KiCad Default (Footprints)" ) );
281  manager.Save( cs );
282 
283  auto migrateLegacyColor = [&] ( const std::string& aKey, int aLayerId )
284  {
285  wxString str;
286 
287  if( aCfg->Read( aKey, &str ) )
288  cs->SetColor( aLayerId, COLOR4D( str ) );
289  };
290 
291  for( int i = 0; i < PCB_LAYER_ID_COUNT; ++i )
292  {
293  wxString layer = LSET::Name( PCB_LAYER_ID( i ) );
294  migrateLegacyColor( f + "Color4DPCBLayer_" + layer.ToStdString(), PCB_LAYER_ID( i ) );
295  }
296 
297  migrateLegacyColor( f + "Color4DAnchorEx", LAYER_ANCHOR );
298  migrateLegacyColor( f + "Color4DAuxItems", LAYER_AUX_ITEMS );
299  migrateLegacyColor( f + "Color4DGrid", LAYER_GRID );
300  migrateLegacyColor( f + "Color4DNoNetPadMarker", LAYER_NO_CONNECTS );
301  migrateLegacyColor( f + "Color4DNonPlatedEx", LAYER_NON_PLATEDHOLES );
302  migrateLegacyColor( f + "Color4DPadBackEx", LAYER_PAD_BK );
303  migrateLegacyColor( f + "Color4DPadFrontEx", LAYER_PAD_FR );
304  migrateLegacyColor( f + "Color4DPadThruHoleEx", LAYER_PADS_TH );
305  migrateLegacyColor( f + "Color4DPCBBackground", LAYER_PCB_BACKGROUND );
306  migrateLegacyColor( f + "Color4DPCBCursor", LAYER_CURSOR );
307  migrateLegacyColor( f + "Color4DRatsEx", LAYER_RATSNEST );
308  migrateLegacyColor( f + "Color4DTxtBackEx", LAYER_MOD_TEXT_BK );
309  migrateLegacyColor( f + "Color4DTxtFrontEx", LAYER_MOD_TEXT_FR );
310  migrateLegacyColor( f + "Color4DTxtInvisEx", LAYER_MOD_TEXT_INVISIBLE );
311  migrateLegacyColor( f + "Color4DViaBBlindEx", LAYER_VIA_BBLIND );
312  migrateLegacyColor( f + "Color4DViaMicroEx", LAYER_VIA_MICROVIA );
313  migrateLegacyColor( f + "Color4DViaThruEx", LAYER_VIA_THROUGH );
314  migrateLegacyColor( f + "Color4DWorksheet", LAYER_WORKSHEET );
315 
316  manager.SaveColorSettings( cs, "board" );
317 
318  ( *this )[PointerFromString( "appearance.color_theme" )] = "user_footprints";
319 
320  double x, y;
321  f = "ModEditFrame";
322 
323  if( aCfg->Read( f + "PcbUserGrid_X", &x ) && aCfg->Read( f + "PcbUserGrid_Y", &y ) )
324  {
325  EDA_UNITS u = static_cast<EDA_UNITS>( aCfg->ReadLong( f + "PcbUserGrid_Unit",
326  static_cast<long>( EDA_UNITS::INCHES ) ) );
327 
328  // Convert to internal units
329  x = From_User_Unit( u, x );
330  y = From_User_Unit( u, y );
331 
332  ( *this )[PointerFromString( "window.grid.user_grid_x" )] = StringFromValue( u, x, true, true );
333  ( *this )[PointerFromString( "window.grid.user_grid_y" )] = StringFromValue( u, y, true, true );
334  }
335 
336  return ret;
337 }
338 
339 
341 {
342  bool ret = true;
343  int filever = at( PointerFromString( "meta.version" ) ).get<int>();
344 
345  if( filever == 0 )
346  {
347  ret &= migrateSchema0to1();
348 
349  if( ret )
350  {
351  ( *this )[PointerFromString( "meta.version" )] = 1;
352  }
353  }
354 
355  return ret;
356 }
357 
358 
360 {
368  if( !m_manager )
369  {
370  wxLogTrace(
371  traceSettings, "Error: FOOTPRINT_EDITOR_SETTINGS migration cannot run unmanaged!" );
372  return false;
373  }
374 
375  nlohmann::json::json_pointer theme_ptr( "/appearance/color_theme" );
376 
377  wxString selected = at( theme_ptr ).get<wxString>();
378  wxString search = selected + wxT( "_footprints" );
379 
380  for( COLOR_SETTINGS* settings : Pgm().GetSettingsManager().GetColorSettingsList() )
381  {
382  if( settings->GetFilename() == search )
383  {
384  wxLogTrace( traceSettings, "Updating footprint editor theme from %s to %s",
385  selected, search );
386  ( *this )[theme_ptr] = search;
387  return true;
388  }
389  }
390 
391  return true;
392 }
EDA_UNITS
Definition: common.h:198
#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:296
multilayer pads, usually with holes
#define TEXTS_MAX_WIDTH
Maximum text width in internal units (10 inches)
Definition: pcbnew.h:34
Implementation of conversion functions that require both schematic and board internal units.
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)
double From_User_Unit(EDA_UNITS aUnits, double aValue, bool aUseMils)
Return in internal units the value "val" given in a real unit such as "in", "mm" or "deg".
Definition: base_units.cpp:321
#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:92
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:388
Functions to provide common constants and other functions to assist in making a consistent UI.
void SetName(const wxString &aName)
#define TEXTS_MAX_SIZE
Maximum text size in internal units (10 inches)
Definition: pcbnew.h:33
SETTINGS_MANAGER * GetSettingsManager()
int m_LineThickness[LAYER_CLASS_COUNT]
#define TEXTS_MIN_SIZE
Minimum text size in internal units (1 mil)
Definition: pcbnew.h:32
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
Only some of these settings are actually used for footprint editing.
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 constexpr int Millimeter2iu(double mm)
static nlohmann::json::json_pointer PointerFromString(std::string aPath)
Builds a JSON pointer based on a given string.
wxString StringFromValue(EDA_UNITS aUnits, double aValue, bool aAddUnitSymbol, bool aUseMils, EDA_DATA_TYPE aType)
Function StringFromValue returns the string from aValue according to units (inch, mm ....
Definition: base_units.cpp:233
MAGNETIC_OPTIONS tracks
void SetColor(int aLayer, COLOR4D aColor)
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:99