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.

542 lines
20 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
  5. * Copyright (C) 2011 Wayne Stambaugh <stambaughw@gmail.com>
  6. * Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, you may find one here:
  20. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  21. * or you may search the http://www.gnu.org website for the version 2 license,
  22. * or you may write to the Free Software Foundation, Inc.,
  23. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  24. */
  25. /**
  26. * @file sch_sheet_path.h
  27. * @brief Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
  28. */
  29. #ifndef CLASS_DRAWSHEET_PATH_H
  30. #define CLASS_DRAWSHEET_PATH_H
  31. #include <base_struct.h>
  32. #include <map>
  33. /** Info about complex hierarchies handling:
  34. * A hierarchical schematic uses sheets (hierarchical sheets) included in a
  35. * given sheet. Each sheet corresponds to a schematic drawing handled by a
  36. * SCH_SCREEN structure. A SCH_SCREEN structure contains drawings, and have
  37. * a filename to write it's data. Also a SCH_SCREEN display a sheet number
  38. * and the name of the sheet.
  39. *
  40. * In simple (and flat) hierarchies a sheet is linked to a SCH_SCREEN,
  41. * and a SCH_SCREEN is used by only one hierarchical sheet.
  42. *
  43. * In complex hierarchies the same SCH_SCREEN (and its data) is shared between
  44. * more than one sheet. Therefore subsheets (like subsheets in a SCH_SCREEN
  45. * shared by many sheets) can be also shared. So the same SCH_SCREEN must
  46. * handle different components references and parts selection depending on
  47. * which sheet is currently selected, and how a given subsheet is selected.
  48. * 2 sheets share the same SCH_SCREEN (the same drawings) if they have the
  49. * same filename.
  50. *
  51. * In KiCad each component and sheet receives (when created) an unique
  52. * identification called Time Stamp. So each sheet has 2 ids: its time stamp
  53. * (that cannot change) and its name ( that can be edited and therefore is
  54. * not reliable for strong identification). KiCad uses Time Stamp ( a unique
  55. * 32 bit id), to identify sheets in hierarchies.
  56. * A given sheet in a hierarchy is fully labeled by its path (or sheet path)
  57. * that is the list of time stamp found to access it through the hierarchy
  58. * the root sheet is /. All other sheets have a path like /1234ABCD or
  59. * /4567FEDC/AA2233DD/. This path can be displayed as human readable sheet
  60. * name like: / or /sheet1/include_sheet/ or /sheet2/include_sheet/
  61. *
  62. * So to know for a given SCH_SCREEN (a given schematic drawings) we must:
  63. * 1) Handle all references possibilities.
  64. * 2) When acceded by a given selected sheet, display (update) the
  65. * corresponding references and sheet path
  66. *
  67. * The class SCH_SHEET_PATH handles paths used to access a sheet. The class
  68. * SCH_SHEET_LIST allows one to handle the full (or partial) list of sheets and
  69. * their paths in a complex hierarchy. The class EDA_ScreenList allows one
  70. * to handle the list of SCH_SCREEN. It is useful to clear or save data,
  71. * but is not suitable to handle the full complex hierarchy possibilities
  72. * (usable in flat and simple hierarchies).
  73. */
  74. class wxFindReplaceData;
  75. class SCH_SHEET;
  76. class SCH_SCREEN;
  77. class SCH_MARKER;
  78. class SCH_ITEM;
  79. class SCH_REFERENCE_LIST;
  80. #define SHEET_NOT_FOUND -1
  81. /**
  82. * Type SCH_MULTI_UNIT_REFERENCE_MAP
  83. * is used to create a map of reference designators for multi-unit parts.
  84. */
  85. typedef std::map<wxString, SCH_REFERENCE_LIST> SCH_MULTI_UNIT_REFERENCE_MAP;
  86. /**
  87. * Class SCH_SHEET_PATH
  88. *
  89. * handles access to a stack of flattened #SCH_SHEET objects by way of a path for
  90. * creating a flattened schematic hierarchy.
  91. *
  92. * <p>
  93. * The #SCH_SHEET objects are stored in a list from first (usually the root sheet) to a
  94. * given sheet in last position. The _last_ sheet is usually the sheet we want to select
  95. * or reach (which is what the function Last() returns). Others sheets constitute the
  96. * "path" from the first to the last sheet.
  97. * </p>
  98. */
  99. class SCH_SHEET_PATH
  100. {
  101. protected:
  102. std::vector< SCH_SHEET* > m_sheets;
  103. size_t m_current_hash;
  104. int m_pageNumber; /// Page numbers are maintained by the sheet load order.
  105. public:
  106. SCH_SHEET_PATH();
  107. /// Forwarded method from std::vector
  108. SCH_SHEET* at( size_t aIndex ) const { return m_sheets.at( aIndex ); }
  109. /// Forwarded method from std::vector
  110. void clear()
  111. {
  112. m_sheets.clear();
  113. Rehash();
  114. }
  115. /// Forwarded method from std::vector
  116. bool empty() const { return m_sheets.empty(); }
  117. /// Forwarded method from std::vector
  118. void pop_back()
  119. {
  120. m_sheets.pop_back();
  121. Rehash();
  122. }
  123. /// Forwarded method from std::vector
  124. void push_back( SCH_SHEET* aSheet )
  125. {
  126. m_sheets.push_back( aSheet );
  127. Rehash();
  128. }
  129. /// Forwarded method from std::vector
  130. size_t size() const { return m_sheets.size(); }
  131. void Rehash();
  132. size_t GetCurrentHash() const { return m_current_hash; }
  133. void SetPageNumber( int aPageNumber ) { m_pageNumber = aPageNumber; }
  134. int GetPageNumber() const { return m_pageNumber; }
  135. const SCH_SHEET* GetSheet( unsigned aIndex ) const
  136. {
  137. SCH_SHEET* retv = NULL;
  138. if( aIndex < size() )
  139. retv = at( aIndex );
  140. return const_cast< SCH_SHEET* >( retv );
  141. }
  142. SCH_SHEET* GetSheet( unsigned aIndex )
  143. {
  144. return const_cast< SCH_SHEET* >( static_cast< const SCH_SHEET_PATH& >( *this ).GetSheet( aIndex ) );
  145. }
  146. /**
  147. * Function Cmp
  148. * Compare if this is the same sheet path as aSheetPathToTest
  149. * @param aSheetPathToTest = sheet path to compare
  150. * @return 1 if this sheet path has more sheets than aSheetPathToTest,
  151. * -1 if this sheet path has fewer sheets than aSheetPathToTest,
  152. * or 0 if same
  153. */
  154. int Cmp( const SCH_SHEET_PATH& aSheetPathToTest ) const;
  155. /**
  156. * Function Last
  157. * returns a pointer to the last sheet of the list
  158. * One can see the others sheet as the "path" to reach this last sheet
  159. */
  160. SCH_SHEET* Last() const;
  161. /**
  162. * Function LastScreen
  163. * @return the SCH_SCREEN relative to the last sheet in list
  164. */
  165. SCH_SCREEN* LastScreen() const;
  166. /**
  167. * Function LastDrawList
  168. * @return a pointer to the first schematic item handled by the
  169. * SCH_SCREEN relative to the last sheet in list
  170. */
  171. SCH_ITEM* LastDrawList() const;
  172. /**
  173. * Get the last schematic item relative to the first sheet in the list.
  174. *
  175. * @return Last schematic item relative to the first sheet in the list if list
  176. * is not empty. Otherwise NULL.
  177. */
  178. SCH_ITEM* FirstDrawList() const;
  179. /**
  180. * Function Path
  181. * the path uses the time stamps which do not changes even when editing
  182. * sheet parameters
  183. * a path is something like / (root) or /34005677 or /34005677/00AE4523
  184. */
  185. wxString Path() const;
  186. /**
  187. * Function PathHumanReadable
  188. * returns the sheet path in a human readable form, i.e. as a path made
  189. * from sheet names. The the "normal" path instead uses the time
  190. * stamps in the path. (Time stamps do not change even when editing
  191. * sheet parameters).
  192. */
  193. wxString PathHumanReadable() const;
  194. /**
  195. * Function UpdateAllScreenReferences
  196. * updates the reference and the m_Multi parameter (part selection) for all
  197. * components on a screen depending on the actual sheet path.
  198. * Mandatory in complex hierarchies because sheets use the same screen
  199. * (basic schematic)
  200. * but with different references and part selections according to the
  201. * displayed sheet
  202. */
  203. void UpdateAllScreenReferences();
  204. /**
  205. * Function GetComponents
  206. * adds a SCH_REFERENCE() object to \a aReferences for each component in the sheet.
  207. *
  208. * @param aReferences List of references to populate.
  209. * @param aIncludePowerSymbols : false to only get normal components.
  210. * @param aForceIncludeOrphanComponents : true to include components having no symbol found in lib.
  211. * ( orphan components)
  212. * The normal option is false, and set to true only to build the full list of components.
  213. */
  214. void GetComponents( SCH_REFERENCE_LIST& aReferences, bool aIncludePowerSymbols = true,
  215. bool aForceIncludeOrphanComponents = false );
  216. /**
  217. * Function GetMultiUnitComponents
  218. * adds a SCH_REFERENCE_LIST object to \a aRefList for each same-reference set of
  219. * multi-unit parts in the sheet. The map key for each element will be the
  220. * reference designator.
  221. *
  222. * @param aRefList Map of reference designators to reference lists
  223. * @param aIncludePowerSymbols : false to only get normal components.
  224. */
  225. void GetMultiUnitComponents( SCH_MULTI_UNIT_REFERENCE_MAP &aRefList,
  226. bool aIncludePowerSymbols = true );
  227. /**
  228. * Function SetFootprintField
  229. * searches last sheet in the path for a component with \a aReference and set the footprint
  230. * field to \a aFootPrint if found.
  231. *
  232. * @param aReference The reference designator of the component.
  233. * @param aFootPrint The value to set the footprint field.
  234. * @param aSetVisible The value to set the field visibility flag.
  235. * @return true if \a aReference was found otherwise false.
  236. */
  237. bool SetComponentFootprint( const wxString& aReference, const wxString& aFootPrint,
  238. bool aSetVisible );
  239. /**
  240. * Find the next schematic item in this sheet object.
  241. *
  242. * @param aType - The type of schematic item object to search for.
  243. * @param aLastItem - Start search from aLastItem. If no aLastItem, search from
  244. * the beginning of the list.
  245. * @param aWrap - Wrap around the end of the list to find the next item if aLastItem
  246. * is defined.
  247. * @return - The next schematic item if found. Otherwise, NULL is returned.
  248. */
  249. SCH_ITEM* FindNextItem( KICAD_T aType, SCH_ITEM* aLastItem = NULL, bool aWrap = false ) const;
  250. /**
  251. * Find the previous schematic item in this sheet path object.
  252. *
  253. * @param aType - The type of schematic item object to search for.
  254. * @param aLastItem - Start search from aLastItem. If no aLastItem, search from
  255. * the end of the list.
  256. * @param aWrap - Wrap around the beginning of the list to find the next item if aLastItem
  257. * is defined.
  258. * @return - The previous schematic item if found. Otherwise, NULL is returned.
  259. */
  260. SCH_ITEM* FindPreviousItem( KICAD_T aType, SCH_ITEM* aLastItem = NULL, bool aWrap = false ) const;
  261. /**
  262. * Function TestForRecursion
  263. *
  264. * test the SCH_SHEET_PATH file names to check adding the sheet stored in the file
  265. * \a aSrcFileName to the sheet stored in file \a aDestFileName will cause a sheet
  266. * path recursion.
  267. *
  268. * @param aSrcFileName is the source file name of the sheet add to \a aDestFileName.
  269. * @param aDestFileName is the file name of the destination sheet for \a aSrcFileName.
  270. * @return true if \a aFileName will cause recursion in the sheet path. Otherwise false.
  271. */
  272. bool TestForRecursion( const wxString& aSrcFileName, const wxString& aDestFileName ) const;
  273. int FindSheet( const wxString& aFileName ) const;
  274. /**
  275. * Function FindSheetByName
  276. *
  277. * searches the #SCH_SHEET_PATH for a sheet named \a aSheetName.
  278. *
  279. * @param aSheetName is the name of the sheet to find.
  280. * @return a pointer to the sheet named \a aSheetName if found or NULL if not found.
  281. */
  282. SCH_SHEET* FindSheetByName( const wxString& aSheetName );
  283. /**
  284. * Function FindSheetByPageNumber
  285. *
  286. * searches the #SCH_SHEET_LIST for a sheet with \a aPageNumber.
  287. *
  288. * @param aPageNumber is the number of the sheet to find.
  289. * @return a pointer to a #SCH_SHEET object page \a aPageNumber if found or NULL if not found.
  290. */
  291. SCH_SHEET* FindSheetByPageNumber( int aPageNumber );
  292. bool operator==( const SCH_SHEET_PATH& d1 ) const;
  293. bool operator!=( const SCH_SHEET_PATH& d1 ) const { return !( *this == d1 ) ; }
  294. bool operator<( const SCH_SHEET_PATH& d1 ) const { return m_sheets < d1.m_sheets; }
  295. };
  296. namespace std
  297. {
  298. template<> struct hash<SCH_SHEET_PATH>
  299. {
  300. size_t operator()( const SCH_SHEET_PATH& path ) const;
  301. };
  302. }
  303. typedef std::vector< SCH_SHEET_PATH > SCH_SHEET_PATHS;
  304. typedef SCH_SHEET_PATHS::iterator SCH_SHEET_PATHS_ITER;
  305. typedef SCH_SHEET_PATHS::const_iterator SCH_SHEET_PATHS_CITER;
  306. typedef SCH_SHEET_PATHS::reverse_iterator SCH_SHEET_PATHS_RITER;
  307. typedef SCH_SHEET_PATHS::const_reverse_iterator SCH_SHEET_PATHS_CRITER;
  308. /**
  309. * Class SCH_SHEET_LIST
  310. *
  311. * handles a list of #SCH_SHEET_PATH objects in a flattened hierarchy.
  312. *
  313. * #SCH_SHEET objects are not unique, there can be many sheets with the same filename and
  314. * that share the same #SCH_SCREEN reference. Each The schematic file (#SCH_SCREEN) may
  315. * be shared between these sheets and component references are specific to a sheet path.
  316. * When a sheet is entered, component references and sheet page number are updated.
  317. */
  318. class SCH_SHEET_LIST : public SCH_SHEET_PATHS
  319. {
  320. private:
  321. bool m_isRootSheet;
  322. SCH_SHEET_PATH m_currentSheetPath;
  323. public:
  324. /**
  325. * Constructor
  326. * build a flattened list of SCH_SHEET_PATH objects from \a aSheet.
  327. *
  328. * If aSheet == NULL, then this is an empty hierarchy which the user can populate.
  329. */
  330. SCH_SHEET_LIST( SCH_SHEET* aSheet = NULL );
  331. ~SCH_SHEET_LIST() {}
  332. /**
  333. * Function GetSheetByPath
  334. * returns a sheet matching the path name in \a aPath.
  335. *
  336. * @param aPath A wxString object containing path of the sheet to get.
  337. * @param aHumanReadable True uses the human readable path for comparison.
  338. * False uses the timestamp generated path.
  339. * @return The sheet that matches \a aPath or NULL if no sheet matching
  340. * \a aPath is found.
  341. */
  342. SCH_SHEET_PATH* GetSheetByPath( const wxString& aPath, bool aHumanReadable = true );
  343. /**
  344. * Function IsModified
  345. * checks the entire hierarchy for any modifications.
  346. * @return True if the hierarchy is modified otherwise false.
  347. */
  348. bool IsModified();
  349. void ClearModifyStatus();
  350. /**
  351. * Function AnnotatePowerSymbols
  352. * Silently annotates the not yet annotated power symbols of the entire hierarchy
  353. * of the sheet path list.
  354. * It is called before creating a netlist, to annotate power symbols, without prompting
  355. * the user about not annotated or duplicate for these symbols, if only these symbols
  356. * need annotation ( a very frequent case ).
  357. */
  358. void AnnotatePowerSymbols();
  359. /**
  360. * Function GetComponents
  361. * adds a SCH_REFERENCE() object to \a aReferences for each component in the list
  362. * of sheets.
  363. *
  364. * @param aReferences List of references to populate.
  365. * @param aIncludePowerSymbols Set to false to only get normal components.
  366. * @param aForceIncludeOrphanComponents : true to include components having no symbol found in lib.
  367. * ( orphan components)
  368. * The normal option is false, and set to true only to build the full list of components.
  369. */
  370. void GetComponents( SCH_REFERENCE_LIST& aReferences, bool aIncludePowerSymbols = true,
  371. bool aForceIncludeOrphanComponents = false );
  372. /**
  373. * Function GetMultiUnitComponents
  374. * adds a SCH_REFERENCE_LIST object to \a aRefList for each same-reference set of
  375. * multi-unit parts in the list of sheets. The map key for each element will be the
  376. * reference designator.
  377. *
  378. * @param aRefList Map of reference designators to reference lists
  379. * @param aIncludePowerSymbols Set to false to only get normal components.
  380. */
  381. void GetMultiUnitComponents( SCH_MULTI_UNIT_REFERENCE_MAP &aRefList,
  382. bool aIncludePowerSymbols = true );
  383. /**
  384. * Function FindNextItem
  385. * searches the entire schematic for the next schematic object.
  386. *
  387. * @param aType - The type of schematic item to find.
  388. * @param aSheetFound - The sheet the item was found in. NULL if the next item
  389. * is not found.
  390. * @param aLastItem - Find next item after aLastItem if not NULL.
  391. * @param aWrap - Wrap past around the end of the list of sheets.
  392. * @return If found, Returns the next schematic item. Otherwise, returns NULL.
  393. */
  394. SCH_ITEM* FindNextItem( KICAD_T aType, SCH_SHEET_PATH** aSheetFound = NULL,
  395. SCH_ITEM* aLastItem = NULL, bool aWrap = true );
  396. /**
  397. * Function FindPreviousItem
  398. * searches the entire schematic for the previous schematic item.
  399. *
  400. * @param aType - The type of schematic item to find.
  401. * @param aSheetFound - The sheet the item was found in. NULL if the previous item
  402. * is not found.
  403. * @param aLastItem - Find the previous item before aLastItem if not NULL.
  404. * @param aWrap - Wrap past around the beginning of the list of sheets.
  405. * @return If found, the previous schematic item. Otherwise, NULL.
  406. */
  407. SCH_ITEM* FindPreviousItem( KICAD_T aType, SCH_SHEET_PATH** aSheetFound = NULL,
  408. SCH_ITEM* aLastItem = NULL, bool aWrap = true );
  409. /**
  410. * Function SetFootprintField
  411. * searches all the sheets for a component with \a aReference and set the footprint
  412. * field to \a aFootPrint if found.
  413. *
  414. * @param aReference The reference designator of the component.
  415. * @param aFootPrint The value to set the footprint field.
  416. * @param aSetVisible The value to set the field visibility flag.
  417. * @return True if \a aReference was found otherwise false.
  418. */
  419. bool SetComponentFootprint( const wxString& aReference, const wxString& aFootPrint,
  420. bool aSetVisible );
  421. /**
  422. * Function IsComplexHierarchy
  423. * searches all of the sheets for duplicate files names which indicates a complex
  424. * hierarchy.
  425. *
  426. * @return true if the #SCH_SHEET_LIST is a complex hierarchy.
  427. */
  428. bool IsComplexHierarchy() const;
  429. /**
  430. * Function TestForRecursion
  431. *
  432. * test every SCH_SHEET_PATH in the SCH_SHEET_LIST to verify if adding the sheets stored
  433. * in \a aSrcSheetHierarchy to the sheet stored in \a aDestFileName will cause recursion.
  434. *
  435. * @param aSrcSheetHierarchy is the SCH_SHEET_LIST of the source sheet add to \a aDestFileName.
  436. * @param aDestFileName is the file name of the destination sheet for \a aSrcFileName.
  437. * @return true if \a aFileName will cause recursion in the sheet path. Otherwise false.
  438. */
  439. bool TestForRecursion( const SCH_SHEET_LIST& aSrcSheetHierarchy,
  440. const wxString& aDestFileName ) const;
  441. /**
  442. * Function FindSheetByName
  443. *
  444. * searches the entire #SCH_SHEET_LIST for a sheet named \a aSheetName.
  445. *
  446. * @param aSheetName is the name of the sheet to find.
  447. * @return a pointer to the sheet named \a aSheetName if found or NULL if not found.
  448. */
  449. SCH_SHEET* FindSheetByName( const wxString& aSheetName );
  450. /**
  451. * Function FindSheetForScreen
  452. *
  453. * returns the first sheetPath (not necessarily the only one) using a particular screen
  454. */
  455. SCH_SHEET_PATH* FindSheetForScreen( SCH_SCREEN* aScreen );
  456. /**
  457. * Function BuildSheetList
  458. * builds the list of sheets and their sheet path from \a aSheet.
  459. * If \a aSheet is the root sheet, the full sheet path and sheet list are built.
  460. *
  461. * @param aSheet is the starting sheet from which the list is built, or NULL
  462. * indicating that g_RootSheet should be used.
  463. * @throw std::bad_alloc if the memory for the sheet path list could not be allocated.
  464. */
  465. void BuildSheetList( SCH_SHEET* aSheet );
  466. };
  467. #endif // CLASS_DRAWSHEET_PATH_H