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.

300 lines
8.9 KiB

18 years ago
18 years ago
18 years ago
11 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
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) 2007-2008 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
  5. * Copyright (C) 2004-2017 KiCad Developers, see change_log.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. /**
  25. * @file collector.h
  26. * @brief COLLECTOR class definition.
  27. */
  28. #ifndef COLLECTOR_H
  29. #define COLLECTOR_H
  30. #include <vector>
  31. #include <base_struct.h> // SEARCH_RESULT
  32. #include <common.h> // GetNewTimeStamp()
  33. #include <eda_rect.h>
  34. class EDA_ITEM;
  35. /**
  36. * Class COLLECTOR
  37. * is an abstract class that will find and hold all the objects according to
  38. * an inspection done by the Inspect() function which must be implemented by
  39. * any derived class. When Inspect() finds an object that it wants to collect,
  40. * i.e. one that it "likes", then it only has to do an Append( testItem )
  41. * on it to add it to its collection, but in all cases for the scan to continue,
  42. * Inspect() must return SEARCH_CONTINUE.
  43. *
  44. * Later, after collection, the user can iterate through all the objects
  45. * in the remembered collection using GetCount() and the [int] operator.
  46. */
  47. class COLLECTOR
  48. {
  49. protected:
  50. std::vector<EDA_ITEM*> m_List;
  51. const KICAD_T* m_ScanTypes;
  52. INSPECTOR_FUNC m_inspector;
  53. wxPoint m_RefPos; // Reference position used to generate the collection.
  54. EDA_RECT m_RefBox; // Selection rectangle used to generate the collection.
  55. timestamp_t m_TimeAtCollection; // The time at which the collection was made.
  56. public:
  57. int m_Threshold; // Hit-test threshold in internal units.
  58. wxString m_MenuTitle; // The title of selection disambiguation menu (if needed)
  59. bool m_MenuCancelled; // Indicates selection disambiguation menu was cancelled
  60. public:
  61. COLLECTOR() :
  62. m_ScanTypes( 0 ),
  63. // Inspect() is virtual so calling it from a class common inspector preserves polymorphism.
  64. m_inspector( [=] ( EDA_ITEM* aItem, void* aTestData ) { return this->Inspect( aItem, aTestData ); } ),
  65. m_TimeAtCollection( 0 ),
  66. m_Threshold( 0 ),
  67. m_MenuCancelled( false )
  68. {
  69. }
  70. virtual ~COLLECTOR() {}
  71. virtual SEARCH_RESULT Inspect( EDA_ITEM* aItem, void* aTestData ) { return SEARCH_QUIT; };
  72. using ITER = std::vector<EDA_ITEM*>::iterator;
  73. using CITER = std::vector<EDA_ITEM*>::const_iterator;
  74. ITER begin() { return m_List.begin(); }
  75. ITER end() { return m_List.end(); }
  76. CITER begin() const { return m_List.cbegin(); }
  77. CITER end() const { return m_List.cend(); }
  78. /**
  79. * Function IsValidIndex
  80. * tests if \a aIndex is with the limits of the list of collected items.
  81. *
  82. * @param aIndex The index to test.
  83. * @return True if \a aIndex is with the limits of the list of collected items,
  84. * otherwise false.
  85. */
  86. bool IsValidIndex( int aIndex )
  87. {
  88. return ( (unsigned) aIndex < m_List.size() );
  89. }
  90. /**
  91. * Function GetCount
  92. * returns the number of objects in the list
  93. */
  94. int GetCount() const
  95. {
  96. return (int) m_List.size();
  97. }
  98. /**
  99. * Function Empty
  100. * sets the list to empty
  101. */
  102. void Empty()
  103. {
  104. m_List.clear();
  105. }
  106. /**
  107. * Function Append
  108. * adds an item to the end of the list.
  109. * @param item An EDA_ITEM* to add.
  110. */
  111. void Append( EDA_ITEM* item )
  112. {
  113. m_List.push_back( item );
  114. }
  115. /**
  116. * Function Remove
  117. * removes the item at \a aIndex (first position is 0);
  118. * @param aIndex The index into the list.
  119. */
  120. void Remove( int aIndex )
  121. {
  122. m_List.erase( m_List.begin() + aIndex );
  123. }
  124. /**
  125. * Function Remove
  126. * removes the item aItem (if exists in the collector).
  127. * @param aItem the item to be removed.
  128. */
  129. void Remove( const EDA_ITEM* aItem )
  130. {
  131. for( size_t i = 0; i < m_List.size(); i++ )
  132. {
  133. if( m_List[i] == aItem )
  134. {
  135. m_List.erase( m_List.begin() + i);
  136. return;
  137. }
  138. }
  139. }
  140. /**
  141. * Function operator[int]
  142. * is used for read only access and returns the object at \a aIndex.
  143. * @param aIndex The index into the list.
  144. * @return EDA_ITEM* - or something derived from it, or NULL.
  145. */
  146. virtual EDA_ITEM* operator[]( int aIndex ) const
  147. {
  148. if( (unsigned)aIndex < (unsigned)GetCount() ) // (unsigned) excludes aIndex<0 also
  149. return m_List[ aIndex ];
  150. return NULL;
  151. }
  152. /**
  153. * Function BasePtr
  154. * returns the address of the first element in the array. Only call this
  155. * if there is at least one element in the vector m_List, otherwise a
  156. * C++ exception should get thrown.
  157. */
  158. EDA_ITEM* const* BasePtr() const
  159. {
  160. return &m_List[0];
  161. }
  162. /**
  163. * Function HasItem
  164. * tests if \a aItem has already been collected.
  165. *
  166. * @param aItem The EDA_ITEM* to be tested.
  167. * @return True if \a aItem is already collected.
  168. */
  169. bool HasItem( const EDA_ITEM* aItem ) const
  170. {
  171. for( size_t i = 0; i < m_List.size(); i++ )
  172. {
  173. if( m_List[i] == aItem )
  174. return true;
  175. }
  176. return false;
  177. }
  178. /**
  179. * Function SetScanTypes
  180. * records the list of KICAD_T types to consider for collection by
  181. * the Inspect() function.
  182. * @param scanTypes An array of KICAD_T, terminated by EOT. No copy is
  183. * is made of this array (so cannot come from caller's stack).
  184. */
  185. void SetScanTypes( const KICAD_T* scanTypes )
  186. {
  187. m_ScanTypes = scanTypes;
  188. }
  189. void SetTimeNow()
  190. {
  191. m_TimeAtCollection = GetNewTimeStamp();
  192. }
  193. timestamp_t GetTime()
  194. {
  195. return m_TimeAtCollection;
  196. }
  197. void SetRefPos( const wxPoint& aRefPos ) { m_RefPos = aRefPos; }
  198. const wxPoint& GetRefPos() const { return m_RefPos; }
  199. void SetBoundingBox( const EDA_RECT& aRefBox ) { m_RefBox = aRefBox; }
  200. const EDA_RECT& GetBoundingBox() const { return m_RefBox; }
  201. /**
  202. * Function IsSimilarPointAndTime
  203. * returns true if the given reference point is "similar" (defined here)
  204. * to the internal reference point and the current time is within a few
  205. * seconds of the internal m_TimeAtCollection.
  206. *
  207. * @param aRefPos A wxPoint to compare to.
  208. * @return bool - true if the point and time are similar, else false.
  209. */
  210. bool IsSimilarPointAndTime( const wxPoint& aRefPos )
  211. {
  212. const int distMax = 2; // adjust these here
  213. const timestamp_t timeMax = 3; // seconds
  214. int dx = abs( aRefPos.x - m_RefPos.x );
  215. int dy = abs( aRefPos.y - m_RefPos.y );
  216. if( dx <= distMax && dy <= distMax &&
  217. GetNewTimeStamp() - m_TimeAtCollection <= timeMax )
  218. return true;
  219. else
  220. return false;
  221. }
  222. /**
  223. * Function CountType
  224. * counts the number of items matching aType
  225. * @param aType type we are interested in
  226. * @return number of occurences
  227. */
  228. int CountType( KICAD_T aType )
  229. {
  230. int cnt = 0;
  231. for( size_t i = 0; i < m_List.size(); i++ )
  232. {
  233. if( m_List[i]->Type() == aType )
  234. cnt++;
  235. }
  236. return cnt;
  237. }
  238. /**
  239. * Function Collect
  240. * scans an EDA_ITEM using this class's Inspector method, which does
  241. * the collection.
  242. * @param container An EDA_ITEM to scan, including those items it contains.
  243. * @param aRefPos A wxPoint to use in hit-testing.
  244. *
  245. * example implementation, in derived class:
  246. *
  247. void Collect( EDA_ITEM* container, const wxPoint& aRefPos )
  248. {
  249. example implementation:
  250. SetRefPos( aRefPos ); // remember where the snapshot was taken from
  251. Empty(); // empty the collection
  252. // visit the board with the INSPECTOR (me).
  253. container->Visit( inspector, &aRefPos,
  254. m_ScanTypes);
  255. SetTimeNow(); // when it was taken
  256. }
  257. */
  258. };
  259. #endif // COLLECTOR_H