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.

527 lines
14 KiB

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