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.

571 lines
20 KiB

18 years ago
18 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 The 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. #ifndef SCH_SHEEET_H
  25. #define SCH_SHEEET_H
  26. #include <sch_field.h>
  27. class KIID_PATH;
  28. class SCH_SCREEN;
  29. class SCH_IO_KICAD_SEXPR_PARSER;
  30. class SCH_SHEET_LIST;
  31. class SCH_SHEET_PIN;
  32. class SCH_SHEET_PATH;
  33. class EDA_DRAW_FRAME;
  34. #define MIN_SHEET_WIDTH 500 // Units are mils.
  35. #define MIN_SHEET_HEIGHT 150 // Units are mils.
  36. /**
  37. * Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
  38. */
  39. class SCH_SHEET : public SCH_ITEM
  40. {
  41. public:
  42. SCH_SHEET( EDA_ITEM* aParent = nullptr, const VECTOR2I& aPos = VECTOR2I( 0, 0 ),
  43. VECTOR2I aSize = VECTOR2I( schIUScale.MilsToIU( MIN_SHEET_WIDTH ),
  44. schIUScale.MilsToIU( MIN_SHEET_HEIGHT ) ) );
  45. /**
  46. * Copy \a aSheet into a new object.
  47. *
  48. * All sheet pins are copied as is except and the #SCH_SHEET_PIN object's #m_Parent pointers
  49. * are set to the new copied parent object.
  50. */
  51. SCH_SHEET( const SCH_SHEET& aSheet );
  52. ~SCH_SHEET();
  53. static inline bool ClassOf( const EDA_ITEM* aItem )
  54. {
  55. return aItem && SCH_SHEET_T == aItem->Type();
  56. }
  57. wxString GetClass() const override
  58. {
  59. return wxT( "SCH_SHEET" );
  60. }
  61. /**
  62. * Return true for items which are moved with the anchor point at mouse cursor
  63. * and false for items moved with no reference to anchor.
  64. *
  65. * Usually return true for small items (labels, junctions) and false for
  66. * items which can be large (hierarchical sheets, symbols).
  67. *
  68. * @return false for a hierarchical sheet.
  69. */
  70. bool IsMovableFromAnchorPoint() const override { return false; }
  71. /**
  72. * Return a reference to the vector holding the sheet's fields
  73. */
  74. std::vector<SCH_FIELD>& GetFields() { return m_fields; }
  75. const std::vector<SCH_FIELD>& GetFields() const { return m_fields; }
  76. /**
  77. * Return a mandatory field in this sheet. The const version will return nullptr if the
  78. * field does not exist; the non-const version will create it.
  79. */
  80. SCH_FIELD* GetField( FIELD_T aFieldType );
  81. const SCH_FIELD* GetField( FIELD_T aFieldNdx ) const;
  82. /**
  83. * Return the next ordinal for a user field for this sheet
  84. */
  85. int GetNextFieldOrdinal() const;
  86. /**
  87. * Set multiple schematic fields.
  88. *
  89. * @param aFields are the fields to set in this symbol.
  90. */
  91. void SetFields( const std::vector<SCH_FIELD>& aFields );
  92. wxString GetShownName( bool aAllowExtraText ) const
  93. {
  94. return GetField( FIELD_T::SHEET_NAME )->GetShownText( aAllowExtraText );
  95. }
  96. wxString GetName() const { return GetField( FIELD_T::SHEET_NAME )->GetText(); }
  97. void SetName( const wxString& aName ) { GetField( FIELD_T::SHEET_NAME )->SetText( aName ); }
  98. SCH_SCREEN* GetScreen() const { return m_screen; }
  99. VECTOR2I GetSize() const { return m_size; }
  100. void SetSize( const VECTOR2I& aSize ) { m_size = aSize; }
  101. int GetBorderWidth() const { return m_borderWidth; }
  102. void SetBorderWidth( int aWidth ) { m_borderWidth = aWidth; }
  103. KIGFX::COLOR4D GetBorderColor() const { return m_borderColor; }
  104. void SetBorderColor( KIGFX::COLOR4D aColor ) { m_borderColor = aColor; }
  105. KIGFX::COLOR4D GetBackgroundColor() const { return m_backgroundColor; }
  106. void SetBackgroundColor( KIGFX::COLOR4D aColor ) { m_backgroundColor = aColor; }
  107. /**
  108. * @return true if this sheet is the root sheet.
  109. */
  110. bool IsRootSheet() const;
  111. /**
  112. * Set the #SCH_SCREEN associated with this sheet to \a aScreen.
  113. *
  114. * The screen reference counting is performed by SetScreen. If \a aScreen is not
  115. * the same as the current screen, the current screen reference count is decremented
  116. * and \a aScreen becomes the screen for the sheet. If the current screen reference
  117. * count reaches zero, the current screen is deleted. NULL is a valid value for
  118. * \a aScreen.
  119. *
  120. * @param aScreen The new screen to associate with the sheet.
  121. */
  122. void SetScreen( SCH_SCREEN* aScreen );
  123. /**
  124. * Return the number of times the associated screen for the sheet is being used.
  125. *
  126. * If no screen is associated with the sheet, then zero is returned.
  127. */
  128. int GetScreenCount() const;
  129. /**
  130. * Return the list of system text vars & fields for this sheet.
  131. */
  132. void GetContextualTextVars( wxArrayString* aVars ) const;
  133. /**
  134. * Resolve any references to system tokens supported by the sheet.
  135. *
  136. * @param aDepth is a counter to limit recursion and circular references.
  137. */
  138. bool ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, int aDepth = 0 ) const;
  139. void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
  140. /* there is no member for orientation in sch_sheet, to preserve file
  141. * format, we detect orientation based on pin edges
  142. */
  143. bool IsVerticalOrientation() const;
  144. void SetPositionIgnoringPins( const VECTOR2I& aPosition );
  145. /**
  146. * Add aSheetPin to the sheet.
  147. *
  148. * @note Once a sheet pin is added to the sheet, it is owned by the sheet.
  149. * Do not delete the sheet pin object or you will likely get a segfault
  150. * when the sheet is destroyed.
  151. *
  152. * @param aSheetPin The sheet pin item to add to the sheet.
  153. */
  154. void AddPin( SCH_SHEET_PIN* aSheetPin );
  155. std::vector<SCH_SHEET_PIN*>& GetPins() { return m_pins; }
  156. const std::vector<SCH_SHEET_PIN*>& GetPins() const { return m_pins; }
  157. /**
  158. * Remove \a aSheetPin from the sheet.
  159. *
  160. * @param aSheetPin The sheet pin item to remove from the sheet.
  161. */
  162. void RemovePin( const SCH_SHEET_PIN* aSheetPin );
  163. /**
  164. * Delete sheet label which do not have a corresponding hierarchical label.
  165. *
  166. * @note Make sure you save a copy of the sheet in the undo list before calling
  167. * CleanupSheet() otherwise any unreferenced sheet labels will be lost.
  168. */
  169. void CleanupSheet();
  170. /**
  171. * Return the sheet pin item found at \a aPosition in the sheet.
  172. *
  173. * @param aPosition The position to check for a sheet pin.
  174. *
  175. * @return The sheet pin found at \a aPosition or NULL if no sheet pin is found.
  176. */
  177. SCH_SHEET_PIN* GetPin( const VECTOR2I& aPosition );
  178. /**
  179. * Check if the sheet already has a sheet pin named \a aName.
  180. *
  181. * @param aName Name of the sheet pin to search for.
  182. * @return True if sheet pin with \a aName is found, otherwise false.
  183. */
  184. bool HasPin( const wxString& aName ) const;
  185. bool HasPins() const { return !m_pins.empty(); }
  186. /**
  187. * Check all sheet labels against schematic for undefined hierarchical labels.
  188. *
  189. * @return True if there are any undefined labels.
  190. */
  191. bool HasUndefinedPins() const;
  192. /**
  193. * Return the minimum width of the sheet based on the widths of the sheet pin text.
  194. *
  195. * The minimum sheet width is determined by the width of the bounding box of each
  196. * hierarchical sheet pin. If two pins are horizontally adjacent ( same Y position )
  197. * to each other, the sum of the bounding box widths is used. If at some point in
  198. * the future sheet objects can be rotated or pins can be placed in the vertical
  199. * orientation, this function will need to be changed.
  200. *
  201. * @return The minimum width the sheet can be resized.
  202. */
  203. int GetMinWidth( bool aFromLeft ) const;
  204. /**
  205. * Return the minimum height that the sheet can be resized based on the sheet pin positions.
  206. *
  207. * The minimum width of a sheet is determined by the Y axis location of the bottom
  208. * most sheet pin. If at some point in the future sheet objects can be rotated or
  209. * pins can be placed in the vertical orientation, this function will need to be
  210. * changed.
  211. *
  212. * @return The minimum height the sheet can be resized.
  213. */
  214. int GetMinHeight( bool aFromTop ) const;
  215. int GetPenWidth() const override;
  216. /**
  217. * Return a bounding box for the sheet body but not the fields.
  218. */
  219. const BOX2I GetBodyBoundingBox() const;
  220. const BOX2I GetBoundingBox() const override;
  221. /**
  222. * Rotating around the boundingBox's center can cause walking when the sheetname or
  223. * filename is longer than the edge it's on.
  224. *
  225. * Use this instead, which always returns the center of the sheet itself.
  226. */
  227. VECTOR2I GetRotationCenter() const;
  228. void SwapData( SCH_ITEM* aItem ) override;
  229. /**
  230. * Count our own symbols, without the power symbols.
  231. */
  232. int SymbolCount() const;
  233. /**
  234. * Search the existing hierarchy for an instance of screen loaded from \a aFileName.
  235. *
  236. * @param aFilename The filename to find (MUST be absolute, and in wxPATH_NATIVE encoding).
  237. * @param aScreen A location to return a pointer to the screen (if found).
  238. * @return true if found, and a pointer to the screen
  239. */
  240. bool SearchHierarchy( const wxString& aFilename, SCH_SCREEN** aScreen );
  241. /**
  242. * Search the existing hierarchy for an instance of screen loaded from \a aFileName.
  243. *
  244. * Don't bother looking at the root sheet, it must be unique. No other references to
  245. * its m_screen otherwise there would be loops in the hierarchy.
  246. *
  247. * @param[in] aScreen The SCH_SCREEN* screen that we search for.
  248. * @param[in] aList The SCH_SHEET_PATH* that must be used.
  249. * @return true if found.
  250. */
  251. bool LocatePathOfScreen( SCH_SCREEN* aScreen, SCH_SHEET_PATH* aList );
  252. /**
  253. * Count the number of sheets found in "this" sheet including all of the subsheets.
  254. *
  255. * @return the full count of sheets+subsheets contained by "this"
  256. */
  257. int CountSheets() const;
  258. /**
  259. * Count the number of sheets that refer to a specific file
  260. * including all of the subsheets.
  261. * @param aFileName The filename to search for.
  262. * @return the full count of sheets+subsheets that refer to aFileName
  263. */
  264. int CountSheets( const wxString& aFileName ) const;
  265. /**
  266. * Return the filename corresponding to this sheet.
  267. *
  268. * @return a wxString containing the filename
  269. */
  270. wxString GetFileName() const
  271. {
  272. return GetField( FIELD_T::SHEET_FILENAME )->GetText();
  273. }
  274. // Set a new filename without changing anything else
  275. void SetFileName( const wxString& aFilename )
  276. {
  277. // Filenames are stored using unix notation
  278. wxString tmp = aFilename;
  279. tmp.Replace( wxT( "\\" ), wxT( "/" ) );
  280. GetField( FIELD_T::SHEET_FILENAME )->SetText( tmp );
  281. }
  282. // Geometric transforms (used in block operations):
  283. void Move( const VECTOR2I& aMoveVector ) override;
  284. void MirrorHorizontally( int aCenter ) override;
  285. void MirrorVertically( int aCenter ) override;
  286. void Rotate( const VECTOR2I& aCenter, bool aRotateCCW ) override;
  287. bool Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const override;
  288. bool IsReplaceable() const override { return true; }
  289. /**
  290. * Resize this sheet to aSize and adjust all of the labels accordingly.
  291. *
  292. * @param[in] aSize The new size for this sheet.
  293. */
  294. void Resize( const VECTOR2I& aSize );
  295. void AutoplaceFields( SCH_SCREEN* aScreen, AUTOPLACE_ALGO aAlgo ) override;
  296. void GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList ) override;
  297. bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
  298. std::vector<DANGLING_END_ITEM>& aItemListByPos,
  299. const SCH_SHEET_PATH* aPath = nullptr ) override;
  300. bool IsConnectable() const override { return true; }
  301. bool HasConnectivityChanges( const SCH_ITEM* aItem,
  302. const SCH_SHEET_PATH* aInstance = nullptr ) const override;
  303. bool CanConnect( const SCH_ITEM* aItem ) const override
  304. {
  305. return ( aItem->Type() == SCH_LINE_T && aItem->GetLayer() == LAYER_WIRE )
  306. || ( aItem->Type() == SCH_LINE_T && aItem->GetLayer() == LAYER_BUS )
  307. || ( aItem->Type() == SCH_NO_CONNECT_T )
  308. || ( aItem->Type() == SCH_SYMBOL_T );
  309. }
  310. std::vector<VECTOR2I> GetConnectionPoints() const override;
  311. INSPECT_RESULT Visit( INSPECTOR inspector, void* testData,
  312. const std::vector<KICAD_T>& aScanTypes ) override;
  313. void RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction ) override;
  314. /**
  315. * Set or clear the exclude from simulation flag.
  316. */
  317. void SetExcludedFromSim( bool aExcludeFromSim ) override { m_excludedFromSim = aExcludeFromSim; }
  318. bool GetExcludedFromSim() const override { return m_excludedFromSim; }
  319. /**
  320. * Set or clear the exclude from schematic bill of materials flag.
  321. */
  322. void SetExcludedFromBOM( bool aExcludeFromBOM ) { m_excludedFromBOM = aExcludeFromBOM; }
  323. bool GetExcludedFromBOM() const { return m_excludedFromBOM; }
  324. /**
  325. * Set or clear exclude from board netlist flag.
  326. */
  327. void SetExcludedFromBoard( bool aExcludeFromBoard ) { m_excludedFromBoard = aExcludeFromBoard; }
  328. bool GetExcludedFromBoard() const { return m_excludedFromBoard; }
  329. /**
  330. * Set or clear the 'Do Not Populate' flags
  331. */
  332. bool GetDNP() const { return m_DNP; }
  333. void SetDNP( bool aDNP ) { m_DNP = aDNP; }
  334. wxString GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const override;
  335. BITMAPS GetMenuImage() const override;
  336. SCH_SHEET& operator=( const SCH_ITEM& aSheet );
  337. bool operator <( const SCH_ITEM& aItem ) const override;
  338. std::vector<int> ViewGetLayers() const override;
  339. VECTOR2I GetPosition() const override { return m_pos; }
  340. void SetPosition( const VECTOR2I& aPosition ) override;
  341. bool HitTest( const VECTOR2I& aPosition, int aAccuracy ) const override;
  342. bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy = 0 ) const override;
  343. void Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
  344. int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed ) override;
  345. EDA_ITEM* Clone() const override;
  346. /**
  347. * @return the list of #SCH_SHEET_INSTANCE objects for this sheet.
  348. */
  349. const std::vector<SCH_SHEET_INSTANCE>& GetInstances() const { return m_instances; }
  350. /**
  351. * Check to see if this sheet has a root sheet instance.
  352. *
  353. * @note It is possible for sheets to contain both sheet instances from other projects as
  354. * well as a root sheet instance for this schematic. This will happen with a
  355. * shared schematic is opened by the schematic editor in stand alone model.
  356. *
  357. * @return true if the instance data contains a root sheet instance.
  358. */
  359. bool HasRootInstance() const;
  360. /**
  361. * Return the root sheet instance data.
  362. *
  363. * @note If no root sheet instance data exists, an assertion will be raise in debug builds
  364. * and an empty instance will be returned.
  365. *
  366. * @return the root sheet instance data.
  367. */
  368. const SCH_SHEET_INSTANCE& GetRootInstance() const;
  369. void RemoveInstance( const KIID_PATH& aInstancePath );
  370. void AddInstance( const SCH_SHEET_INSTANCE& aInstance );
  371. /**
  372. * Check if the instance data of this sheet has any changes compared to \a aOther.
  373. *
  374. * @param aOther is the sheet to compare against.
  375. * @return true if there are page number changes with \a aOther otherwise false.
  376. */
  377. bool HasPageNumberChanges( const SCH_SHEET& aOther ) const;
  378. /**
  379. * Compare page numbers of schematic sheets.
  380. *
  381. * @return 0 if the page numbers are equal, -1 if aPageNumberA < aPageNumberB, 1 otherwise
  382. */
  383. static int ComparePageNum( const wxString& aPageNumberA, const wxString& aPageNumberB );
  384. double Similarity( const SCH_ITEM& aOther ) const override;
  385. bool operator==( const SCH_ITEM& aOther ) const override;
  386. #if defined(DEBUG)
  387. void Show( int nestLevel, std::ostream& os ) const override;
  388. #endif
  389. protected:
  390. friend SCH_SHEET_PATH;
  391. friend SCH_IO_KICAD_SEXPR_PARSER;
  392. void setInstances( const std::vector<SCH_SHEET_INSTANCE>& aInstances )
  393. {
  394. m_instances = aInstances;
  395. }
  396. /**
  397. * Add a new instance \a aSheetPath to the instance list.
  398. *
  399. * If \a aSheetPath does not already exist, it is added to the list. If already exists
  400. * in the list, do nothing. Sheet instances allow for the sharing in complex hierarchies
  401. * which allows for per instance data such as page number for sheets to stored.
  402. *
  403. * @warning The #KIID_PATH object must be a full hierarchical path which means the sheet
  404. * at index 0 must be the root sheet.
  405. *
  406. * @param[in] aInstance is the #SCH_SHEET_PATH of the sheet instance to the instance list.
  407. * @return false if the instance already exists, true if the instance was added.
  408. */
  409. bool addInstance( const KIID_PATH& aInstance );
  410. /**
  411. * Return the sheet page number for \a aInstance.
  412. *
  413. * @warning The #KIID_PATH object must be a full hierarchical path which means the sheet
  414. * at index 0 must be the root sheet.
  415. *
  416. * @return the page number for the requested sheet instance.
  417. */
  418. wxString getPageNumber( const KIID_PATH& aInstance ) const;
  419. /**
  420. * Set the page number for the sheet instance \a aInstance.
  421. *
  422. * @warning The #KIID_PATH object must be a full hierarchical path which means the sheet
  423. * at index 0 must be the root sheet.
  424. *
  425. * @param[in] aInstance is the hierarchical path of the sheet.
  426. * @param[in] aReference is the new page number for the sheet.
  427. */
  428. void setPageNumber( const KIID_PATH& aInstance, const wxString& aPageNumber );
  429. bool getInstance( SCH_SHEET_INSTANCE& aInstance, const KIID_PATH& aSheetPath,
  430. bool aTestFromEnd = false ) const;
  431. /**
  432. * Renumber the sheet pins in the sheet.
  433. *
  434. * This method is used internally by SCH_SHEET to update the pin numbering
  435. * when the pin list changes. Make sure you call this method any time a
  436. * sheet pin is added or removed.
  437. */
  438. void renumberPins();
  439. /**
  440. * Get the sheetpath of this sheet. NB: REQUIRES that the current sheet hierarchy contains
  441. * the given sheet.
  442. */
  443. SCH_SHEET_PATH findSelf() const;
  444. private:
  445. bool doIsConnected( const VECTOR2I& aPosition ) const override;
  446. friend class SCH_SHEET_PIN;
  447. friend class SCH_SHEET_LIST;
  448. private:
  449. SCH_SCREEN* m_screen; // Screen that contains the physical data for the
  450. // sheet. In complex hierarchies multiple sheets
  451. // can share a common screen.
  452. std::vector<SCH_SHEET_PIN*> m_pins; // The list of sheet connection points.
  453. std::vector<SCH_FIELD> m_fields;
  454. bool m_excludedFromSim;
  455. bool m_excludedFromBOM;
  456. bool m_excludedFromBoard;
  457. bool m_DNP;
  458. VECTOR2I m_pos; // The position of the sheet.
  459. VECTOR2I m_size; // The size of the sheet.
  460. int m_borderWidth;
  461. KIGFX::COLOR4D m_borderColor;
  462. KIGFX::COLOR4D m_backgroundColor;
  463. std::vector<SCH_SHEET_INSTANCE> m_instances;
  464. };
  465. #endif // SCH_SHEEET_H