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.

365 lines
12 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2020-2023 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 <sch_sheet_path.h>
  23. #include <schematic_settings.h>
  24. class BUS_ALIAS;
  25. class CONNECTION_GRAPH;
  26. class EDA_BASE_FRAME;
  27. class ERC_SETTINGS;
  28. class PROJECT;
  29. class SCH_SCREEN;
  30. class SCH_SHEET;
  31. class SCH_SHEET_LIST;
  32. class SCH_GLOBALLABEL;
  33. class SCHEMATIC_IFACE
  34. {
  35. public:
  36. SCHEMATIC_IFACE() {};
  37. virtual ~SCHEMATIC_IFACE() {};
  38. virtual CONNECTION_GRAPH* ConnectionGraph() const = 0;
  39. virtual SCH_SHEET_LIST GetSheets() const = 0;
  40. virtual void SetCurrentSheet( const SCH_SHEET_PATH& aPath ) = 0;
  41. virtual SCH_SHEET_PATH& CurrentSheet() const = 0;
  42. virtual wxString GetFileName() const = 0;
  43. virtual PROJECT& Prj() const = 0;
  44. };
  45. class SCHEMATIC;
  46. class SCHEMATIC_LISTENER
  47. {
  48. public:
  49. virtual ~SCHEMATIC_LISTENER() {}
  50. virtual void OnSchItemsAdded( SCHEMATIC& aSch, std::vector<SCH_ITEM*>& aSchItem ) {}
  51. virtual void OnSchItemsRemoved( SCHEMATIC& aSch, std::vector<SCH_ITEM*>& aSchItem ) {}
  52. virtual void OnSchItemsChanged( SCHEMATIC& aSch, std::vector<SCH_ITEM*>& aSchItem ) {}
  53. // This is called when the user changes to a new sheet, not when a sheet is altered.
  54. // Sheet alteration events will call OnSchItems*
  55. virtual void OnSchSheetChanged( SCHEMATIC& aSch ) {}
  56. };
  57. /**
  58. * Holds all the data relating to one schematic.
  59. *
  60. * A schematic may consist of one or more sheets (and one root sheet)
  61. * Right now, Eeschema can have only one schematic open at a time, but this could change.
  62. * Please keep this possibility in mind when adding to this object.
  63. */
  64. class SCHEMATIC : public SCHEMATIC_IFACE, public EDA_ITEM
  65. {
  66. public:
  67. SCHEMATIC( PROJECT* aPrj );
  68. virtual ~SCHEMATIC();
  69. virtual wxString GetClass() const override
  70. {
  71. return wxT( "SCHEMATIC" );
  72. }
  73. /// Initialize this schematic to a blank one, unloading anything existing.
  74. void Reset();
  75. /// Return a reference to the project this schematic is part of
  76. PROJECT& Prj() const override { return *m_project; }
  77. void SetProject( PROJECT* aPrj );
  78. const std::map<wxString, wxString>* GetProperties() { return &m_properties; }
  79. /**
  80. * Builds and returns an updated schematic hierarchy
  81. * TODO: can this be cached?
  82. * @return a SCH_SHEET_LIST containing the schematic hierarchy
  83. */
  84. SCH_SHEET_LIST GetSheets() const override
  85. {
  86. return SCH_SHEET_LIST( m_rootSheet );
  87. }
  88. SCH_SHEET_LIST GetUnorderedSheets() const
  89. {
  90. SCH_SHEET_LIST sheets;
  91. sheets.BuildSheetList( m_rootSheet, false );
  92. return sheets;
  93. }
  94. SCH_ITEM* GetItem( const KIID& aID, SCH_SHEET_PATH* aPathOut = nullptr ) const
  95. {
  96. return GetUnorderedSheets().GetItem( aID, aPathOut );
  97. }
  98. SCH_SHEET& Root() const
  99. {
  100. return *m_rootSheet;
  101. }
  102. /**
  103. * Initialize the schematic with a new root sheet.
  104. *
  105. * This is typically done by calling a file loader that returns the new root sheet
  106. * As a side-effect, takes care of some post-load initialization.
  107. *
  108. * @param aRootSheet is the new root sheet for this schematic.
  109. */
  110. void SetRoot( SCH_SHEET* aRootSheet );
  111. /// A simple test if the schematic is loaded, not a complete one
  112. bool IsValid() const
  113. {
  114. return m_rootSheet != nullptr;
  115. }
  116. /// Helper to retrieve the screen of the root sheet
  117. SCH_SCREEN* RootScreen() const;
  118. void GetContextualTextVars( wxArrayString* aVars ) const;
  119. bool ResolveTextVar( const SCH_SHEET_PATH* aSheetPath, wxString* token, int aDepth ) const;
  120. /// Helper to retrieve the filename from the root sheet screen
  121. wxString GetFileName() const override;
  122. SCH_SHEET_PATH& CurrentSheet() const override
  123. {
  124. return *m_currentSheet;
  125. }
  126. void SetCurrentSheet( const SCH_SHEET_PATH& aPath ) override
  127. {
  128. *m_currentSheet = aPath;
  129. }
  130. CONNECTION_GRAPH* ConnectionGraph() const override
  131. {
  132. return m_connectionGraph;
  133. }
  134. SCHEMATIC_SETTINGS& Settings() const;
  135. ERC_SETTINGS& ErcSettings() const;
  136. std::vector<SCH_MARKER*> ResolveERCExclusions();
  137. /**
  138. * Return a pointer to a bus alias object for the given label, or null if one
  139. * doesn't exist.
  140. */
  141. std::shared_ptr<BUS_ALIAS> GetBusAlias( const wxString& aLabel ) const;
  142. /**
  143. * Return the set of netname candidates for netclass assignment. The list will include both
  144. * composite names (buses) and atomic net names. Names are fetched from available labels,
  145. * power pins, etc.
  146. */
  147. std::set<wxString> GetNetClassAssignmentCandidates();
  148. /**
  149. * Resolves text vars that refer to other items.
  150. * Note that 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. * Return the full schematic flattened hierarchical sheet list.
  161. */
  162. SCH_SHEET_LIST& GetFullHierarchy() const;
  163. /**
  164. * Update the symbol value and footprint instance data for legacy designs.
  165. *
  166. * Prior to schematic file format version 20200828 and legacy file format version, only
  167. * symbol reference field and unit were saved in the instance data. The value and footprint
  168. * fields must be carried forward from the original symbol to prevent data loss.
  169. */
  170. void SetLegacySymbolInstanceData();
  171. /**
  172. * @return a filename that can be used in plot and print functions for the current screen
  173. * and sheet path. This filename is unique and must be used instead of the screen filename
  174. * when one must create files for each sheet in the hierarchy.
  175. * Name is &ltroot sheet filename&gt-&ltsheet path&gt and has no extension.
  176. * However if filename is too long name is &ltsheet filename&gt-&ltsheet number&gt
  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. Called after the simulation completes.
  199. */
  200. void SetOperatingPoint( const wxString& aSignal, double aValue )
  201. {
  202. m_operatingPoints[ aSignal ] = aValue;
  203. }
  204. wxString GetOperatingPoint( const wxString& aNetName, int aPrecision, const wxString& aRange );
  205. /**
  206. * Add junctions to this schematic where required. This function is needed for some plugins
  207. * (e.g. Legacy and Cadstar) in order to retain connectivity after loading.
  208. */
  209. void FixupJunctions();
  210. /**
  211. * Scan existing markers and record data from any that are Excluded.
  212. */
  213. void RecordERCExclusions();
  214. /**
  215. * Update markers to match recorded exclusions.
  216. */
  217. void ResolveERCExclusionsPostUpdate();
  218. /**
  219. * Must be used if Add() is used using a BULK_x ADD_MODE to generate a change event for
  220. * listeners.
  221. */
  222. void OnItemsAdded( std::vector<SCH_ITEM*>& aNewItems );
  223. /**
  224. * Must be used if Remove() is used using a BULK_x REMOVE_MODE to generate a change event
  225. * for listeners.
  226. */
  227. void OnItemsRemoved( std::vector<SCH_ITEM*>& aRemovedItems );
  228. /**
  229. * Notify the schematic and its listeners that an item on the schematic has
  230. * been modified in some way.
  231. */
  232. void OnItemsChanged( std::vector<SCH_ITEM*>& aItems );
  233. /**
  234. * Notify the schematic and its listeners that the current sheet has been changed.
  235. * This is called when the user navigates to a different sheet, not when the sheet is
  236. * altered.
  237. */
  238. void OnSchSheetChanged();
  239. /**
  240. * Add a listener to the schematic to receive calls whenever something on the
  241. * schematic has been modified. The schematic does not take ownership of the
  242. * listener object. Make sure to call RemoveListener before deleting the
  243. * listener object. The order of listener invocations is not guaranteed.
  244. * If the specified listener object has been added before, it will not be
  245. * added again.
  246. */
  247. void AddListener( SCHEMATIC_LISTENER* aListener );
  248. /**
  249. * Remove the specified listener. If it has not been added before, it
  250. * will do nothing.
  251. */
  252. void RemoveListener( SCHEMATIC_LISTENER* aListener );
  253. /**
  254. * Remove all listeners
  255. */
  256. void RemoveAllListeners();
  257. #if defined(DEBUG)
  258. void Show( int nestLevel, std::ostream& os ) const override {}
  259. #endif
  260. private:
  261. friend class SCH_EDIT_FRAME;
  262. template <typename Func, typename... Args>
  263. void InvokeListeners( Func&& aFunc, Args&&... args )
  264. {
  265. for( auto&& l : m_listeners )
  266. ( l->*aFunc )( std::forward<Args>( args )... );
  267. }
  268. PROJECT* m_project;
  269. /// The top-level sheet in this schematic hierarchy (or potentially the only one)
  270. SCH_SHEET* m_rootSheet;
  271. /**
  272. * The sheet path of the sheet currently being edited or displayed.
  273. * Note that this was moved here from SCH_EDIT_FRAME because currently many places in the code
  274. * want to know the current sheet. Potentially this can be moved back to the UI code once
  275. * the only places that want to know it are UI-related
  276. */
  277. SCH_SHEET_PATH* m_currentSheet;
  278. /// Holds and calculates connectivity information of this schematic
  279. CONNECTION_GRAPH* m_connectionGraph;
  280. /**
  281. * Holds a map of labels to the page sequence (virtual page number) that they appear on. It is
  282. * used for updating global label intersheet references.
  283. */
  284. std::map<wxString, std::set<int>> m_labelToPageRefsMap;
  285. /**
  286. * Properties for text variable substitution (and perhaps other uses in future).
  287. */
  288. std::map<wxString, wxString> m_properties;
  289. /**
  290. * Simulation operating points for text variable substitution.
  291. */
  292. std::map<wxString, double> m_operatingPoints;
  293. /**
  294. * Currently installed listeners
  295. */
  296. std::vector<SCHEMATIC_LISTENER*> m_listeners;
  297. };
  298. #endif