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.

1862 lines
51 KiB

7 years ago
Make the new schematic and symbol library file formats the default. This is a very large and potentially disruptive change so this will be an unusually long and detailed commit message. The new file formats are now the default in both the schematic and symbol library editors. Existing symbol libraries will be saved in their current format until new features are added to library symbols. Once this happens, both the legacy schematic and symbol file formats will be no longer be savable and existing libraries will have to be converted. Saving to the legacy file formats is still available for round robin testing and should not be used for normal editing. When loading the legacy schematic file, it is imperative that the schematic library symbols are rescued and/or remapped to valid library identifiers. Otherwise, there will be no way to link to the original library symbol and the user will be required manually set the library identifier. The cached symbol will be saved in the schematic file so the last library symbol in the cache will still be used but there will be no way to update it from the original library. The next save after loading a legacy schematic file will be converted to the s-expression file format. Schematics with hierarchical sheets will automatically have all sheet file name extensions changed to .kicad_sym and saved to the new format as well. Appending schematics requires that the schematic to append has already been converted to the new file format. This is required to ensure that library symbols are guaranteed to be valid for the appended schematic. The schematic symbol library symbol link resolution has been moved out of the SCH_COMPONENT object and move into the SCH_SCREEN object that owns the symbol. This was done to ensure that there is a single place where the library symbol links get resolved rather than the dozen or so different code paths that previously existed. It also removes the necessity of the SCH_COMPONENT object of requiring any knowledge of the symbol library table and/or the cache library. When opening an s-expression schematic, the legacy cache library is not loaded so any library symbols not rescued cannot be loaded. Broken library symbol links will have to be manually resolved by adding the cache library to the symbol library table and changing the links in the schematic symbol. Now that the library symbols are embedded in the schematic file, the SCH_SCREEN object maintains the list of library symbols for the schematic automatically. No external manipulation of this library cache should ever occur. ADDED: S-expression schematic and symbol library file formats.
6 years ago
Make the new schematic and symbol library file formats the default. This is a very large and potentially disruptive change so this will be an unusually long and detailed commit message. The new file formats are now the default in both the schematic and symbol library editors. Existing symbol libraries will be saved in their current format until new features are added to library symbols. Once this happens, both the legacy schematic and symbol file formats will be no longer be savable and existing libraries will have to be converted. Saving to the legacy file formats is still available for round robin testing and should not be used for normal editing. When loading the legacy schematic file, it is imperative that the schematic library symbols are rescued and/or remapped to valid library identifiers. Otherwise, there will be no way to link to the original library symbol and the user will be required manually set the library identifier. The cached symbol will be saved in the schematic file so the last library symbol in the cache will still be used but there will be no way to update it from the original library. The next save after loading a legacy schematic file will be converted to the s-expression file format. Schematics with hierarchical sheets will automatically have all sheet file name extensions changed to .kicad_sym and saved to the new format as well. Appending schematics requires that the schematic to append has already been converted to the new file format. This is required to ensure that library symbols are guaranteed to be valid for the appended schematic. The schematic symbol library symbol link resolution has been moved out of the SCH_COMPONENT object and move into the SCH_SCREEN object that owns the symbol. This was done to ensure that there is a single place where the library symbol links get resolved rather than the dozen or so different code paths that previously existed. It also removes the necessity of the SCH_COMPONENT object of requiring any knowledge of the symbol library table and/or the cache library. When opening an s-expression schematic, the legacy cache library is not loaded so any library symbols not rescued cannot be loaded. Broken library symbol links will have to be manually resolved by adding the cache library to the symbol library table and changing the links in the schematic symbol. Now that the library symbols are embedded in the schematic file, the SCH_SCREEN object maintains the list of library symbols for the schematic automatically. No external manipulation of this library cache should ever occur. ADDED: S-expression schematic and symbol library file formats.
6 years ago
Make the new schematic and symbol library file formats the default. This is a very large and potentially disruptive change so this will be an unusually long and detailed commit message. The new file formats are now the default in both the schematic and symbol library editors. Existing symbol libraries will be saved in their current format until new features are added to library symbols. Once this happens, both the legacy schematic and symbol file formats will be no longer be savable and existing libraries will have to be converted. Saving to the legacy file formats is still available for round robin testing and should not be used for normal editing. When loading the legacy schematic file, it is imperative that the schematic library symbols are rescued and/or remapped to valid library identifiers. Otherwise, there will be no way to link to the original library symbol and the user will be required manually set the library identifier. The cached symbol will be saved in the schematic file so the last library symbol in the cache will still be used but there will be no way to update it from the original library. The next save after loading a legacy schematic file will be converted to the s-expression file format. Schematics with hierarchical sheets will automatically have all sheet file name extensions changed to .kicad_sym and saved to the new format as well. Appending schematics requires that the schematic to append has already been converted to the new file format. This is required to ensure that library symbols are guaranteed to be valid for the appended schematic. The schematic symbol library symbol link resolution has been moved out of the SCH_COMPONENT object and move into the SCH_SCREEN object that owns the symbol. This was done to ensure that there is a single place where the library symbol links get resolved rather than the dozen or so different code paths that previously existed. It also removes the necessity of the SCH_COMPONENT object of requiring any knowledge of the symbol library table and/or the cache library. When opening an s-expression schematic, the legacy cache library is not loaded so any library symbols not rescued cannot be loaded. Broken library symbol links will have to be manually resolved by adding the cache library to the symbol library table and changing the links in the schematic symbol. Now that the library symbols are embedded in the schematic file, the SCH_SCREEN object maintains the list of library symbols for the schematic automatically. No external manipulation of this library cache should ever occur. ADDED: S-expression schematic and symbol library file formats.
6 years ago
Make the new schematic and symbol library file formats the default. This is a very large and potentially disruptive change so this will be an unusually long and detailed commit message. The new file formats are now the default in both the schematic and symbol library editors. Existing symbol libraries will be saved in their current format until new features are added to library symbols. Once this happens, both the legacy schematic and symbol file formats will be no longer be savable and existing libraries will have to be converted. Saving to the legacy file formats is still available for round robin testing and should not be used for normal editing. When loading the legacy schematic file, it is imperative that the schematic library symbols are rescued and/or remapped to valid library identifiers. Otherwise, there will be no way to link to the original library symbol and the user will be required manually set the library identifier. The cached symbol will be saved in the schematic file so the last library symbol in the cache will still be used but there will be no way to update it from the original library. The next save after loading a legacy schematic file will be converted to the s-expression file format. Schematics with hierarchical sheets will automatically have all sheet file name extensions changed to .kicad_sym and saved to the new format as well. Appending schematics requires that the schematic to append has already been converted to the new file format. This is required to ensure that library symbols are guaranteed to be valid for the appended schematic. The schematic symbol library symbol link resolution has been moved out of the SCH_COMPONENT object and move into the SCH_SCREEN object that owns the symbol. This was done to ensure that there is a single place where the library symbol links get resolved rather than the dozen or so different code paths that previously existed. It also removes the necessity of the SCH_COMPONENT object of requiring any knowledge of the symbol library table and/or the cache library. When opening an s-expression schematic, the legacy cache library is not loaded so any library symbols not rescued cannot be loaded. Broken library symbol links will have to be manually resolved by adding the cache library to the symbol library table and changing the links in the schematic symbol. Now that the library symbols are embedded in the schematic file, the SCH_SCREEN object maintains the list of library symbols for the schematic automatically. No external manipulation of this library cache should ever occur. ADDED: S-expression schematic and symbol library file formats.
6 years ago
Make the new schematic and symbol library file formats the default. This is a very large and potentially disruptive change so this will be an unusually long and detailed commit message. The new file formats are now the default in both the schematic and symbol library editors. Existing symbol libraries will be saved in their current format until new features are added to library symbols. Once this happens, both the legacy schematic and symbol file formats will be no longer be savable and existing libraries will have to be converted. Saving to the legacy file formats is still available for round robin testing and should not be used for normal editing. When loading the legacy schematic file, it is imperative that the schematic library symbols are rescued and/or remapped to valid library identifiers. Otherwise, there will be no way to link to the original library symbol and the user will be required manually set the library identifier. The cached symbol will be saved in the schematic file so the last library symbol in the cache will still be used but there will be no way to update it from the original library. The next save after loading a legacy schematic file will be converted to the s-expression file format. Schematics with hierarchical sheets will automatically have all sheet file name extensions changed to .kicad_sym and saved to the new format as well. Appending schematics requires that the schematic to append has already been converted to the new file format. This is required to ensure that library symbols are guaranteed to be valid for the appended schematic. The schematic symbol library symbol link resolution has been moved out of the SCH_COMPONENT object and move into the SCH_SCREEN object that owns the symbol. This was done to ensure that there is a single place where the library symbol links get resolved rather than the dozen or so different code paths that previously existed. It also removes the necessity of the SCH_COMPONENT object of requiring any knowledge of the symbol library table and/or the cache library. When opening an s-expression schematic, the legacy cache library is not loaded so any library symbols not rescued cannot be loaded. Broken library symbol links will have to be manually resolved by adding the cache library to the symbol library table and changing the links in the schematic symbol. Now that the library symbols are embedded in the schematic file, the SCH_SCREEN object maintains the list of library symbols for the schematic automatically. No external manipulation of this library cache should ever occur. ADDED: S-expression schematic and symbol library file formats.
6 years ago
Make the new schematic and symbol library file formats the default. This is a very large and potentially disruptive change so this will be an unusually long and detailed commit message. The new file formats are now the default in both the schematic and symbol library editors. Existing symbol libraries will be saved in their current format until new features are added to library symbols. Once this happens, both the legacy schematic and symbol file formats will be no longer be savable and existing libraries will have to be converted. Saving to the legacy file formats is still available for round robin testing and should not be used for normal editing. When loading the legacy schematic file, it is imperative that the schematic library symbols are rescued and/or remapped to valid library identifiers. Otherwise, there will be no way to link to the original library symbol and the user will be required manually set the library identifier. The cached symbol will be saved in the schematic file so the last library symbol in the cache will still be used but there will be no way to update it from the original library. The next save after loading a legacy schematic file will be converted to the s-expression file format. Schematics with hierarchical sheets will automatically have all sheet file name extensions changed to .kicad_sym and saved to the new format as well. Appending schematics requires that the schematic to append has already been converted to the new file format. This is required to ensure that library symbols are guaranteed to be valid for the appended schematic. The schematic symbol library symbol link resolution has been moved out of the SCH_COMPONENT object and move into the SCH_SCREEN object that owns the symbol. This was done to ensure that there is a single place where the library symbol links get resolved rather than the dozen or so different code paths that previously existed. It also removes the necessity of the SCH_COMPONENT object of requiring any knowledge of the symbol library table and/or the cache library. When opening an s-expression schematic, the legacy cache library is not loaded so any library symbols not rescued cannot be loaded. Broken library symbol links will have to be manually resolved by adding the cache library to the symbol library table and changing the links in the schematic symbol. Now that the library symbols are embedded in the schematic file, the SCH_SCREEN object maintains the list of library symbols for the schematic automatically. No external manipulation of this library cache should ever occur. ADDED: S-expression schematic and symbol library file formats.
6 years ago
Make the new schematic and symbol library file formats the default. This is a very large and potentially disruptive change so this will be an unusually long and detailed commit message. The new file formats are now the default in both the schematic and symbol library editors. Existing symbol libraries will be saved in their current format until new features are added to library symbols. Once this happens, both the legacy schematic and symbol file formats will be no longer be savable and existing libraries will have to be converted. Saving to the legacy file formats is still available for round robin testing and should not be used for normal editing. When loading the legacy schematic file, it is imperative that the schematic library symbols are rescued and/or remapped to valid library identifiers. Otherwise, there will be no way to link to the original library symbol and the user will be required manually set the library identifier. The cached symbol will be saved in the schematic file so the last library symbol in the cache will still be used but there will be no way to update it from the original library. The next save after loading a legacy schematic file will be converted to the s-expression file format. Schematics with hierarchical sheets will automatically have all sheet file name extensions changed to .kicad_sym and saved to the new format as well. Appending schematics requires that the schematic to append has already been converted to the new file format. This is required to ensure that library symbols are guaranteed to be valid for the appended schematic. The schematic symbol library symbol link resolution has been moved out of the SCH_COMPONENT object and move into the SCH_SCREEN object that owns the symbol. This was done to ensure that there is a single place where the library symbol links get resolved rather than the dozen or so different code paths that previously existed. It also removes the necessity of the SCH_COMPONENT object of requiring any knowledge of the symbol library table and/or the cache library. When opening an s-expression schematic, the legacy cache library is not loaded so any library symbols not rescued cannot be loaded. Broken library symbol links will have to be manually resolved by adding the cache library to the symbol library table and changing the links in the schematic symbol. Now that the library symbols are embedded in the schematic file, the SCH_SCREEN object maintains the list of library symbols for the schematic automatically. No external manipulation of this library cache should ever occur. ADDED: S-expression schematic and symbol library file formats.
6 years ago
Make the new schematic and symbol library file formats the default. This is a very large and potentially disruptive change so this will be an unusually long and detailed commit message. The new file formats are now the default in both the schematic and symbol library editors. Existing symbol libraries will be saved in their current format until new features are added to library symbols. Once this happens, both the legacy schematic and symbol file formats will be no longer be savable and existing libraries will have to be converted. Saving to the legacy file formats is still available for round robin testing and should not be used for normal editing. When loading the legacy schematic file, it is imperative that the schematic library symbols are rescued and/or remapped to valid library identifiers. Otherwise, there will be no way to link to the original library symbol and the user will be required manually set the library identifier. The cached symbol will be saved in the schematic file so the last library symbol in the cache will still be used but there will be no way to update it from the original library. The next save after loading a legacy schematic file will be converted to the s-expression file format. Schematics with hierarchical sheets will automatically have all sheet file name extensions changed to .kicad_sym and saved to the new format as well. Appending schematics requires that the schematic to append has already been converted to the new file format. This is required to ensure that library symbols are guaranteed to be valid for the appended schematic. The schematic symbol library symbol link resolution has been moved out of the SCH_COMPONENT object and move into the SCH_SCREEN object that owns the symbol. This was done to ensure that there is a single place where the library symbol links get resolved rather than the dozen or so different code paths that previously existed. It also removes the necessity of the SCH_COMPONENT object of requiring any knowledge of the symbol library table and/or the cache library. When opening an s-expression schematic, the legacy cache library is not loaded so any library symbols not rescued cannot be loaded. Broken library symbol links will have to be manually resolved by adding the cache library to the symbol library table and changing the links in the schematic symbol. Now that the library symbols are embedded in the schematic file, the SCH_SCREEN object maintains the list of library symbols for the schematic automatically. No external manipulation of this library cache should ever occur. ADDED: S-expression schematic and symbol library file formats.
6 years ago
18 years ago
18 years ago
18 years ago
18 years ago
7 years ago
7 years ago
5 years ago
7 years ago
7 years ago
18 years ago
18 years ago
18 years ago
18 years ago
Make the new schematic and symbol library file formats the default. This is a very large and potentially disruptive change so this will be an unusually long and detailed commit message. The new file formats are now the default in both the schematic and symbol library editors. Existing symbol libraries will be saved in their current format until new features are added to library symbols. Once this happens, both the legacy schematic and symbol file formats will be no longer be savable and existing libraries will have to be converted. Saving to the legacy file formats is still available for round robin testing and should not be used for normal editing. When loading the legacy schematic file, it is imperative that the schematic library symbols are rescued and/or remapped to valid library identifiers. Otherwise, there will be no way to link to the original library symbol and the user will be required manually set the library identifier. The cached symbol will be saved in the schematic file so the last library symbol in the cache will still be used but there will be no way to update it from the original library. The next save after loading a legacy schematic file will be converted to the s-expression file format. Schematics with hierarchical sheets will automatically have all sheet file name extensions changed to .kicad_sym and saved to the new format as well. Appending schematics requires that the schematic to append has already been converted to the new file format. This is required to ensure that library symbols are guaranteed to be valid for the appended schematic. The schematic symbol library symbol link resolution has been moved out of the SCH_COMPONENT object and move into the SCH_SCREEN object that owns the symbol. This was done to ensure that there is a single place where the library symbol links get resolved rather than the dozen or so different code paths that previously existed. It also removes the necessity of the SCH_COMPONENT object of requiring any knowledge of the symbol library table and/or the cache library. When opening an s-expression schematic, the legacy cache library is not loaded so any library symbols not rescued cannot be loaded. Broken library symbol links will have to be manually resolved by adding the cache library to the symbol library table and changing the links in the schematic symbol. Now that the library symbols are embedded in the schematic file, the SCH_SCREEN object maintains the list of library symbols for the schematic automatically. No external manipulation of this library cache should ever occur. ADDED: S-expression schematic and symbol library file formats.
6 years ago
Make the new schematic and symbol library file formats the default. This is a very large and potentially disruptive change so this will be an unusually long and detailed commit message. The new file formats are now the default in both the schematic and symbol library editors. Existing symbol libraries will be saved in their current format until new features are added to library symbols. Once this happens, both the legacy schematic and symbol file formats will be no longer be savable and existing libraries will have to be converted. Saving to the legacy file formats is still available for round robin testing and should not be used for normal editing. When loading the legacy schematic file, it is imperative that the schematic library symbols are rescued and/or remapped to valid library identifiers. Otherwise, there will be no way to link to the original library symbol and the user will be required manually set the library identifier. The cached symbol will be saved in the schematic file so the last library symbol in the cache will still be used but there will be no way to update it from the original library. The next save after loading a legacy schematic file will be converted to the s-expression file format. Schematics with hierarchical sheets will automatically have all sheet file name extensions changed to .kicad_sym and saved to the new format as well. Appending schematics requires that the schematic to append has already been converted to the new file format. This is required to ensure that library symbols are guaranteed to be valid for the appended schematic. The schematic symbol library symbol link resolution has been moved out of the SCH_COMPONENT object and move into the SCH_SCREEN object that owns the symbol. This was done to ensure that there is a single place where the library symbol links get resolved rather than the dozen or so different code paths that previously existed. It also removes the necessity of the SCH_COMPONENT object of requiring any knowledge of the symbol library table and/or the cache library. When opening an s-expression schematic, the legacy cache library is not loaded so any library symbols not rescued cannot be loaded. Broken library symbol links will have to be manually resolved by adding the cache library to the symbol library table and changing the links in the schematic symbol. Now that the library symbols are embedded in the schematic file, the SCH_SCREEN object maintains the list of library symbols for the schematic automatically. No external manipulation of this library cache should ever occur. ADDED: S-expression schematic and symbol library file formats.
6 years ago
18 years ago
18 years ago
Make the new schematic and symbol library file formats the default. This is a very large and potentially disruptive change so this will be an unusually long and detailed commit message. The new file formats are now the default in both the schematic and symbol library editors. Existing symbol libraries will be saved in their current format until new features are added to library symbols. Once this happens, both the legacy schematic and symbol file formats will be no longer be savable and existing libraries will have to be converted. Saving to the legacy file formats is still available for round robin testing and should not be used for normal editing. When loading the legacy schematic file, it is imperative that the schematic library symbols are rescued and/or remapped to valid library identifiers. Otherwise, there will be no way to link to the original library symbol and the user will be required manually set the library identifier. The cached symbol will be saved in the schematic file so the last library symbol in the cache will still be used but there will be no way to update it from the original library. The next save after loading a legacy schematic file will be converted to the s-expression file format. Schematics with hierarchical sheets will automatically have all sheet file name extensions changed to .kicad_sym and saved to the new format as well. Appending schematics requires that the schematic to append has already been converted to the new file format. This is required to ensure that library symbols are guaranteed to be valid for the appended schematic. The schematic symbol library symbol link resolution has been moved out of the SCH_COMPONENT object and move into the SCH_SCREEN object that owns the symbol. This was done to ensure that there is a single place where the library symbol links get resolved rather than the dozen or so different code paths that previously existed. It also removes the necessity of the SCH_COMPONENT object of requiring any knowledge of the symbol library table and/or the cache library. When opening an s-expression schematic, the legacy cache library is not loaded so any library symbols not rescued cannot be loaded. Broken library symbol links will have to be manually resolved by adding the cache library to the symbol library table and changing the links in the schematic symbol. Now that the library symbols are embedded in the schematic file, the SCH_SCREEN object maintains the list of library symbols for the schematic automatically. No external manipulation of this library cache should ever occur. ADDED: S-expression schematic and symbol library file formats.
6 years ago
Make the new schematic and symbol library file formats the default. This is a very large and potentially disruptive change so this will be an unusually long and detailed commit message. The new file formats are now the default in both the schematic and symbol library editors. Existing symbol libraries will be saved in their current format until new features are added to library symbols. Once this happens, both the legacy schematic and symbol file formats will be no longer be savable and existing libraries will have to be converted. Saving to the legacy file formats is still available for round robin testing and should not be used for normal editing. When loading the legacy schematic file, it is imperative that the schematic library symbols are rescued and/or remapped to valid library identifiers. Otherwise, there will be no way to link to the original library symbol and the user will be required manually set the library identifier. The cached symbol will be saved in the schematic file so the last library symbol in the cache will still be used but there will be no way to update it from the original library. The next save after loading a legacy schematic file will be converted to the s-expression file format. Schematics with hierarchical sheets will automatically have all sheet file name extensions changed to .kicad_sym and saved to the new format as well. Appending schematics requires that the schematic to append has already been converted to the new file format. This is required to ensure that library symbols are guaranteed to be valid for the appended schematic. The schematic symbol library symbol link resolution has been moved out of the SCH_COMPONENT object and move into the SCH_SCREEN object that owns the symbol. This was done to ensure that there is a single place where the library symbol links get resolved rather than the dozen or so different code paths that previously existed. It also removes the necessity of the SCH_COMPONENT object of requiring any knowledge of the symbol library table and/or the cache library. When opening an s-expression schematic, the legacy cache library is not loaded so any library symbols not rescued cannot be loaded. Broken library symbol links will have to be manually resolved by adding the cache library to the symbol library table and changing the links in the schematic symbol. Now that the library symbols are embedded in the schematic file, the SCH_SCREEN object maintains the list of library symbols for the schematic automatically. No external manipulation of this library cache should ever occur. ADDED: S-expression schematic and symbol library file formats.
6 years ago
Make the new schematic and symbol library file formats the default. This is a very large and potentially disruptive change so this will be an unusually long and detailed commit message. The new file formats are now the default in both the schematic and symbol library editors. Existing symbol libraries will be saved in their current format until new features are added to library symbols. Once this happens, both the legacy schematic and symbol file formats will be no longer be savable and existing libraries will have to be converted. Saving to the legacy file formats is still available for round robin testing and should not be used for normal editing. When loading the legacy schematic file, it is imperative that the schematic library symbols are rescued and/or remapped to valid library identifiers. Otherwise, there will be no way to link to the original library symbol and the user will be required manually set the library identifier. The cached symbol will be saved in the schematic file so the last library symbol in the cache will still be used but there will be no way to update it from the original library. The next save after loading a legacy schematic file will be converted to the s-expression file format. Schematics with hierarchical sheets will automatically have all sheet file name extensions changed to .kicad_sym and saved to the new format as well. Appending schematics requires that the schematic to append has already been converted to the new file format. This is required to ensure that library symbols are guaranteed to be valid for the appended schematic. The schematic symbol library symbol link resolution has been moved out of the SCH_COMPONENT object and move into the SCH_SCREEN object that owns the symbol. This was done to ensure that there is a single place where the library symbol links get resolved rather than the dozen or so different code paths that previously existed. It also removes the necessity of the SCH_COMPONENT object of requiring any knowledge of the symbol library table and/or the cache library. When opening an s-expression schematic, the legacy cache library is not loaded so any library symbols not rescued cannot be loaded. Broken library symbol links will have to be manually resolved by adding the cache library to the symbol library table and changing the links in the schematic symbol. Now that the library symbols are embedded in the schematic file, the SCH_SCREEN object maintains the list of library symbols for the schematic automatically. No external manipulation of this library cache should ever occur. ADDED: S-expression schematic and symbol library file formats.
6 years ago
Make the new schematic and symbol library file formats the default. This is a very large and potentially disruptive change so this will be an unusually long and detailed commit message. The new file formats are now the default in both the schematic and symbol library editors. Existing symbol libraries will be saved in their current format until new features are added to library symbols. Once this happens, both the legacy schematic and symbol file formats will be no longer be savable and existing libraries will have to be converted. Saving to the legacy file formats is still available for round robin testing and should not be used for normal editing. When loading the legacy schematic file, it is imperative that the schematic library symbols are rescued and/or remapped to valid library identifiers. Otherwise, there will be no way to link to the original library symbol and the user will be required manually set the library identifier. The cached symbol will be saved in the schematic file so the last library symbol in the cache will still be used but there will be no way to update it from the original library. The next save after loading a legacy schematic file will be converted to the s-expression file format. Schematics with hierarchical sheets will automatically have all sheet file name extensions changed to .kicad_sym and saved to the new format as well. Appending schematics requires that the schematic to append has already been converted to the new file format. This is required to ensure that library symbols are guaranteed to be valid for the appended schematic. The schematic symbol library symbol link resolution has been moved out of the SCH_COMPONENT object and move into the SCH_SCREEN object that owns the symbol. This was done to ensure that there is a single place where the library symbol links get resolved rather than the dozen or so different code paths that previously existed. It also removes the necessity of the SCH_COMPONENT object of requiring any knowledge of the symbol library table and/or the cache library. When opening an s-expression schematic, the legacy cache library is not loaded so any library symbols not rescued cannot be loaded. Broken library symbol links will have to be manually resolved by adding the cache library to the symbol library table and changing the links in the schematic symbol. Now that the library symbols are embedded in the schematic file, the SCH_SCREEN object maintains the list of library symbols for the schematic automatically. No external manipulation of this library cache should ever occur. ADDED: S-expression schematic and symbol library file formats.
6 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
  5. * Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, you may find one here:
  19. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  20. * or you may search the http://www.gnu.org website for the version 2 license,
  21. * or you may write to the Free Software Foundation, Inc.,
  22. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  23. */
  24. #include <sch_edit_frame.h>
  25. #include <widgets/msgpanel.h>
  26. #include <bitmaps.h>
  27. #include <core/mirror.h>
  28. #include <lib_rectangle.h>
  29. #include <lib_pin.h>
  30. #include <lib_text.h>
  31. #include <sch_component.h>
  32. #include <sch_sheet_path.h>
  33. #include <schematic.h>
  34. #include <trace_helpers.h>
  35. #include <trigo.h>
  36. /**
  37. * Convert a wxString to UTF8 and replace any control characters with a ~,
  38. * where a control character is one of the first ASCII values up to ' ' 32d.
  39. */
  40. std::string toUTFTildaText( const wxString& txt )
  41. {
  42. std::string ret = TO_UTF8( txt );
  43. for( std::string::iterator it = ret.begin(); it!=ret.end(); ++it )
  44. {
  45. if( (unsigned char) *it <= ' ' )
  46. *it = '~';
  47. }
  48. return ret;
  49. }
  50. /**
  51. * Used to draw a dummy shape when a LIB_PART is not found in library
  52. *
  53. * This component is a 400 mils square with the text ??
  54. * DEF DUMMY U 0 40 Y Y 1 0 N
  55. * F0 "U" 0 -350 60 H V
  56. * F1 "DUMMY" 0 350 60 H V
  57. * DRAW
  58. * T 0 0 0 150 0 0 0 ??
  59. * S -200 200 200 -200 0 1 0
  60. * ENDDRAW
  61. * ENDDEF
  62. */
  63. static LIB_PART* dummy()
  64. {
  65. static LIB_PART* part;
  66. if( !part )
  67. {
  68. part = new LIB_PART( wxEmptyString );
  69. LIB_RECTANGLE* square = new LIB_RECTANGLE( part );
  70. square->MoveTo( wxPoint( Mils2iu( -200 ), Mils2iu( 200 ) ) );
  71. square->SetEndPosition( wxPoint( Mils2iu( 200 ), Mils2iu( -200 ) ) );
  72. LIB_TEXT* text = new LIB_TEXT( part );
  73. text->SetTextSize( wxSize( Mils2iu( 150 ), Mils2iu( 150 ) ) );
  74. text->SetText( wxString( wxT( "??" ) ) );
  75. part->AddDrawItem( square );
  76. part->AddDrawItem( text );
  77. }
  78. return part;
  79. }
  80. SCH_COMPONENT::SCH_COMPONENT( const wxPoint& aPos, SCH_ITEM* aParent ) :
  81. SCH_ITEM( aParent, SCH_COMPONENT_T )
  82. {
  83. Init( aPos );
  84. }
  85. SCH_COMPONENT::SCH_COMPONENT( LIB_PART& aPart, LIB_ID aLibId, SCH_SHEET_PATH* sheet,
  86. int unit, int convert, const wxPoint& pos ) :
  87. SCH_ITEM( NULL, SCH_COMPONENT_T )
  88. {
  89. Init( pos );
  90. m_unit = unit;
  91. m_convert = convert;
  92. m_lib_id = aLibId;
  93. std::unique_ptr< LIB_PART > part;
  94. part = aPart.Flatten();
  95. part->SetParent();
  96. SetLibSymbol( part.release() );
  97. // Copy fields from the library component
  98. UpdateFields( true, true );
  99. // Update the reference -- just the prefix for now.
  100. if( sheet )
  101. SetRef( sheet, m_part->GetReferenceField().GetText() + wxT( "?" ) );
  102. else
  103. m_prefix = m_part->GetReferenceField().GetText() + wxT( "?" );
  104. // Inherit the include in bill of materials and board netlist settings from library symbol.
  105. m_inBom = aPart.GetIncludeInBom();
  106. m_onBoard = aPart.GetIncludeOnBoard();
  107. }
  108. SCH_COMPONENT::SCH_COMPONENT( LIB_PART& aPart, SCH_SHEET_PATH* aSheet, PICKED_SYMBOL& aSel,
  109. const wxPoint& pos ) :
  110. SCH_COMPONENT( aPart, aSel.LibId, aSheet, aSel.Unit, aSel.Convert, pos )
  111. {
  112. // Set any fields that were modified as part of the component selection
  113. for( auto const& i : aSel.Fields )
  114. {
  115. auto field = this->GetField( i.first );
  116. if( field )
  117. field->SetText( i.second );
  118. }
  119. }
  120. SCH_COMPONENT::SCH_COMPONENT( const SCH_COMPONENT& aComponent ) :
  121. SCH_ITEM( aComponent )
  122. {
  123. m_parent = aComponent.m_parent;
  124. m_pos = aComponent.m_pos;
  125. m_unit = aComponent.m_unit;
  126. m_convert = aComponent.m_convert;
  127. m_lib_id = aComponent.m_lib_id;
  128. m_isInNetlist = aComponent.m_isInNetlist;
  129. m_inBom = aComponent.m_inBom;
  130. m_onBoard = aComponent.m_onBoard;
  131. if( aComponent.m_part )
  132. SetLibSymbol( new LIB_PART( *aComponent.m_part.get() ) );
  133. const_cast<KIID&>( m_Uuid ) = aComponent.m_Uuid;
  134. m_transform = aComponent.m_transform;
  135. m_prefix = aComponent.m_prefix;
  136. m_instanceReferences = aComponent.m_instanceReferences;
  137. m_fields = aComponent.m_fields;
  138. // Re-parent the fields, which before this had aComponent as parent
  139. for( SCH_FIELD& field : m_fields )
  140. field.SetParent( this );
  141. m_fieldsAutoplaced = aComponent.m_fieldsAutoplaced;
  142. }
  143. void SCH_COMPONENT::Init( const wxPoint& pos )
  144. {
  145. m_pos = pos;
  146. m_unit = 1; // In multi unit chip - which unit to draw.
  147. m_convert = LIB_ITEM::LIB_CONVERT::BASE; // De Morgan Handling
  148. // The rotation/mirror transformation matrix. pos normal
  149. m_transform = TRANSFORM();
  150. // construct only the mandatory fields, which are the first 4 only.
  151. for( int i = 0; i < MANDATORY_FIELDS; ++i )
  152. {
  153. m_fields.emplace_back( pos, i, this, TEMPLATE_FIELDNAME::GetDefaultFieldName( i ) );
  154. if( i == REFERENCE_FIELD )
  155. m_fields.back().SetLayer( LAYER_REFERENCEPART );
  156. else if( i == VALUE_FIELD )
  157. m_fields.back().SetLayer( LAYER_VALUEPART );
  158. else
  159. m_fields.back().SetLayer( LAYER_FIELDS );
  160. }
  161. m_prefix = wxString( wxT( "U" ) );
  162. m_isInNetlist = true;
  163. m_inBom = true;
  164. m_onBoard = true;
  165. }
  166. EDA_ITEM* SCH_COMPONENT::Clone() const
  167. {
  168. return new SCH_COMPONENT( *this );
  169. }
  170. void SCH_COMPONENT::ViewGetLayers( int aLayers[], int& aCount ) const
  171. {
  172. aCount = 3;
  173. aLayers[0] = LAYER_DEVICE;
  174. aLayers[1] = LAYER_DEVICE_BACKGROUND;
  175. aLayers[2] = LAYER_SELECTION_SHADOWS;
  176. }
  177. void SCH_COMPONENT::SetLibId( const LIB_ID& aLibId )
  178. {
  179. if( m_lib_id != aLibId )
  180. {
  181. m_lib_id = aLibId;
  182. SetModified();
  183. }
  184. }
  185. wxString SCH_COMPONENT::GetSchSymbolLibraryName() const
  186. {
  187. if( !m_schLibSymbolName.IsEmpty() )
  188. return m_schLibSymbolName;
  189. else
  190. return m_lib_id.Format().wx_str();
  191. }
  192. void SCH_COMPONENT::SetLibSymbol( LIB_PART* aLibSymbol )
  193. {
  194. wxCHECK2( ( aLibSymbol == nullptr ) || ( aLibSymbol->IsRoot() ), aLibSymbol = nullptr );
  195. m_part.reset( aLibSymbol );
  196. UpdatePins();
  197. }
  198. wxString SCH_COMPONENT::GetDescription() const
  199. {
  200. if( m_part )
  201. return m_part->GetDescription();
  202. return wxEmptyString;
  203. }
  204. wxString SCH_COMPONENT::GetDatasheet() const
  205. {
  206. if( m_part )
  207. return m_part->GetDatasheetField().GetText();
  208. return wxEmptyString;
  209. }
  210. void SCH_COMPONENT::UpdatePins()
  211. {
  212. std::map<wxString, wxString> altPinMap;
  213. for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
  214. {
  215. if( !pin->GetAlt().IsEmpty() )
  216. altPinMap[ pin->GetNumber() ] = pin->GetAlt();
  217. }
  218. m_pins.clear();
  219. m_pinMap.clear();
  220. if( !m_part )
  221. return;
  222. unsigned i = 0;
  223. for( LIB_PIN* libPin = m_part->GetNextPin(); libPin; libPin = m_part->GetNextPin( libPin ) )
  224. {
  225. wxASSERT( libPin->Type() == LIB_PIN_T );
  226. if( libPin->GetConvert() && m_convert && ( m_convert != libPin->GetConvert() ) )
  227. continue;
  228. m_pins.push_back( std::make_unique<SCH_PIN>( libPin, this ) );
  229. auto ii = altPinMap.find( libPin->GetNumber() );
  230. if( ii != altPinMap.end() )
  231. m_pins.back()->SetAlt( ii->second );
  232. m_pinMap[ libPin ] = i;
  233. ++i;
  234. }
  235. }
  236. void SCH_COMPONENT::SetUnit( int aUnit )
  237. {
  238. if( m_unit != aUnit )
  239. {
  240. m_unit = aUnit;
  241. SetModified();
  242. }
  243. }
  244. void SCH_COMPONENT::UpdateUnit( int aUnit )
  245. {
  246. m_unit = aUnit;
  247. }
  248. void SCH_COMPONENT::SetConvert( int aConvert )
  249. {
  250. if( m_convert != aConvert )
  251. {
  252. m_convert = aConvert;
  253. // The convert may have a different pin layout so the update the pin map.
  254. UpdatePins();
  255. SetModified();
  256. }
  257. }
  258. void SCH_COMPONENT::SetTransform( const TRANSFORM& aTransform )
  259. {
  260. if( m_transform != aTransform )
  261. {
  262. m_transform = aTransform;
  263. SetModified();
  264. }
  265. }
  266. int SCH_COMPONENT::GetUnitCount() const
  267. {
  268. if( m_part )
  269. return m_part->GetUnitCount();
  270. return 0;
  271. }
  272. void SCH_COMPONENT::Print( RENDER_SETTINGS* aSettings, const wxPoint& aOffset )
  273. {
  274. PART_DRAW_OPTIONS opts;
  275. opts.transform = m_transform;
  276. opts.draw_visible_fields = false;
  277. opts.draw_hidden_fields = false;
  278. if( m_part )
  279. {
  280. m_part->Print( aSettings, m_pos + aOffset, m_unit, m_convert, opts );
  281. }
  282. else // Use dummy() part if the actual cannot be found.
  283. {
  284. dummy()->Print( aSettings, m_pos + aOffset, 0, 0, opts );
  285. }
  286. for( SCH_FIELD& field : m_fields )
  287. field.Print( aSettings, aOffset );
  288. }
  289. void SCH_COMPONENT::AddHierarchicalReference( const KIID_PATH& aPath, const wxString& aRef,
  290. int aUnit, const wxString& aValue,
  291. const wxString& aFootprint )
  292. {
  293. // Search for an existing path and remove it if found (should not occur)
  294. for( unsigned ii = 0; ii < m_instanceReferences.size(); ii++ )
  295. {
  296. if( m_instanceReferences[ii].m_Path == aPath )
  297. {
  298. wxLogTrace( traceSchSheetPaths, "Removing symbol instance:\n"
  299. " sheet path %s\n"
  300. " reference %s, unit %d from symbol %s.",
  301. aPath.AsString(),
  302. m_instanceReferences[ii].m_Reference,
  303. m_instanceReferences[ii].m_Unit,
  304. m_Uuid.AsString() );
  305. m_instanceReferences.erase( m_instanceReferences.begin() + ii );
  306. ii--;
  307. }
  308. }
  309. SYMBOL_INSTANCE_REFERENCE instance;
  310. instance.m_Path = aPath;
  311. instance.m_Reference = aRef;
  312. instance.m_Unit = aUnit;
  313. instance.m_Value = aValue;
  314. instance.m_Footprint = aFootprint;
  315. wxLogTrace( traceSchSheetPaths, "Adding symbol instance:\n"
  316. " sheet path %s\n"
  317. " reference %s, unit %d to symbol %s.",
  318. aPath.AsString(),
  319. aRef,
  320. aUnit,
  321. m_Uuid.AsString() );
  322. m_instanceReferences.push_back( instance );
  323. }
  324. const wxString SCH_COMPONENT::GetRef( const SCH_SHEET_PATH* sheet, bool aIncludeUnit ) const
  325. {
  326. KIID_PATH path = sheet->Path();
  327. wxString ref;
  328. for( const SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )
  329. {
  330. if( instance.m_Path == path )
  331. {
  332. ref = instance.m_Reference;
  333. break;
  334. }
  335. }
  336. // If it was not found in m_Paths array, then see if it is in m_Field[REFERENCE] -- if so,
  337. // use this as a default for this path. This will happen if we load a version 1 schematic
  338. // file. It will also mean that multiple instances of the same sheet by default all have
  339. // the same component references, but perhaps this is best.
  340. if( ref.IsEmpty() && !GetField( REFERENCE_FIELD )->GetText().IsEmpty() )
  341. {
  342. const_cast<SCH_COMPONENT*>( this )->SetRef( sheet, GetField( REFERENCE_FIELD )->GetText() );
  343. ref = GetField( REFERENCE_FIELD )->GetText();
  344. }
  345. if( ref.IsEmpty() )
  346. ref = m_prefix;
  347. if( aIncludeUnit && GetUnitCount() > 1 )
  348. ref += LIB_PART::SubReference( GetUnit() );
  349. return ref;
  350. }
  351. bool SCH_COMPONENT::IsReferenceStringValid( const wxString& aReferenceString )
  352. {
  353. wxString text = aReferenceString;
  354. bool ok = true;
  355. // Try to unannotate this reference
  356. while( !text.IsEmpty() && ( text.Last() == '?' || wxIsdigit( text.Last() ) ) )
  357. text.RemoveLast();
  358. if( text.IsEmpty() )
  359. ok = false;
  360. return ok;
  361. }
  362. void SCH_COMPONENT::SetRef( const SCH_SHEET_PATH* sheet, const wxString& ref )
  363. {
  364. KIID_PATH path = sheet->Path();
  365. bool notInArray = true;
  366. // check to see if it is already there before inserting it
  367. for( SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )
  368. {
  369. if( instance.m_Path == path )
  370. {
  371. instance.m_Reference = ref;
  372. notInArray = false;
  373. }
  374. }
  375. if( notInArray )
  376. AddHierarchicalReference( path, ref, m_unit );
  377. for( std::unique_ptr<SCH_PIN>& pin : m_pins )
  378. pin->ClearDefaultNetName( sheet );
  379. SCH_FIELD* rf = GetField( REFERENCE_FIELD );
  380. // @todo Should we really be checking for what is a "reasonable" position?
  381. if( rf->GetText().IsEmpty()
  382. || ( abs( rf->GetTextPos().x - m_pos.x ) +
  383. abs( rf->GetTextPos().y - m_pos.y ) > Mils2iu( 10000 ) ) )
  384. {
  385. // move it to a reasonable position
  386. rf->SetTextPos( m_pos + wxPoint( Mils2iu( 50 ), Mils2iu( 50 ) ) );
  387. }
  388. rf->SetText( ref ); // for drawing.
  389. // Reinit the m_prefix member if needed
  390. wxString prefix = ref;
  391. if( IsReferenceStringValid( prefix ) )
  392. {
  393. while( prefix.Last() == '?' || wxIsdigit( prefix.Last() ) )
  394. prefix.RemoveLast();
  395. }
  396. else
  397. {
  398. prefix = wxT( "U" ); // Set to default ref prefix
  399. }
  400. if( m_prefix != prefix )
  401. m_prefix = prefix;
  402. // Power components have references starting with # and are not included in netlists
  403. m_isInNetlist = ! ref.StartsWith( wxT( "#" ) );
  404. }
  405. bool SCH_COMPONENT::IsAnnotated( const SCH_SHEET_PATH* aSheet )
  406. {
  407. KIID_PATH path = aSheet->Path();
  408. for( const SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )
  409. {
  410. if( instance.m_Path == path )
  411. return instance.m_Reference.Last() != '?';
  412. }
  413. return false;
  414. }
  415. int SCH_COMPONENT::GetUnitSelection( const SCH_SHEET_PATH* aSheet ) const
  416. {
  417. KIID_PATH path = aSheet->Path();
  418. for( const SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )
  419. {
  420. if( instance.m_Path == path )
  421. return instance.m_Unit;
  422. }
  423. // If it was not found in m_Paths array, then use m_unit. This will happen if we load a
  424. // version 1 schematic file.
  425. return m_unit;
  426. }
  427. void SCH_COMPONENT::SetUnitSelection( const SCH_SHEET_PATH* aSheet, int aUnitSelection )
  428. {
  429. KIID_PATH path = aSheet->Path();
  430. // check to see if it is already there before inserting it
  431. for( SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )
  432. {
  433. if( instance.m_Path == path )
  434. {
  435. instance.m_Unit = aUnitSelection;
  436. return;
  437. }
  438. }
  439. // didn't find it; better add it
  440. AddHierarchicalReference( path, m_prefix, aUnitSelection );
  441. }
  442. const wxString SCH_COMPONENT::GetValue( const SCH_SHEET_PATH* sheet, bool aResolve ) const
  443. {
  444. KIID_PATH path = sheet->Path();
  445. for( const SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )
  446. {
  447. if( instance.m_Path == path && !instance.m_Value.IsEmpty() )
  448. {
  449. // This can only be an override from an Update Schematic from PCB, and therefore
  450. // will always be fully resolved.
  451. return instance.m_Value;
  452. }
  453. }
  454. if( !aResolve )
  455. return GetField( VALUE_FIELD )->GetText();
  456. return GetField( VALUE_FIELD )->GetShownText();
  457. }
  458. void SCH_COMPONENT::SetValue( const SCH_SHEET_PATH* sheet, const wxString& aValue )
  459. {
  460. if( sheet == nullptr )
  461. {
  462. // Clear instance overrides and set primary field value
  463. for( SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )
  464. instance.m_Value = wxEmptyString;
  465. m_fields[ VALUE_FIELD ].SetText( aValue );
  466. return;
  467. }
  468. KIID_PATH path = sheet->Path();
  469. // check to see if it is already there before inserting it
  470. for( SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )
  471. {
  472. if( instance.m_Path == path )
  473. {
  474. instance.m_Value = aValue;
  475. return;
  476. }
  477. }
  478. // didn't find it; better add it
  479. AddHierarchicalReference( path, m_prefix, m_unit, aValue, wxEmptyString );
  480. }
  481. const wxString SCH_COMPONENT::GetFootprint( const SCH_SHEET_PATH* sheet, bool aResolve ) const
  482. {
  483. KIID_PATH path = sheet->Path();
  484. for( const SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )
  485. {
  486. if( instance.m_Path == path && !instance.m_Footprint.IsEmpty() )
  487. {
  488. // This can only be an override from an Update Schematic from PCB, and therefore
  489. // will always be fully resolved.
  490. return instance.m_Footprint;
  491. }
  492. }
  493. if( !aResolve )
  494. return GetField( FOOTPRINT_FIELD )->GetText();
  495. return GetField( FOOTPRINT_FIELD )->GetShownText();
  496. }
  497. void SCH_COMPONENT::SetFootprint( const SCH_SHEET_PATH* sheet, const wxString& aFootprint )
  498. {
  499. if( sheet == nullptr )
  500. {
  501. // Clear instance overrides and set primary field value
  502. for( SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )
  503. instance.m_Footprint = wxEmptyString;
  504. m_fields[ FOOTPRINT_FIELD ].SetText( aFootprint );
  505. return;
  506. }
  507. KIID_PATH path = sheet->Path();
  508. // check to see if it is already there before inserting it
  509. for( SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )
  510. {
  511. if( instance.m_Path == path )
  512. {
  513. instance.m_Footprint = aFootprint;
  514. return;
  515. }
  516. }
  517. // didn't find it; better add it
  518. AddHierarchicalReference( path, m_prefix, m_unit, wxEmptyString, aFootprint );
  519. }
  520. SCH_FIELD* SCH_COMPONENT::GetField( int aFieldNdx )
  521. {
  522. if( (unsigned) aFieldNdx < m_fields.size() )
  523. return &m_fields[aFieldNdx];
  524. return nullptr;
  525. }
  526. const SCH_FIELD* SCH_COMPONENT::GetField( int aFieldNdx ) const
  527. {
  528. if( (unsigned) aFieldNdx < m_fields.size() )
  529. return &m_fields[aFieldNdx];
  530. return nullptr;
  531. }
  532. wxString SCH_COMPONENT::GetFieldText( const wxString& aFieldName, SCH_EDIT_FRAME* aFrame ) const
  533. {
  534. for( const SCH_FIELD& field : m_fields )
  535. {
  536. if( aFieldName == field.GetName() || aFieldName == field.GetCanonicalName() )
  537. return field.GetText();
  538. }
  539. return wxEmptyString;
  540. }
  541. void SCH_COMPONENT::GetFields( std::vector<SCH_FIELD*>& aVector, bool aVisibleOnly )
  542. {
  543. for( SCH_FIELD& field : m_fields )
  544. {
  545. if( !aVisibleOnly || ( field.IsVisible() && !field.IsVoid() ) )
  546. aVector.push_back( &field );
  547. }
  548. }
  549. SCH_FIELD* SCH_COMPONENT::AddField( const SCH_FIELD& aField )
  550. {
  551. int newNdx = m_fields.size();
  552. m_fields.push_back( aField );
  553. return &m_fields[newNdx];
  554. }
  555. void SCH_COMPONENT::RemoveField( const wxString& aFieldName )
  556. {
  557. for( unsigned i = MANDATORY_FIELDS; i < m_fields.size(); ++i )
  558. {
  559. if( aFieldName == m_fields[i].GetName( false ) )
  560. {
  561. m_fields.erase( m_fields.begin() + i );
  562. return;
  563. }
  564. }
  565. }
  566. SCH_FIELD* SCH_COMPONENT::FindField( const wxString& aFieldName, bool aIncludeDefaultFields )
  567. {
  568. unsigned start = aIncludeDefaultFields ? 0 : MANDATORY_FIELDS;
  569. for( unsigned i = start; i < m_fields.size(); ++i )
  570. {
  571. if( aFieldName == m_fields[i].GetName( false ) )
  572. return &m_fields[i];
  573. }
  574. return NULL;
  575. }
  576. void SCH_COMPONENT::UpdateFields( bool aResetStyle, bool aResetRef )
  577. {
  578. if( m_part )
  579. {
  580. wxString symbolName;
  581. std::vector<LIB_FIELD*> fields;
  582. m_part->GetFields( fields );
  583. for( const LIB_FIELD* libField : fields )
  584. {
  585. int idx = libField->GetId();
  586. SCH_FIELD* schField;
  587. if( idx == REFERENCE_FIELD && !aResetRef )
  588. continue;
  589. if( idx >= 0 && idx < MANDATORY_FIELDS )
  590. {
  591. schField = GetField( idx );
  592. }
  593. else
  594. {
  595. schField = FindField( libField->GetCanonicalName() );
  596. if( !schField )
  597. {
  598. wxString fieldName = libField->GetCanonicalName();
  599. SCH_FIELD newField( wxPoint( 0, 0), GetFieldCount(), this, fieldName );
  600. schField = AddField( newField );
  601. }
  602. }
  603. if( aResetStyle )
  604. {
  605. schField->ImportValues( *libField );
  606. schField->SetTextPos( m_pos + libField->GetTextPos() );
  607. }
  608. if( idx == VALUE_FIELD )
  609. {
  610. schField->SetText( m_lib_id.GetLibItemName() ); // fetch alias-specific value
  611. symbolName = m_lib_id.GetLibItemName();
  612. }
  613. else if( idx == DATASHEET_FIELD )
  614. {
  615. schField->SetText( GetDatasheet() ); // fetch alias-specific value
  616. }
  617. else
  618. {
  619. schField->SetText( libField->GetText() );
  620. }
  621. }
  622. }
  623. }
  624. void SCH_COMPONENT::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction )
  625. {
  626. for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
  627. aFunction( pin.get() );
  628. for( SCH_FIELD& field : m_fields )
  629. aFunction( &field );
  630. }
  631. SCH_PIN* SCH_COMPONENT::GetPin( const wxString& aNumber )
  632. {
  633. for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
  634. {
  635. if( pin->GetNumber() == aNumber )
  636. return pin.get();
  637. }
  638. return nullptr;
  639. }
  640. void SCH_COMPONENT::GetLibPins( std::vector<LIB_PIN*>& aPinsList )
  641. {
  642. if( m_part )
  643. m_part->GetPins( aPinsList, m_unit, m_convert );
  644. }
  645. SCH_PIN* SCH_COMPONENT::GetPin( LIB_PIN* aLibPin )
  646. {
  647. wxASSERT( m_pinMap.count( aLibPin ) );
  648. return m_pins[ m_pinMap.at( aLibPin ) ].get();
  649. }
  650. std::vector<SCH_PIN*> SCH_COMPONENT::GetPins( const SCH_SHEET_PATH* aSheet ) const
  651. {
  652. std::vector<SCH_PIN*> pins;
  653. if( aSheet == nullptr )
  654. {
  655. wxCHECK_MSG( Schematic(), pins, "Can't call GetPins on a component with no schematic" );
  656. aSheet = &Schematic()->CurrentSheet();
  657. }
  658. int unit = GetUnitSelection( aSheet );
  659. for( const auto& p : m_pins )
  660. {
  661. if( unit && p->GetLibPin()->GetUnit() && ( p->GetLibPin()->GetUnit() != unit ) )
  662. continue;
  663. pins.push_back( p.get() );
  664. }
  665. return pins;
  666. }
  667. void SCH_COMPONENT::SwapData( SCH_ITEM* aItem )
  668. {
  669. wxCHECK_RET( (aItem != NULL) && (aItem->Type() == SCH_COMPONENT_T),
  670. wxT( "Cannot swap data with invalid component." ) );
  671. SCH_COMPONENT* component = (SCH_COMPONENT*) aItem;
  672. std::swap( m_lib_id, component->m_lib_id );
  673. LIB_PART* part = component->m_part.release();
  674. component->m_part.reset( m_part.release() );
  675. component->UpdatePins();
  676. m_part.reset( part );
  677. UpdatePins();
  678. std::swap( m_pos, component->m_pos );
  679. std::swap( m_unit, component->m_unit );
  680. std::swap( m_convert, component->m_convert );
  681. m_fields.swap( component->m_fields ); // std::vector's swap()
  682. for( SCH_FIELD& field : component->m_fields )
  683. field.SetParent( component );
  684. for( SCH_FIELD& field : m_fields )
  685. field.SetParent( this );
  686. TRANSFORM tmp = m_transform;
  687. m_transform = component->m_transform;
  688. component->m_transform = tmp;
  689. std::swap( m_instanceReferences, component->m_instanceReferences );
  690. }
  691. void SCH_COMPONENT::GetContextualTextVars( wxArrayString* aVars ) const
  692. {
  693. for( int i = 0; i < MANDATORY_FIELDS; ++i )
  694. aVars->push_back( m_fields[i].GetCanonicalName().Upper() );
  695. for( size_t i = MANDATORY_FIELDS; i < m_fields.size(); ++i )
  696. aVars->push_back( m_fields[i].GetName() );
  697. aVars->push_back( wxT( "FOOTPRINT_LIBRARY" ) );
  698. aVars->push_back( wxT( "FOOTPRINT_NAME" ) );
  699. aVars->push_back( wxT( "UNIT" ) );
  700. }
  701. bool SCH_COMPONENT::ResolveTextVar( wxString* token, int aDepth ) const
  702. {
  703. SCHEMATIC* schematic = Schematic();
  704. for( int i = 0; i < MANDATORY_FIELDS; ++i )
  705. {
  706. if( token->IsSameAs( m_fields[ i ].GetCanonicalName().Upper() ) )
  707. {
  708. if( i == REFERENCE_FIELD && schematic )
  709. *token = GetRef( &schematic->CurrentSheet(), true );
  710. else if( i == VALUE_FIELD && schematic )
  711. *token = GetValue( &schematic->CurrentSheet(), true );
  712. else if( i == FOOTPRINT_FIELD && schematic )
  713. *token = GetFootprint( &schematic->CurrentSheet(), true );
  714. else
  715. *token = m_fields[ i ].GetShownText( aDepth + 1 );
  716. return true;
  717. }
  718. }
  719. for( size_t i = MANDATORY_FIELDS; i < m_fields.size(); ++i )
  720. {
  721. if( token->IsSameAs( m_fields[ i ].GetName() )
  722. || token->IsSameAs( m_fields[ i ].GetName().Upper() ) )
  723. {
  724. *token = m_fields[ i ].GetShownText( aDepth + 1 );
  725. return true;
  726. }
  727. }
  728. if( token->IsSameAs( wxT( "FOOTPRINT_LIBRARY" ) ) )
  729. {
  730. wxString footprint;
  731. if( schematic )
  732. footprint = GetFootprint( &schematic->CurrentSheet(), true );
  733. else
  734. footprint = m_fields[ FOOTPRINT_FIELD ].GetShownText();
  735. wxArrayString parts = wxSplit( footprint, ':' );
  736. *token = parts[ 0 ];
  737. return true;
  738. }
  739. else if( token->IsSameAs( wxT( "FOOTPRINT_NAME" ) ) )
  740. {
  741. wxString footprint;
  742. if( schematic )
  743. footprint = GetFootprint( &schematic->CurrentSheet(), true );
  744. else
  745. footprint = m_fields[ FOOTPRINT_FIELD ].GetShownText();
  746. wxArrayString parts = wxSplit( footprint, ':' );
  747. *token = parts[ std::min( 1, (int) parts.size() - 1 ) ];
  748. return true;
  749. }
  750. else if( token->IsSameAs( wxT( "UNIT" ) ) )
  751. {
  752. int unit;
  753. if( schematic )
  754. unit = GetUnitSelection( &schematic->CurrentSheet() );
  755. else
  756. unit = GetUnit();
  757. *token = LIB_PART::SubReference( unit );
  758. return true;
  759. }
  760. return false;
  761. }
  762. void SCH_COMPONENT::ClearAnnotation( const SCH_SHEET_PATH* aSheetPath )
  763. {
  764. // Build a reference with no annotation,
  765. // i.e. a reference ended by only one '?'
  766. wxString defRef = m_prefix;
  767. if( !IsReferenceStringValid( defRef ) )
  768. { // This is a malformed reference: reinit this reference
  769. m_prefix = defRef = wxT("U"); // Set to default ref prefix
  770. }
  771. while( defRef.Last() == '?' )
  772. defRef.RemoveLast();
  773. defRef.Append( wxT( "?" ) );
  774. if( aSheetPath )
  775. {
  776. KIID_PATH path = aSheetPath->Path();
  777. for( SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )
  778. {
  779. if( instance.m_Path == path )
  780. instance.m_Reference = defRef;
  781. }
  782. }
  783. else
  784. {
  785. for( SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )
  786. instance.m_Reference = defRef;
  787. }
  788. for( std::unique_ptr<SCH_PIN>& pin : m_pins )
  789. pin->ClearDefaultNetName( aSheetPath );
  790. // These 2 changes do not work in complex hierarchy.
  791. // When a clear annotation is made, the calling function must call a
  792. // UpdateAllScreenReferences for the active sheet.
  793. // But this call cannot made here.
  794. m_fields[REFERENCE_FIELD].SetText( defRef ); //for drawing.
  795. }
  796. bool SCH_COMPONENT::AddSheetPathReferenceEntryIfMissing( const KIID_PATH& aSheetPath )
  797. {
  798. // a empty sheet path is illegal:
  799. wxCHECK( aSheetPath.size() > 0, false );
  800. wxString reference_path;
  801. for( const SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )
  802. {
  803. // if aSheetPath is found, nothing to do:
  804. if( instance.m_Path == aSheetPath )
  805. return false;
  806. }
  807. // This entry does not exist: add it, with its last-used reference
  808. AddHierarchicalReference( aSheetPath, m_fields[REFERENCE_FIELD].GetText(), m_unit );
  809. return true;
  810. }
  811. bool SCH_COMPONENT::ReplaceInstanceSheetPath( const KIID_PATH& aOldSheetPath,
  812. const KIID_PATH& aNewSheetPath )
  813. {
  814. auto it = std::find_if( m_instanceReferences.begin(), m_instanceReferences.end(),
  815. [ aOldSheetPath ]( SYMBOL_INSTANCE_REFERENCE& r )->bool
  816. {
  817. return aOldSheetPath == r.m_Path;
  818. }
  819. );
  820. if( it != m_instanceReferences.end() )
  821. {
  822. wxLogTrace( traceSchSheetPaths,
  823. "Replacing sheet path %s\n with sheet path %s\n for symbol %s.",
  824. aOldSheetPath.AsString(), aNewSheetPath.AsString(), m_Uuid.AsString() );
  825. it->m_Path = aNewSheetPath;
  826. return true;
  827. }
  828. wxLogTrace( traceSchSheetPaths,
  829. "Could not find sheet path %s\n to replace with sheet path %s\n for symbol %s.",
  830. aOldSheetPath.AsString(), aNewSheetPath.AsString(), m_Uuid.AsString() );
  831. return false;
  832. }
  833. void SCH_COMPONENT::SetOrientation( int aOrientation )
  834. {
  835. TRANSFORM temp = TRANSFORM();
  836. bool transform = false;
  837. switch( aOrientation )
  838. {
  839. case CMP_ORIENT_0:
  840. case CMP_NORMAL: // default transform matrix
  841. m_transform.x1 = 1;
  842. m_transform.y2 = -1;
  843. m_transform.x2 = m_transform.y1 = 0;
  844. break;
  845. case CMP_ROTATE_COUNTERCLOCKWISE: // Rotate + (incremental rotation)
  846. temp.x1 = temp.y2 = 0;
  847. temp.y1 = 1;
  848. temp.x2 = -1;
  849. transform = true;
  850. break;
  851. case CMP_ROTATE_CLOCKWISE: // Rotate - (incremental rotation)
  852. temp.x1 = temp.y2 = 0;
  853. temp.y1 = -1;
  854. temp.x2 = 1;
  855. transform = true;
  856. break;
  857. case CMP_MIRROR_Y: // Mirror Y (incremental rotation)
  858. temp.x1 = -1;
  859. temp.y2 = 1;
  860. temp.y1 = temp.x2 = 0;
  861. transform = true;
  862. break;
  863. case CMP_MIRROR_X: // Mirror X (incremental rotation)
  864. temp.x1 = 1;
  865. temp.y2 = -1;
  866. temp.y1 = temp.x2 = 0;
  867. transform = true;
  868. break;
  869. case CMP_ORIENT_90:
  870. SetOrientation( CMP_ORIENT_0 );
  871. SetOrientation( CMP_ROTATE_COUNTERCLOCKWISE );
  872. break;
  873. case CMP_ORIENT_180:
  874. SetOrientation( CMP_ORIENT_0 );
  875. SetOrientation( CMP_ROTATE_COUNTERCLOCKWISE );
  876. SetOrientation( CMP_ROTATE_COUNTERCLOCKWISE );
  877. break;
  878. case CMP_ORIENT_270:
  879. SetOrientation( CMP_ORIENT_0 );
  880. SetOrientation( CMP_ROTATE_CLOCKWISE );
  881. break;
  882. case ( CMP_ORIENT_0 + CMP_MIRROR_X ):
  883. SetOrientation( CMP_ORIENT_0 );
  884. SetOrientation( CMP_MIRROR_X );
  885. break;
  886. case ( CMP_ORIENT_0 + CMP_MIRROR_Y ):
  887. SetOrientation( CMP_ORIENT_0 );
  888. SetOrientation( CMP_MIRROR_Y );
  889. break;
  890. case ( CMP_ORIENT_90 + CMP_MIRROR_X ):
  891. SetOrientation( CMP_ORIENT_90 );
  892. SetOrientation( CMP_MIRROR_X );
  893. break;
  894. case ( CMP_ORIENT_90 + CMP_MIRROR_Y ):
  895. SetOrientation( CMP_ORIENT_90 );
  896. SetOrientation( CMP_MIRROR_Y );
  897. break;
  898. case ( CMP_ORIENT_180 + CMP_MIRROR_X ):
  899. SetOrientation( CMP_ORIENT_180 );
  900. SetOrientation( CMP_MIRROR_X );
  901. break;
  902. case ( CMP_ORIENT_180 + CMP_MIRROR_Y ):
  903. SetOrientation( CMP_ORIENT_180 );
  904. SetOrientation( CMP_MIRROR_Y );
  905. break;
  906. case ( CMP_ORIENT_270 + CMP_MIRROR_X ):
  907. SetOrientation( CMP_ORIENT_270 );
  908. SetOrientation( CMP_MIRROR_X );
  909. break;
  910. case ( CMP_ORIENT_270 + CMP_MIRROR_Y ):
  911. SetOrientation( CMP_ORIENT_270 );
  912. SetOrientation( CMP_MIRROR_Y );
  913. break;
  914. default:
  915. transform = false;
  916. wxFAIL_MSG( "Invalid schematic symbol orientation type." );
  917. break;
  918. }
  919. if( transform )
  920. {
  921. /* The new matrix transform is the old matrix transform modified by the
  922. * requested transformation, which is the temp transform (rot,
  923. * mirror ..) in order to have (in term of matrix transform):
  924. * transform coord = new_m_transform * coord
  925. * where transform coord is the coord modified by new_m_transform from
  926. * the initial value coord.
  927. * new_m_transform is computed (from old_m_transform and temp) to
  928. * have:
  929. * transform coord = old_m_transform * temp
  930. */
  931. TRANSFORM newTransform;
  932. newTransform.x1 = m_transform.x1 * temp.x1 + m_transform.x2 * temp.y1;
  933. newTransform.y1 = m_transform.y1 * temp.x1 + m_transform.y2 * temp.y1;
  934. newTransform.x2 = m_transform.x1 * temp.x2 + m_transform.x2 * temp.y2;
  935. newTransform.y2 = m_transform.y1 * temp.x2 + m_transform.y2 * temp.y2;
  936. m_transform = newTransform;
  937. }
  938. }
  939. int SCH_COMPONENT::GetOrientation()
  940. {
  941. int rotate_values[] =
  942. {
  943. CMP_ORIENT_0,
  944. CMP_ORIENT_90,
  945. CMP_ORIENT_180,
  946. CMP_ORIENT_270,
  947. CMP_MIRROR_X + CMP_ORIENT_0,
  948. CMP_MIRROR_X + CMP_ORIENT_90,
  949. CMP_MIRROR_X + CMP_ORIENT_270,
  950. CMP_MIRROR_Y,
  951. CMP_MIRROR_Y + CMP_ORIENT_0,
  952. CMP_MIRROR_Y + CMP_ORIENT_90,
  953. CMP_MIRROR_Y + CMP_ORIENT_180,
  954. CMP_MIRROR_Y + CMP_ORIENT_270
  955. };
  956. // Try to find the current transform option:
  957. TRANSFORM transform = m_transform;
  958. for( int type_rotate : rotate_values )
  959. {
  960. SetOrientation( type_rotate );
  961. if( transform == m_transform )
  962. return type_rotate;
  963. }
  964. // Error: orientation not found in list (should not happen)
  965. wxFAIL_MSG( "Schematic symbol orientation matrix internal error." );
  966. m_transform = transform;
  967. return CMP_NORMAL;
  968. }
  969. #if defined(DEBUG)
  970. void SCH_COMPONENT::Show( int nestLevel, std::ostream& os ) const
  971. {
  972. // for now, make it look like XML:
  973. NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str()
  974. << " ref=\"" << TO_UTF8( GetField( 0 )->GetName() )
  975. << '"' << " chipName=\""
  976. << GetLibId().Format() << '"' << m_pos
  977. << " layer=\"" << m_layer
  978. << '"' << ">\n";
  979. // skip the reference, it's been output already.
  980. for( int i = 1; i < GetFieldCount(); ++i )
  981. {
  982. wxString value = GetField( i )->GetText();
  983. if( !value.IsEmpty() )
  984. {
  985. NestedSpace( nestLevel + 1, os ) << "<field" << " name=\""
  986. << TO_UTF8( GetField( i )->GetName() )
  987. << '"' << " value=\""
  988. << TO_UTF8( value ) << "\"/>\n";
  989. }
  990. }
  991. NestedSpace( nestLevel, os ) << "</" << TO_UTF8( GetClass().Lower() ) << ">\n";
  992. }
  993. #endif
  994. EDA_RECT SCH_COMPONENT::GetBodyBoundingBox() const
  995. {
  996. EDA_RECT bBox;
  997. if( m_part )
  998. bBox = m_part->GetBodyBoundingBox( m_unit, m_convert );
  999. else
  1000. bBox = dummy()->GetBodyBoundingBox( m_unit, m_convert );
  1001. int x0 = bBox.GetX();
  1002. int xm = bBox.GetRight();
  1003. // We must reverse Y values, because matrix orientation
  1004. // suppose Y axis normal for the library items coordinates,
  1005. // m_transform reverse Y values, but bBox is already reversed!
  1006. int y0 = -bBox.GetY();
  1007. int ym = -bBox.GetBottom();
  1008. // Compute the real Boundary box (rotated, mirrored ...)
  1009. int x1 = m_transform.x1 * x0 + m_transform.y1 * y0;
  1010. int y1 = m_transform.x2 * x0 + m_transform.y2 * y0;
  1011. int x2 = m_transform.x1 * xm + m_transform.y1 * ym;
  1012. int y2 = m_transform.x2 * xm + m_transform.y2 * ym;
  1013. bBox.SetX( x1 );
  1014. bBox.SetY( y1 );
  1015. bBox.SetWidth( x2 - x1 );
  1016. bBox.SetHeight( y2 - y1 );
  1017. bBox.Normalize();
  1018. bBox.Offset( m_pos );
  1019. return bBox;
  1020. }
  1021. const EDA_RECT SCH_COMPONENT::GetBoundingBox() const
  1022. {
  1023. EDA_RECT bbox = GetBodyBoundingBox();
  1024. for( const SCH_FIELD& field : m_fields )
  1025. bbox.Merge( field.GetBoundingBox() );
  1026. return bbox;
  1027. }
  1028. const EDA_RECT SCH_COMPONENT::GetBoundingBox( bool aIncludeInvisibleText ) const
  1029. {
  1030. EDA_RECT bbox = GetBodyBoundingBox();
  1031. for( const SCH_FIELD& field : m_fields )
  1032. {
  1033. if( field.IsVisible() || aIncludeInvisibleText )
  1034. bbox.Merge( field.GetBoundingBox() );
  1035. }
  1036. return bbox;
  1037. }
  1038. void SCH_COMPONENT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList )
  1039. {
  1040. wxString msg;
  1041. SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( aFrame );
  1042. SCH_SHEET_PATH* currentSheet = schframe ? &schframe->GetCurrentSheet() : nullptr;
  1043. // part and alias can differ if alias is not the root
  1044. if( m_part )
  1045. {
  1046. if( m_part.get() != dummy() )
  1047. {
  1048. aList.push_back( MSG_PANEL_ITEM( _( "Reference" ), GetRef( currentSheet ) ) );
  1049. msg = m_part->IsPower() ? _( "Power symbol" ) : _( "Value" );
  1050. aList.push_back( MSG_PANEL_ITEM( msg, GetValue( currentSheet, true ) ) );
  1051. #if 0 // Display component flags, for debug only
  1052. aList.push_back( MSG_PANEL_ITEM( _( "flags" ), wxString::Format( "%X",
  1053. GetEditFlags() ) ) );
  1054. #endif
  1055. // Display component reference in library and library
  1056. aList.push_back( MSG_PANEL_ITEM( _( "Name" ), GetLibId().GetLibItemName() ) );
  1057. if( !m_part->IsRoot() )
  1058. {
  1059. msg = _( "Missing parent" );
  1060. std::shared_ptr< LIB_PART > parent = m_part->GetParent().lock();
  1061. if( parent )
  1062. msg = parent->GetName();
  1063. aList.push_back( MSG_PANEL_ITEM( _( "Alias of" ), msg ) );
  1064. }
  1065. else if( !m_lib_id.GetLibNickname().empty() )
  1066. {
  1067. aList.push_back( MSG_PANEL_ITEM( _( "Library" ), m_lib_id.GetLibNickname() ) );
  1068. }
  1069. else
  1070. {
  1071. aList.push_back( MSG_PANEL_ITEM( _( "Library" ), _( "Undefined!!!" ) ) );
  1072. }
  1073. // Display the current associated footprint, if exists.
  1074. msg = GetFootprint( currentSheet, true );
  1075. if( msg.IsEmpty() )
  1076. msg = _( "<Unknown>" );
  1077. aList.push_back( MSG_PANEL_ITEM( _( "Footprint" ), msg ) );
  1078. // Display description of the component, and keywords found in lib
  1079. aList.push_back( MSG_PANEL_ITEM( _( "Description" ), m_part->GetDescription(),
  1080. DARKCYAN ) );
  1081. aList.push_back( MSG_PANEL_ITEM( _( "Keywords" ), m_part->GetKeyWords() ) );
  1082. }
  1083. }
  1084. else
  1085. {
  1086. aList.push_back( MSG_PANEL_ITEM( _( "Reference" ), GetRef( currentSheet ) ) );
  1087. aList.push_back( MSG_PANEL_ITEM( _( "Value" ), GetValue( currentSheet, true ) ) );
  1088. aList.push_back( MSG_PANEL_ITEM( _( "Name" ), GetLibId().GetLibItemName() ) );
  1089. wxString libNickname = GetLibId().GetLibNickname();
  1090. if( libNickname.empty() )
  1091. {
  1092. aList.push_back( MSG_PANEL_ITEM( _( "Library" ), _( "No library defined!" ) ) );
  1093. }
  1094. else
  1095. {
  1096. msg.Printf( _( "Symbol not found in %s!" ), libNickname );
  1097. aList.push_back( MSG_PANEL_ITEM( _( "Library" ), msg ) );
  1098. }
  1099. }
  1100. }
  1101. BITMAP_DEF SCH_COMPONENT::GetMenuImage() const
  1102. {
  1103. return add_component_xpm;
  1104. }
  1105. void SCH_COMPONENT::MirrorY( int aYaxis_position )
  1106. {
  1107. int dx = m_pos.x;
  1108. SetOrientation( CMP_MIRROR_Y );
  1109. MIRROR( m_pos.x, aYaxis_position );
  1110. dx -= m_pos.x; // dx,0 is the move vector for this transform
  1111. for( SCH_FIELD& field : m_fields )
  1112. {
  1113. // Move the fields to the new position because the component itself has moved.
  1114. wxPoint pos = field.GetTextPos();
  1115. pos.x -= dx;
  1116. field.SetTextPos( pos );
  1117. }
  1118. }
  1119. void SCH_COMPONENT::MirrorX( int aXaxis_position )
  1120. {
  1121. int dy = m_pos.y;
  1122. SetOrientation( CMP_MIRROR_X );
  1123. MIRROR( m_pos.y, aXaxis_position );
  1124. dy -= m_pos.y; // dy,0 is the move vector for this transform
  1125. for( SCH_FIELD& field : m_fields )
  1126. {
  1127. // Move the fields to the new position because the component itself has moved.
  1128. wxPoint pos = field.GetTextPos();
  1129. pos.y -= dy;
  1130. field.SetTextPos( pos );
  1131. }
  1132. }
  1133. void SCH_COMPONENT::Rotate( wxPoint aPosition )
  1134. {
  1135. wxPoint prev = m_pos;
  1136. RotatePoint( &m_pos, aPosition, 900 );
  1137. SetOrientation( CMP_ROTATE_COUNTERCLOCKWISE );
  1138. for( SCH_FIELD& field : m_fields )
  1139. {
  1140. // Move the fields to the new position because the component itself has moved.
  1141. wxPoint pos = field.GetTextPos();
  1142. pos.x -= prev.x - m_pos.x;
  1143. pos.y -= prev.y - m_pos.y;
  1144. field.SetTextPos( pos );
  1145. }
  1146. }
  1147. bool SCH_COMPONENT::Matches( wxFindReplaceData& aSearchData, void* aAuxData )
  1148. {
  1149. wxLogTrace( traceFindItem, wxT( " item " ) + GetSelectMenuText( EDA_UNITS::MILLIMETRES ) );
  1150. // Components are searchable via the child field and pin item text.
  1151. return false;
  1152. }
  1153. void SCH_COMPONENT::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
  1154. {
  1155. for( auto& pin : m_pins )
  1156. {
  1157. LIB_PIN* lib_pin = pin->GetLibPin();
  1158. if( lib_pin->GetUnit() && m_unit && ( m_unit != lib_pin->GetUnit() ) )
  1159. continue;
  1160. DANGLING_END_ITEM item( PIN_END, lib_pin, GetPinPhysicalPosition( lib_pin ), this );
  1161. aItemList.push_back( item );
  1162. }
  1163. }
  1164. bool SCH_COMPONENT::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
  1165. const SCH_SHEET_PATH* aPath )
  1166. {
  1167. bool changed = false;
  1168. for( std::unique_ptr<SCH_PIN>& pin : m_pins )
  1169. {
  1170. bool previousState = pin->IsDangling();
  1171. pin->SetIsDangling( true );
  1172. wxPoint pos = m_transform.TransformCoordinate( pin->GetLocalPosition() ) + m_pos;
  1173. for( DANGLING_END_ITEM& each_item : aItemList )
  1174. {
  1175. // Some people like to stack pins on top of each other in a symbol to indicate
  1176. // internal connection. While technically connected, it is not particularly useful
  1177. // to display them that way, so skip any pins that are in the same symbol as this
  1178. // one.
  1179. if( each_item.GetParent() == this )
  1180. continue;
  1181. switch( each_item.GetType() )
  1182. {
  1183. case PIN_END:
  1184. case LABEL_END:
  1185. case SHEET_LABEL_END:
  1186. case WIRE_START_END:
  1187. case WIRE_END_END:
  1188. case NO_CONNECT_END:
  1189. case JUNCTION_END:
  1190. if( pos == each_item.GetPosition() )
  1191. pin->SetIsDangling( false );
  1192. break;
  1193. default:
  1194. break;
  1195. }
  1196. if( !pin->IsDangling() )
  1197. break;
  1198. }
  1199. changed = ( changed || ( previousState != pin->IsDangling() ) );
  1200. }
  1201. return changed;
  1202. }
  1203. wxPoint SCH_COMPONENT::GetPinPhysicalPosition( const LIB_PIN* Pin ) const
  1204. {
  1205. wxCHECK_MSG( Pin != NULL && Pin->Type() == LIB_PIN_T, wxPoint( 0, 0 ),
  1206. wxT( "Cannot get physical position of pin." ) );
  1207. return m_transform.TransformCoordinate( Pin->GetPosition() ) + m_pos;
  1208. }
  1209. std::vector<wxPoint> SCH_COMPONENT::GetConnectionPoints() const
  1210. {
  1211. std::vector<wxPoint> retval;
  1212. for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
  1213. {
  1214. // Collect only pins attached to the current unit and convert.
  1215. // others are not associated to this component instance
  1216. int pin_unit = pin->GetLibPin()->GetUnit();
  1217. int pin_convert = pin->GetLibPin()->GetConvert();
  1218. if( pin_unit > 0 && pin_unit != GetUnit() )
  1219. continue;
  1220. if( pin_convert > 0 && pin_convert != GetConvert() )
  1221. continue;
  1222. retval.push_back( m_transform.TransformCoordinate( pin->GetLocalPosition() ) + m_pos );
  1223. }
  1224. return retval;
  1225. }
  1226. LIB_ITEM* SCH_COMPONENT::GetDrawItem( const wxPoint& aPosition, KICAD_T aType )
  1227. {
  1228. if( m_part )
  1229. {
  1230. // Calculate the position relative to the component.
  1231. wxPoint libPosition = aPosition - m_pos;
  1232. return m_part->LocateDrawItem( m_unit, m_convert, aType, libPosition, m_transform );
  1233. }
  1234. return NULL;
  1235. }
  1236. wxString SCH_COMPONENT::GetSelectMenuText( EDA_UNITS aUnits ) const
  1237. {
  1238. return wxString::Format( _( "Symbol %s [%s]" ),
  1239. GetField( REFERENCE_FIELD )->GetShownText(),
  1240. GetLibId().GetLibItemName().wx_str() );
  1241. }
  1242. SEARCH_RESULT SCH_COMPONENT::Visit( INSPECTOR aInspector, void* aTestData,
  1243. const KICAD_T aFilterTypes[] )
  1244. {
  1245. KICAD_T stype;
  1246. for( const KICAD_T* p = aFilterTypes; (stype = *p) != EOT; ++p )
  1247. {
  1248. if( stype == SCH_LOCATE_ANY_T
  1249. || ( stype == SCH_COMPONENT_T )
  1250. || ( stype == SCH_COMPONENT_LOCATE_POWER_T && m_part && m_part->IsPower() ) )
  1251. {
  1252. if( SEARCH_RESULT::QUIT == aInspector( this, aTestData ) )
  1253. return SEARCH_RESULT::QUIT;
  1254. }
  1255. if( stype == SCH_LOCATE_ANY_T || stype == SCH_FIELD_T )
  1256. {
  1257. for( SCH_FIELD& field : m_fields )
  1258. {
  1259. if( SEARCH_RESULT::QUIT == aInspector( &field, (void*) this ) )
  1260. return SEARCH_RESULT::QUIT;
  1261. }
  1262. }
  1263. if( stype == SCH_FIELD_LOCATE_REFERENCE_T )
  1264. {
  1265. if( SEARCH_RESULT::QUIT == aInspector( GetField( REFERENCE_FIELD ), (void*) this ) )
  1266. return SEARCH_RESULT::QUIT;
  1267. }
  1268. if( stype == SCH_FIELD_LOCATE_VALUE_T
  1269. || ( stype == SCH_COMPONENT_LOCATE_POWER_T && m_part && m_part->IsPower() ) )
  1270. {
  1271. if( SEARCH_RESULT::QUIT == aInspector( GetField( VALUE_FIELD ), (void*) this ) )
  1272. return SEARCH_RESULT::QUIT;
  1273. }
  1274. if( stype == SCH_FIELD_LOCATE_FOOTPRINT_T )
  1275. {
  1276. if( SEARCH_RESULT::QUIT == aInspector( GetField( FOOTPRINT_FIELD ), (void*) this ) )
  1277. return SEARCH_RESULT::QUIT;
  1278. }
  1279. if( stype == SCH_FIELD_LOCATE_DATASHEET_T )
  1280. {
  1281. if( SEARCH_RESULT::QUIT == aInspector( GetField( DATASHEET_FIELD ), (void*) this ) )
  1282. return SEARCH_RESULT::QUIT;
  1283. }
  1284. if( stype == SCH_LOCATE_ANY_T || stype == SCH_PIN_T )
  1285. {
  1286. for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
  1287. {
  1288. // Collect only pins attached to the current unit and convert.
  1289. // others are not associated to this component instance
  1290. int pin_unit = pin->GetLibPin()->GetUnit();
  1291. int pin_convert = pin->GetLibPin()->GetConvert();
  1292. if( pin_unit > 0 && pin_unit != GetUnit() )
  1293. continue;
  1294. if( pin_convert > 0 && pin_convert != GetConvert() )
  1295. continue;
  1296. if( SEARCH_RESULT::QUIT == aInspector( pin.get(), (void*) this ) )
  1297. return SEARCH_RESULT::QUIT;
  1298. }
  1299. }
  1300. }
  1301. return SEARCH_RESULT::CONTINUE;
  1302. }
  1303. bool SCH_COMPONENT::operator <( const SCH_ITEM& aItem ) const
  1304. {
  1305. if( Type() != aItem.Type() )
  1306. return Type() < aItem.Type();
  1307. auto component = static_cast<const SCH_COMPONENT*>( &aItem );
  1308. EDA_RECT rect = GetBodyBoundingBox();
  1309. if( rect.GetArea() != component->GetBodyBoundingBox().GetArea() )
  1310. return rect.GetArea() < component->GetBodyBoundingBox().GetArea();
  1311. if( m_pos.x != component->m_pos.x )
  1312. return m_pos.x < component->m_pos.x;
  1313. if( m_pos.y != component->m_pos.y )
  1314. return m_pos.y < component->m_pos.y;
  1315. return m_Uuid < aItem.m_Uuid; // Ensure deterministic sort
  1316. }
  1317. bool SCH_COMPONENT::operator==( const SCH_COMPONENT& aComponent ) const
  1318. {
  1319. if( GetFieldCount() != aComponent.GetFieldCount() )
  1320. return false;
  1321. for( int i = VALUE_FIELD; i < GetFieldCount(); i++ )
  1322. {
  1323. if( GetField( i )->GetText().Cmp( aComponent.GetField( i )->GetText() ) != 0 )
  1324. return false;
  1325. }
  1326. return true;
  1327. }
  1328. bool SCH_COMPONENT::operator!=( const SCH_COMPONENT& aComponent ) const
  1329. {
  1330. return !( *this == aComponent );
  1331. }
  1332. SCH_COMPONENT& SCH_COMPONENT::operator=( const SCH_ITEM& aItem )
  1333. {
  1334. wxCHECK_MSG( Type() == aItem.Type(), *this,
  1335. wxT( "Cannot assign object type " ) + aItem.GetClass() + wxT( " to type " ) +
  1336. GetClass() );
  1337. if( &aItem != this )
  1338. {
  1339. SCH_ITEM::operator=( aItem );
  1340. SCH_COMPONENT* c = (SCH_COMPONENT*) &aItem;
  1341. m_lib_id = c->m_lib_id;
  1342. LIB_PART* libSymbol = c->m_part ? new LIB_PART( *c->m_part.get() ) : nullptr;
  1343. m_part.reset( libSymbol );
  1344. m_pos = c->m_pos;
  1345. m_unit = c->m_unit;
  1346. m_convert = c->m_convert;
  1347. m_transform = c->m_transform;
  1348. m_instanceReferences = c->m_instanceReferences;
  1349. m_fields = c->m_fields; // std::vector's assignment operator
  1350. // Reparent fields after assignment to new component.
  1351. for( SCH_FIELD& field : m_fields )
  1352. field.SetParent( this );
  1353. UpdatePins();
  1354. }
  1355. return *this;
  1356. }
  1357. bool SCH_COMPONENT::HitTest( const wxPoint& aPosition, int aAccuracy ) const
  1358. {
  1359. EDA_RECT bBox = GetBodyBoundingBox();
  1360. bBox.Inflate( aAccuracy );
  1361. if( bBox.Contains( aPosition ) )
  1362. return true;
  1363. return false;
  1364. }
  1365. bool SCH_COMPONENT::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
  1366. {
  1367. if( m_flags & STRUCT_DELETED || m_flags & SKIP_STRUCT )
  1368. return false;
  1369. EDA_RECT rect = aRect;
  1370. rect.Inflate( aAccuracy );
  1371. if( aContained )
  1372. return rect.Contains( GetBodyBoundingBox() );
  1373. return rect.Intersects( GetBodyBoundingBox() );
  1374. }
  1375. bool SCH_COMPONENT::doIsConnected( const wxPoint& aPosition ) const
  1376. {
  1377. wxPoint new_pos = m_transform.InverseTransform().TransformCoordinate( aPosition - m_pos );
  1378. for( const auto& pin : m_pins )
  1379. {
  1380. if( pin->GetType() == ELECTRICAL_PINTYPE::PT_NC )
  1381. continue;
  1382. // Collect only pins attached to the current unit and convert.
  1383. // others are not associated to this component instance
  1384. int pin_unit = pin->GetLibPin()->GetUnit();
  1385. int pin_convert = pin->GetLibPin()->GetConvert();
  1386. if( pin_unit > 0 && pin_unit != GetUnit() )
  1387. continue;
  1388. if( pin_convert > 0 && pin_convert != GetConvert() )
  1389. continue;
  1390. if( pin->GetLocalPosition() == new_pos )
  1391. return true;
  1392. }
  1393. return false;
  1394. }
  1395. bool SCH_COMPONENT::IsInNetlist() const
  1396. {
  1397. return m_isInNetlist;
  1398. }
  1399. void SCH_COMPONENT::Plot( PLOTTER* aPlotter )
  1400. {
  1401. if( m_part )
  1402. {
  1403. TRANSFORM temp = GetTransform();
  1404. aPlotter->StartBlock( nullptr );
  1405. m_part->Plot( aPlotter, GetUnit(), GetConvert(), m_pos, temp );
  1406. for( SCH_FIELD field : m_fields )
  1407. field.Plot( aPlotter );
  1408. aPlotter->EndBlock( nullptr );
  1409. }
  1410. }
  1411. bool SCH_COMPONENT::HasBrightenedPins()
  1412. {
  1413. for( const auto& pin : m_pins )
  1414. {
  1415. if( pin->IsBrightened() )
  1416. return true;
  1417. }
  1418. return false;
  1419. }
  1420. void SCH_COMPONENT::ClearBrightenedPins()
  1421. {
  1422. for( auto& pin : m_pins )
  1423. pin->ClearBrightened();
  1424. }