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.

415 lines
12 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
  5. *
  6. * This program is free software: you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the
  8. * Free Software Foundation, either version 3 of the License, or (at your
  9. * option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifndef KICAD_SCHEMATIC_H
  20. #define KICAD_SCHEMATIC_H
  21. #include <eda_item.h>
  22. #include <embedded_files.h>
  23. #include <sch_sheet_path.h>
  24. #include <schematic_settings.h>
  25. #include <project.h>
  26. class BUS_ALIAS;
  27. class CONNECTION_GRAPH;
  28. class EDA_BASE_FRAME;
  29. class ERC_SETTINGS;
  30. class PROJECT;
  31. class SCH_SCREEN;
  32. class SCH_SHEET;
  33. class SCH_SHEET_LIST;
  34. class SCH_GLOBALLABEL;
  35. namespace KIFONT
  36. {
  37. class OUTLINE_FONT;
  38. }
  39. class SCHEMATIC;
  40. class SCHEMATIC_LISTENER
  41. {
  42. public:
  43. virtual ~SCHEMATIC_LISTENER() {}
  44. virtual void OnSchItemsAdded( SCHEMATIC& aSch, std::vector<SCH_ITEM*>& aSchItem ) {}
  45. virtual void OnSchItemsRemoved( SCHEMATIC& aSch, std::vector<SCH_ITEM*>& aSchItem ) {}
  46. virtual void OnSchItemsChanged( SCHEMATIC& aSch, std::vector<SCH_ITEM*>& aSchItem ) {}
  47. // This is called when the user changes to a new sheet, not when a sheet is altered.
  48. // Sheet alteration events will call OnSchItems*
  49. virtual void OnSchSheetChanged( SCHEMATIC& aSch ) {}
  50. };
  51. /**
  52. * Holds all the data relating to one schematic.
  53. *
  54. * A schematic may consist of one or more sheets (and one root sheet)
  55. * Right now, Eeschema can have only one schematic open at a time, but this could change.
  56. * Please keep this possibility in mind when adding to this object.
  57. */
  58. class SCHEMATIC : public EDA_ITEM, public EMBEDDED_FILES, public PROJECT::_ELEM
  59. {
  60. public:
  61. SCHEMATIC( PROJECT* aPrj );
  62. virtual ~SCHEMATIC();
  63. virtual wxString GetClass() const override
  64. {
  65. return wxT( "SCHEMATIC" );
  66. }
  67. /// Initialize this schematic to a blank one, unloading anything existing.
  68. void Reset();
  69. /// Return a reference to the project this schematic is part of
  70. PROJECT& Prj() const { return *m_project; }
  71. void SetProject( PROJECT* aPrj );
  72. const std::map<wxString, wxString>* GetProperties() { return &m_properties; }
  73. SCH_SHEET_LIST BuildSheetListSortedByPageNumbers() const
  74. {
  75. SCH_SHEET_LIST hierarchy( m_rootSheet );
  76. hierarchy.SortByPageNumbers();
  77. return hierarchy;
  78. }
  79. SCH_SHEET_LIST BuildUnorderedSheetList() const
  80. {
  81. SCH_SHEET_LIST sheets;
  82. sheets.BuildSheetList( m_rootSheet, false );
  83. return sheets;
  84. }
  85. /**
  86. * Return the full schematic flattened hierarchical sheet list.
  87. */
  88. SCH_SHEET_LIST Hierarchy() const;
  89. void RefreshHierarchy();
  90. SCH_ITEM* GetItem( const KIID& aID, SCH_SHEET_PATH* aPathOut = nullptr ) const
  91. {
  92. return BuildUnorderedSheetList().GetItem( aID, aPathOut );
  93. }
  94. SCH_SHEET& Root() const
  95. {
  96. return *m_rootSheet;
  97. }
  98. /**
  99. * Initialize the schematic with a new root sheet.
  100. *
  101. * This is typically done by calling a file loader that returns the new root sheet
  102. * As a side-effect, takes care of some post-load initialization.
  103. *
  104. * @param aRootSheet is the new root sheet for this schematic.
  105. */
  106. void SetRoot( SCH_SHEET* aRootSheet );
  107. /// A simple test if the schematic is loaded, not a complete one
  108. bool IsValid() const
  109. {
  110. return m_rootSheet != nullptr;
  111. }
  112. /// Helper to retrieve the screen of the root sheet
  113. SCH_SCREEN* RootScreen() const;
  114. void GetContextualTextVars( wxArrayString* aVars ) const;
  115. bool ResolveTextVar( const SCH_SHEET_PATH* aSheetPath, wxString* token, int aDepth ) const;
  116. /// Helper to retrieve the filename from the root sheet screen
  117. wxString GetFileName() const;
  118. SCH_SHEET_PATH& CurrentSheet() const
  119. {
  120. return *m_currentSheet;
  121. }
  122. void SetCurrentSheet( const SCH_SHEET_PATH& aPath )
  123. {
  124. *m_currentSheet = aPath;
  125. }
  126. CONNECTION_GRAPH* ConnectionGraph() const
  127. {
  128. return m_connectionGraph;
  129. }
  130. SCHEMATIC_SETTINGS& Settings() const;
  131. ERC_SETTINGS& ErcSettings() const;
  132. std::vector<SCH_MARKER*> ResolveERCExclusions();
  133. EMBEDDED_FILES* GetEmbeddedFiles() override;
  134. const EMBEDDED_FILES* GetEmbeddedFiles() const;
  135. /**
  136. * Return a pointer to a bus alias object for the given label, or null if one
  137. * doesn't exist.
  138. */
  139. std::shared_ptr<BUS_ALIAS> GetBusAlias( const wxString& aLabel ) const;
  140. /**
  141. * Return the set of netname candidates for netclass assignment.
  142. *
  143. * The list will include both composite names (buses) and atomic net names. Names are
  144. * fetched from available labels, power pins, etc.
  145. */
  146. std::set<wxString> GetNetClassAssignmentCandidates();
  147. /**
  148. * Resolves text vars that refer to other items.
  149. *
  150. * @note The actual resolve is delegated to the symbol/sheet in question. This routine
  151. * just does the look-up and delegation.
  152. */
  153. bool ResolveCrossReference( wxString* token, int aDepth ) const;
  154. std::map<wxString, std::set<int>>& GetPageRefsMap() { return m_labelToPageRefsMap; }
  155. std::map<int, wxString> GetVirtualPageToSheetNamesMap() const;
  156. std::map<int, wxString> GetVirtualPageToSheetPagesMap() const;
  157. wxString ConvertRefsToKIIDs( const wxString& aSource ) const;
  158. wxString ConvertKIIDsToRefs( const wxString& aSource ) const;
  159. /**
  160. * Update the symbol value and footprint instance data for legacy designs.
  161. *
  162. * Prior to schematic file format version 20200828 and legacy file format version, only
  163. * symbol reference field and unit were saved in the instance data. The value and footprint
  164. * fields must be carried forward from the original symbol to prevent data loss.
  165. */
  166. void SetLegacySymbolInstanceData();
  167. /**
  168. * Get the unique file name for the current sheet.
  169. *
  170. * This file name is unique and must be used instead of the screen file name when one must
  171. * create files for each sheet in the hierarchy. The name is
  172. * &ltroot sheet filename&gt-&ltsheet path&gt and has no extension.
  173. * If filename is too long name is &ltsheet filename&gt-&ltsheet number&gt
  174. *
  175. * @return a filename that can be used in plot and print functions for the current screen
  176. * and sheet path.
  177. */
  178. wxString GetUniqueFilenameForCurrentSheet();
  179. /**
  180. * Set the m_ScreenNumber and m_NumberOfScreens members for screens.
  181. *
  182. * @note This must be called after deleting or adding a sheet and when entering a sheet.
  183. */
  184. void SetSheetNumberAndCount();
  185. /**
  186. * Update the schematic's page reference map for all global labels, and refresh the labels
  187. * so that they are redrawn with up-to-date references.
  188. */
  189. void RecomputeIntersheetRefs( const std::function<void( SCH_GLOBALLABEL* )>& aItemCallback );
  190. /**
  191. * Clear operating points from a .op simulation.
  192. */
  193. void ClearOperatingPoints()
  194. {
  195. m_operatingPoints.clear();
  196. }
  197. /**
  198. * Set operating points from a .op simulation.
  199. *
  200. * Called after the simulation completes.
  201. */
  202. void SetOperatingPoint( const wxString& aSignal, double aValue )
  203. {
  204. m_operatingPoints[ aSignal ] = aValue;
  205. }
  206. wxString GetOperatingPoint( const wxString& aNetName, int aPrecision, const wxString& aRange );
  207. /**
  208. * Add junctions to this schematic where required.
  209. *
  210. * This function is needed for some plugins (e.g. Legacy and Cadstar) in order to retain
  211. * connectivity after loading.
  212. */
  213. void FixupJunctions();
  214. /**
  215. * Scan existing markers and record data from any that are Excluded.
  216. */
  217. void RecordERCExclusions();
  218. /**
  219. * Update markers to match recorded exclusions.
  220. */
  221. void ResolveERCExclusionsPostUpdate();
  222. /**
  223. * Must be used if Add() is used using a BULK_x ADD_MODE to generate a change event for
  224. * listeners.
  225. */
  226. void OnItemsAdded( std::vector<SCH_ITEM*>& aNewItems );
  227. /**
  228. * Must be used if Remove() is used using a BULK_x REMOVE_MODE to generate a change event
  229. * for listeners.
  230. */
  231. void OnItemsRemoved( std::vector<SCH_ITEM*>& aRemovedItems );
  232. /**
  233. * Notify the schematic and its listeners that an item on the schematic has
  234. * been modified in some way.
  235. */
  236. void OnItemsChanged( std::vector<SCH_ITEM*>& aItems );
  237. /**
  238. * Notify the schematic and its listeners that the current sheet has been changed.
  239. *
  240. * This is called when the user navigates to a different sheet, not when the sheet is
  241. * altered.
  242. */
  243. void OnSchSheetChanged();
  244. /**
  245. * Add a listener to the schematic to receive calls whenever something on the
  246. * schematic has been modified.
  247. *
  248. * The schematic does not take ownership of the listener object. Make sure to call
  249. * RemoveListener before deleting the listener object. The order of listener invocations
  250. * is not guaranteed. If the specified listener object has been added before, it will
  251. * not be added again.
  252. */
  253. void AddListener( SCHEMATIC_LISTENER* aListener );
  254. /**
  255. * Remove the specified listener.
  256. *
  257. * If it has not been added before, it will do nothing.
  258. */
  259. void RemoveListener( SCHEMATIC_LISTENER* aListener );
  260. /**
  261. * Remove all listeners.
  262. */
  263. void RemoveAllListeners();
  264. /**
  265. * Embed fonts in the schematic.
  266. */
  267. void EmbedFonts() override;
  268. /**
  269. * Get a set of fonts used in the schematic.
  270. */
  271. std::set<KIFONT::OUTLINE_FONT*> GetFonts() const override;
  272. /**
  273. * Return a list of schematic files in the current project that contain instance data for
  274. * multiple projects.
  275. *
  276. * @return all of the #SCH_SCREEN objects that contain instance data for multiple projects.
  277. */
  278. std::set<const SCH_SCREEN*> GetSchematicsSharedByMultipleProjects() const;
  279. /**
  280. * Test if the schematic is a complex hierarchy.
  281. *
  282. * @return true if the schematic is a complex hierarchy or false if it's a simple hierarchy.
  283. */
  284. bool IsComplexHierarchy() const;
  285. /**
  286. * True if a SCHEMATIC exists, false if not
  287. */
  288. static bool m_IsSchematicExists;
  289. #if defined(DEBUG)
  290. void Show( int nestLevel, std::ostream& os ) const override {}
  291. #endif
  292. PROJECT::ELEM ProjectElementType() override { return PROJECT::ELEM::SCHEMATIC; }
  293. private:
  294. friend class SCH_EDIT_FRAME;
  295. template <typename Func, typename... Args>
  296. void InvokeListeners( Func&& aFunc, Args&&... args )
  297. {
  298. for( auto&& l : m_listeners )
  299. ( l->*aFunc )( std::forward<Args>( args )... );
  300. }
  301. PROJECT* m_project;
  302. /// The top-level sheet in this schematic hierarchy (or potentially the only one)
  303. SCH_SHEET* m_rootSheet;
  304. /**
  305. * The sheet path of the sheet currently being edited or displayed.
  306. *
  307. * @note This was moved here from #SCH_EDIT_FRAME because currently many places in the code
  308. * want to know the current sheet. Potentially this can be moved back to the UI code once
  309. * the only places that want to know it are UI-related.
  310. */
  311. SCH_SHEET_PATH* m_currentSheet;
  312. /// Hold and calculate connectivity information of this schematic.
  313. CONNECTION_GRAPH* m_connectionGraph;
  314. /**
  315. * Holds a map of labels to the page sequence (virtual page number) that they appear on.
  316. *
  317. * It is used for updating global label intersheet references.
  318. */
  319. std::map<wxString, std::set<int>> m_labelToPageRefsMap;
  320. /**
  321. * Properties for text variable substitution (and perhaps other uses in future).
  322. */
  323. std::map<wxString, wxString> m_properties;
  324. /**
  325. * Simulation operating points for text variable substitution.
  326. */
  327. std::map<wxString, double> m_operatingPoints;
  328. /**
  329. * Cache of the entire schematic hierarchy sorted by sheet page number.
  330. */
  331. SCH_SHEET_LIST m_hierarchy;
  332. /**
  333. * Currently installed listeners.
  334. */
  335. std::vector<SCHEMATIC_LISTENER*> m_listeners;
  336. };
  337. #endif