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.

583 lines
18 KiB

12 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2013-2014 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. #ifndef WS_DRAW_ITEM_H
  25. #define WS_DRAW_ITEM_H
  26. #include <core/typeinfo.h>
  27. #include <math/vector2d.h>
  28. #include <eda_text.h>
  29. #include <bitmap_base.h>
  30. #include "widgets/msgpanel.h"
  31. #include <geometry/shape_poly_set.h>
  32. #include <eda_units.h>
  33. #include <algorithm>
  34. #include <vector>
  35. class WS_DATA_ITEM;
  36. class TITLE_BLOCK;
  37. class PAGE_INFO;
  38. class EDA_ITEM;
  39. class EDA_DRAW_FRAME;
  40. class PROJECT;
  41. /**
  42. * Base class to handle basic graphic items.
  43. *
  44. * Used to draw and/or plot:
  45. * - title blocks and frame references
  46. * - segments
  47. * - rect
  48. * - polygons (for logos)
  49. * - graphic texts
  50. * - bitmaps (also for logos, but they cannot be plot by SVG, GERBER or HPGL plotters
  51. * where we just plot the bounding box)
  52. */
  53. class WS_DRAW_ITEM_BASE : public EDA_ITEM
  54. {
  55. public:
  56. virtual ~WS_DRAW_ITEM_BASE() {}
  57. WS_DATA_ITEM* GetPeer() const { return m_peer; }
  58. int GetIndexInPeer() const { return m_index; }
  59. void ViewGetLayers( int aLayers[], int& aCount ) const override;
  60. virtual void SetEnd( wxPoint aPos ) { /* not all types will need this */ }
  61. virtual int GetPenWidth() const
  62. {
  63. if( m_penWidth > 0 )
  64. return m_penWidth;
  65. else
  66. return 1;
  67. }
  68. // The function to print a WS_DRAW_ITEM
  69. virtual void PrintWsItem( const RENDER_SETTINGS* aSettings )
  70. {
  71. PrintWsItem( aSettings, wxPoint( 0, 0 ) );
  72. }
  73. // More advanced version of DrawWsItem. This is what must be defined in the derived type.
  74. virtual void PrintWsItem( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset ) = 0;
  75. // Derived types must define GetBoundingBox() as a minimum, and can then override the
  76. // two HitTest() functions if they need something more specific.
  77. const EDA_RECT GetBoundingBox() const override = 0;
  78. bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override
  79. {
  80. // This is just here to prevent annoying compiler warnings about hidden overloaded
  81. // virtual functions
  82. return EDA_ITEM::HitTest( aPosition, aAccuracy );
  83. }
  84. bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override;
  85. void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList ) override;
  86. protected:
  87. WS_DRAW_ITEM_BASE( WS_DATA_ITEM* aPeer, int aIndex, KICAD_T aType ) :
  88. EDA_ITEM( aType )
  89. {
  90. m_peer = aPeer;
  91. m_index = aIndex;
  92. m_penWidth = 0;
  93. m_flags = 0;
  94. }
  95. WS_DATA_ITEM* m_peer; // the parent WS_DATA_ITEM item in the WS_DATA_MODEL
  96. int m_index; // the index in the parent's repeat count
  97. int m_penWidth;
  98. };
  99. // This class draws a thick segment
  100. class WS_DRAW_ITEM_LINE : public WS_DRAW_ITEM_BASE
  101. {
  102. public:
  103. WS_DRAW_ITEM_LINE( WS_DATA_ITEM* aPeer, int aIndex, wxPoint aStart, wxPoint aEnd,
  104. int aPenWidth ) :
  105. WS_DRAW_ITEM_BASE( aPeer, aIndex, WSG_LINE_T )
  106. {
  107. m_start = aStart;
  108. m_end = aEnd;
  109. m_penWidth = aPenWidth;
  110. }
  111. virtual wxString GetClass() const override { return wxT( "WS_DRAW_ITEM_LINE" ); }
  112. const wxPoint& GetStart() const { return m_start; }
  113. void SetStart( wxPoint aPos ) { m_start = aPos; }
  114. const wxPoint& GetEnd() const { return m_end; }
  115. void SetEnd( wxPoint aPos ) override { m_end = aPos; }
  116. wxPoint GetPosition() const override { return GetStart(); }
  117. void SetPosition( const wxPoint& aPos ) override { SetStart( aPos ); }
  118. const EDA_RECT GetBoundingBox() const override;
  119. bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
  120. void PrintWsItem( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset ) override;
  121. wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
  122. #if defined(DEBUG)
  123. void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
  124. #endif
  125. private:
  126. wxPoint m_start; // start point of line/rect
  127. wxPoint m_end; // end point
  128. };
  129. class WS_DRAW_ITEM_POLYPOLYGONS : public WS_DRAW_ITEM_BASE
  130. {
  131. public:
  132. WS_DRAW_ITEM_POLYPOLYGONS( WS_DATA_ITEM* aPeer, int aIndex, wxPoint aPos, int aPenWidth ) :
  133. WS_DRAW_ITEM_BASE( aPeer, aIndex, WSG_POLY_T )
  134. {
  135. m_penWidth = aPenWidth;
  136. m_pos = aPos;
  137. }
  138. virtual wxString GetClass() const override { return wxT( "WS_DRAW_ITEM_POLYPOLYGONS" ); }
  139. SHAPE_POLY_SET& GetPolygons() { return m_Polygons; }
  140. wxPoint GetPosition() const override { return m_pos; }
  141. void SetPosition( const wxPoint& aPos ) override;
  142. const EDA_RECT GetBoundingBox() const override;
  143. bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
  144. bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override;
  145. void PrintWsItem( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset ) override;
  146. wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
  147. #if defined(DEBUG)
  148. void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
  149. #endif
  150. public:
  151. /**
  152. * The list of polygons.
  153. *
  154. * Because these polygons are only for drawing purposes, each polygon is expected to
  155. * have no holes just a main outline.
  156. */
  157. SHAPE_POLY_SET m_Polygons;
  158. private:
  159. wxPoint m_pos; // position of reference point, from the WS_DATA_ITEM_POLYGONS parent
  160. // (used only in page layout editor to draw anchors)
  161. };
  162. /**
  163. * Non filled rectangle with thick segment.
  164. */
  165. class WS_DRAW_ITEM_RECT : public WS_DRAW_ITEM_BASE
  166. {
  167. public:
  168. WS_DRAW_ITEM_RECT( WS_DATA_ITEM* aPeer, int aIndex, wxPoint aStart, wxPoint aEnd,
  169. int aPenWidth ) :
  170. WS_DRAW_ITEM_BASE( aPeer, aIndex, WSG_RECT_T )
  171. {
  172. m_start = aStart;
  173. m_end = aEnd;
  174. m_penWidth = aPenWidth;
  175. }
  176. virtual wxString GetClass() const override { return wxT( "WS_DRAW_ITEM_RECT" ); }
  177. const wxPoint& GetStart() const { return m_start; }
  178. void SetStart( wxPoint aPos ) { m_start = aPos; }
  179. const wxPoint& GetEnd() const { return m_end; }
  180. void SetEnd( wxPoint aPos ) override { m_end = aPos; }
  181. wxPoint GetPosition() const override { return GetStart(); }
  182. void SetPosition( const wxPoint& aPos ) override { SetStart( aPos ); }
  183. void PrintWsItem( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset ) override;
  184. const EDA_RECT GetBoundingBox() const override;
  185. bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
  186. bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override;
  187. wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
  188. #if defined(DEBUG)
  189. void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
  190. #endif
  191. private:
  192. wxPoint m_start; // start point of line/rect
  193. wxPoint m_end; // end point
  194. };
  195. /**
  196. * A rectangle with thick segment showing the page limits and a marker showing the coordinate
  197. * origin.
  198. *
  199. * This only a draw item only. Therefore m_peer ( the parent WS_DATA_ITEM item in the
  200. * WS_DATA_MODEL) is always a nullptr.
  201. */
  202. class WS_DRAW_ITEM_PAGE : public WS_DRAW_ITEM_BASE
  203. {
  204. public:
  205. WS_DRAW_ITEM_PAGE( int aPenWidth, double aMarkerSize ) :
  206. WS_DRAW_ITEM_BASE( nullptr, 0, WSG_PAGE_T )
  207. {
  208. m_penWidth = aPenWidth;
  209. m_markerSize = aMarkerSize;
  210. }
  211. virtual wxString GetClass() const override { return wxT( "WS_DRAW_ITEM_PAGE" ); }
  212. void SetPageSize( wxSize aSize ) { m_pageSize = aSize; }
  213. wxSize GetPageSize() const { return m_pageSize; }
  214. const wxPoint& GetMarkerPos() const { return m_markerPos; }
  215. void SetMarkerPos( wxPoint aPos ) { m_markerPos = aPos; }
  216. double GetMarkerSize() const { return m_markerSize; }
  217. wxPoint GetPosition() const override { return wxPoint( 0, 0 ); }
  218. void SetPosition( const wxPoint& aPos ) override { /* do nothing */ }
  219. void PrintWsItem( const RENDER_SETTINGS* , const wxPoint& ) override { /* do nothing */ }
  220. const EDA_RECT GetBoundingBox() const override;
  221. bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override { return false; }
  222. wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
  223. #if defined(DEBUG)
  224. void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
  225. #endif
  226. private:
  227. wxPoint m_markerPos; // position of the marker
  228. wxSize m_pageSize; // full size of the page
  229. double m_markerSize;
  230. };
  231. /**
  232. * A graphic text.
  233. *
  234. * It is derived from an #EDA_TEXT, so it handle all characteristics of this graphic text
  235. * (justification, rotation ... ).
  236. */
  237. class WS_DRAW_ITEM_TEXT : public WS_DRAW_ITEM_BASE, public EDA_TEXT
  238. {
  239. public:
  240. WS_DRAW_ITEM_TEXT( WS_DATA_ITEM* aPeer, int aIndex, wxString& aText, wxPoint aPos,
  241. wxSize aSize, int aPenWidth, bool aItalic = false,
  242. bool aBold = false ) :
  243. WS_DRAW_ITEM_BASE( aPeer, aIndex, WSG_TEXT_T),
  244. EDA_TEXT( aText )
  245. {
  246. SetTextPos( aPos );
  247. SetTextSize( aSize );
  248. SetTextThickness( aPenWidth );
  249. SetItalic( aItalic );
  250. SetBold( aBold );
  251. }
  252. virtual wxString GetClass() const override { return wxT( "WS_DRAW_ITEM_TEXT" ); }
  253. void PrintWsItem( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset ) override;
  254. void SetTextAngle( double aAngle ) override;
  255. wxPoint GetPosition() const override { return GetTextPos(); }
  256. void SetPosition( const wxPoint& aPos ) override { SetTextPos( aPos ); }
  257. const EDA_RECT GetBoundingBox() const override;
  258. bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
  259. bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override;
  260. wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
  261. #if defined(DEBUG)
  262. void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
  263. #endif
  264. };
  265. /**
  266. * A bitmap.
  267. */
  268. class WS_DRAW_ITEM_BITMAP : public WS_DRAW_ITEM_BASE
  269. {
  270. public:
  271. WS_DRAW_ITEM_BITMAP( WS_DATA_ITEM* aPeer, int aIndex, wxPoint aPos ) :
  272. WS_DRAW_ITEM_BASE( aPeer, aIndex, WSG_BITMAP_T )
  273. {
  274. m_pos = aPos;
  275. }
  276. ~WS_DRAW_ITEM_BITMAP() {}
  277. virtual wxString GetClass() const override { return wxT( "WS_DRAW_ITEM_BITMAP" ); }
  278. wxPoint GetPosition() const override { return m_pos; }
  279. void SetPosition( const wxPoint& aPos ) override { m_pos = aPos; }
  280. void PrintWsItem( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset ) override;
  281. bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
  282. bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override;
  283. const EDA_RECT GetBoundingBox() const override;
  284. wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
  285. #if defined(DEBUG)
  286. void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
  287. #endif
  288. private:
  289. wxPoint m_pos; // position of reference point
  290. };
  291. /**
  292. * Store the list of graphic items:
  293. * rect, lines, polygons and texts to draw/plot
  294. * the title block and frame references, and parameters to
  295. * draw/plot them
  296. */
  297. class WS_DRAW_ITEM_LIST
  298. {
  299. public:
  300. WS_DRAW_ITEM_LIST()
  301. {
  302. m_idx = 0;
  303. m_milsToIu = 1.0;
  304. m_penSize = 1;
  305. m_pageNumber = "1";
  306. m_sheetCount = 1;
  307. m_sheetLayer = nullptr;
  308. m_titleBlock = nullptr;
  309. m_paperFormat = nullptr;
  310. m_project = nullptr;
  311. m_isFirstPage = true;
  312. }
  313. ~WS_DRAW_ITEM_LIST()
  314. {
  315. // Items in the m_graphicList are owned by their respective WORKSHEET_DATAITEMs.
  316. // for( WS_DRAW_ITEM_BASE* item : m_graphicList )
  317. // delete item;
  318. }
  319. void SetProject( const PROJECT* aProject ) { m_project = aProject; }
  320. /**
  321. * Set the title block (mainly for page layout editor)
  322. */
  323. void SetTitleBlock( const TITLE_BLOCK* aTblock ) { m_titleBlock = aTblock; }
  324. /**
  325. * Set the paper format name (mainly for page layout editor)
  326. */
  327. void SetPaperFormat( const wxString* aFormatName ) { m_paperFormat = aFormatName; }
  328. /**
  329. * Set the filename to draw/plot
  330. */
  331. void SetFileName( const wxString& aFileName )
  332. {
  333. m_fileName = aFileName;
  334. }
  335. /**
  336. * Set the sheet name to draw/plot
  337. */
  338. void SetSheetName( const wxString& aSheetName )
  339. {
  340. m_sheetFullName = aSheetName;
  341. }
  342. /**
  343. * Set the sheet layer to draw/plot
  344. */
  345. void SetSheetLayer( const wxString& aSheetLayer )
  346. {
  347. m_sheetLayer = &aSheetLayer;
  348. }
  349. void SetDefaultPenSize( int aPenSize ) { m_penSize = aPenSize; }
  350. int GetDefaultPenSize() const { return m_penSize; }
  351. /**
  352. * Set the scalar to convert pages units (mils) to draw/plot units
  353. */
  354. void SetMilsToIUfactor( double aMils2Iu )
  355. {
  356. m_milsToIu = aMils2Iu;
  357. }
  358. /**
  359. * Get the scalar to convert pages units (mils) to draw/plot units
  360. */
  361. double GetMilsToIUfactor() { return m_milsToIu; }
  362. /**
  363. * Set the value of the sheet number.
  364. */
  365. void SetPageNumber( const wxString& aPageNumber )
  366. {
  367. m_pageNumber = aPageNumber;
  368. }
  369. /**
  370. * Set if the page is the first page.
  371. */
  372. void SetIsFirstPage( bool aIsFirstPage ) { m_isFirstPage = aIsFirstPage; }
  373. /**
  374. * Set the value of the count of sheets, for basic inscriptions
  375. */
  376. void SetSheetCount( int aSheetCount )
  377. {
  378. m_sheetCount = aSheetCount;
  379. }
  380. void Append( WS_DRAW_ITEM_BASE* aItem )
  381. {
  382. m_graphicList.push_back( aItem );
  383. }
  384. void Remove( WS_DRAW_ITEM_BASE* aItem )
  385. {
  386. auto newEnd = std::remove( m_graphicList.begin(), m_graphicList.end(), aItem );
  387. m_graphicList.erase( newEnd, m_graphicList.end() );
  388. }
  389. WS_DRAW_ITEM_BASE* GetFirst()
  390. {
  391. m_idx = 0;
  392. if( m_graphicList.size() )
  393. return m_graphicList[0];
  394. else
  395. return NULL;
  396. }
  397. WS_DRAW_ITEM_BASE* GetNext()
  398. {
  399. m_idx++;
  400. if( m_graphicList.size() > m_idx )
  401. return m_graphicList[m_idx];
  402. else
  403. return NULL;
  404. }
  405. void GetAllItems( std::vector<WS_DRAW_ITEM_BASE*>* aList )
  406. {
  407. *aList = m_graphicList;
  408. }
  409. /**
  410. * Draws the item list created by BuildWorkSheetGraphicList
  411. */
  412. void Print( const RENDER_SETTINGS* aSettings );
  413. /**
  414. * Drawing or plot the page layout.
  415. *
  416. * Before calling this function, some parameters should be initialized by calling:
  417. * SetPenSize( aPenWidth );
  418. * SetMilsToIUfactor( aMils2Iu );
  419. * SetSheetNumber( aSheetNumber );
  420. * SetSheetCount( aSheetCount );
  421. * SetFileName( aFileName );
  422. * SetSheetName( aFullSheetName );
  423. *
  424. * @param aPageInfo The PAGE_INFO, for page size, margins...
  425. * @param aTitleBlock The sheet title block, for basic inscriptions.
  426. * @param aColor The color for drawing.
  427. * @param aAltColor The color for items which need to be "highlighted".
  428. */
  429. void BuildWorkSheetGraphicList( const PAGE_INFO& aPageInfo, const TITLE_BLOCK& aTitleBlock );
  430. static void GetTextVars( wxArrayString* aVars );
  431. /**
  432. * Return the full text corresponding to the aTextbase,
  433. * after replacing format symbols by the corresponding value
  434. *
  435. * Basic texts in Ki_WorkSheetData struct use format notation
  436. * like "Title %T" to identify at run time the full text
  437. * to display.
  438. * Currently format identifier is % followed by a letter or 2 letters
  439. *
  440. * %% = replaced by %
  441. * %K = Kicad version
  442. * %Z = paper format name (A4, USLetter)
  443. * %Y = company name
  444. * %D = date
  445. * %R = revision
  446. * %S = sheet number
  447. * %N = number of sheets
  448. * %Cx = comment (x = 0 to 9 to identify the comment)
  449. * %F = filename
  450. * %P = sheet path or sheet full name
  451. * %T = title
  452. * Other fields like Developer, Verifier, Approver could use %Cx
  453. * and are seen as comments for format
  454. *
  455. * @param aTextbase = the text with format symbols
  456. * @return the text, after replacing the format symbols by the actual value
  457. */
  458. wxString BuildFullText( const wxString& aTextbase );
  459. protected:
  460. std::vector <WS_DRAW_ITEM_BASE*> m_graphicList; // Items to draw/plot
  461. unsigned m_idx; // for GetFirst, GetNext functions
  462. double m_milsToIu; // the scalar to convert pages units ( mils)
  463. // to draw/plot units.
  464. int m_penSize; // The default line width for drawings.
  465. // used when an item has a pen size = 0
  466. bool m_isFirstPage; ///< Is this the first page or not.
  467. int m_sheetCount; ///< The number of sheets
  468. // for basic inscriptions, in schematic
  469. const TITLE_BLOCK* m_titleBlock; // for basic inscriptions
  470. const wxString* m_paperFormat; // for basic inscriptions
  471. wxString m_fileName; // for basic inscriptions
  472. wxString m_sheetFullName; // for basic inscriptions
  473. wxString m_pageNumber; ///< The actual page number displayed in the title block.
  474. const wxString* m_sheetLayer; // for basic inscriptions
  475. const PROJECT* m_project; // for project-based variable substitutions
  476. };
  477. #endif // WS_DRAW_ITEM_H