You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

489 lines
23 KiB

  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-2023 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. #include <common.h>
  21. #include <footprint_editor_settings.h>
  22. #include <layer_ids.h>
  23. #include <lset.h>
  24. #include <pgm_base.h>
  25. #include <eda_text.h>
  26. #include <settings/common_settings.h>
  27. #include <settings/json_settings_internals.h>
  28. #include <settings/parameters.h>
  29. #include <settings/settings_manager.h>
  30. #include <wx/config.h>
  31. #include <base_units.h>
  32. #include <wx/log.h>
  33. ///! Update the schema version whenever a migration is required
  34. const int fpEditSchemaVersion = 2;
  35. FOOTPRINT_EDITOR_SETTINGS::FOOTPRINT_EDITOR_SETTINGS() :
  36. PCB_VIEWERS_SETTINGS_BASE( "fpedit", fpEditSchemaVersion ),
  37. m_DesignSettings( nullptr, "fpedit.settings" ),
  38. m_MagneticItems(),
  39. m_Display(),
  40. m_UserGrid(),
  41. m_PolarCoords( false ),
  42. m_DisplayInvertXAxis( false ),
  43. m_DisplayInvertYAxis( false ),
  44. m_RotationAngle( ANGLE_90 ),
  45. m_Use45Limit( true ),
  46. m_ArcEditMode( ARC_EDIT_MODE::KEEP_CENTER_ADJUST_ANGLE_RADIUS ),
  47. m_LibWidth( 250 ),
  48. m_LastExportPath(),
  49. m_FootprintTextShownColumns()
  50. {
  51. m_MagneticItems.pads = MAGNETIC_OPTIONS::CAPTURE_ALWAYS;
  52. m_MagneticItems.tracks = MAGNETIC_OPTIONS::NO_EFFECT;
  53. m_MagneticItems.graphics = true;
  54. m_MagneticItems.allLayers = false;
  55. m_AuiPanels.appearance_panel_tab = 0;
  56. m_AuiPanels.right_panel_width = -1;
  57. m_AuiPanels.show_layer_manager = true;
  58. m_params.emplace_back( new PARAM<int>( "window.lib_width",
  59. &m_LibWidth, 250 ) );
  60. m_params.emplace_back( new PARAM<bool>( "aui.show_layer_manager",
  61. &m_AuiPanels.show_layer_manager, true ) );
  62. m_params.emplace_back( new PARAM<int>( "aui.right_panel_width",
  63. &m_AuiPanels.right_panel_width, -1 ) );
  64. m_params.emplace_back( new PARAM<int>( "aui.appearance_panel_tab",
  65. &m_AuiPanels.appearance_panel_tab, 0, 0, 2 ) );
  66. m_params.emplace_back( new PARAM<int>( "aui.properties_panel_width",
  67. &m_AuiPanels.properties_panel_width, -1 ) );
  68. m_params.emplace_back( new PARAM<float>( "aui.properties_splitter_proportion",
  69. &m_AuiPanels.properties_splitter, 0.5f ) );
  70. m_params.emplace_back( new PARAM<bool>( "aui.show_properties",
  71. &m_AuiPanels.show_properties, false ) );
  72. m_params.emplace_back( new PARAM<int>( "library.sort_mode",
  73. &m_LibrarySortMode, 0 ) );
  74. m_params.emplace_back( new PARAM<wxString>( "system.last_import_export_path",
  75. &m_LastExportPath, "" ) );
  76. m_params.emplace_back( new PARAM<bool>( "pcb_display.graphics_fill",
  77. &m_ViewersDisplay.m_DisplayGraphicsFill, true ) );
  78. m_params.emplace_back( new PARAM<bool>( "pcb_display.text_fill",
  79. &m_ViewersDisplay.m_DisplayTextFill, true ) );
  80. m_params.emplace_back( new PARAM<bool>( "pcb_display.pad_fill",
  81. &m_ViewersDisplay.m_DisplayPadFill, true ) );
  82. m_params.emplace_back( new PARAM<bool>( "pcb_display.pad_numbers",
  83. &m_ViewersDisplay.m_DisplayPadNumbers, true ) );
  84. m_params.emplace_back( new PARAM<wxString>( "window.footprint_text_shown_columns",
  85. &m_FootprintTextShownColumns, "0 1 2 3 4 5 7" ) );
  86. m_params.emplace_back( new PARAM<int>( "editing.magnetic_pads",
  87. reinterpret_cast<int*>( &m_MagneticItems.pads ),
  88. static_cast<int>( MAGNETIC_OPTIONS::CAPTURE_ALWAYS ) ) );
  89. m_params.emplace_back( new PARAM<bool>( "editing.magnetic_graphics",
  90. &m_MagneticItems.graphics, true ) );
  91. m_params.emplace_back( new PARAM<bool>( "editing.magnetic_all_layers",
  92. &m_MagneticItems.allLayers, false ) );
  93. m_params.emplace_back( new PARAM<bool>( "editing.polar_coords",
  94. &m_PolarCoords, false ) );
  95. m_params.emplace_back( new PARAM<bool>( "origin_invert_x_axis",
  96. &m_DisplayInvertXAxis, false ) );
  97. m_params.emplace_back( new PARAM<bool>( "origin_invert_y_axis",
  98. &m_DisplayInvertYAxis, false ) );
  99. m_params.emplace_back( new PARAM_LAMBDA<int>( "editing.rotation_angle",
  100. [this] () -> int
  101. {
  102. return m_RotationAngle.AsTenthsOfADegree();
  103. },
  104. [this] ( int aVal )
  105. {
  106. if( aVal )
  107. m_RotationAngle = EDA_ANGLE( aVal, TENTHS_OF_A_DEGREE_T );
  108. },
  109. 900 ) );
  110. m_params.emplace_back( new PARAM<bool>( "editing.fp_use_45_degree_limit",
  111. &m_Use45Limit, false ) );
  112. m_params.emplace_back( new PARAM_LAYER_PRESET( "pcb_display.layer_presets", &m_LayerPresets ) );
  113. m_params.emplace_back( new PARAM<wxString>( "pcb_display.active_layer_preset",
  114. &m_ActiveLayerPreset, "" ) );
  115. m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>(
  116. "design_settings.default_footprint_text_items",
  117. [&] () -> nlohmann::json
  118. {
  119. nlohmann::json js = nlohmann::json::array();
  120. for( const TEXT_ITEM_INFO& item : m_DesignSettings.m_DefaultFPTextItems )
  121. {
  122. js.push_back( nlohmann::json( { item.m_Text.ToUTF8(),
  123. item.m_Visible,
  124. item.m_Layer } ) );
  125. }
  126. return js;
  127. },
  128. [&] ( const nlohmann::json& aObj )
  129. {
  130. m_DesignSettings.m_DefaultFPTextItems.clear();
  131. if( !aObj.is_array() )
  132. return;
  133. for( const nlohmann::json& entry : aObj )
  134. {
  135. if( entry.empty() || !entry.is_array() )
  136. continue;
  137. TEXT_ITEM_INFO textInfo( wxT( "" ), true, F_SilkS );
  138. textInfo.m_Text = entry.at(0).get<wxString>();
  139. textInfo.m_Visible = entry.at(1).get<bool>();
  140. textInfo.m_Layer = entry.at(2).get<int>();
  141. m_DesignSettings.m_DefaultFPTextItems.push_back( std::move( textInfo ) );
  142. }
  143. },
  144. nlohmann::json::array( {
  145. { "REF**", true, F_SilkS },
  146. { "", true, F_Fab },
  147. { "${REFERENCE}", true, F_Fab }
  148. } ) ) );
  149. int minTextSize = pcbIUScale.mmToIU( TEXT_MIN_SIZE_MM );
  150. int maxTextSize = pcbIUScale.mmToIU( TEXT_MAX_SIZE_MM );
  151. int minStroke = 1;
  152. int maxStroke = pcbIUScale.mmToIU( 100 );
  153. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_line_width",
  154. &m_DesignSettings.m_LineThickness[ LAYER_CLASS_SILK ],
  155. pcbIUScale.mmToIU( DEFAULT_SILK_LINE_WIDTH ), minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
  156. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_text_size_h",
  157. &m_DesignSettings.m_TextSize[ LAYER_CLASS_SILK ].x,
  158. pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_SIZE ), minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
  159. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_text_size_v",
  160. &m_DesignSettings.m_TextSize[ LAYER_CLASS_SILK ].y,
  161. pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_SIZE ), minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
  162. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_text_thickness",
  163. &m_DesignSettings.m_TextThickness[ LAYER_CLASS_SILK ],
  164. pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_WIDTH ), 1, maxTextSize, pcbIUScale.MM_PER_IU ) );
  165. m_params.emplace_back( new PARAM<bool>( "design_settings.silk_text_italic",
  166. &m_DesignSettings.m_TextItalic[ LAYER_CLASS_SILK ], false ) );
  167. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_line_width",
  168. &m_DesignSettings.m_LineThickness[ LAYER_CLASS_COPPER ],
  169. pcbIUScale.mmToIU( DEFAULT_COPPER_LINE_WIDTH ), minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
  170. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_text_size_h",
  171. &m_DesignSettings.m_TextSize[ LAYER_CLASS_COPPER ].x,
  172. pcbIUScale.mmToIU( DEFAULT_COPPER_TEXT_SIZE ), minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
  173. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_text_size_v",
  174. &m_DesignSettings.m_TextSize[ LAYER_CLASS_COPPER ].y,
  175. pcbIUScale.mmToIU( DEFAULT_COPPER_TEXT_SIZE ), minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
  176. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_text_thickness",
  177. &m_DesignSettings.m_TextThickness[ LAYER_CLASS_COPPER ],
  178. pcbIUScale.mmToIU( DEFAULT_COPPER_TEXT_WIDTH ), minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
  179. m_params.emplace_back( new PARAM<bool>( "design_settings.copper_text_italic",
  180. &m_DesignSettings.m_TextItalic[ LAYER_CLASS_COPPER ], false ) );
  181. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.edge_line_width",
  182. &m_DesignSettings.m_LineThickness[ LAYER_CLASS_EDGES ],
  183. pcbIUScale.mmToIU( DEFAULT_EDGE_WIDTH ), minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
  184. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.courtyard_line_width",
  185. &m_DesignSettings.m_LineThickness[ LAYER_CLASS_COURTYARD ],
  186. pcbIUScale.mmToIU( DEFAULT_COURTYARD_WIDTH ), minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
  187. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_line_width",
  188. &m_DesignSettings.m_LineThickness[ LAYER_CLASS_FAB ],
  189. pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ), minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
  190. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_text_size_h",
  191. &m_DesignSettings.m_TextSize[ LAYER_CLASS_FAB ].x,
  192. pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ), minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
  193. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_text_size_v",
  194. &m_DesignSettings.m_TextSize[ LAYER_CLASS_FAB ].y,
  195. pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ), minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
  196. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_text_thickness",
  197. &m_DesignSettings.m_TextThickness[ LAYER_CLASS_FAB ],
  198. pcbIUScale.mmToIU( DEFAULT_TEXT_WIDTH ), 1, maxTextSize, pcbIUScale.MM_PER_IU ) );
  199. m_params.emplace_back( new PARAM<bool>( "design_settings.fab_text_italic",
  200. &m_DesignSettings.m_TextItalic[ LAYER_CLASS_FAB ], false ) );
  201. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_line_width",
  202. &m_DesignSettings.m_LineThickness[ LAYER_CLASS_OTHERS ],
  203. pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ), minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
  204. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_text_size_h",
  205. &m_DesignSettings.m_TextSize[ LAYER_CLASS_OTHERS ].x,
  206. pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ), minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
  207. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_text_size_v",
  208. &m_DesignSettings.m_TextSize[ LAYER_CLASS_OTHERS ].y,
  209. pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ), minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
  210. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_text_thickness",
  211. &m_DesignSettings.m_TextThickness[ LAYER_CLASS_OTHERS ],
  212. pcbIUScale.mmToIU( DEFAULT_TEXT_WIDTH ), 1, maxTextSize, pcbIUScale.MM_PER_IU ) );
  213. m_params.emplace_back( new PARAM<bool>( "design_settings.others_text_italic",
  214. &m_DesignSettings.m_TextItalic[ LAYER_CLASS_OTHERS ], false ) );
  215. m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "editing.selection_filter",
  216. [&]() -> nlohmann::json
  217. {
  218. nlohmann::json ret;
  219. ret["lockedItems"] = m_SelectionFilter.lockedItems;
  220. ret["footprints"] = m_SelectionFilter.footprints;
  221. ret["text"] = m_SelectionFilter.text;
  222. ret["tracks"] = m_SelectionFilter.tracks;
  223. ret["vias"] = m_SelectionFilter.vias;
  224. ret["pads"] = m_SelectionFilter.pads;
  225. ret["graphics"] = m_SelectionFilter.graphics;
  226. ret["zones"] = m_SelectionFilter.zones;
  227. ret["keepouts"] = m_SelectionFilter.keepouts;
  228. ret["dimensions"] = m_SelectionFilter.dimensions;
  229. ret["otherItems"] = m_SelectionFilter.otherItems;
  230. return ret;
  231. },
  232. [&]( const nlohmann::json& aVal )
  233. {
  234. if( aVal.empty() || !aVal.is_object() )
  235. return;
  236. SetIfPresent( aVal, "lockedItems", m_SelectionFilter.lockedItems );
  237. SetIfPresent( aVal, "footprints", m_SelectionFilter.footprints );
  238. SetIfPresent( aVal, "text", m_SelectionFilter.text );
  239. SetIfPresent( aVal, "tracks", m_SelectionFilter.tracks );
  240. SetIfPresent( aVal, "vias", m_SelectionFilter.vias );
  241. SetIfPresent( aVal, "pads", m_SelectionFilter.pads );
  242. SetIfPresent( aVal, "graphics", m_SelectionFilter.graphics );
  243. SetIfPresent( aVal, "zones", m_SelectionFilter.zones );
  244. SetIfPresent( aVal, "keepouts", m_SelectionFilter.keepouts );
  245. SetIfPresent( aVal, "dimensions", m_SelectionFilter.dimensions );
  246. SetIfPresent( aVal, "otherItems", m_SelectionFilter.otherItems );
  247. },
  248. {
  249. { "lockedItems", false },
  250. { "footprints", true },
  251. { "text", true },
  252. { "tracks", true },
  253. { "vias", true },
  254. { "pads", true },
  255. { "graphics", true },
  256. { "zones", true },
  257. { "keepouts", true },
  258. { "dimensions", true },
  259. { "otherItems", true }
  260. } ) );
  261. registerMigration( 0, 1, std::bind( &FOOTPRINT_EDITOR_SETTINGS::migrateSchema0to1, this ) );
  262. registerMigration( 1, 2,
  263. [&]() -> bool
  264. {
  265. // This is actually a migration for APP_SETTINGS_BASE::m_LibTree
  266. return migrateLibTreeWidth();
  267. } );
  268. }
  269. bool FOOTPRINT_EDITOR_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
  270. {
  271. bool ret = APP_SETTINGS_BASE::MigrateFromLegacy( aCfg );
  272. //
  273. // NOTE: there's no value in line-wrapping these; it just makes the table unreadable.
  274. //
  275. ret &= fromLegacy<int>( aCfg, "ModeditLibWidth", "window.lib_width" );
  276. ret &= fromLegacyString( aCfg, "import_last_path", "system.last_import_export_path" );
  277. ret &= fromLegacyString( aCfg, "LibFootprintTextShownColumns", "window.footprint_text_shown_columns" );
  278. ret &= fromLegacy<int>( aCfg, "FpEditorMagneticPads", "editing.magnetic_pads" );
  279. ret &= fromLegacy<bool>( aCfg, "FpEditorDisplayPolarCoords", "editing.polar_coords" );
  280. ret &= fromLegacy<int>( aCfg, "FpEditorUse45DegreeGraphicSegments", "editing.use_45_degree_graphic_segments" );
  281. ret &= fromLegacy<bool>( aCfg, "FpEditorGraphicLinesDisplayMode", "pcb_display.graphic_items_fill" );
  282. ret &= fromLegacy<bool>( aCfg, "FpEditorPadDisplayMode", "pcb_display.pad_fill" );
  283. ret &= fromLegacy<bool>( aCfg, "FpEditorTextsDisplayMode", "pcb_display.footprint_text" );
  284. ret &= fromLegacy<double>( aCfg, "FpEditorSilkLineWidth", "design_settings.silk_line_width" );
  285. ret &= fromLegacy<double>( aCfg, "FpEditorSilkTextSizeH", "design_settings.silk_text_size_h" );
  286. ret &= fromLegacy<double>( aCfg, "FpEditorSilkTextSizeV", "design_settings.silk_text_size_v" );
  287. ret &= fromLegacy<double>( aCfg, "FpEditorSilkTextThickness", "design_settings.silk_text_thickness" );
  288. ret &= fromLegacy<bool>( aCfg, "FpEditorSilkTextItalic", "design_settings.silk_text_italic" );
  289. ret &= fromLegacy<double>( aCfg, "FpEditorCopperLineWidth", "design_settings.copper_line_width" );
  290. ret &= fromLegacy<double>( aCfg, "FpEditorCopperTextSizeH", "design_settings.copper_text_size_h" );
  291. ret &= fromLegacy<double>( aCfg, "FpEditorCopperTextSizeV", "design_settings.copper_text_size_v" );
  292. ret &= fromLegacy<double>( aCfg, "FpEditorCopperTextThickness", "design_settings.copper_text_thickness" );
  293. ret &= fromLegacy<bool>( aCfg, "FpEditorCopperTextItalic", "design_settings.copper_text_italic" );
  294. ret &= fromLegacy<double>( aCfg, "FpEditorEdgeCutLineWidth", "design_settings.edge_line_width" );
  295. ret &= fromLegacy<double>( aCfg, "FpEditorCourtyardLineWidth", "design_settings.courtyard_line_width" );
  296. ret &= fromLegacy<double>( aCfg, "FpEditorOthersLineWidth", "design_settings.others_line_width" );
  297. ret &= fromLegacy<double>( aCfg, "FpEditorOthersTextSizeH", "design_settings.others_text_size_h" );
  298. ret &= fromLegacy<double>( aCfg, "FpEditorOthersTextSizeV", "design_settings.others_text_size_v" );
  299. ret &= fromLegacy<double>( aCfg, "FpEditorOthersTextThickness", "design_settings.others_text_thickness" );
  300. ret &= fromLegacy<bool>( aCfg, "FpEditorOthersTextItalic", "design_settings.others_text_italic" );
  301. nlohmann::json textItems = nlohmann::json::array( {
  302. { "REF**", true, F_SilkS },
  303. { "", true, F_Fab }
  304. } );
  305. Set( "design_settings.default_footprint_text_items", std::move( textItems ) );
  306. ret &= fromLegacyString( aCfg, "FpEditorRefDefaultText", "design_settings.default_footprint_text_items.0.0" );
  307. ret &= fromLegacy<bool>( aCfg, "FpEditorRefDefaultVisibility", "design_settings.default_footprint_text_items.0.1" );
  308. ret &= fromLegacy<int>( aCfg, "FpEditorRefDefaultLayer", "design_settings.default_footprint_text_items.0.2" );
  309. ret &= fromLegacyString( aCfg, "FpEditorValueDefaultText", "design_settings.default_footprint_text_items.1.0" );
  310. ret &= fromLegacy<bool>( aCfg, "FpEditorValueDefaultVisibility", "design_settings.default_footprint_text_items.1.1" );
  311. ret &= fromLegacy<int>( aCfg, "FpEditorValueDefaultLayer", "design_settings.default_footprint_text_items.1.2" );
  312. std::string f = "ModEdit";
  313. // Migrate color settings that were stored in the pcbnew config file
  314. // We create a copy of the user scheme for the footprint editor context
  315. SETTINGS_MANAGER& manager = Pgm().GetSettingsManager();
  316. COLOR_SETTINGS* cs = manager.AddNewColorSettings( "user_footprints" );
  317. cs->SetName( wxT( "User (Footprints)" ) );
  318. manager.Save( cs );
  319. auto migrateLegacyColor = [&] ( const std::string& aKey, int aLayerId )
  320. {
  321. wxString str;
  322. if( aCfg->Read( aKey, &str ) )
  323. cs->SetColor( aLayerId, COLOR4D( str ) );
  324. };
  325. for( int i = 0; i < PCB_LAYER_ID_COUNT; ++i )
  326. {
  327. wxString layer = LSET::Name( PCB_LAYER_ID( i ) );
  328. migrateLegacyColor( f + "Color4DPCBLayer_" + layer.ToStdString(), PCB_LAYER_ID( i ) );
  329. }
  330. migrateLegacyColor( f + "Color4DAnchorEx", LAYER_ANCHOR );
  331. migrateLegacyColor( f + "Color4DAuxItems", LAYER_AUX_ITEMS );
  332. migrateLegacyColor( f + "Color4DGrid", LAYER_GRID );
  333. migrateLegacyColor( f + "Color4DNonPlatedEx", LAYER_NON_PLATEDHOLES );
  334. migrateLegacyColor( f + "Color4DPadThruHoleEx", LAYER_PADS_TH );
  335. migrateLegacyColor( f + "Color4DPCBBackground", LAYER_PCB_BACKGROUND );
  336. migrateLegacyColor( f + "Color4DPCBCursor", LAYER_CURSOR );
  337. migrateLegacyColor( f + "Color4DRatsEx", LAYER_RATSNEST );
  338. migrateLegacyColor( f + "Color4DTxtInvisEx", LAYER_HIDDEN_TEXT );
  339. migrateLegacyColor( f + "Color4DViaBBlindEx", LAYER_VIA_BBLIND );
  340. migrateLegacyColor( f + "Color4DViaMicroEx", LAYER_VIA_MICROVIA );
  341. migrateLegacyColor( f + "Color4DViaThruEx", LAYER_VIA_THROUGH );
  342. migrateLegacyColor( f + "Color4DWorksheet", LAYER_DRAWINGSHEET );
  343. manager.SaveColorSettings( cs, "board" );
  344. ( *m_internals )[m_internals->PointerFromString( "appearance.color_theme" )] = "user_footprints";
  345. double x = 0, y = 0;
  346. f = "ModEditFrame";
  347. if( aCfg->Read( f + "PcbUserGrid_X", &x ) && aCfg->Read( f + "PcbUserGrid_Y", &y ) )
  348. {
  349. EDA_UNITS u = static_cast<EDA_UNITS>( aCfg->ReadLong( f + "PcbUserGrid_Unit",
  350. static_cast<long>( EDA_UNITS::INCHES ) ) );
  351. // Convert to internal units
  352. x = EDA_UNIT_UTILS::UI::FromUserUnit( pcbIUScale, u, x );
  353. y = EDA_UNIT_UTILS::UI::FromUserUnit( pcbIUScale, u, y );
  354. Set( "window.grid.user_grid_x", EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, u, x ) );
  355. Set( "window.grid.user_grid_y", EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, u, y ) );
  356. }
  357. return ret;
  358. }
  359. bool FOOTPRINT_EDITOR_SETTINGS::migrateSchema0to1()
  360. {
  361. /**
  362. * Schema version 0 to 1:
  363. *
  364. * - Check to see if a footprints version of the currently selected theme exists.
  365. * - If so, select it
  366. */
  367. if( !m_manager )
  368. {
  369. wxLogTrace( traceSettings,
  370. wxT( "Error: FOOTPRINT_EDITOR_SETTINGS migration cannot run unmanaged!" ) );
  371. return false;
  372. }
  373. std::string theme_ptr( "appearance.color_theme" );
  374. if( !Contains( theme_ptr ) )
  375. return true;
  376. wxString selected = At( theme_ptr ).get<wxString>();
  377. wxString search = selected + wxT( "_footprints" );
  378. for( COLOR_SETTINGS* settings : Pgm().GetSettingsManager().GetColorSettingsList() )
  379. {
  380. if( settings->GetFilename() == search )
  381. {
  382. wxLogTrace( traceSettings, wxT( "Updating footprint editor theme from %s to %s" ),
  383. selected, search );
  384. Set( theme_ptr, search );
  385. return true;
  386. }
  387. }
  388. return true;
  389. }