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.

493 lines
13 KiB

18 years ago
18 years ago
18 years ago
18 years ago
14 years ago
14 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
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-2007 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. #include <collectors.h>
  25. #include <class_board_item.h> // class BOARD_ITEM
  26. #include <class_module.h>
  27. #include <class_pad.h>
  28. #include <class_track.h>
  29. #include <class_marker_pcb.h>
  30. /* This module contains out of line member functions for classes given in
  31. * collectors.h. Those classes augment the functionality of class PCB_EDIT_FRAME.
  32. */
  33. // see collectors.h
  34. const KICAD_T GENERAL_COLLECTOR::AllBoardItems[] = {
  35. // there are some restrictions on the order of items in the general case.
  36. // all items in m_Drawings for instance should be contiguous.
  37. // *** all items in a same list (shown here) must be contiguous ****
  38. PCB_MARKER_T, // in m_markers
  39. PCB_TEXT_T, // in m_Drawings
  40. PCB_LINE_T, // in m_Drawings
  41. PCB_DIMENSION_T, // in m_Drawings
  42. PCB_TARGET_T, // in m_Drawings
  43. PCB_VIA_T, // in m_Tracks
  44. PCB_TRACE_T, // in m_Tracks
  45. PCB_PAD_T, // in modules
  46. PCB_MODULE_TEXT_T, // in modules
  47. PCB_MODULE_T, // in m_Modules
  48. PCB_ZONE_T, // in m_Zones
  49. PCB_ZONE_AREA_T, // in m_ZoneDescriptorList
  50. EOT
  51. };
  52. /*
  53. * const KICAD_T GENERAL_COLLECTOR::PrimaryItems[] = {
  54. * PCB_TEXT_T,
  55. * PCB_LINE_T,
  56. * PCB_DIMENSION_T,
  57. * PCB_VIA_T,
  58. * PCB_TRACE_T,
  59. * PCB_MODULE_T,
  60. * EOT
  61. * };
  62. */
  63. const KICAD_T GENERAL_COLLECTOR::AllButZones[] = {
  64. PCB_MARKER_T,
  65. PCB_TEXT_T,
  66. PCB_LINE_T,
  67. PCB_DIMENSION_T,
  68. PCB_TARGET_T,
  69. PCB_VIA_T,
  70. PCB_TRACE_T,
  71. PCB_PAD_T,
  72. PCB_MODULE_TEXT_T,
  73. PCB_MODULE_T,
  74. PCB_ZONE_AREA_T, // if it is visible on screen, it should be selectable
  75. EOT
  76. };
  77. const KICAD_T GENERAL_COLLECTOR::Modules[] = {
  78. PCB_MODULE_T,
  79. EOT
  80. };
  81. const KICAD_T GENERAL_COLLECTOR::PadsOrModules[] = {
  82. PCB_PAD_T,
  83. PCB_MODULE_T,
  84. EOT
  85. };
  86. const KICAD_T GENERAL_COLLECTOR::PadsTracksOrZones[] = {
  87. PCB_PAD_T,
  88. PCB_VIA_T,
  89. PCB_TRACE_T,
  90. PCB_ZONE_T,
  91. PCB_ZONE_AREA_T,
  92. EOT
  93. };
  94. const KICAD_T GENERAL_COLLECTOR::ModulesAndTheirItems[] = {
  95. PCB_MODULE_TEXT_T,
  96. PCB_MODULE_EDGE_T,
  97. PCB_PAD_T,
  98. PCB_MODULE_T,
  99. EOT
  100. };
  101. const KICAD_T GENERAL_COLLECTOR::ModuleItems[] = {
  102. PCB_MODULE_TEXT_T,
  103. PCB_MODULE_EDGE_T,
  104. PCB_PAD_T,
  105. EOT
  106. };
  107. const KICAD_T GENERAL_COLLECTOR::Tracks[] = {
  108. PCB_TRACE_T,
  109. PCB_VIA_T,
  110. EOT
  111. };
  112. const KICAD_T GENERAL_COLLECTOR::Zones[] = {
  113. PCB_ZONE_AREA_T,
  114. EOT
  115. };
  116. /**
  117. * Function Inspect
  118. * is the examining function within the INSPECTOR which is passed to the
  119. * Iterate function. Searches and collects all the objects that the old
  120. * function PcbGeneralLocateAndDisplay() would find, except that it keeps all
  121. * that it finds and does not do any displaying.
  122. *
  123. * @param testItem An EDA_ITEM to examine.
  124. * @param testData not used here.
  125. * @return SEARCH_RESULT - SEARCH_QUIT if the Iterator is to stop the scan,
  126. * else SCAN_CONTINUE;
  127. */
  128. SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData )
  129. {
  130. BOARD_ITEM* item = (BOARD_ITEM*) testItem;
  131. MODULE* module = NULL;
  132. D_PAD* pad = NULL;
  133. bool pad_through = false;
  134. VIA* via = NULL;
  135. MARKER_PCB* marker = NULL;
  136. #if 0 // debugging
  137. static int breakhere = 0;
  138. switch( item->Type() )
  139. {
  140. case PCB_PAD_T:
  141. {
  142. MODULE* m = (MODULE*) item->GetParent();
  143. if( m->GetReference() == wxT( "Y2" ) )
  144. {
  145. breakhere++;
  146. }
  147. }
  148. break;
  149. case PCB_VIA_T:
  150. breakhere++;
  151. break;
  152. case PCB_TRACE_T:
  153. breakhere++;
  154. break;
  155. case PCB_ZONE_T:
  156. breakhere++;
  157. break;
  158. case PCB_TEXT_T:
  159. breakhere++;
  160. break;
  161. case PCB_LINE_T:
  162. breakhere++;
  163. break;
  164. case PCB_DIMENSION_T:
  165. breakhere++;
  166. break;
  167. case PCB_MODULE_TEXT_T:
  168. {
  169. TEXTE_MODULE* tm = (TEXTE_MODULE*) item;
  170. if( tm->GetText() == wxT( "10uH" ) )
  171. {
  172. breakhere++;
  173. }
  174. }
  175. break;
  176. case PCB_MODULE_T:
  177. {
  178. MODULE* m = (MODULE*) item;
  179. if( m->GetReference() == wxT( "C98" ) )
  180. {
  181. breakhere++;
  182. }
  183. }
  184. break;
  185. case PCB_MARKER_T:
  186. breakhere++;
  187. break;
  188. default:
  189. breakhere++;
  190. break;
  191. }
  192. #endif
  193. switch( item->Type() )
  194. {
  195. case PCB_PAD_T:
  196. // there are pad specific visibility controls.
  197. // Criterias to select a pad is:
  198. // for smd pads: the module parent must be seen, and pads on the corresponding
  199. // board side must be seen
  200. // if pad is a thru hole, then it can be visible when its parent module is not.
  201. // for through pads: pads on Front or Back board sides must be seen
  202. pad = (D_PAD*) item;
  203. if( (pad->GetAttribute() != PAD_ATTRIB_SMD) &&
  204. (pad->GetAttribute() != PAD_ATTRIB_CONN) ) // a hole is present, so multiple layers
  205. {
  206. // proceed to the common tests below, but without the parent module test,
  207. // by leaving module==NULL, but having pad != null
  208. pad_through = true;
  209. }
  210. else // smd, so use pads test after module test
  211. {
  212. module = static_cast<MODULE*>( item->GetParent() );
  213. }
  214. break;
  215. case PCB_VIA_T: // vias are on many layers, so layer test is specific
  216. via = static_cast<VIA*>( item );
  217. break;
  218. case PCB_TRACE_T:
  219. break;
  220. case PCB_ZONE_T:
  221. break;
  222. case PCB_ZONE_AREA_T:
  223. break;
  224. case PCB_TEXT_T:
  225. break;
  226. case PCB_LINE_T:
  227. break;
  228. case PCB_DIMENSION_T:
  229. break;
  230. case PCB_TARGET_T:
  231. break;
  232. case PCB_MODULE_TEXT_T:
  233. {
  234. TEXTE_MODULE *text = static_cast<TEXTE_MODULE*>( item );
  235. if( m_Guide->IgnoreMTextsMarkedNoShow() && !text->IsVisible() )
  236. goto exit;
  237. if( m_Guide->IgnoreMTextsOnBack() && IsBackLayer( text->GetLayer() ) )
  238. goto exit;
  239. if( m_Guide->IgnoreMTextsOnFront() && IsFrontLayer( text->GetLayer() ) )
  240. goto exit;
  241. /* The three text types have different criteria: reference
  242. * and value have their own ignore flags; user text instead
  243. * follows their layer visibility. Checking this here is
  244. * simpler than later (when layer visibility is checked for
  245. * other entities) */
  246. switch( text->GetType() )
  247. {
  248. case TEXTE_MODULE::TEXT_is_REFERENCE:
  249. if( m_Guide->IgnoreModulesRefs() )
  250. goto exit;
  251. break;
  252. case TEXTE_MODULE::TEXT_is_VALUE:
  253. if( m_Guide->IgnoreModulesVals() )
  254. goto exit;
  255. break;
  256. case TEXTE_MODULE::TEXT_is_DIVERS:
  257. if( !m_Guide->IsLayerVisible( text->GetLayer() )
  258. && m_Guide->IgnoreNonVisibleLayers() )
  259. goto exit;
  260. break;
  261. }
  262. // Extract the module since it could be hidden
  263. module = static_cast<MODULE*>( item->GetParent() );
  264. }
  265. break;
  266. case PCB_MODULE_T:
  267. module = static_cast<MODULE*>( item );
  268. break;
  269. case PCB_MARKER_T:
  270. marker = static_cast<MARKER_PCB*>( item );
  271. break;
  272. default:
  273. break;
  274. }
  275. // common tests:
  276. if( module ) // true from case PCB_PAD_T, PCB_MODULE_TEXT_T, or PCB_MODULE_T
  277. {
  278. if( m_Guide->IgnoreModulesOnBack() && (module->GetLayer() == B_Cu) )
  279. goto exit;
  280. if( m_Guide->IgnoreModulesOnFront() && (module->GetLayer() == F_Cu) )
  281. goto exit;
  282. }
  283. // Pads are not sensitive to the layer visibility controls.
  284. // They all have their own separate visibility controls
  285. // skip them if not visible
  286. if( pad )
  287. {
  288. if( m_Guide->IgnorePads() )
  289. goto exit;
  290. if( ! pad_through )
  291. {
  292. if( m_Guide->IgnorePadsOnFront() && pad->IsOnLayer(F_Cu ) )
  293. goto exit;
  294. if( m_Guide->IgnorePadsOnBack() && pad->IsOnLayer(B_Cu ) )
  295. goto exit;
  296. }
  297. }
  298. if( marker )
  299. {
  300. // Markers are not sensitive to the layer
  301. if( marker->HitTest( m_RefPos ) )
  302. Append( item );
  303. goto exit;
  304. }
  305. if( item->IsOnLayer( m_Guide->GetPreferredLayer() ) ||
  306. m_Guide->IgnorePreferredLayer() )
  307. {
  308. LAYER_ID layer = item->GetLayer();
  309. /* Modules and their subcomponents: reference, value and pads
  310. * are not sensitive to the layer visibility controls. They all
  311. * have their own separate visibility controls for vias,
  312. * GetLayer() has no meaning, but IsOnLayer() works fine. User
  313. * text in module *is* sensitive to layer visibility but that
  314. * was already handled */
  315. if( via || module || pad || m_Guide->IsLayerVisible( layer )
  316. || !m_Guide->IgnoreNonVisibleLayers() )
  317. {
  318. if( !m_Guide->IsLayerLocked( layer ) || !m_Guide->IgnoreLockedLayers() )
  319. {
  320. if( !item->IsLocked() || !m_Guide->IgnoreLockedItems() )
  321. {
  322. if( item->HitTest( m_RefPos ) )
  323. {
  324. Append( item );
  325. goto exit;
  326. }
  327. }
  328. }
  329. }
  330. }
  331. if( m_Guide->IncludeSecondary() )
  332. {
  333. // for now, "secondary" means "tolerate any layer". It has
  334. // no effect on other criteria, since there is a separate "ignore" control for
  335. // those in the COLLECTORS_GUIDE
  336. LAYER_ID layer = item->GetLayer();
  337. /* Modules and their subcomponents: reference, value and pads
  338. * are not sensitive to the layer visibility controls. They all
  339. * have their own separate visibility controls. User texts
  340. * follows layer visibility controls (but that was already
  341. * checked) */
  342. if( via || module || pad || m_Guide->IsLayerVisible( layer )
  343. || !m_Guide->IgnoreNonVisibleLayers() )
  344. {
  345. if( !m_Guide->IsLayerLocked( layer ) || !m_Guide->IgnoreLockedLayers() )
  346. {
  347. if( !item->IsLocked() || !m_Guide->IgnoreLockedItems() )
  348. {
  349. if( item->HitTest( m_RefPos ) )
  350. {
  351. Append2nd( item );
  352. goto exit;
  353. }
  354. }
  355. }
  356. }
  357. }
  358. exit:
  359. return SEARCH_CONTINUE; // always when collecting
  360. }
  361. // see collectors.h
  362. void GENERAL_COLLECTOR::Collect( BOARD_ITEM* aItem, const KICAD_T aScanList[],
  363. const wxPoint& aRefPos, const COLLECTORS_GUIDE& aGuide )
  364. {
  365. Empty(); // empty the collection, primary criteria list
  366. Empty2nd(); // empty the collection, secondary criteria list
  367. // remember guide, pass it to Inspect()
  368. SetGuide( &aGuide );
  369. SetScanTypes( aScanList );
  370. // remember where the snapshot was taken from and pass refPos to
  371. // the Inspect() function.
  372. SetRefPos( aRefPos );
  373. aItem->Visit( m_inspector, NULL, m_ScanTypes );
  374. SetTimeNow(); // when snapshot was taken
  375. // record the length of the primary list before concatenating on to it.
  376. m_PrimaryLength = m_List.size();
  377. // append 2nd list onto end of the first list
  378. for( unsigned i = 0; i<m_List2nd.size(); ++i )
  379. Append( m_List2nd[i] );
  380. Empty2nd();
  381. }
  382. // see collectors.h
  383. SEARCH_RESULT PCB_TYPE_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData )
  384. {
  385. // The Vist() function only visits the testItem if its type was in the
  386. // the scanList, so therefore we can collect anything given to us here.
  387. Append( testItem );
  388. return SEARCH_CONTINUE; // always when collecting
  389. }
  390. void PCB_TYPE_COLLECTOR::Collect( BOARD_ITEM* aBoard, const KICAD_T aScanList[] )
  391. {
  392. Empty(); // empty any existing collection
  393. aBoard->Visit( m_inspector, NULL, aScanList );
  394. }